1 /*
2 
3     Copyright (C) 2014, The University of Texas at Austin
4 
5     This file is part of libflame and is available under the 3-Clause
6     BSD license, which can be found in the LICENSE file at the top-level
7     directory, or at http://opensource.org/licenses/BSD-3-Clause
8 
9 */
10 
11 #include "FLAME.h"
12 
13 
14 #ifdef FLA_ENABLE_SCC
15 typedef volatile unsigned char* t_vcharp;
16 t_vcharp RCCE_shmalloc(size_t);
17 void     RCCE_shfree(t_vcharp);
18 int      RCCE_ue(void);
19 
20 
FLA_shmalloc(size_t size)21 void* FLA_shmalloc( size_t size )
22 {
23   return ( void * ) RCCE_shmalloc( size );
24 }
25 
26 
FLA_shfree(void * ptr)27 void FLA_shfree( void* ptr )
28 {
29   RCCE_shfree( ( t_vcharp ) ptr );
30 }
31 
32 
FLA_is_owner(void)33 FLA_Bool FLA_is_owner( void )
34 {
35   if ( RCCE_ue() == 0 )
36     return TRUE;
37   return FALSE;
38 }
39 #endif
40 
FLA_Obj_nullify(FLA_Obj * obj)41 FLA_Error FLA_Obj_nullify( FLA_Obj *obj )
42 {
43   // Nullify the fields in the view object.
44   obj->m       = 0;
45   obj->n       = 0;
46   obj->offm    = 0;
47   obj->offn    = 0;
48   obj->m_inner = 0;
49   obj->n_inner = 0;
50   obj->base    = NULL;
51 
52   return FLA_SUCCESS;
53 }
54 
FLA_Obj_create(FLA_Datatype datatype,dim_t m,dim_t n,dim_t rs,dim_t cs,FLA_Obj * obj)55 FLA_Error FLA_Obj_create( FLA_Datatype datatype, dim_t m, dim_t n, dim_t rs, dim_t cs, FLA_Obj *obj )
56 {
57   FLA_Obj_create_ext( datatype, FLA_SCALAR, m, n, m, n, rs, cs, obj );
58 
59   return FLA_SUCCESS;
60 }
61 
62 
63 
FLA_Obj_create_ext(FLA_Datatype datatype,FLA_Elemtype elemtype,dim_t m,dim_t n,dim_t m_inner,dim_t n_inner,dim_t rs,dim_t cs,FLA_Obj * obj)64 FLA_Error FLA_Obj_create_ext( FLA_Datatype datatype, FLA_Elemtype elemtype, dim_t m, dim_t n, dim_t m_inner, dim_t n_inner, dim_t rs, dim_t cs, FLA_Obj *obj )
65 {
66   size_t buffer_size;
67   size_t n_elem;
68 
69   // Adjust the strides, if necessary.
70   FLA_adjust_strides( m, n, &rs, &cs );
71 
72   if ( FLA_Check_error_level() >= FLA_MIN_ERROR_CHECKING )
73     FLA_Obj_create_ext_check( datatype, elemtype, m, n, m_inner, n_inner, rs, cs, obj );
74 
75   // Populate the fields in the view object.
76   obj->m                = m;
77   obj->n                = n;
78   obj->offm             = 0;
79   obj->offn             = 0;
80   obj->m_inner          = m_inner;
81   obj->n_inner          = n_inner;
82 
83   // Allocate the base object field.
84   obj->base             = ( FLA_Base_obj * ) FLA_malloc( sizeof( FLA_Base_obj ) );
85 
86   // Populate the fields in the base object.
87   obj->base->datatype   = datatype;
88   obj->base->elemtype   = elemtype;
89   obj->base->m          = m;
90   obj->base->n          = n;
91   obj->base->m_inner    = m_inner;
92   obj->base->n_inner    = n_inner;
93   obj->base->id         = ( unsigned long ) obj->base;
94   obj->base->m_index    = 0;
95   obj->base->n_index    = 0;
96 
97   // Compute the number of elements needed for the buffer, adjusting
98   // the strides for alignment if needed.
99   n_elem = FLA_compute_num_elem( FLA_Obj_elem_size( *obj ),
100                                  m, n, &rs, &cs );
101 
102   // Compute the buffer size in bytes.
103   buffer_size = ( size_t ) n_elem *
104                 ( size_t ) FLA_Obj_elem_size( *obj );
105 
106   // Allocate the base object's element buffer.
107 #ifdef FLA_ENABLE_SCC
108   obj->base->buffer = ( FLA_Obj_elemtype( *obj ) == FLA_MATRIX ? FLA_malloc( buffer_size ) : FLA_shmalloc( buffer_size ) );
109 #else
110   obj->base->buffer = FLA_malloc( buffer_size );
111 #endif
112   obj->base->buffer_info = 0;
113 
114   // Just in case this is a FLASH object, save the number of elements
115   // allocated so that we can more easily free the elements later on.
116   obj->base->n_elem_alloc = n_elem;
117 
118   // Save the row and column strides used in the memory allocation.
119   obj->base->rs     = rs;
120   obj->base->cs     = cs;
121 
122 #ifdef FLA_ENABLE_SUPERMATRIX
123   // Initialize SuperMatrix fields.
124   obj->base->n_read_tasks   = 0;
125   obj->base->read_task_head = NULL;
126   obj->base->read_task_tail = NULL;
127   obj->base->write_task     = NULL;
128 #endif
129 
130   return FLA_SUCCESS;
131 }
132 
133 
FLA_compute_num_elem(dim_t elem_size,dim_t m,dim_t n,dim_t * rs,dim_t * cs)134 dim_t FLA_compute_num_elem( dim_t elem_size, dim_t m, dim_t n, dim_t* rs, dim_t* cs )
135 {
136   dim_t n_elem;
137 
138   // Determine the amount of space we need to allocate based on the values of
139   // the row and column strides.
140   if ( m == 0 || n == 0 )
141   {
142     // For empty objects, set the length of the buffer to 0. Row and column
143     // strides should remain unchanged (because alignment is not needed).
144     n_elem = 0;
145   }
146   else if ( *rs == 1 )
147   {
148     // For column-major storage, use cs for computing the length of the buffer
149     // to allocate.
150 
151     // Align the leading dimension to some user-defined address multiple,
152     // if requested at configure-time.
153     *cs = FLA_align_ldim( *cs, elem_size );
154 
155     // Compute the length of the buffer needed for the object we're creating.
156     n_elem = ( size_t ) *cs *
157              ( size_t ) n;
158   }
159   else if ( *cs == 1 )
160   {
161     // For row-major storage, use rs for computing the length of the buffer
162     // to allocate.
163 
164     // Align the leading dimension to some user-defined address multiple,
165     // if requested at configure-time.
166     *rs = FLA_align_ldim( *rs, elem_size );
167 
168     // Compute the length of the buffer needed for the object we're creating.
169     n_elem = ( size_t ) m *
170              ( size_t ) *rs;
171   }
172   else
173   {
174     // For general storage, use rs and cs to compute the length of the buffer
175     // to allocate.
176 
177     // Compute the size of the buffer needed for the object we're creating.
178     if ( *rs < *cs )
179     {
180       *cs = FLA_align_ldim( *cs, elem_size );
181 
182       n_elem = ( size_t ) *cs *
183                ( size_t ) n;
184     }
185     else if ( *rs > *cs )
186     {
187       *rs = FLA_align_ldim( *rs, elem_size );
188 
189       n_elem = ( size_t ) m *
190                ( size_t ) *rs;
191     }
192     else // if ( rs == cs )
193     {
194       //rs = FLA_align_ldim( rs, FLA_Obj_elem_size( *obj ) );
195       *cs = FLA_align_ldim( *cs, elem_size );
196 
197       // Note that if rs == cs, then we must be creating either a 1-by-n matrix
198       // or a m-by-1 matrix. This constraint is enforced in
199       // FLA_Check_matrix_strides(). Thus, we can compute the buffer length:
200       // m * n * (rs|cs).
201       n_elem = ( size_t ) m *
202                ( size_t ) n *
203                ( size_t ) *cs;
204     }
205   }
206 
207   return n_elem;
208 }
209 
210 
FLA_align_ldim(dim_t ldim,dim_t elem_size)211 dim_t FLA_align_ldim( dim_t ldim, dim_t elem_size )
212 {
213 #ifdef FLA_ENABLE_MEMORY_ALIGNMENT
214   #ifdef FLA_ENABLE_LDIM_ALIGNMENT
215     // Increase ldim so that ( ldim * elem_size ) is a multiple of the desired
216     // alignment.
217     ldim = ( ( ldim * elem_size + FLA_MEMORY_ALIGNMENT_BOUNDARY - 1 ) /
218              FLA_MEMORY_ALIGNMENT_BOUNDARY ) *
219            FLA_MEMORY_ALIGNMENT_BOUNDARY /
220            elem_size;
221   #endif
222 #endif
223 
224   return ldim;
225 }
226 
227 
FLA_adjust_strides(dim_t m,dim_t n,dim_t * rs,dim_t * cs)228 void FLA_adjust_strides( dim_t m, dim_t n, dim_t* rs, dim_t* cs )
229 {
230   // Check the strides, and modify them if needed.
231   if ( *rs == 0 && *cs == 0 )
232   {
233     // Default values induce column-major storage, except when m == 1,
234     // because we dont want both strides to be unit.
235     if ( m == 1 && n > 1 )
236     {
237       *rs = n;
238       *cs = 1;
239     }
240     else
241     {
242       *rs = 1;
243       *cs = m;
244     }
245   }
246   else if ( *rs == 1 && *cs == 1 )
247   {
248     // If both strides are unit, this is probably a "lazy" request for a
249     // single vector (but could also be a request for a 1xn matrix in column-
250     // major order or an mx1 matrix in row-major order). In libflame, we have
251     // decided to "reserve" the case where rs == cs == 1 for scalars only, as
252     // having unit strides can upset the BLAS error checking when attempting
253     // to induce a row-major operation. Also, there is another special case
254     // where rs == cs == 1 and one or both of m and n equal zero. This last
255     // case is supported to allow creating "empty" objects.
256 
257     if ( m == 0 || n == 0 )
258     {
259       // Nothing needs to be done for the "empty" case where m and/or n
260       // equal zero.
261     }
262     else if ( m == 1 && n == 1 )
263     {
264       // Nothing needs to be done for the scalar case where m == n == 1.
265     }
266     else if ( m > 1 && n == 1 )
267     {
268       // Set the column stride to indicate that this is a column vector stored
269       // in column-major order. This is necessary because, in some cases, we
270       // have to satisify the error checking in the underlying BLAS library,
271       // which expects the leading dimension to be set to at least m, even if
272       // it will never be used for indexing since it is a vector and thus only
273       // has one column of data.
274       *cs = m;
275     }
276     else if ( m == 1 && n > 1 )
277     {
278       // Set the row stride to indicate that this is a row vector stored
279       // in row-major order.
280       *rs = n;
281     }
282   }
283 }
284 
285 
FLA_Obj_create_conf_to(FLA_Trans trans,FLA_Obj obj_cur,FLA_Obj * obj_new)286 FLA_Error FLA_Obj_create_conf_to( FLA_Trans trans, FLA_Obj obj_cur, FLA_Obj *obj_new )
287 {
288   FLA_Datatype datatype;
289   FLA_Elemtype elemtype;
290   dim_t        m, n;
291   dim_t        rs, cs;
292 
293   if ( FLA_Check_error_level() >= FLA_MIN_ERROR_CHECKING )
294     FLA_Obj_create_conf_to_check( trans, obj_cur, obj_new );
295 
296   datatype = FLA_Obj_datatype( obj_cur );
297   elemtype = FLA_Obj_elemtype( obj_cur );
298 
299   // Query the dimensions of the existing object.
300   if ( trans == FLA_NO_TRANSPOSE || trans == FLA_CONJ_NO_TRANSPOSE )
301   {
302     m = FLA_Obj_length( obj_cur );
303     n = FLA_Obj_width( obj_cur );
304   }
305   else // if ( trans == FLA_TRANSPOSE || trans == FLA_CONJ_TRANSPOSE )
306   {
307     m = FLA_Obj_width( obj_cur );
308     n = FLA_Obj_length( obj_cur );
309   }
310 
311   // Query the row and column strides of the existing object. We don't care
312   // about the actual leading dimension of the existing object, only whether
313   // it is in row- or column-major format.
314   rs = FLA_Obj_row_stride( obj_cur );
315   cs = FLA_Obj_col_stride( obj_cur );
316 
317   if ( ( rs == 1 && cs == 1 ) )
318   {
319     // Do nothing. This special case will be handled by FLA_adjust_strides().
320     ;
321   }
322   else if ( rs == 1 )
323   {
324     // For column-major storage, use the m dimension as the column stride.
325     // Row stride is already set to 1.
326     cs = m;
327   }
328   else if ( cs == 1 )
329   {
330     // For row-major storage, use the n dimension as the row stride.
331     // Column stride is already set to 1.
332     rs = n;
333   }
334 
335   // Handle empty views.
336   if ( m == 0 ) cs = 1;
337   if ( n == 0 ) rs = 1;
338 
339   FLA_Obj_create_ext( datatype, elemtype, m, n, m, n, rs, cs, obj_new );
340 
341   return FLA_SUCCESS;
342 }
343 
344 
FLA_Obj_create_copy_of(FLA_Trans trans,FLA_Obj obj_cur,FLA_Obj * obj_new)345 FLA_Error FLA_Obj_create_copy_of( FLA_Trans trans, FLA_Obj obj_cur, FLA_Obj *obj_new )
346 {
347   // Create a new object conformal to the current object.
348   FLA_Obj_create_conf_to( trans, obj_cur, obj_new );
349 
350 #ifdef FLA_ENABLE_SCC
351   if ( !FLA_is_owner() )
352     return FLA_SUCCESS;
353 #endif
354 
355   // Copy the contents of the current object to the new object.
356   FLA_Copyt_external( trans, obj_cur, *obj_new );
357 
358   return FLA_SUCCESS;
359 }
360 
361 
FLA_Obj_create_without_buffer(FLA_Datatype datatype,dim_t m,dim_t n,FLA_Obj * obj)362 FLA_Error FLA_Obj_create_without_buffer( FLA_Datatype datatype, dim_t m, dim_t n, FLA_Obj *obj )
363 {
364   if ( FLA_Check_error_level() >= FLA_MIN_ERROR_CHECKING )
365     FLA_Obj_create_without_buffer_check( datatype, m, n, obj );
366 
367   // Populate the fields in the view object.
368   obj->m                = m;
369   obj->n                = n;
370   obj->offm             = 0;
371   obj->offn             = 0;
372   obj->m_inner          = m;
373   obj->n_inner          = n;
374 
375   // Allocate the base object field.
376   obj->base             = ( FLA_Base_obj * ) FLA_malloc( sizeof( FLA_Base_obj ) );
377 
378   // Populate the fields in the base object.
379   obj->base->datatype   = datatype;
380   obj->base->elemtype   = FLA_SCALAR;
381   obj->base->m          = m;
382   obj->base->n          = n;
383   obj->base->m_inner    = m;
384   obj->base->n_inner    = n;
385   obj->base->id         = ( unsigned long ) obj->base;
386   obj->base->m_index    = 0;
387   obj->base->n_index    = 0;
388 
389   // Set the row and column strides to invalid values.
390   obj->base->rs         = 0;
391   obj->base->cs         = 0;
392 
393   // Initialize the base object's element buffer to NULL.
394   obj->base->buffer       = NULL;
395   obj->base->buffer_info  = 0;
396   obj->base->n_elem_alloc = 0;
397 
398 #ifdef FLA_ENABLE_SUPERMATRIX
399   // Initialize SuperMatrix fields.
400   obj->base->n_read_tasks   = 0;
401   obj->base->read_task_head = NULL;
402   obj->base->read_task_tail = NULL;
403   obj->base->write_task     = NULL;
404 #endif
405 
406   return FLA_SUCCESS;
407 }
408 
409 
410 
FLA_Obj_create_constant(double const_real,FLA_Obj * obj)411 FLA_Error FLA_Obj_create_constant( double const_real, FLA_Obj *obj )
412 {
413   int*      temp_i;
414   float*    temp_s;
415   double*   temp_d;
416   scomplex* temp_c;
417   dcomplex* temp_z;
418 
419   if ( FLA_Check_error_level() >= FLA_MIN_ERROR_CHECKING )
420     FLA_Obj_create_constant_check( const_real, obj );
421 
422   FLA_Obj_create( FLA_CONSTANT, 1, 1, 0, 0, obj );
423 
424 #ifdef FLA_ENABLE_SCC
425   if ( !FLA_is_owner() )
426     return FLA_SUCCESS;
427 #endif
428 
429   temp_i       = FLA_INT_PTR( *obj );
430   temp_s       = FLA_FLOAT_PTR( *obj );
431   temp_d       = FLA_DOUBLE_PTR( *obj );
432   temp_c       = FLA_COMPLEX_PTR( *obj );
433   temp_z       = FLA_DOUBLE_COMPLEX_PTR( *obj );
434 
435   *temp_i      = ( int   ) const_real;
436   *temp_s      = ( float ) const_real;
437   *temp_d      =           const_real;
438   temp_c->real = ( float ) const_real;
439   temp_c->imag = ( float ) 0.0;
440   temp_z->real =           const_real;
441   temp_z->imag =           0.0;
442 
443   return FLA_SUCCESS;
444 }
445 
446 
447 
FLA_Obj_create_constant_ext(float const_s,double const_d,FLA_Obj * obj)448 FLA_Error FLA_Obj_create_constant_ext( float const_s, double const_d, FLA_Obj *obj )
449 {
450   int*      temp_i;
451   float*    temp_s;
452   double*   temp_d;
453   scomplex* temp_c;
454   dcomplex* temp_z;
455 
456   if ( FLA_Check_error_level() >= FLA_MIN_ERROR_CHECKING )
457     FLA_Obj_create_constant_ext_check( const_s, const_d, obj );
458 
459   FLA_Obj_create( FLA_CONSTANT, 1, 1, 0, 0, obj );
460 
461 #ifdef FLA_ENABLE_SCC
462   if ( !FLA_is_owner() )
463     return FLA_SUCCESS;
464 #endif
465 
466   temp_i       = FLA_INT_PTR( *obj );
467   temp_s       = FLA_FLOAT_PTR( *obj );
468   temp_d       = FLA_DOUBLE_PTR( *obj );
469   temp_c       = FLA_COMPLEX_PTR( *obj );
470   temp_z       = FLA_DOUBLE_COMPLEX_PTR( *obj );
471 
472   *temp_i      = ( int   ) const_s;
473   *temp_s      =           const_s;
474   *temp_d      =           const_d;
475   temp_c->real =           const_s;
476   temp_c->imag =           0.0F;
477   temp_z->real =           const_d;
478   temp_z->imag =           0.0;
479 
480   return FLA_SUCCESS;
481 }
482 
483 
484 
FLA_Obj_create_complex_constant(double const_real,double const_imag,FLA_Obj * obj)485 FLA_Error FLA_Obj_create_complex_constant( double const_real, double const_imag, FLA_Obj *obj )
486 {
487   int*      temp_i;
488   float*    temp_s;
489   double*   temp_d;
490   scomplex* temp_c;
491   dcomplex* temp_z;
492 
493   if ( FLA_Check_error_level() >= FLA_MIN_ERROR_CHECKING )
494     FLA_Obj_create_complex_constant_check( const_real, const_imag, obj );
495 
496   FLA_Obj_create( FLA_CONSTANT, 1, 1, 0, 0, obj );
497 
498 #ifdef FLA_ENABLE_SCC
499   if ( !FLA_is_owner() )
500     return FLA_SUCCESS;
501 #endif
502 
503   temp_i       = FLA_INT_PTR( *obj );
504   temp_s       = FLA_FLOAT_PTR( *obj );
505   temp_d       = FLA_DOUBLE_PTR( *obj );
506   temp_c       = FLA_COMPLEX_PTR( *obj );
507   temp_z       = FLA_DOUBLE_COMPLEX_PTR( *obj );
508 
509   *temp_i      = ( int   ) const_real;
510   *temp_s      = ( float ) const_real;
511   *temp_d      =           const_real;
512   temp_c->real = ( float ) const_real;
513   temp_c->imag = ( float ) const_imag;
514   temp_z->real =           const_real;
515   temp_z->imag =           const_imag;
516 
517   return FLA_SUCCESS;
518 }
519 
520 
521 
FLA_Obj_attach_buffer(void * buffer,dim_t rs,dim_t cs,FLA_Obj * obj)522 FLA_Error FLA_Obj_attach_buffer( void *buffer, dim_t rs, dim_t cs, FLA_Obj *obj )
523 {
524   dim_t m, n;
525 
526   m = FLA_Obj_length( *obj );
527   n = FLA_Obj_width( *obj );
528 
529   // Adjust the strides, if necessary.
530   FLA_adjust_strides( m, n, &rs, &cs );
531 
532   if ( FLA_Check_error_level() >= FLA_MIN_ERROR_CHECKING )
533     FLA_Obj_attach_buffer_check( buffer, rs, cs, obj );
534 
535   obj->base->buffer      = buffer;
536   obj->base->rs          = rs;
537   obj->base->cs          = cs;
538 
539   return FLA_SUCCESS;
540 }
541 
542 
543 
FLA_Obj_create_buffer(dim_t rs,dim_t cs,FLA_Obj * obj)544 FLA_Error FLA_Obj_create_buffer( dim_t rs, dim_t cs, FLA_Obj *obj )
545 {
546   size_t buffer_size;
547   size_t n_elem;
548   dim_t  m, n;
549 
550   m = FLA_Obj_length( *obj );
551   n = FLA_Obj_width( *obj );
552 
553   // Adjust the strides, if necessary.
554   FLA_adjust_strides( m, n, &rs, &cs );
555 
556   if ( FLA_Check_error_level() >= FLA_MIN_ERROR_CHECKING )
557     FLA_Obj_create_buffer_check( rs, cs, obj );
558 
559   // Compute the number of elements needed for the buffer, adjusting
560   // the strides for alignment if needed.
561   n_elem = FLA_compute_num_elem( FLA_Obj_elem_size( *obj ),
562                                  m, n, &rs, &cs );
563 
564   // Compute the buffer size in bytes.
565   buffer_size = ( size_t ) n_elem *
566                 ( size_t ) FLA_Obj_elem_size( *obj );
567 
568   // Allocate the base object's element buffer.
569 #ifdef FLA_ENABLE_SCC
570   obj->base->buffer = ( FLA_Obj_elemtype( *obj ) == FLA_MATRIX ? FLA_malloc( buffer_size ) : FLA_shmalloc( buffer_size ) );
571 #else
572   obj->base->buffer = FLA_malloc( buffer_size );
573 #endif
574   obj->base->buffer_info = 0;
575 
576   // Save the number of elements allocated (for use with FLASH).
577   obj->base->n_elem_alloc = n_elem;
578 
579   // Save the row and column strides used in the memory allocation.
580   obj->base->rs     = rs;
581   obj->base->cs     = cs;
582 
583   return FLA_SUCCESS;
584 }
585 
586 
587 
FLA_Obj_free(FLA_Obj * obj)588 FLA_Error FLA_Obj_free( FLA_Obj *obj )
589 {
590   if ( FLA_Check_error_level() >= FLA_MIN_ERROR_CHECKING )
591     FLA_Obj_free_check( obj );
592 
593   if ( obj->base != NULL )
594   {
595 #ifdef FLA_ENABLE_SCC
596     ( FLA_Obj_elemtype( *obj ) == FLA_MATRIX ? FLA_free( obj->base->buffer ) : FLA_shfree( obj->base->buffer ) );
597 #else
598     //printf( "freeing buff %p\n", obj->base->buffer ); fflush( stdout );
599     FLA_free( obj->base->buffer );
600 #endif
601     //printf( "freeing base %p\n", obj->base ); fflush( stdout );
602     FLA_free( ( void * ) obj->base );
603   }
604 
605   obj->offm = 0;
606   obj->offn = 0;
607   obj->m    = 0;
608   obj->n    = 0;
609 
610   return FLA_SUCCESS;
611 }
612 
613 
614 
FLA_Obj_free_without_buffer(FLA_Obj * obj)615 FLA_Error FLA_Obj_free_without_buffer( FLA_Obj *obj )
616 {
617   if ( FLA_Check_error_level() >= FLA_MIN_ERROR_CHECKING )
618     FLA_Obj_free_without_buffer_check( obj );
619 
620   FLA_free( ( void * ) obj->base );
621 
622   obj->offm = 0;
623   obj->offn = 0;
624   obj->m    = 0;
625   obj->n    = 0;
626 
627   return FLA_SUCCESS;
628 }
629 
630 
631 
FLA_Obj_free_buffer(FLA_Obj * obj)632 FLA_Error FLA_Obj_free_buffer( FLA_Obj *obj )
633 {
634   if ( FLA_Check_error_level() >= FLA_MIN_ERROR_CHECKING )
635     FLA_Obj_free_buffer_check( obj );
636 
637 #ifdef FLA_ENABLE_SCC
638   ( FLA_Obj_elemtype( *obj ) == FLA_MATRIX ? FLA_free( obj->base->buffer ) : FLA_shfree( obj->base->buffer ) );
639 #else
640   FLA_free( obj->base->buffer );
641 #endif
642   obj->base->buffer = NULL;
643 
644   return FLA_SUCCESS;
645 }
646 
FLA_Obj_flip_base(FLA_Obj * obj)647 FLA_Error FLA_Obj_flip_base( FLA_Obj *obj )
648 {
649   FLA_Error e_val;
650   dim_t temp;
651 
652   if ( FLA_Check_error_level() >= FLA_MIN_ERROR_CHECKING )
653   {
654     e_val = FLA_Check_null_pointer( obj );
655     FLA_Check_error_code( e_val );
656 
657     e_val = FLA_Check_null_pointer( obj->base );
658     FLA_Check_error_code( e_val );
659   }
660 
661   exchange( obj->base->m,       obj->base->n,       temp );
662   exchange( obj->base->cs,      obj->base->rs,      temp );
663   exchange( obj->base->m_inner, obj->base->n_inner, temp );
664   exchange( obj->base->m_index, obj->base->n_index, temp );
665 
666   return FLA_SUCCESS;
667 }
668 
FLA_Obj_flip_view(FLA_Obj * obj)669 FLA_Error FLA_Obj_flip_view( FLA_Obj *obj )
670 {
671   FLA_Error e_val;
672   dim_t temp;
673 
674   if ( FLA_Check_error_level() >= FLA_MIN_ERROR_CHECKING )
675   {
676     e_val = FLA_Check_null_pointer( obj );
677     FLA_Check_error_code( e_val );
678   }
679 
680   exchange( obj->offm,    obj->offn,    temp );
681   exchange( obj->m,       obj->n,       temp );
682   exchange( obj->m_inner, obj->n_inner, temp );
683 
684   return FLA_SUCCESS;
685 }
686