|
Sierra Toolkit
Version of the Day
|
00001 00015 #ifndef STK_UTIL_UTIL_Array_h 00016 #define STK_UTIL_UTIL_Array_h 00017 00018 #include <cstddef> 00019 #include <utility> 00020 #include <algorithm> 00021 #include <stdexcept> 00022 #include <stk_util/util/TypeList.hpp> 00023 #include <stk_util/diag/FArray.hpp> 00024 00025 namespace sierra { 00026 00031 00073 template< class ElementType, 00074 class Tag0, 00075 class Tag1 = TypeListEnd, 00076 class Tag2 = TypeListEnd, 00077 class Tag3 = TypeListEnd, 00078 class Tag4 = TypeListEnd, 00079 class Tag5 = TypeListEnd, 00080 class Tag6 = TypeListEnd, 00081 class Tag7 = TypeListEnd> 00082 class Array; 00083 00084 //---------------------------------------------------------------------- 00091 template< class ElementType, 00092 class Tag0, 00093 class Tag1 = TypeListEnd, 00094 class Tag2 = TypeListEnd, 00095 class Tag3 = TypeListEnd, 00096 class Tag4 = TypeListEnd, 00097 class Tag5 = TypeListEnd, 00098 class Tag6 = TypeListEnd, 00099 class Tag7 = TypeListEnd, 00100 class A = std::allocator<ElementType> > 00101 class ArrayContainer; 00102 00103 00104 //---------------------------------------------------------------------- 00105 // A typeless array is invalid... 00106 00107 template< class Tag0, 00108 class Tag1, 00109 class Tag2, 00110 class Tag3, 00111 class Tag4, 00112 class Tag5, 00113 class Tag6, 00114 class Tag7> 00115 class Array<void, Tag0, Tag1, Tag2, Tag3, Tag4, Tag5, Tag6, Tag7> {}; 00116 00117 template <class ElementType> 00118 class Array<ElementType, TypeListEnd, TypeListEnd, TypeListEnd, TypeListEnd, TypeListEnd, TypeListEnd, TypeListEnd, TypeListEnd> 00119 { 00120 public: 00121 typedef ElementType element_type; 00122 00123 typedef Array< element_type, TypeListEnd, TypeListEnd, TypeListEnd, TypeListEnd, TypeListEnd, TypeListEnd, TypeListEnd, TypeListEnd> SelfType; 00124 00125 // typedef Array< const element_type, TypeListEnd, TypeListEnd, TypeListEnd, TypeListEnd, TypeListEnd, TypeListEnd, TypeListEnd, TypeListEnd > Const; 00126 00127 typedef typename MakeTypeList<TypeListEnd, TypeListEnd, TypeListEnd, TypeListEnd, TypeListEnd, TypeListEnd, TypeListEnd, TypeListEnd>::type TagList; 00128 00131 enum { NumDim = 0 }; 00132 }; 00133 00134 00135 00136 //---------------------------------------------------------------------- 00137 //---------------------------------------------------------------------- 00138 template< class ElementType, 00139 class Tag0, 00140 class Tag1, 00141 class Tag2, 00142 class Tag3, 00143 class Tag4, 00144 class Tag5, 00145 class Tag6, 00146 class Tag7> 00147 class Array : public FArray<ElementType, TypeListLength<typename MakeTypeList<Tag0, Tag1, Tag2, Tag3, Tag4, Tag5, Tag6, Tag7>::type>::value> 00148 { 00149 public: 00150 typedef ElementType element_type; 00151 00152 typedef Array< element_type, Tag0, Tag1, Tag2, Tag3, Tag4, Tag5, Tag6, Tag7> SelfType; 00153 00154 typedef Array< const element_type, Tag0, Tag1, Tag2, Tag3, Tag4, Tag5, Tag6, Tag7 > Const; 00155 00156 typedef typename MakeTypeList<Tag0, Tag1, Tag2, Tag3, Tag4, Tag5, Tag6, Tag7>::type TagList; 00157 00158 typedef FArray<ElementType, TypeListLength<typename MakeTypeList<Tag0, Tag1, Tag2, Tag3, Tag4, Tag5, Tag6, Tag7>::type>::value> BaseType; 00159 00162 enum { NumDim = TypeListLength<TagList>::value }; 00163 00164 typedef Array< ElementType, 00165 typename TypeListAt<typename TypeListEraseAt<TagList, NumDim - 1>::list_type, 0>::type, 00166 typename TypeListAt<typename TypeListEraseAt<TagList, NumDim - 1>::list_type, 1>::type, 00167 typename TypeListAt<typename TypeListEraseAt<TagList, NumDim - 1>::list_type, 2>::type, 00168 typename TypeListAt<typename TypeListEraseAt<TagList, NumDim - 1>::list_type, 3>::type, 00169 typename TypeListAt<typename TypeListEraseAt<TagList, NumDim - 1>::list_type, 4>::type, 00170 typename TypeListAt<typename TypeListEraseAt<TagList, NumDim - 1>::list_type, 5>::type, 00171 typename TypeListAt<typename TypeListEraseAt<TagList, NumDim - 1>::list_type, 6>::type, 00172 TypeListEnd> Trunc; 00173 00174 //---------------------------------------- 00177 const unsigned * dimension() const { 00178 return BaseType::dimension(); 00179 } 00180 00181 const unsigned * stride() const { 00182 return BaseType::stride(); 00183 } 00184 00185 template<unsigned I> 00186 unsigned dimension() const { 00187 enum { ok = stk_classic::StaticAssert< I < NumDim >::OK }; 00188 00189 return BaseType::m_dim[I]; 00190 } 00191 00192 unsigned dimension( const unsigned i ) const { 00193 this->array_dimension_verify(0, i, NumDim ); 00194 return BaseType::m_dim[i]; 00195 } 00196 00197 unsigned stride( const unsigned i ) const { 00198 this->array_dimension_verify(0, i, NumDim ); 00199 return BaseType::m_stride[i]; 00200 } 00201 00202 template<unsigned I> 00203 unsigned stride() const { 00204 enum { ok = stk_classic::StaticAssert< I < NumDim >::OK }; 00205 return BaseType::m_stride[I]; 00206 } 00207 00208 template<class Tag> 00209 unsigned dimension() const{ 00210 enum { I = TypeListIndex<TagList, Tag>::value }; 00211 enum { ok = stk_classic::StaticAssert< 0 <= I >::OK }; 00212 return BaseType::m_dim[I]; 00213 } 00214 00215 template<class Tag, unsigned Ordinal> 00216 unsigned dimension() const { 00217 enum { I = TypeListIndex<TagList, Tag, Ordinal>::value }; 00218 enum { ok = stk_classic::StaticAssert< 0 <= I >::OK }; 00219 return BaseType::m_dim[I]; 00220 } 00221 00222 template<class Tag> 00223 unsigned stride() const { 00224 enum { I = TypeListIndex<TagList, Tag>::value }; 00225 enum { ok = stk_classic::StaticAssert< 0 <= I >::OK }; 00226 return BaseType::m_stride[I]; 00227 } 00228 00229 template<class Tag, unsigned Ordinal> 00230 unsigned stride() const { 00231 enum { I = TypeListIndex<TagList, Tag, Ordinal>::value }; 00232 enum { ok = stk_classic::StaticAssert< 0 <= I >::OK }; 00233 return BaseType::m_stride[I]; 00234 } 00235 00236 bool operator == ( const SelfType & a ) const { 00237 return ArrayHelper<NumDim>::equal( BaseType::m_dim, a.m_dim ) && 00238 ArrayHelper<NumDim>::equal(BaseType::m_dim, BaseType::m_ptr, BaseType::m_stride, a.m_ptr, a.m_stride); 00239 } 00240 00241 template<typename T> 00242 bool operator == (const Array<T, Tag0, Tag1, Tag2, Tag3, Tag4, Tag5, Tag6, Tag7> & a) const { 00243 return ArrayHelper<NumDim>::equal( BaseType::m_dim, a.dimension() ) && 00244 ArrayHelper<NumDim>::equal(BaseType::m_dim, BaseType::m_ptr, BaseType::m_stride, a.ptr(), a.stride()); 00245 } 00246 00247 bool operator != ( const SelfType & a ) const { 00248 return ! operator == ( a ); 00249 } 00250 00251 template<typename T> 00252 bool operator != ( const Array<T, Tag0, Tag1, Tag2, Tag3, Tag4, Tag5, Tag6, Tag7> & a ) const { 00253 return ! operator == ( a ); 00254 } 00255 00256 public: 00257 ~Array() 00258 {} 00259 00260 Array() : BaseType() 00261 {} 00262 00263 Array( const SelfType & a ) 00264 : BaseType( a ) 00265 {} 00266 00267 template<typename T> 00268 Array( const Array<T, Tag0, Tag1, Tag2, Tag3, Tag4, Tag5, Tag6, Tag7> & a ) 00269 : BaseType( a ) 00270 {} 00271 00272 Array( element_type * const in_ptr, 00273 const unsigned n0, const unsigned n1, 00274 const unsigned n2, const unsigned n3, 00275 const unsigned n4, const unsigned n5, 00276 const unsigned n6, const unsigned n7 ) 00277 : BaseType( in_ptr, n0, n1, n2, n3, n4, n5, n6, n7) 00278 {} 00279 00280 Array( element_type * const in_ptr, 00281 const unsigned n0, const unsigned n1, 00282 const unsigned n2, const unsigned n3, 00283 const unsigned n4, const unsigned n5, 00284 const unsigned n6 ) 00285 : BaseType( in_ptr, n0, n1, n2, n3, n4, n5, n6) 00286 {} 00287 00288 Array( element_type * const in_ptr, 00289 const unsigned n0, const unsigned n1, 00290 const unsigned n2, const unsigned n3, 00291 const unsigned n4, const unsigned n5 ) 00292 : BaseType( in_ptr, n0, n1, n2, n3, n4, n5) 00293 {} 00294 00295 Array( element_type * const in_ptr, 00296 const unsigned n0, const unsigned n1, 00297 const unsigned n2, const unsigned n3, 00298 const unsigned n4 ) 00299 : BaseType( in_ptr, n0, n1, n2, n3, n4) 00300 {} 00301 00302 Array( element_type * const in_ptr, 00303 const unsigned n0, const unsigned n1, 00304 const unsigned n2, const unsigned n3 ) 00305 : BaseType( in_ptr, n0, n1, n2, n3) 00306 {} 00307 00308 Array( element_type * const in_ptr, 00309 const unsigned n0, const unsigned n1, 00310 const unsigned n2 ) 00311 : BaseType( in_ptr, n0, n1, n2) 00312 {} 00313 00314 Array( element_type * const in_ptr, 00315 const unsigned n0, const unsigned n1 ) 00316 : BaseType( in_ptr, n0, n1) 00317 {} 00318 00319 Array( element_type * const in_ptr, 00320 const unsigned n0 ) 00321 : BaseType( in_ptr, n0) 00322 {} 00323 00324 Array( element_type * const in_ptr, 00325 const unsigned n[NumDim] ) 00326 : BaseType( in_ptr, n){} 00327 00328 void set( const SelfType & a ) { 00329 BaseType::m_ptr = a.m_ptr; 00330 00331 ArrayHelper<NumDim >::copy( a.m_dim, BaseType::m_dim ); 00332 ArrayHelper<NumDim+1>::copy( a.m_stride, BaseType::m_stride ); 00333 } 00334 00335 void set( element_type * const in_ptr, 00336 const unsigned n0, const unsigned n1, 00337 const unsigned n2, const unsigned n3, 00338 const unsigned n4, const unsigned n5, 00339 const unsigned n6, const unsigned n7 ) { 00340 BaseType::set(in_ptr, n0, n1, n2, n3, n4, n5, n6, n7); 00341 } 00342 00343 void set( element_type * const in_ptr, 00344 const unsigned n0, const unsigned n1, 00345 const unsigned n2, const unsigned n3, 00346 const unsigned n4, const unsigned n5, 00347 const unsigned n6 ) { 00348 BaseType::set(in_ptr, n0, n1, n2, n3, n4, n5, n6); 00349 } 00350 00351 void set( element_type * const in_ptr, 00352 const unsigned n0, const unsigned n1, 00353 const unsigned n2, const unsigned n3, 00354 const unsigned n4, const unsigned n5 ) { 00355 BaseType::set(in_ptr, n0, n1, n2, n3, n4, n5); 00356 } 00357 00358 void set( element_type * const in_ptr, 00359 const unsigned n0, const unsigned n1, 00360 const unsigned n2, const unsigned n3, 00361 const unsigned n4 ) { 00362 BaseType::set(in_ptr, n0, n1, n2, n3, n4); 00363 } 00364 00365 void set( element_type * const in_ptr, 00366 const unsigned n0, const unsigned n1, 00367 const unsigned n2, const unsigned n3 ) { 00368 BaseType::set(in_ptr, n0, n1, n2, n3); 00369 } 00370 00371 void set( element_type * const in_ptr, 00372 const unsigned n0, const unsigned n1, 00373 const unsigned n2 ) { 00374 BaseType::set(in_ptr, n0, n1, n2); 00375 } 00376 00377 void set( element_type * const in_ptr, 00378 const unsigned n0, const unsigned n1 ) { 00379 BaseType::set(in_ptr, n0, n1); 00380 } 00381 00382 void set( element_type * const in_ptr, 00383 const unsigned n0 ) { 00384 BaseType::set(in_ptr, n0); 00385 } 00386 00387 void set( element_type * const in_ptr, 00388 const unsigned n[NumDim] ) { 00389 BaseType::set(in_ptr, n); 00390 } 00391 00392 Trunc dive(int i) { 00393 this->array_dimension_verify(0, i, BaseType::m_dim[NumDim - 1] ); 00394 00395 element_type *calc_ptr = BaseType::m_ptr + i*BaseType::m_stride[NumDim - 1]; 00396 00397 return Trunc(calc_ptr, BaseType::m_dim); 00398 } 00399 00400 const Trunc dive(int i) const { 00401 this->array_dimension_verify(0, i, BaseType::m_dim[NumDim - 1] ); 00402 00403 element_type *calc_ptr = BaseType::m_ptr + i*BaseType::m_stride[NumDim - 1]; 00404 00405 return Trunc(calc_ptr, BaseType::m_dim); 00406 } 00407 00408 template<typename T> 00409 void copy( const Array<T, Tag0, Tag1, Tag2, Tag3, Tag4, Tag5, Tag6, Tag7> & a ) { 00410 ArrayHelper<NumDim>::copy(BaseType::m_dim, BaseType::m_ptr, BaseType::m_stride, a.ptr(), a.stride() ); 00411 } 00412 00413 template<typename T> 00414 void fill( const T & value ) { 00415 ArrayHelper<NumDim>::fill(BaseType::m_dim, BaseType::m_ptr, BaseType::m_stride, value); 00416 } 00417 00418 private: 00419 // Mutation (non-const methods) is not allowed so as to 00420 // provide derived classes with complete control over mutation. 00421 00422 SelfType & operator = ( SelfType const & a ); 00423 }; 00424 00425 template< class ElementType, 00426 class Tag0, 00427 class Tag1, 00428 class Tag2, 00429 class Tag3, 00430 class Tag4, 00431 class Tag5, 00432 class Tag6, 00433 class Tag7, 00434 class A> 00435 class ArrayContainer 00436 : public Array<ElementType, Tag0, Tag1, Tag2, Tag3, Tag4, Tag5, Tag6, Tag7> 00437 { 00438 public: 00439 typedef ArrayContainer<ElementType, Tag0, Tag1, Tag2, Tag3, Tag4, Tag5, Tag6, Tag7> SelfType; 00440 00441 typedef Array<ElementType, Tag0, Tag1, Tag2, Tag3, Tag4, Tag5, Tag6, Tag7> BaseType; 00442 00443 typedef typename BaseType::element_type element_type; 00444 00445 typedef typename BaseType::TagList TagList; 00446 00447 enum { NumDim = BaseType::NumDim }; 00448 00449 private: 00450 using BaseType::m_ptr; 00451 using BaseType::m_dim; 00452 using BaseType::m_stride; 00453 00454 void resize_memory( const unsigned new_size ) { 00455 if ( m_capacity < new_size ) { 00456 if ( m_capacity ) 00457 m_allocator.deallocate(m_ptr, m_capacity); 00458 m_capacity = new_size; 00459 m_ptr = m_allocator.allocate(m_capacity); 00460 } 00461 } 00462 00463 public: 00464 ~ArrayContainer() { 00465 if ( m_capacity ) { 00466 m_allocator.deallocate(m_ptr, m_capacity); 00467 m_capacity = 0; 00468 } 00469 } 00470 00471 //---------------------------------------- 00472 // Constructors for initial view of contiguous memory. 00473 00474 ArrayContainer( ) 00475 : BaseType( ), 00476 m_capacity(0) 00477 {} 00478 00479 ArrayContainer( const SelfType & a ) 00480 : BaseType(), 00481 m_capacity(0) 00482 { 00483 resize_memory( BaseType::set_dim( a.m_dim ) ); 00484 this->copy(a); 00485 } 00486 00487 template<typename T> 00488 ArrayContainer( const Array<T, Tag0, Tag1, Tag2, Tag3, Tag4, Tag5, Tag6, Tag7> & a ) 00489 : BaseType(), m_capacity(0) 00490 { 00491 resize_memory( BaseType::set_dim( a.dimension() ) ); 00492 this->copy(a); 00493 } 00494 00495 SelfType & operator = ( const SelfType & a ) { 00496 resize_memory( BaseType::set_dim( a.dimension() ) ); 00497 this->copy(a); 00498 return *this; 00499 } 00500 00501 template<typename T> 00502 SelfType & operator =( const Array<T, Tag0, Tag1, Tag2, Tag3, Tag4, Tag5, Tag6, Tag7> & a ) { 00503 resize_memory( BaseType::set_dim( a.dimension() ) ); 00504 this->copy(a); 00505 return *this; 00506 } 00507 00508 //---------------------------------------- 00509 00510 ArrayContainer( const unsigned n0, const unsigned n1, 00511 const unsigned n2, const unsigned n3, 00512 const unsigned n4, const unsigned n5, 00513 const unsigned n6, const unsigned n7 ) 00514 : BaseType(NULL, n0, n1, n2, n3, n4, n5, n6, n7 ), 00515 m_capacity(0) 00516 { 00517 resize_memory( m_stride[NumDim] ); 00518 } 00519 00520 ArrayContainer( const unsigned n0, const unsigned n1, 00521 const unsigned n2, const unsigned n3, 00522 const unsigned n4, const unsigned n5, 00523 const unsigned n6 ) 00524 : BaseType( NULL, n0, n1, n2, n3, n4, n5, n6 ), 00525 m_capacity(0) 00526 { 00527 resize_memory( m_stride[NumDim] ); 00528 } 00529 00530 ArrayContainer( const unsigned n0, const unsigned n1, 00531 const unsigned n2, const unsigned n3, 00532 const unsigned n4, const unsigned n5 ) 00533 : BaseType( NULL, n0, n1, n2, n3, n4, n5 ), 00534 m_capacity(0) 00535 { 00536 resize_memory( m_stride[NumDim] ); 00537 } 00538 00539 ArrayContainer( const unsigned n0, const unsigned n1, 00540 const unsigned n2, const unsigned n3, 00541 const unsigned n4 ) 00542 : BaseType( NULL, n0, n1, n2, n3, n4 ), 00543 m_capacity(0) 00544 { 00545 resize_memory( m_stride[NumDim] ); 00546 } 00547 00548 ArrayContainer( const unsigned n0, const unsigned n1, 00549 const unsigned n2, const unsigned n3 ) 00550 : BaseType( NULL, n0, n1, n2, n3 ), 00551 m_capacity(0) 00552 { 00553 resize_memory( m_stride[NumDim] ); 00554 } 00555 00556 ArrayContainer( const unsigned n0, const unsigned n1, 00557 const unsigned n2 ) 00558 : BaseType( NULL, n0, n1, n2 ), 00559 m_capacity(0) 00560 { 00561 resize_memory( m_stride[NumDim] ); 00562 } 00563 00564 ArrayContainer( const unsigned n0, const unsigned n1 ) 00565 : BaseType( NULL, n0, n1 ), 00566 m_capacity(0) 00567 { 00568 resize_memory( m_stride[NumDim] ); 00569 } 00570 00571 ArrayContainer( const unsigned n0 ) 00572 : BaseType( NULL, n0 ), 00573 m_capacity(0) 00574 { 00575 resize_memory( m_stride[NumDim] ); 00576 } 00577 00578 ArrayContainer( const unsigned n[] ) 00579 : BaseType( NULL, n ), 00580 m_capacity(0) 00581 { 00582 resize_memory( m_stride[NumDim] ); 00583 } 00584 00585 //---------------------------------------- 00586 00587 template<typename T> 00588 SelfType & resize( const Array<T, Tag0, Tag1, Tag2, Tag3, Tag4, Tag5, Tag6, Tag7> & a ) { 00589 resize_memory( BaseType::set_dim( a.dimension() ) ); 00590 return *this; 00591 } 00592 00593 SelfType & resize( const unsigned n0, const unsigned n1, 00594 const unsigned n2, const unsigned n3, 00595 const unsigned n4, const unsigned n5, 00596 const unsigned n6, const unsigned n7 ) 00597 { 00598 resize_memory(BaseType::set_dim(n0, n1, n2, n3, n4, n5, n6, n7)); 00599 return *this; 00600 } 00601 00602 SelfType & resize( const unsigned n0, const unsigned n1, 00603 const unsigned n2, const unsigned n3, 00604 const unsigned n4, const unsigned n5, 00605 const unsigned n6 ) 00606 { 00607 resize_memory(BaseType::set_dim(n0, n1, n2, n3, n4, n5, n6)); 00608 return *this; 00609 } 00610 00611 SelfType & resize( const unsigned n0, const unsigned n1, 00612 const unsigned n2, const unsigned n3, 00613 const unsigned n4, const unsigned n5 ) 00614 { 00615 resize_memory(BaseType::set_dim(n0, n1, n2, n3, n4, n5)); 00616 return *this; 00617 } 00618 00619 SelfType & resize( const unsigned n0, const unsigned n1, 00620 const unsigned n2, const unsigned n3, 00621 const unsigned n4 ) 00622 { 00623 resize_memory(BaseType::set_dim(n0, n1, n2, n3, n4)); 00624 return *this; 00625 } 00626 00627 SelfType & resize( const unsigned n0, const unsigned n1, 00628 const unsigned n2, const unsigned n3 ) 00629 { 00630 resize_memory(BaseType::set_dim(n0, n1, n2, n3)); 00631 return *this; 00632 } 00633 00634 00635 SelfType & resize( const unsigned n0, const unsigned n1, 00636 const unsigned n2 ) 00637 { 00638 resize_memory(BaseType::set_dim(n0, n1, n2)); 00639 return *this; 00640 } 00641 00642 SelfType & resize( const unsigned n0, const unsigned n1 ) 00643 { 00644 resize_memory(BaseType::set_dim(n0, n1)); 00645 return *this; 00646 } 00647 00648 SelfType & resize( const unsigned n0 ) 00649 { 00650 resize_memory(BaseType::set_dim(n0)); 00651 return *this; 00652 } 00653 00654 SelfType & resize( const unsigned n[] ) 00655 { 00656 resize_memory( BaseType::set_dim(n) ); 00657 return *this; 00658 } 00659 00660 //---------------------------------------- 00661 00662 private: 00663 A m_allocator; 00664 unsigned m_capacity; 00665 }; 00666 00670 00671 } // namespace sierra 00672 00673 #endif // STK_UTIL_UTIL_Array_h