00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef util_Array_hpp
00025 #define util_Array_hpp
00026
00027 #ifdef ARRAY_BOUNDS_CHECKING
00028 #define ARRAY_CHECK( X ) X
00029 #else
00030 #define ARRAY_CHECK( X )
00031 #endif
00032
00033 #include <vector>
00034 #include <string>
00035 #include <Phalanx_SimpleArrayOps.hpp>
00036
00037 namespace PHX {
00038
00101
00107 enum ArrayOrder {
00111 NaturalOrder ,
00112
00116 FortranOrder ,
00117
00121 RankZero
00122 };
00123
00124 template< typename Scalar , ArrayOrder Order ,
00125 class Tag1 = void , class Tag2 = void ,
00126 class Tag3 = void , class Tag4 = void ,
00127 class Tag5 = void , class Tag6 = void ,
00128 class Tag7 = void , class Tag8 = void >
00129 class Array ;
00130
00131
00132
00133 template< class ArrayType , class Tag > struct ArrayAppend ;
00134
00135
00160 struct ArrayDimTag {
00161
00163 virtual const char * name() const = 0 ;
00164
00168 virtual std::string to_string( unsigned dimension ,
00169 unsigned index ) const ;
00170
00174 virtual unsigned to_index( unsigned dimension ,
00175 const std::string & label ) const ;
00176
00177 protected:
00178 virtual ~ArrayDimTag();
00179 ArrayDimTag() {}
00180 private:
00181 ArrayDimTag( const ArrayDimTag & );
00182 ArrayDimTag & operator = ( const ArrayDimTag & );
00183 };
00184
00190 struct ArrayDimension : public ArrayDimTag {
00191
00192 const char * name() const ;
00193
00194 static const ArrayDimension & tag();
00195
00196 private:
00197 ~ArrayDimension();
00198 ArrayDimension() {}
00199 ArrayDimension( const ArrayDimension & );
00200 ArrayDimension & operator = ( const ArrayDimension & );
00201 };
00202
00203 }
00204
00205
00206
00207
00208 #include <Phalanx_ArrayPrivate.hpp>
00209
00210 namespace PHX {
00211
00212
00232 template< typename Scalar , ArrayOrder array_order ,
00233 class Tag1 , class Tag2 , class Tag3 , class Tag4 ,
00234 class Tag5 , class Tag6 , class Tag7 , class Tag8 >
00235 class Array
00236 {
00237 private:
00238 typedef
00239 Array<void,array_order,Tag1,Tag2,Tag3,Tag4,Tag5,Tag6,Tag7,Tag8>
00240 md_type ;
00241 public:
00247 typedef Scalar value_type ;
00248
00250 typedef unsigned size_type ;
00251
00253 typedef const ArrayDimTag * tag_type ;
00254
00255
00256
00258 enum { Rank = md_type::Rank };
00259
00261 enum { Natural = NaturalOrder == array_order };
00262
00264 enum { Reverse = FortranOrder == array_order };
00265
00267 enum { Contiguous = true };
00268
00270 unsigned rank() const { return Rank ; }
00271
00273 bool natural() const { return Natural ; }
00274
00276 bool reverse() const { return Reverse ; }
00277
00279 bool contiguous() const { return Contiguous ; }
00280
00281
00282
00283 #ifndef DOXYGEN_COMPILE
00284
00285 template < unsigned ordinate >
00286 struct Tag { typedef typename ArrayTagAt<Array,ordinate>::type type ; };
00287 #endif
00288
00290 tag_type tag( const unsigned ordinate ) const
00291 {
00292 array_check_ordinal( Rank , ordinate );
00293 return
00294 array_dim_tags<Tag1,Tag2,Tag3,Tag4,Tag5,Tag6,Tag7,Tag8>()[ordinate];
00295 }
00296
00297
00299 template < unsigned ordinate > unsigned dimension() const
00300 {
00301 array_check_ordinal_is_less<ordinate,Rank>();
00302 return ArrayStrideDim<array_order,Rank,ordinate>::dimension(m_stride);
00303 }
00304
00306 unsigned dimension( const unsigned ordinate ) const
00307 {
00308 array_check_ordinal( Rank , ordinate );
00309 return ArrayStrideDim<array_order,Rank>::dimension(m_stride,ordinate);
00310 }
00311
00313 void dimensions( std::vector<unsigned> & n )
00314 {
00315 n.resize( Rank );
00316 for ( unsigned i = 0 ; i < Rank ; ++i ) { n[i] = dimension(i); }
00317 }
00318
00320 size_type size() const { return m_stride[ Rank - 1 ]; }
00321
00323
00331 typedef typename ArrayTruncate<Array>::type TruncateType ;
00332
00337 TruncateType truncate( const unsigned i ) const
00338 {
00339 TruncateType tmp ;
00340 tmp.m_ptr = m_ptr + i * ( 1 < Rank ? m_stride[ Rank - 2 ] : 1 );
00341 Copy<Rank-1>( tmp.m_stride , m_stride );
00342 return tmp ;
00343 }
00344
00345
00347 value_type * contiguous_data() const { return m_ptr ; }
00348
00350 value_type & operator[]( size_type i ) const
00351 {
00352 ARRAY_CHECK( array_check_offset(size(),i) );
00353 return m_ptr[ i ];
00354 }
00355
00357 value_type & operator()( const unsigned i1 , const unsigned i2 ,
00358 const unsigned i3 , const unsigned i4 ,
00359 const unsigned i5 , const unsigned i6 ,
00360 const unsigned i7 , const unsigned i8 ) const
00361 { return m_ptr[
00362 array_offset<array_order,Rank>(m_stride,i1,i2,i3,i4,i5,i6,i7,i8) ];
00363 }
00364
00366 value_type & operator()( const unsigned i1 , const unsigned i2 ,
00367 const unsigned i3 , const unsigned i4 ,
00368 const unsigned i5 , const unsigned i6 ,
00369 const unsigned i7 ) const
00370 { return m_ptr[
00371 array_offset<array_order,Rank>(m_stride,i1,i2,i3,i4,i5,i6,i7) ];
00372 }
00373
00375 value_type & operator()( const unsigned i1 , const unsigned i2 ,
00376 const unsigned i3 , const unsigned i4 ,
00377 const unsigned i5 , const unsigned i6 ) const
00378 { return m_ptr[
00379 array_offset<array_order,Rank>(m_stride,i1,i2,i3,i4,i5,i6) ];
00380 }
00381
00383 value_type & operator()( const unsigned i1 , const unsigned i2 ,
00384 const unsigned i3 , const unsigned i4 ,
00385 const unsigned i5 ) const
00386 { return m_ptr[ array_offset<array_order,Rank>(m_stride,i1,i2,i3,i4,i5) ]; }
00387
00389 value_type & operator()( const unsigned i1 , const unsigned i2 ,
00390 const unsigned i3 , const unsigned i4 ) const
00391 { return m_ptr[ array_offset<array_order,Rank>(m_stride,i1,i2,i3,i4) ]; }
00392
00394 value_type & operator()( const unsigned i1 , const unsigned i2 ,
00395 const unsigned i3 ) const
00396 { return m_ptr[ array_offset<array_order,Rank>(m_stride,i1,i2,i3) ]; }
00397
00399 value_type & operator()( const unsigned i1 , const unsigned i2 ) const
00400 { return m_ptr[ array_offset<array_order,Rank>(m_stride,i1,i2) ]; }
00401
00403 value_type & operator()( const unsigned i1 ) const
00404 { return m_ptr[ array_offset<array_order,Rank>(m_stride,i1) ]; }
00405
00407
00415 typedef typename ArrayReverse< Array >::type ReverseType ;
00416
00418 Array() : m_ptr(NULL) { Copy<Rank>( m_stride , (size_type) 0 ); }
00419
00421 Array( const Array & rhs )
00422 : m_ptr( rhs.m_ptr ) { Copy<Rank>( m_stride , rhs.m_stride ); }
00423
00425 Array & operator = ( const Array & rhs )
00426 {
00427 m_ptr = rhs.m_ptr ;
00428 Copy<Rank>( m_stride , rhs.m_stride );
00429 return *this ;
00430 }
00431
00433 Array( const ReverseType & rhs )
00434 : m_ptr( rhs.m_ptr ) { Copy<Rank>( m_stride , rhs.m_stride ); }
00435
00437 Array & operator = ( const ReverseType & rhs )
00438 {
00439 m_ptr = rhs.m_ptr ;
00440 Copy<Rank>( m_stride , rhs.m_stride );
00441 return *this ;
00442 }
00443
00445 Array( value_type * arg_ptr , const unsigned * const dims )
00446 : m_ptr( arg_ptr ) { md_type::assign( m_stride , dims ); }
00447
00449 Array( value_type * arg_ptr ,
00450 const unsigned n1 , const unsigned n2 ,
00451 const unsigned n3 , const unsigned n4 ,
00452 const unsigned n5 , const unsigned n6 ,
00453 const unsigned n7 , const unsigned n8 )
00454 : m_ptr( arg_ptr )
00455 { md_type::assign( m_stride , n1 , n2 , n3 , n4 , n5 , n6 , n7 , n8 ); }
00456
00460 Array( value_type * arg_ptr ,
00461 const unsigned n1 , const unsigned n2 ,
00462 const unsigned n3 , const unsigned n4 ,
00463 const unsigned n5 , const unsigned n6 ,
00464 const unsigned n7 )
00465 : m_ptr( arg_ptr )
00466 { md_type::assign( m_stride , n1 , n2 , n3 , n4 , n5 , n6 , n7 ); }
00467
00471 Array( value_type * arg_ptr ,
00472 const unsigned n1 , const unsigned n2 ,
00473 const unsigned n3 , const unsigned n4 ,
00474 const unsigned n5 , const unsigned n6 )
00475 : m_ptr( arg_ptr )
00476 { md_type::assign( m_stride , n1 , n2 , n3 , n4 , n5 , n6 ); }
00477
00481 Array( value_type * arg_ptr ,
00482 const unsigned n1 , const unsigned n2 ,
00483 const unsigned n3 , const unsigned n4 ,
00484 const unsigned n5 )
00485 : m_ptr( arg_ptr )
00486 { md_type::assign( m_stride , n1 , n2 , n3 , n4 , n5 ); }
00487
00491 Array( value_type * arg_ptr ,
00492 const unsigned n1 , const unsigned n2 ,
00493 const unsigned n3 , const unsigned n4 )
00494 : m_ptr( arg_ptr )
00495 { md_type::assign( m_stride , n1 , n2 , n3 , n4 ); }
00496
00500 Array( value_type * arg_ptr ,
00501 const unsigned n1 , const unsigned n2 ,
00502 const unsigned n3 )
00503 : m_ptr( arg_ptr )
00504 { md_type::assign( m_stride , n1 , n2 , n3 ); }
00505
00509 Array( value_type * arg_ptr , const unsigned n1 , const unsigned n2 )
00510 : m_ptr( arg_ptr ) { md_type::assign( m_stride , n1 , n2 ); }
00511
00515 Array( value_type * arg_ptr , const unsigned n1 )
00516 : m_ptr( arg_ptr ) { md_type::assign( m_stride , n1 ); }
00517
00519 Array( value_type * arg_ptr )
00520 : m_ptr( arg_ptr ) { md_type::assign( m_stride ); }
00521
00523 protected:
00524
00526 value_type * m_ptr ;
00527
00529 size_type m_stride[ Rank ];
00530
00531 template< typename , ArrayOrder ,
00532 class , class , class , class ,
00533 class , class , class , class >
00534 friend class PHX::Array ;
00535 };
00536
00537
00538
00539 #ifndef DOXYGEN_COMPILE
00540
00544 template< typename Scalar >
00545 class Array<Scalar,RankZero,void,void,void,void,void,void,void,void>
00546 {
00547 public:
00548
00549 typedef Scalar value_type ;
00550 typedef unsigned size_type ;
00551 typedef const ArrayDimTag * tag_type ;
00552
00553
00554
00555 enum { Rank = 0 };
00556 enum { Natural = false };
00557 enum { Reverse = false };
00558 enum { Contiguous = true };
00559
00560 unsigned rank() const { return Rank ; }
00561 bool natural() const { return Natural ; }
00562 bool reverse() const { return Reverse ; }
00563 bool contiguous() const { return Contiguous ; }
00564
00565
00566
00568 size_type size() const { return m_ptr ? 1 : 0 ; }
00569
00570
00572 value_type * contiguous_data() const { return m_ptr ; }
00573
00575 value_type & operator()() const { return *m_ptr ; }
00576
00577
00578
00579
00580 Array() : m_ptr(NULL) {}
00581
00582 Array( const Array & rhs ) : m_ptr( rhs.m_ptr ) {}
00583
00584 Array & operator = ( const Array & rhs )
00585 { m_ptr = rhs.m_ptr ; return *this ; }
00586
00587
00588
00589
00590 Array( value_type * arg_ptr ) : m_ptr( arg_ptr ) {}
00591
00592 protected:
00593
00594 value_type * m_ptr ;
00595
00596 template< typename , ArrayOrder ,
00597 class , class , class , class ,
00598 class , class , class , class >
00599 friend class PHX::Array ;
00600 };
00601
00602 #endif
00603
00604
00618 template< typename Scalar , ArrayOrder array_order >
00619 class Array<Scalar,array_order,void,void,void,void,void,void,void,void>
00620 {
00621 public:
00627 typedef Scalar value_type ;
00628
00630 typedef unsigned size_type ;
00631
00633 typedef const ArrayDimTag * tag_type ;
00634
00635
00636
00638 enum { Natural = NaturalOrder == array_order };
00639
00641 enum { Reverse = FortranOrder == array_order };
00642
00644 enum { Contiguous = true };
00645
00647 unsigned rank() const { return m_rank ; }
00648
00650 bool natural() const { return Natural ; }
00651
00653 bool reverse() const { return Reverse ; }
00654
00656 bool contiguous() const { return Contiguous ; }
00657
00658
00659
00661 tag_type tag( const unsigned ordinal ) const
00662 {
00663 array_check_ordinal( m_rank , ordinal );
00664 const int i = Natural ? ( m_rank - 1 ) - ordinal : ordinal ;
00665 return m_tag[i];
00666 }
00667
00668
00669
00671 unsigned dimension( const unsigned ordinal ) const
00672 {
00673 array_check_ordinal( m_rank , ordinal );
00674 const int i = Natural ? ( m_rank - 1 ) - ordinal : ordinal ;
00675 return i ? m_stride[i] / m_stride[i-1] : m_stride[i] ;
00676 }
00677
00679 void dimensions( std::vector<unsigned> & n )
00680 {
00681 n.resize( m_rank );
00682 for ( unsigned i = 0 ; i < m_rank ; ++i ) { n[i] = dimension(i); }
00683 }
00684
00686 size_type size() const { return m_stride[ m_rank - 1 ]; }
00687
00689
00697 Array truncate( const unsigned i ) const
00698 {
00699 Array tmp ;
00700 if ( 1 < m_rank ) {
00701 tmp.m_ptr = m_ptr + m_stride[ m_rank - 2 ] * i ;
00702 tmp.m_rank = m_rank - 1 ;
00703 unsigned k ;
00704 for ( k = 0 ; k < m_rank - 1 ; ++k ) { tmp.m_stride[i] = m_stride[i] ; }
00705 for ( ; k < 8 ; ++k ) { tmp.m_stride[i] = 0 ; }
00706 for ( k = 0 ; k < m_rank - 1 ; ++k ) { tmp.m_tag[i] = m_tag[i] ; }
00707 for ( ; k < 8 ; ++k ) { tmp.m_tag[i] = NULL ; }
00708 }
00709 return tmp ;
00710 }
00711
00713 value_type * contiguous_data() const { return m_ptr ; }
00714
00716 value_type & operator[]( size_type i ) const
00717 {
00718 ARRAY_CHECK( array_check_offset(size(),i) );
00719 return m_ptr[ i ];
00720 }
00721
00722
00724 value_type & operator()( const unsigned i1 , const unsigned i2 ,
00725 const unsigned i3 , const unsigned i4 ,
00726 const unsigned i5 , const unsigned i6 ,
00727 const unsigned i7 , const unsigned i8 ) const
00728 {
00729 ARRAY_CHECK( array_check_rank( m_rank , 8 ) );
00730 return m_ptr[
00731 array_offset<array_order,8>(m_stride,i1,i2,i3,i4,i5,i6,i7,i8) ];
00732 }
00733
00734 value_type & operator()( const unsigned i1 , const unsigned i2 ,
00735 const unsigned i3 , const unsigned i4 ,
00736 const unsigned i5 , const unsigned i6 ,
00737 const unsigned i7 ) const
00738 {
00739 ARRAY_CHECK( array_check_rank( m_rank , 7 ) );
00740 return m_ptr[
00741 array_offset<array_order,7>(m_stride,i1,i2,i3,i4,i5,i6,i7) ];
00742 }
00743
00744 value_type & operator()( const unsigned i1 , const unsigned i2 ,
00745 const unsigned i3 , const unsigned i4 ,
00746 const unsigned i5 , const unsigned i6 ) const
00747 {
00748 ARRAY_CHECK( array_check_rank( m_rank , 6 ) );
00749 return m_ptr[ array_offset<array_order,6>(m_stride,i1,i2,i3,i4,i5,i6) ];
00750 }
00751
00752 value_type & operator()( const unsigned i1 , const unsigned i2 ,
00753 const unsigned i3 , const unsigned i4 ,
00754 const unsigned i5 ) const
00755 {
00756 ARRAY_CHECK( array_check_rank( m_rank , 5 ) );
00757 return m_ptr[ array_offset<array_order,5>(m_stride,i1,i2,i3,i4,i5) ];
00758 }
00759
00760 value_type & operator()( const unsigned i1 , const unsigned i2 ,
00761 const unsigned i3 , const unsigned i4 ) const
00762 {
00763 ARRAY_CHECK( array_check_rank( m_rank , 4 ) );
00764 return m_ptr[ array_offset<array_order,4>(m_stride,i1,i2,i3,i4) ];
00765 }
00766
00767 value_type & operator()( const unsigned i1 , const unsigned i2 ,
00768 const unsigned i3 ) const
00769 {
00770 ARRAY_CHECK( array_check_rank( m_rank , 3 ) );
00771 return m_ptr[ array_offset<array_order,3>(m_stride,i1,i2,i3) ];
00772 }
00773
00774 value_type & operator()( const unsigned i1 , const unsigned i2 ) const
00775 {
00776 ARRAY_CHECK( array_check_rank( m_rank , 2 ) );
00777 return m_ptr[ array_offset<array_order,2>(m_stride,i1,i2) ];
00778 }
00779
00780 value_type & operator()( const unsigned i1 ) const
00781 {
00782 ARRAY_CHECK( array_check_rank( m_rank , 1 ) );
00783 return m_ptr[ array_offset<array_order,1>(m_stride,i1) ];
00784 }
00785
00787
00792 typedef typename ArrayReverse< Array >::type ReverseType ;
00793
00794
00795
00796 Array()
00797 : m_ptr(NULL), m_rank(0)
00798 {
00799 Copy<8>( m_stride , (size_type) 0 );
00800 Copy<8>( m_tag , (tag_type) NULL );
00801 }
00802
00803 Array( const Array & rhs )
00804 : m_ptr( rhs.m_ptr ), m_rank( rhs.m_rank )
00805 {
00806 Copy<8>( m_stride , rhs.m_stride );
00807 Copy<8>( m_tag , rhs.m_tag );
00808 }
00809
00810 Array & operator = ( const Array & rhs )
00811 {
00812 m_ptr = rhs.m_ptr ;
00813 m_rank = rhs.m_rank ;
00814 Copy<8>( m_stride , rhs.m_stride );
00815 Copy<8>( m_tag , rhs.m_tag );
00816 return *this ;
00817 }
00818
00820 Array( const ReverseType & rhs )
00821 : m_ptr( rhs.m_ptr ), m_rank( rhs.m_rank )
00822 {
00823 Copy<8>( m_stride , rhs.m_stride );
00824 Copy<8>( m_tag , rhs.m_tag );
00825 }
00826
00828 Array & operator = ( const ReverseType & rhs )
00829 {
00830 m_ptr = rhs.m_ptr ;
00831 m_rank = rhs.m_rank ;
00832 Copy<8>( m_stride , rhs.m_stride );
00833 Copy<8>( m_tag , rhs.m_tag );
00834 return *this ;
00835 }
00836
00837
00838
00842 template< ArrayOrder order ,
00843 class Tag1 , class Tag2 , class Tag3 , class Tag4 ,
00844 class Tag5 , class Tag6 , class Tag7 , class Tag8 >
00845 Array(
00846 const Array<value_type,order,Tag1,Tag2,Tag3,Tag4,Tag5,Tag6,Tag7,Tag8> & rhs )
00847 : m_ptr( rhs.m_ptr ), m_rank( 0 )
00848 {
00849 typedef Array<value_type,order,Tag1,Tag2,Tag3,Tag4,Tag5,Tag6,Tag7,Tag8> a_t ;
00850 enum { inRank = a_t::Rank };
00851 enum { inNatural = a_t::Natural };
00852 m_rank = inRank ;
00853 Copy< inRank >( m_stride , rhs.m_stride );
00854 Copy< 8 - inRank >( m_stride + inRank , (size_type) 0 );
00855 unsigned i = 0 ;
00856 if ( inNatural ) {
00857 for ( ; i < inRank ; ++i ) { m_tag[i] = rhs.tag((inRank-1)-i); }
00858 }
00859 else {
00860 for ( ; i < inRank ; ++i ) { m_tag[i] = rhs.tag(i); }
00861 }
00862 for ( ; i < 8 ; ++i ) { m_tag[i] = NULL ; }
00863 }
00864
00865
00866
00867
00868 Array( value_type * ptr ,
00869 const unsigned rank ,
00870 const unsigned * const dims ,
00871 const tag_type * const tags )
00872 : m_ptr( ptr ), m_rank( rank )
00873 {
00874 if ( Natural ) {
00875 size_type n = 1 ;
00876 unsigned i ;
00877 for ( i = 0 ; i < rank ; ++i ) { m_stride[i] = n *= dims[(rank-1)-i]; }
00878 for ( ; i < 8 ; ++i ) { m_stride[i] = 0 ; }
00879 for ( i = 0 ; i < rank ; ++i ) { m_tag[i] = tags[(rank-1)-i]; }
00880 for ( ; i < 8 ; ++i ) { m_tag[i] = NULL ; }
00881 }
00882 else {
00883 size_type n = 1 ;
00884 unsigned i ;
00885 for ( i = 0 ; i < rank ; ++i ) { m_stride[i] = n *= dims[i] ; }
00886 for ( ; i < 8 ; ++i ) { m_stride[i] = 0 ; }
00887 for ( i = 0 ; i < rank ; ++i ) { m_tag[i] = tags[i]; }
00888 for ( ; i < 8 ; ++i ) { m_tag[i] = NULL ; }
00889 }
00890 }
00891
00893 protected:
00894
00896 value_type * m_ptr ;
00897
00899 unsigned m_rank ;
00900
00902 size_type m_stride[8];
00903
00905 tag_type m_tag[8] ;
00906
00907 template< typename , ArrayOrder ,
00908 class , class , class , class ,
00909 class , class , class , class >
00910 friend class PHX::Array ;
00911 };
00912
00913
00914
00915
00916 }
00917
00918 #undef ARRAY_CHECK
00919
00920 #endif
00921