shards Version of the Day
Shards_Array.hpp
00001 /*
00002 //@HEADER
00003 // ************************************************************************
00004 //
00005 //                Shards : Shared Discretization Tools
00006 //                 Copyright 2008 Sandia Corporation
00007 //
00008 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00009 // the U.S. Government retains certain rights in this software.
00010 //
00011 // Redistribution and use in source and binary forms, with or without
00012 // modification, are permitted provided that the following conditions are
00013 // met:
00014 //
00015 // 1. Redistributions of source code must retain the above copyright
00016 // notice, this list of conditions and the following disclaimer.
00017 //
00018 // 2. Redistributions in binary form must reproduce the above copyright
00019 // notice, this list of conditions and the following disclaimer in the
00020 // documentation and/or other materials provided with the distribution.
00021 //
00022 // 3. Neither the name of the Corporation nor the names of the
00023 // contributors may be used to endorse or promote products derived from
00024 // this software without specific prior written permission.
00025 //
00026 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00027 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00029 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00030 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00031 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00032 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00033 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00034 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00035 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00036 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00037 //
00038 // Questions? Contact Carter Edwards (hcedwar@sandia.gov),
00039 //                    Pavel Bochev (pbboche@sandia.gov), or
00040 //                    Denis Ridzal (dridzal@sandia.gov).
00041 //
00042 // ************************************************************************
00043 //@HEADER
00044 */
00045 
00046 #ifndef Shards_Array_hpp
00047 #define Shards_Array_hpp
00048 
00049 //----------------------------------------------------------------------
00050 
00051 #include <vector>
00052 #include <string>
00053 #include <Shards_SimpleArrayOps.hpp>
00054 
00055 //----------------------------------------------------------------------
00056 // Macro to compile in array bounds checking:
00057 
00058 #ifdef SHARDS_ARRAY_BOUNDS_CHECKING
00059 #define SHARDS_ARRAY_CHECK( X ) X
00060 #else
00061 #define SHARDS_ARRAY_CHECK( X )
00062 #endif
00063 
00064 //----------------------------------------------------------------------
00065 
00066 namespace shards {
00067 
00072 namespace array_traits {
00073 typedef int int_t ;
00074 } // namespace array_traits
00075 
00076 //----------------------------------------------------------------------
00082 enum ArrayOrder {
00086   NaturalOrder ,
00087 
00091   FortranOrder ,
00092 
00096   RankZero
00097 };
00098 
00099 //----------------------------------------------------------------------
00100 
00101 template< typename Scalar , ArrayOrder Order , 
00102           class Tag1 = void , class Tag2 = void ,
00103           class Tag3 = void , class Tag4 = void ,
00104           class Tag5 = void , class Tag6 = void ,
00105           class Tag7 = void , class Tag8 = void >
00106 class Array ;
00107 
00108 //----------------------------------------------------------------------
00109 
00133 class ArrayDimTag {
00134 public:
00135 
00136   typedef array_traits::int_t size_type ;
00137 
00139   virtual const char * name() const = 0 ;
00140 
00145   virtual std::string to_string( size_type dimension ,
00146                                  size_type index ) const ;
00147 
00152   virtual size_type to_index( size_type dimension ,
00153                               const std::string & label ) const ; 
00154  
00155 protected:
00156   virtual ~ArrayDimTag();
00157   ArrayDimTag() {}
00158   
00159 private:
00160   ArrayDimTag( const ArrayDimTag & );
00161   ArrayDimTag & operator = ( const ArrayDimTag & );
00162 };
00163 
00168 class ArrayDimension : public ArrayDimTag {
00169 public:
00170 
00171   const char * name() const ;
00172 
00174   static const ArrayDimension & tag();
00175 
00176 private:
00177   ~ArrayDimension();
00178   ArrayDimension();
00179   ArrayDimension( const ArrayDimension & );
00180   ArrayDimension & operator = ( const ArrayDimension & );
00181 };
00182 
00186 #define SHARDS_ARRAY_DIM_TAG_SIMPLE_DECLARATION( ADT ) \
00187   class ADT : public shards::ArrayDimTag { \
00188   public: \
00189     const char * name() const ; \
00190     static const ADT & tag(); \
00191   private: \
00192     ~ADT(); \
00193     ADT(); \
00194     ADT( const ADT & ); \
00195     ADT & operator = ( const ADT & ); \
00196   };
00197 
00201 #define SHARDS_ARRAY_DIM_TAG_SIMPLE_IMPLEMENTATION( ADT ) \
00202   ADT::ADT() {} \
00203   ADT::~ADT() {} \
00204   const char * ADT::name() const { static const char n[] = # ADT; return n; } \
00205   const ADT & ADT::tag() { static const ADT self ; return self ; }
00206 
00207 //----------------------------------------------------------------------
00208 //----------------------------------------------------------------------
00209 
00212 } // namespace shards
00213 
00214 //----------------------------------------------------------------------
00215 //----------------------------------------------------------------------
00216 // Private implementation details for the array
00217 
00218 #ifndef DOXYGEN_COMPILE
00219 
00220 namespace shards {
00221 namespace array_traits {
00222 
00223 //----------------------------------------------------------------------
00225 template< typename iType >
00226 inline
00227 iType stride_size(
00228   const iType & rank ,
00229   const iType * const stride )
00230 { return 0 < rank ? stride[ rank - 1 ] : 0 ; }
00231 
00233 template< typename iType >
00234 inline
00235 void stride_to_natural_dimensions(
00236   const iType   rank ,
00237   const iType * const stride ,
00238         iType * const dim )
00239 {
00240   iType n = 1 ;
00241   for ( iType i = 0 ; i < rank ; ++i )
00242     { dim[(rank-1)-i] = stride[i] / n ; n = stride[i] ; }
00243 }
00244 
00246 template< typename iType >
00247 inline
00248 void stride_to_natural_indices(
00249   const iType   rank ,
00250   const iType * const stride ,
00251         iType   offset ,
00252         iType * const indices )
00253 {
00254   iType * i = indices ;
00255   for ( const iType * s = stride + rank - 1 ; stride < s-- ; ++i ) {
00256     *i = offset / *s ;
00257     offset %= *s ;
00258   }
00259   *i = offset ;
00260 }
00261 
00263 template< typename iType >
00264 inline
00265 void stride_from_natural_dimensions( 
00266   const iType rank ,
00267         iType * const stride ,
00268   const iType * const dim )
00269 {
00270   iType n = 1 ;
00271   for ( iType i = 0 ; i < rank ; ++i ) { stride[i] = n *= dim[(rank-1)-i]; }
00272 }
00273 
00274 //----------------------------------------------------------------------
00275 
00276 void throw_bad_conversion( const int_t lhs_rank ,
00277                            const ArrayDimTag * const lhs_tags[] ,
00278                            const int_t rhs_rank ,
00279                            const ArrayDimTag * const rhs_tags[] );
00280 
00281 void check_rank( const int_t rank ,
00282                  const int_t test_rank );
00283 
00284 void check_range( const int_t index , const int_t bound );
00285 
00286 void check_indices( const bool ,
00287                     const int_t rank ,
00288                     const int_t * const stride ,
00289                     const int_t = 0 ,
00290                     const int_t = 0 ,
00291                     const int_t = 0 ,
00292                     const int_t = 0 ,
00293                     const int_t = 0 ,
00294                     const int_t = 0 ,
00295                     const int_t = 0 ,
00296                     const int_t = 0 );
00297 
00298 void init_dim(
00299          int_t dst_stride[] ,     
00300    const int_t src_dimension[] ,  
00301    const int_t rank , const bool natural );
00302  
00303 void init_tags(
00304    const ArrayDimTag *       dst_tag[] , 
00305    const ArrayDimTag * const src_tag[] , 
00306    const int_t rank , const bool natural );
00307 
00308 //----------------------------------------------------------------------
00309 
00310 template< int_t , int_t > struct CheckRank ;
00311 
00312 template<> struct CheckRank<0,0> { static void ok(){} };
00313 template<> struct CheckRank<1,1> { static void ok(){} };
00314 template<> struct CheckRank<2,2> { static void ok(){} };
00315 template<> struct CheckRank<3,3> { static void ok(){} };
00316 template<> struct CheckRank<4,4> { static void ok(){} };
00317 template<> struct CheckRank<5,5> { static void ok(){} };
00318 template<> struct CheckRank<6,6> { static void ok(){} };
00319 template<> struct CheckRank<7,7> { static void ok(){} };
00320 template<> struct CheckRank<8,8> { static void ok(){} };
00321 
00322 //----------------------------------------------------------------------
00323 
00324 template< int_t Index , int_t Bound > struct CheckRange ;
00325 
00326 template<> struct CheckRange<0,8> { static void ok(){} };
00327 template<> struct CheckRange<1,8> { static void ok(){} };
00328 template<> struct CheckRange<2,8> { static void ok(){} };
00329 template<> struct CheckRange<3,8> { static void ok(){} };
00330 template<> struct CheckRange<4,8> { static void ok(){} };
00331 template<> struct CheckRange<5,8> { static void ok(){} };
00332 template<> struct CheckRange<6,8> { static void ok(){} };
00333 template<> struct CheckRange<7,8> { static void ok(){} };
00334 
00335 template<> struct CheckRange<0,7> { static void ok(){} };
00336 template<> struct CheckRange<1,7> { static void ok(){} };
00337 template<> struct CheckRange<2,7> { static void ok(){} };
00338 template<> struct CheckRange<3,7> { static void ok(){} };
00339 template<> struct CheckRange<4,7> { static void ok(){} };
00340 template<> struct CheckRange<5,7> { static void ok(){} };
00341 template<> struct CheckRange<6,7> { static void ok(){} };
00342 
00343 template<> struct CheckRange<0,6> { static void ok(){} };
00344 template<> struct CheckRange<1,6> { static void ok(){} };
00345 template<> struct CheckRange<2,6> { static void ok(){} };
00346 template<> struct CheckRange<3,6> { static void ok(){} };
00347 template<> struct CheckRange<4,6> { static void ok(){} };
00348 template<> struct CheckRange<5,6> { static void ok(){} };
00349 
00350 template<> struct CheckRange<0,5> { static void ok(){} };
00351 template<> struct CheckRange<1,5> { static void ok(){} };
00352 template<> struct CheckRange<2,5> { static void ok(){} };
00353 template<> struct CheckRange<3,5> { static void ok(){} };
00354 template<> struct CheckRange<4,5> { static void ok(){} };
00355 
00356 template<> struct CheckRange<0,4> { static void ok(){} };
00357 template<> struct CheckRange<1,4> { static void ok(){} };
00358 template<> struct CheckRange<2,4> { static void ok(){} };
00359 template<> struct CheckRange<3,4> { static void ok(){} };
00360 
00361 template<> struct CheckRange<0,3> { static void ok(){} };
00362 template<> struct CheckRange<1,3> { static void ok(){} };
00363 template<> struct CheckRange<2,3> { static void ok(){} };
00364 
00365 template<> struct CheckRange<0,2> { static void ok(){} };
00366 template<> struct CheckRange<1,2> { static void ok(){} };
00367 
00368 template<> struct CheckRange<0,1> { static void ok(){} };
00369 
00370 //----------------------------------------------------------------------
00371 
00372 template< class , int_t > struct TagAt ;
00373 
00374 template< typename Scalar , ArrayOrder order ,
00375           class Tag1 , class Tag2 , class Tag3 , class Tag4 ,
00376           class Tag5 , class Tag6 , class Tag7 , class Tag8 >
00377 struct TagAt<Array<Scalar,order,Tag1,Tag2,Tag3,Tag4,Tag5,Tag6,Tag7,Tag8>,0>
00378 { typedef Tag1 type ; };
00379 
00380 template< typename Scalar , ArrayOrder order ,
00381           class Tag1 , class Tag2 , class Tag3 , class Tag4 ,
00382           class Tag5 , class Tag6 , class Tag7 , class Tag8 >
00383 struct TagAt<Array<Scalar,order,Tag1,Tag2,Tag3,Tag4,Tag5,Tag6,Tag7,Tag8>,1>
00384 { typedef Tag2 type ; };
00385 
00386 template< typename Scalar , ArrayOrder order ,
00387           class Tag1 , class Tag2 , class Tag3 , class Tag4 ,
00388           class Tag5 , class Tag6 , class Tag7 , class Tag8 >
00389 struct TagAt<Array<Scalar,order,Tag1,Tag2,Tag3,Tag4,Tag5,Tag6,Tag7,Tag8>,2>
00390 { typedef Tag3 type ; };
00391 
00392 template< typename Scalar , ArrayOrder order ,
00393           class Tag1 , class Tag2 , class Tag3 , class Tag4 ,
00394           class Tag5 , class Tag6 , class Tag7 , class Tag8 >
00395 struct TagAt<Array<Scalar,order,Tag1,Tag2,Tag3,Tag4,Tag5,Tag6,Tag7,Tag8>,3>
00396 { typedef Tag4 type ; };
00397 
00398 template< typename Scalar , ArrayOrder order ,
00399           class Tag1 , class Tag2 , class Tag3 , class Tag4 ,
00400           class Tag5 , class Tag6 , class Tag7 , class Tag8 >
00401 struct TagAt<Array<Scalar,order,Tag1,Tag2,Tag3,Tag4,Tag5,Tag6,Tag7,Tag8>,4>
00402 { typedef Tag5 type ; };
00403 
00404 template< typename Scalar , ArrayOrder order ,
00405           class Tag1 , class Tag2 , class Tag3 , class Tag4 ,
00406           class Tag5 , class Tag6 , class Tag7 , class Tag8 >
00407 struct TagAt<Array<Scalar,order,Tag1,Tag2,Tag3,Tag4,Tag5,Tag6,Tag7,Tag8>,5>
00408 { typedef Tag6 type ; };
00409 
00410 template< typename Scalar , ArrayOrder order ,
00411           class Tag1 , class Tag2 , class Tag3 , class Tag4 ,
00412           class Tag5 , class Tag6 , class Tag7 , class Tag8 >
00413 struct TagAt<Array<Scalar,order,Tag1,Tag2,Tag3,Tag4,Tag5,Tag6,Tag7,Tag8>,6>
00414 { typedef Tag7 type ; };
00415 
00416 template< typename Scalar , ArrayOrder order ,
00417           class Tag1 , class Tag2 , class Tag3 , class Tag4 ,
00418           class Tag5 , class Tag6 , class Tag7 , class Tag8 >
00419 struct TagAt<Array<Scalar,order,Tag1,Tag2,Tag3,Tag4,Tag5,Tag6,Tag7,Tag8>,7>
00420 { typedef Tag8 type ; };
00421 
00422 //----------------------------------------------------------------------
00423 //----------------------------------------------------------------------
00424 
00425 template< ArrayOrder , int_t Rank , int_t Ordinal = 0 > struct StrideDim ;
00426 
00427 template< int_t Rank , int_t Ordinal >
00428 struct StrideDim<RankZero,Rank,Ordinal> {
00429 
00430   template< typename iType >
00431   static iType dimension( const iType * )
00432     { return 0 ; }
00433 
00434   template< typename iType >
00435   static iType dimension( const iType * , iType )
00436     { return 0 ; }
00437 };
00438 
00439 template< int_t Rank >
00440 struct StrideDim<FortranOrder,Rank,0> {
00441 
00442   template< typename iType >
00443   static iType dimension( const iType * stride )
00444     {
00445       array_traits::CheckRange<0,Rank>::ok();
00446       return stride[0];
00447     }
00448 
00449   template< typename iType >
00450   static iType dimension( const iType * stride , iType ordinal )
00451     {
00452       array_traits::check_range(ordinal,Rank);
00453       return ordinal ? stride[ordinal] / stride[ordinal-1] : stride[0] ;
00454     }
00455 };
00456 
00457 template< int_t Rank >
00458 struct StrideDim<NaturalOrder,Rank,0> {
00459 
00460   template< typename iType >
00461   static iType dimension( const iType * stride )
00462     {
00463       array_traits::CheckRange<0,Rank>::ok();
00464       return stride[0];
00465     }
00466 
00467   template< typename iType >
00468   static iType dimension( const iType * stride , iType ordinal )
00469     {
00470       array_traits::check_range(ordinal,Rank);
00471       ordinal = ( Rank - 1 ) - ordinal ;
00472       return ordinal ? stride[ordinal] / stride[ordinal-1] : stride[0] ;
00473     }
00474 };
00475 
00476 template< int_t Rank , int_t Ordinal >
00477 struct StrideDim<FortranOrder,Rank,Ordinal> {
00478 
00479   template< typename iType >
00480   static iType dimension( const iType * stride )
00481     {
00482       array_traits::CheckRange<Ordinal,Rank>::ok();
00483       return stride[Ordinal] / stride[Ordinal-1];
00484     }
00485 };
00486 
00487 template< int_t Rank , int_t Ordinal >
00488 struct StrideDim<NaturalOrder,Rank,Ordinal> {
00489 
00490   template< typename iType >
00491   static iType dimension( const iType * stride )
00492     {
00493       enum { I = ( Rank - 1 ) - Ordinal };
00494       array_traits::CheckRange<Ordinal,Rank>::ok();
00495       return stride[I] / stride[I-1];
00496     }
00497 };
00498 
00499 //----------------------------------------------------------------------
00500 
00501 template< ArrayOrder > struct Offset ;
00502 
00503 template<>
00504 struct Offset<FortranOrder> {
00505 
00506   template< typename isType , typename iType >
00507   static iType op( const isType * const stride ,
00508                    const iType & i1 , const iType & i2 ,
00509                    const iType & i3 , const iType & i4 ,
00510                    const iType & i5 , const iType & i6 ,
00511                    const iType & i7 , const iType & i8 )
00512   {
00513     SHARDS_ARRAY_CHECK(check_indices(false,8,stride,i1,i2,i3,i4,i5,i6,i7,i8));
00514     return i1             + i2 * stride[0] +
00515            i3 * stride[1] + i4 * stride[2] +
00516            i5 * stride[3] + i6 * stride[4] +
00517            i7 * stride[5] + i8 * stride[6] ;
00518   }
00519 
00520   template< typename isType , typename iType >
00521   static iType op( const isType * const stride ,
00522                    const iType & i1 , const iType & i2 ,
00523                    const iType & i3 , const iType & i4 ,
00524                    const iType & i5 , const iType & i6 ,
00525                    const iType & i7 )
00526   {
00527     SHARDS_ARRAY_CHECK(check_indices(false,7,stride,i1,i2,i3,i4,i5,i6,i7));
00528     return i1             + i2 * stride[0] +
00529            i3 * stride[1] + i4 * stride[2] +
00530            i5 * stride[3] + i6 * stride[4] +
00531            i7 * stride[5] ;
00532   }
00533 
00534   template< typename isType , typename iType >
00535   static iType op( const isType * const stride ,
00536                    const iType & i1 , const iType & i2 ,
00537                    const iType & i3 , const iType & i4 ,
00538                    const iType & i5 , const iType & i6 )
00539   {
00540     SHARDS_ARRAY_CHECK(check_indices(false,6,stride,i1,i2,i3,i4,i5,i6));
00541     return i1             + i2 * stride[0] +
00542            i3 * stride[1] + i4 * stride[2] +
00543            i5 * stride[3] + i6 * stride[4] ;
00544   }
00545 
00546   template< typename isType , typename iType >
00547   static iType op( const isType * const stride ,
00548                    const iType & i1 , const iType & i2 ,
00549                    const iType & i3 , const iType & i4 ,
00550                    const iType & i5 )
00551   {
00552     SHARDS_ARRAY_CHECK(check_indices(false,5,stride,i1,i2,i3,i4,i5));
00553     return i1             + i2 * stride[0] +
00554            i3 * stride[1] + i4 * stride[2] +
00555            i5 * stride[3] ;
00556   }
00557 
00558   template< typename isType , typename iType >
00559   static iType op( const isType * const stride ,
00560                    const iType & i1 , const iType & i2 ,
00561                    const iType & i3 , const iType & i4 )
00562   {
00563     SHARDS_ARRAY_CHECK(check_indices(false,4,stride,i1,i2,i3,i4));
00564     return i1             + i2 * stride[0] +
00565            i3 * stride[1] + i4 * stride[2] ;
00566   }
00567 
00568   template< typename isType , typename iType >
00569   static iType op( const isType * const stride ,
00570                    const iType & i1 , const iType & i2 ,
00571                    const iType & i3 )
00572   {
00573     SHARDS_ARRAY_CHECK(check_indices(false,3,stride,i1,i2,i3));
00574     return i1 + i2 * stride[0] + i3 * stride[1] ;
00575   }
00576 
00577   template< typename isType , typename iType >
00578   static iType op( const isType * const stride ,
00579                    const iType & i1 , const iType & i2 )
00580   {
00581     SHARDS_ARRAY_CHECK(check_indices(false,2,stride,i1,i2));
00582     return i1 + i2 * stride[0] ;
00583   }
00584 
00585   template< typename isType , typename iType >
00586   static iType op( const isType * const SHARDS_ARRAY_CHECK( stride ) ,
00587                    const iType & i1 )
00588   {
00589     SHARDS_ARRAY_CHECK(check_indices(false,1,stride,i1));
00590     return i1 ;
00591   }
00592 };
00593 
00594 //----------------------------------------------------------------------
00595 
00596 template<>
00597 struct Offset<NaturalOrder> {
00598 
00599   template< typename isType , typename iType >
00600   static iType op( const isType * const stride ,
00601                    const iType & i1 , const iType & i2 ,
00602                    const iType & i3 , const iType & i4 ,
00603                    const iType & i5 , const iType & i6 ,
00604                    const iType & i7 , const iType & i8 )
00605   {
00606     SHARDS_ARRAY_CHECK(check_indices(true,8,stride,i1,i2,i3,i4,i5,i6,i7,i8));
00607     return i8             + i7 * stride[0] +
00608            i6 * stride[1] + i5 * stride[2] +
00609            i4 * stride[3] + i3 * stride[4] +
00610            i2 * stride[5] + i1 * stride[6] ;
00611   }
00612 
00613   template< typename isType , typename iType >
00614   static iType op( const isType * const stride ,
00615                    const iType & i1 , const iType & i2 ,
00616                    const iType & i3 , const iType & i4 ,
00617                    const iType & i5 , const iType & i6 ,
00618                    const iType & i7 )
00619   {
00620     SHARDS_ARRAY_CHECK(check_indices(true,7,stride,i1,i2,i3,i4,i5,i6,i7));
00621     return i7             + i6 * stride[0] +
00622            i5 * stride[1] + i4 * stride[2] +
00623            i3 * stride[3] + i2 * stride[4] +
00624            i1 * stride[5] ;
00625   }
00626 
00627   template< typename isType , typename iType >
00628   static iType op( const isType * const stride ,
00629                    const iType & i1 , const iType & i2 ,
00630                    const iType & i3 , const iType & i4 ,
00631                    const iType & i5 , const iType & i6 )
00632   {
00633     SHARDS_ARRAY_CHECK(check_indices(true,6,stride,i1,i2,i3,i4,i5,i6));
00634     return i6             + i5 * stride[0] +
00635            i4 * stride[1] + i3 * stride[2] +
00636            i2 * stride[3] + i1 * stride[4] ;
00637   }
00638 
00639   template< typename isType , typename iType >
00640   static iType op( const isType * const stride ,
00641                    const iType & i1 , const iType & i2 ,
00642                    const iType & i3 , const iType & i4 ,
00643                    const iType & i5 )
00644   {
00645     SHARDS_ARRAY_CHECK(check_indices(true,5,stride,i1,i2,i3,i4,i5));
00646     return i5             + i4 * stride[0] +
00647            i3 * stride[1] + i2 * stride[2] +
00648            i1 * stride[3] ;
00649   }
00650 
00651   template< typename isType , typename iType >
00652   static iType op( const isType * const stride ,
00653                    const iType & i1 , const iType & i2 ,
00654                    const iType & i3 , const iType & i4 )
00655   {
00656     SHARDS_ARRAY_CHECK(check_indices(true,4,stride,i1,i2,i3,i4));
00657     return i4             + i3 * stride[0] +
00658            i2 * stride[1] + i1 * stride[2] ;
00659   }
00660 
00661   template< typename isType , typename iType >
00662   static iType op( const isType * const stride ,
00663                    const iType & i1 , const iType & i2 ,
00664                    const iType & i3 )
00665   {
00666     SHARDS_ARRAY_CHECK(check_indices(true,3,stride,i1,i2,i3));
00667     return i3 + i2 * stride[0] + i1 * stride[1] ;
00668   }
00669 
00670   template< typename isType , typename iType >
00671   static iType op( const isType * const stride ,
00672                    const iType & i1 , const iType & i2 )
00673   {
00674     SHARDS_ARRAY_CHECK(check_indices(true,2,stride,i1,i2));
00675     return i2 + i1 * stride[0] ;
00676   }
00677 
00678   template< typename isType , typename iType >
00679   static iType op( const isType * const SHARDS_ARRAY_CHECK( stride ) ,
00680                    const iType & i1 )
00681   {
00682     SHARDS_ARRAY_CHECK(check_indices(true,1,stride,i1));
00683     return i1 ;
00684   }
00685 };
00686 
00687 //----------------------------------------------------------------------
00688 //----------------------------------------------------------------------
00689 
00690 template< typename Scalar , ArrayOrder Order ,
00691           class Tag1 , class Tag2 , class Tag3 , class Tag4 ,
00692           class Tag5 , class Tag6 , class Tag7 , class Tag8 >
00693 struct Helper ;
00694 
00695 //----------------------------------------------------------------------
00698 template< typename Scalar ,
00699           class Tag1 , class Tag2 , class Tag3 , class Tag4 ,
00700           class Tag5 , class Tag6 , class Tag7 , class Tag8 >
00701 struct Helper<Scalar,NaturalOrder,Tag1,Tag2,Tag3,Tag4,Tag5,Tag6,Tag7,Tag8>
00702 {
00703   typedef
00704     Array<Scalar,FortranOrder,Tag8,Tag7,Tag6,Tag5,Tag4,Tag3,Tag2,Tag1>
00705       reverse ;
00706 
00707   typedef
00708     Array<Scalar,NaturalOrder,Tag2,Tag3,Tag4,Tag5,Tag6,Tag7,Tag8,void>
00709       truncate ;
00710 
00711   enum { Rank = 8 };
00712 
00713   static bool verify( const int_t rank , const ArrayDimTag * const tags[] )
00714     {
00715       return rank    == Rank &&
00716              tags[0] == & Tag8::tag() &&
00717              tags[1] == & Tag7::tag() &&
00718              tags[2] == & Tag6::tag() &&
00719              tags[3] == & Tag5::tag() &&
00720              tags[4] == & Tag4::tag() &&
00721              tags[5] == & Tag3::tag() &&
00722              tags[6] == & Tag2::tag() &&
00723              tags[7] == & Tag1::tag() ;
00724     }
00725 
00726   static void assign_tags( const ArrayDimTag * tags[] )
00727     {
00728       tags[0] = & Tag8::tag();
00729       tags[1] = & Tag7::tag();
00730       tags[2] = & Tag6::tag();
00731       tags[3] = & Tag5::tag();
00732       tags[4] = & Tag4::tag();
00733       tags[5] = & Tag3::tag();
00734       tags[6] = & Tag2::tag();
00735       tags[7] = & Tag1::tag();
00736     }
00737 
00738   template< typename iType >
00739   static void assign( iType * stride )
00740     {
00741         stride[7] = Tag1::Size * (
00742         stride[6] = Tag2::Size * (
00743         stride[5] = Tag3::Size * (
00744         stride[4] = Tag4::Size * (
00745         stride[3] = Tag5::Size * (
00746         stride[2] = Tag6::Size * (
00747         stride[1] = Tag7::Size * (
00748         stride[0] = Tag8::Size )))))));
00749     }
00750 
00751   template< typename iType >
00752   static void assign( iType * stride ,
00753                       const iType & n1 )
00754     {
00755         stride[7] = n1 * (
00756         stride[6] = Tag2::Size * (
00757         stride[5] = Tag3::Size * (
00758         stride[4] = Tag4::Size * (
00759         stride[3] = Tag5::Size * (
00760         stride[2] = Tag6::Size * (
00761         stride[1] = Tag7::Size * (
00762         stride[0] = Tag8::Size )))))));
00763     }
00764 
00765   template< typename iType >
00766   static void assign( iType * stride ,
00767                       const iType & n1 ,
00768                       const iType & n2 )
00769     {
00770         stride[7] = n1 * (
00771         stride[6] = n2 * (
00772         stride[5] = Tag3::Size * (
00773         stride[4] = Tag4::Size * (
00774         stride[3] = Tag5::Size * (
00775         stride[2] = Tag6::Size * (
00776         stride[1] = Tag7::Size * (
00777         stride[0] = Tag8::Size )))))));
00778     }
00779 
00780   template< typename iType >
00781   static void assign( iType * stride ,
00782                       const iType & n1 ,
00783                       const iType & n2 ,
00784                       const iType & n3 )
00785     {
00786         stride[7] = n1 * (
00787         stride[6] = n2 * (
00788         stride[5] = n3 * (
00789         stride[4] = Tag4::Size * (
00790         stride[3] = Tag5::Size * (
00791         stride[2] = Tag6::Size * (
00792         stride[1] = Tag7::Size * (
00793         stride[0] = Tag8::Size )))))));
00794     }
00795 
00796   template< typename iType >
00797   static void assign( iType * stride ,
00798                       const iType & n1 ,
00799                       const iType & n2 ,
00800                       const iType & n3 ,
00801                       const iType & n4 )
00802     {
00803         stride[7] = n1 * (
00804         stride[6] = n2 * (
00805         stride[5] = n3 * (
00806         stride[4] = n4 * (
00807         stride[3] = Tag5::Size * (
00808         stride[2] = Tag6::Size * (
00809         stride[1] = Tag7::Size * (
00810         stride[0] = Tag8::Size )))))));
00811     }
00812 
00813   template< typename iType >
00814   static void assign( iType * stride ,
00815                       const iType & n1 ,
00816                       const iType & n2 ,
00817                       const iType & n3 ,
00818                       const iType & n4 ,
00819                       const iType & n5 )
00820     {
00821         stride[7] = n1 * (
00822         stride[6] = n2 * (
00823         stride[5] = n3 * (
00824         stride[4] = n4 * (
00825         stride[3] = n5 * (
00826         stride[2] = Tag6::Size  * (
00827         stride[1] = Tag7::Size  * (
00828         stride[0] = Tag8::Size  )))))));
00829     }
00830 
00831   template< typename iType >
00832   static void assign( iType * stride ,
00833                       const iType & n1 ,
00834                       const iType & n2 ,
00835                       const iType & n3 ,
00836                       const iType & n4 ,
00837                       const iType & n5 ,
00838                       const iType & n6 )
00839     {
00840         stride[7] = n1 * (
00841         stride[6] = n2 * (
00842         stride[5] = n3 * (
00843         stride[4] = n4 * (
00844         stride[3] = n5 * (
00845         stride[2] = n6 * (
00846         stride[1] = Tag7::Size * (
00847         stride[0] = Tag8::Size )))))));
00848     }
00849 
00850   template< typename iType >
00851   static void assign( iType * stride ,
00852                       const iType & n1 ,
00853                       const iType & n2 ,
00854                       const iType & n3 ,
00855                       const iType & n4 ,
00856                       const iType & n5 ,
00857                       const iType & n6 ,
00858                       const iType & n7 )
00859     {
00860         stride[7] = n1 * (
00861         stride[6] = n2 * (
00862         stride[5] = n3 * (
00863         stride[4] = n4 * (
00864         stride[3] = n5 * (
00865         stride[2] = n6 * (
00866         stride[1] = n7 * (
00867         stride[0] = Tag8::Size )))))));
00868     }
00869 
00870   template< typename iType >
00871   static void assign( iType * stride ,
00872                       const iType & n1 ,
00873                       const iType & n2 ,
00874                       const iType & n3 ,
00875                       const iType & n4 ,
00876                       const iType & n5 ,
00877                       const iType & n6 ,
00878                       const iType & n7 ,
00879                       const iType & n8 )
00880     {
00881         stride[7] = n1 * (
00882         stride[6] = n2 * (
00883         stride[5] = n3 * (
00884         stride[4] = n4 * (
00885         stride[3] = n5 * (
00886         stride[2] = n6 * (
00887         stride[1] = n7 * (
00888         stride[0] = n8 )))))));
00889     }
00890 
00891   template< typename iType >
00892   static void assign( iType * stride ,
00893                       const iType * const dims )
00894     {
00895         stride[7] = dims[0] * (
00896         stride[6] = dims[1] * (
00897         stride[5] = dims[2] * (
00898         stride[4] = dims[3] * (
00899         stride[3] = dims[4] * (
00900         stride[2] = dims[5] * (
00901         stride[1] = dims[6] * (
00902         stride[0] = dims[7] )))))));
00903     }
00904 };
00905 
00906 template< typename Scalar ,
00907           class Tag1 , class Tag2 , class Tag3 , class Tag4 ,
00908           class Tag5 , class Tag6 , class Tag7 , class Tag8 >
00909 struct Helper<Scalar,FortranOrder,Tag1,Tag2,Tag3,Tag4,Tag5,Tag6,Tag7,Tag8>
00910 {
00911   typedef
00912     Array<Scalar,NaturalOrder,Tag8,Tag7,Tag6,Tag5,Tag4,Tag3,Tag2,Tag1>
00913       reverse ;
00914 
00915   typedef
00916     Array<Scalar,FortranOrder,Tag1,Tag2,Tag3,Tag4,Tag5,Tag6,Tag7,void>
00917       truncate ;
00918 
00919   enum { Rank = 8 };
00920 
00921   static bool verify( int_t rank , const ArrayDimTag * tags[] )
00922     {
00923       return rank == Rank &&
00924              tags[0] == & Tag1::tag() &&
00925              tags[1] == & Tag2::tag() &&
00926              tags[2] == & Tag3::tag() &&
00927              tags[3] == & Tag4::tag() &&
00928              tags[4] == & Tag5::tag() &&
00929              tags[5] == & Tag6::tag() &&
00930              tags[6] == & Tag7::tag() &&
00931              tags[7] == & Tag8::tag();
00932     }
00933 
00934   static void assign_tags( const ArrayDimTag * tags[] )
00935     {
00936       tags[0] = & Tag1::tag();
00937       tags[1] = & Tag2::tag();
00938       tags[2] = & Tag3::tag();
00939       tags[3] = & Tag4::tag();
00940       tags[4] = & Tag5::tag();
00941       tags[5] = & Tag6::tag();
00942       tags[6] = & Tag7::tag();
00943       tags[7] = & Tag8::tag();
00944     }
00945 
00946   template< typename iType >
00947   static void assign( iType * stride )
00948     {
00949         stride[7] = Tag8::Size * (
00950         stride[6] = Tag7::Size * (
00951         stride[5] = Tag6::Size * (
00952         stride[4] = Tag5::Size * (
00953         stride[3] = Tag4::Size * (
00954         stride[2] = Tag3::Size * (
00955         stride[1] = Tag2::Size * (
00956         stride[0] = Tag1::Size )))))));
00957     }
00958 
00959   template< typename iType >
00960   static void assign( iType * stride ,
00961                       const iType & n8 )
00962     {
00963         stride[7] = n8 * (
00964         stride[6] = Tag7::Size * (
00965         stride[5] = Tag6::Size * (
00966         stride[4] = Tag5::Size * (
00967         stride[3] = Tag4::Size * (
00968         stride[2] = Tag3::Size * (
00969         stride[1] = Tag2::Size * (
00970         stride[0] = Tag1::Size )))))));
00971     }
00972 
00973   template< typename iType >
00974   static void assign( iType * stride ,
00975                       const iType & n7 ,
00976                       const iType & n8 )
00977     {
00978         stride[7] = n8 * (
00979         stride[6] = n7 * (
00980         stride[5] = Tag6::Size * (
00981         stride[4] = Tag5::Size * (
00982         stride[3] = Tag4::Size * (
00983         stride[2] = Tag3::Size * (
00984         stride[1] = Tag2::Size * (
00985         stride[0] = Tag1::Size )))))));
00986     }
00987 
00988   template< typename iType >
00989   static void assign( iType * stride ,
00990                       const iType & n6 ,
00991                       const iType & n7 ,
00992                       const iType & n8 )
00993     {
00994         stride[7] = n8 * (
00995         stride[6] = n7 * (
00996         stride[5] = n6 * (
00997         stride[4] = Tag5::Size * (
00998         stride[3] = Tag4::Size * (
00999         stride[2] = Tag3::Size * (
01000         stride[1] = Tag2::Size * (
01001         stride[0] = Tag1::Size )))))));
01002     }
01003 
01004   template< typename iType >
01005   static void assign( iType * stride ,
01006                       const iType & n5 ,
01007                       const iType & n6 ,
01008                       const iType & n7 ,
01009                       const iType & n8 )
01010     {
01011         stride[7] = n8 * (
01012         stride[6] = n7 * (
01013         stride[5] = n6 * (
01014         stride[4] = n5 * (
01015         stride[3] = Tag4::Size * (
01016         stride[2] = Tag3::Size * (
01017         stride[1] = Tag2::Size * (
01018         stride[0] = Tag1::Size )))))));
01019     }
01020 
01021   template< typename iType >
01022   static void assign( iType * stride ,
01023                       const iType & n4 ,
01024                       const iType & n5 ,
01025                       const iType & n6 ,
01026                       const iType & n7 ,
01027                       const iType & n8 )
01028     {
01029         stride[7] = n8 * (
01030         stride[6] = n7 * (
01031         stride[5] = n6 * (
01032         stride[4] = n5 * (
01033         stride[3] = n4 * (
01034         stride[2] = Tag3::Size  * (
01035         stride[1] = Tag2::Size  * (
01036         stride[0] = Tag1::Size  )))))));
01037     }
01038 
01039   template< typename iType >
01040   static void assign( iType * stride ,
01041                       const iType & n3 ,
01042                       const iType & n4 ,
01043                       const iType & n5 ,
01044                       const iType & n6 ,
01045                       const iType & n7 ,
01046                       const iType & n8 )
01047     {
01048         stride[7] = n8 * (
01049         stride[6] = n7 * (
01050         stride[5] = n6 * (
01051         stride[4] = n5 * (
01052         stride[3] = n4 * (
01053         stride[2] = n3 * (
01054         stride[1] = Tag2::Size * (
01055         stride[0] = Tag1::Size )))))));
01056     }
01057 
01058   template< typename iType >
01059   static void assign( iType * stride ,
01060                       const iType & n2 ,
01061                       const iType & n3 ,
01062                       const iType & n4 ,
01063                       const iType & n5 ,
01064                       const iType & n6 ,
01065                       const iType & n7 ,
01066                       const iType & n8 )
01067     {
01068         stride[7] = n8 * (
01069         stride[6] = n7 * (
01070         stride[5] = n6 * (
01071         stride[4] = n5 * (
01072         stride[3] = n4 * (
01073         stride[2] = n3 * (
01074         stride[1] = n2 * (
01075         stride[0] = Tag1::Size )))))));
01076     }
01077 
01078   template< typename iType >
01079   static void assign( iType * stride ,
01080                       const iType & n1 ,
01081                       const iType & n2 ,
01082                       const iType & n3 ,
01083                       const iType & n4 ,
01084                       const iType & n5 ,
01085                       const iType & n6 ,
01086                       const iType & n7 ,
01087                       const iType & n8 )
01088     {
01089         stride[7] = n8 * (
01090         stride[6] = n7 * (
01091         stride[5] = n6 * (
01092         stride[4] = n5 * (
01093         stride[3] = n4 * (
01094         stride[2] = n3 * (
01095         stride[1] = n2 * (
01096         stride[0] = n1 )))))));
01097     }
01098 
01099   template< typename iType >
01100   static void assign( iType * stride ,
01101                       const iType * const dims )
01102     {
01103         stride[7] = dims[7] * (
01104         stride[6] = dims[6] * (
01105         stride[5] = dims[5] * (
01106         stride[4] = dims[4] * (
01107         stride[3] = dims[3] * (
01108         stride[2] = dims[2] * (
01109         stride[1] = dims[1] * (
01110         stride[0] = dims[0] )))))));
01111     }
01112 };
01113 
01114 //----------------------------------------------------------------------
01117 template< typename Scalar ,
01118           class Tag1 , class Tag2 , class Tag3 , class Tag4 ,
01119           class Tag5 , class Tag6 , class Tag7 >
01120 struct Helper<Scalar,NaturalOrder,Tag1,Tag2,Tag3,Tag4,Tag5,Tag6,Tag7,void>
01121 {
01122   typedef
01123     Array<Scalar,FortranOrder,Tag7,Tag6,Tag5,Tag4,Tag3,Tag2,Tag1,void>
01124       reverse ;
01125 
01126   typedef
01127     Array<Scalar,NaturalOrder,Tag2,Tag3,Tag4,Tag5,Tag6,Tag7,void,void>
01128       truncate ;
01129 
01130   template< class TagA >
01131   struct append {
01132     typedef
01133       Array<Scalar,NaturalOrder,TagA,Tag1,Tag2,Tag3,Tag4,Tag5,Tag6,Tag7>
01134         natural ;
01135 
01136     typedef
01137       Array<Scalar,FortranOrder,Tag7,Tag6,Tag5,Tag4,Tag3,Tag2,Tag1,TagA>
01138         fortran ;
01139 
01140     typedef  natural  type ;
01141     typedef  fortran  reverse ;
01142   };
01143 
01144   enum { Rank = 7 };
01145 
01146   static bool verify( int_t rank , const ArrayDimTag * tags[] )
01147     {
01148       return rank == Rank &&
01149              tags[0] == & Tag7::tag() &&
01150              tags[1] == & Tag6::tag() &&
01151              tags[2] == & Tag5::tag() &&
01152              tags[3] == & Tag4::tag() &&
01153              tags[4] == & Tag3::tag() &&
01154              tags[5] == & Tag2::tag() &&
01155              tags[6] == & Tag1::tag() ;
01156     }
01157 
01158   static void assign_tags( const ArrayDimTag * tags[] )
01159     {
01160       tags[0] = & Tag7::tag();
01161       tags[1] = & Tag6::tag();
01162       tags[2] = & Tag5::tag();
01163       tags[3] = & Tag4::tag();
01164       tags[4] = & Tag3::tag();
01165       tags[5] = & Tag2::tag();
01166       tags[6] = & Tag1::tag();
01167       tags[7] = NULL ;
01168     }
01169 
01170   template< typename iType >
01171   static void assign( iType * stride )
01172     {
01173       stride[7] = 0 ;
01174       stride[6] = Tag1::Size * (
01175       stride[5] = Tag2::Size * (
01176       stride[4] = Tag3::Size * (
01177       stride[3] = Tag4::Size * (
01178       stride[2] = Tag5::Size * (
01179       stride[1] = Tag6::Size * (
01180       stride[0] = Tag7::Size ))))));
01181     }
01182 
01183   template< typename iType >
01184   static void assign( iType * stride ,
01185                       const iType & n1 )
01186     {
01187       stride[7] = 0 ;
01188       stride[6] = n1 * (
01189       stride[5] = Tag2::Size * (
01190       stride[4] = Tag3::Size * (
01191       stride[3] = Tag4::Size * (
01192       stride[2] = Tag5::Size * (
01193       stride[1] = Tag6::Size * (
01194       stride[0] = Tag7::Size ))))));
01195     }
01196 
01197   template< typename iType >
01198   static void assign( iType * stride ,
01199                       const iType & n1 ,
01200                       const iType & n2 )
01201     {
01202       stride[7] = 0 ;
01203       stride[6] = n1 * (
01204       stride[5] = n2 * (
01205       stride[4] = Tag3::Size * (
01206       stride[3] = Tag4::Size * (
01207       stride[2] = Tag5::Size * (
01208       stride[1] = Tag6::Size * (
01209       stride[0] = Tag7::Size ))))));
01210     }
01211 
01212   template< typename iType >
01213   static void assign( iType * stride ,
01214                       const iType & n1 ,
01215                       const iType & n2 ,
01216                       const iType & n3 )
01217     {
01218       stride[7] = 0 ;
01219       stride[6] = n1 * (
01220       stride[5] = n2 * (
01221       stride[4] = n3 * (
01222       stride[3] = Tag4::Size * (
01223       stride[2] = Tag5::Size * (
01224       stride[1] = Tag6::Size * (
01225       stride[0] = Tag7::Size ))))));
01226     }
01227 
01228   template< typename iType >
01229   static void assign( iType * stride ,
01230                       const iType & n1 ,
01231                       const iType & n2 ,
01232                       const iType & n3 ,
01233                       const iType & n4 )
01234     {
01235       stride[7] = 0 ;
01236       stride[6] = n1 * (
01237       stride[5] = n2 * (
01238       stride[4] = n3 * (
01239       stride[3] = n4 * (
01240       stride[2] = Tag5::Size * (
01241       stride[1] = Tag6::Size * (
01242       stride[0] = Tag7::Size ))))));
01243     }
01244 
01245   template< typename iType >
01246   static void assign( iType * stride ,
01247                       const iType & n1 ,
01248                       const iType & n2 ,
01249                       const iType & n3 ,
01250                       const iType & n4 ,
01251                       const iType & n5 )
01252     {
01253       stride[7] = 0 ;
01254       stride[6] = n1 * (
01255       stride[5] = n2 * (
01256       stride[4] = n3 * (
01257       stride[3] = n4 * (
01258       stride[2] = n5 * (
01259       stride[1] = Tag6::Size * (
01260       stride[0] = Tag7::Size ))))));
01261     }
01262 
01263   template< typename iType >
01264   static void assign( iType * stride ,
01265                       const iType & n1 ,
01266                       const iType & n2 ,
01267                       const iType & n3 ,
01268                       const iType & n4 ,
01269                       const iType & n5 ,
01270                       const iType & n6 )
01271     {
01272       stride[7] = 0 ;
01273       stride[6] = n1 * (
01274       stride[5] = n2 * (
01275       stride[4] = n3 * (
01276       stride[3] = n4 * (
01277       stride[2] = n5 * (
01278       stride[1] = n6 * (
01279       stride[0] = Tag7::Size ))))));
01280     }
01281 
01282   template< typename iType >
01283   static void assign( iType * stride ,
01284                       const iType & n1 ,
01285                       const iType & n2 ,
01286                       const iType & n3 ,
01287                       const iType & n4 ,
01288                       const iType & n5 ,
01289                       const iType & n6 ,
01290                       const iType & n7 )
01291     {
01292       stride[7] = 0 ;
01293       stride[6] = n1 * (
01294       stride[5] = n2 * (
01295       stride[4] = n3 * (
01296       stride[3] = n4 * (
01297       stride[2] = n5 * (
01298       stride[1] = n6 * (
01299       stride[0] = n7 ))))));
01300     }
01301 
01302   template< typename iType >
01303   static void assign( iType * stride ,
01304                       const iType * const dims )
01305     {
01306       stride[7] = 0 ;
01307       stride[6] = dims[0] * (
01308       stride[5] = dims[1] * (
01309       stride[4] = dims[2] * (
01310       stride[3] = dims[3] * (
01311       stride[2] = dims[4] * (
01312       stride[1] = dims[5] * (
01313       stride[0] = dims[6] ))))));
01314     }
01315 };
01316 
01317 template< typename Scalar ,
01318           class Tag1 , class Tag2 , class Tag3 , class Tag4 ,
01319           class Tag5 , class Tag6 , class Tag7 >
01320 struct Helper<Scalar,FortranOrder,Tag1,Tag2,Tag3,Tag4,Tag5,Tag6,Tag7,void>
01321 {
01322   typedef
01323     Array<Scalar,NaturalOrder,Tag7,Tag6,Tag5,Tag4,Tag3,Tag2,Tag1,void>
01324       reverse ;
01325 
01326   typedef
01327     Array<Scalar,FortranOrder,Tag1,Tag2,Tag3,Tag4,Tag5,Tag6,void,void>
01328       truncate ;
01329 
01330   template< class TagA >
01331   struct append {
01332     typedef
01333       Array<Scalar,FortranOrder,Tag1,Tag2,Tag3,Tag4,Tag5,Tag6,Tag7,TagA>
01334         fortran ;
01335 
01336     typedef
01337       Array<Scalar,NaturalOrder,TagA,Tag7,Tag6,Tag5,Tag4,Tag3,Tag2,Tag1>
01338         natural ;
01339 
01340     typedef  fortran  type ;
01341     typedef  natural  reverse ;
01342   };
01343 
01344   enum { Rank = 7 };
01345 
01346   static bool verify( int_t rank , const ArrayDimTag * tags[] )
01347     {
01348       return rank == Rank &&
01349              tags[0] == & Tag1::tag() &&
01350              tags[1] == & Tag2::tag() &&
01351              tags[2] == & Tag3::tag() &&
01352              tags[3] == & Tag4::tag() &&
01353              tags[4] == & Tag5::tag() &&
01354              tags[5] == & Tag6::tag() &&
01355              tags[6] == & Tag7::tag();
01356     }
01357 
01358   static void assign_tags( const ArrayDimTag * tags[] )
01359     {
01360       tags[0] = & Tag1::tag();
01361       tags[1] = & Tag2::tag();
01362       tags[2] = & Tag3::tag();
01363       tags[3] = & Tag4::tag();
01364       tags[4] = & Tag5::tag();
01365       tags[5] = & Tag6::tag();
01366       tags[6] = & Tag7::tag();
01367       tags[7] = NULL ;
01368     }
01369 
01370   template< typename iType >
01371   static void assign( iType * stride )
01372     {
01373       stride[7] = 0 ;
01374       stride[6] = Tag7::Size * (
01375       stride[5] = Tag6::Size * (
01376       stride[4] = Tag5::Size * (
01377       stride[3] = Tag4::Size * (
01378       stride[2] = Tag3::Size * (
01379       stride[1] = Tag2::Size * (
01380       stride[0] = Tag1::Size ))))));
01381     }
01382 
01383   template< typename iType >
01384   static void assign( iType * stride ,
01385                       const iType & n7 )
01386     {
01387       stride[7] = 0 ;
01388       stride[6] = n7 * (
01389       stride[5] = Tag6::Size * (
01390       stride[4] = Tag5::Size * (
01391       stride[3] = Tag4::Size * (
01392       stride[2] = Tag3::Size * (
01393       stride[1] = Tag2::Size * (
01394       stride[0] = Tag1::Size ))))));
01395     }
01396 
01397   template< typename iType >
01398   static void assign( iType * stride ,
01399                       const iType & n6 ,
01400                       const iType & n7 )
01401     {
01402       stride[7] = 0 ;
01403       stride[6] = n7 * (
01404       stride[5] = n6 * (
01405       stride[4] = Tag5::Size * (
01406       stride[3] = Tag4::Size * (
01407       stride[2] = Tag3::Size * (
01408       stride[1] = Tag2::Size * (
01409       stride[0] = Tag1::Size ))))));
01410     }
01411 
01412   template< typename iType >
01413   static void assign( iType * stride ,
01414                       const iType & n5 ,
01415                       const iType & n6 ,
01416                       const iType & n7 )
01417     {
01418       stride[7] = 0 ;
01419       stride[6] = n7 * (
01420       stride[5] = n6 * (
01421       stride[4] = n5 * (
01422       stride[3] = Tag4::Size * (
01423       stride[2] = Tag3::Size * (
01424       stride[1] = Tag2::Size * (
01425       stride[0] = Tag1::Size ))))));
01426     }
01427 
01428   template< typename iType >
01429   static void assign( iType * stride ,
01430                       const iType & n4 ,
01431                       const iType & n5 ,
01432                       const iType & n6 ,
01433                       const iType & n7 )
01434     {
01435       stride[7] = 0 ;
01436       stride[6] = n7 * (
01437       stride[5] = n6 * (
01438       stride[4] = n5 * (
01439       stride[3] = n4 * (
01440       stride[2] = Tag3::Size * (
01441       stride[1] = Tag2::Size * (
01442       stride[0] = Tag1::Size ))))));
01443     }
01444 
01445   template< typename iType >
01446   static void assign( iType * stride ,
01447                       const iType & n3 ,
01448                       const iType & n4 ,
01449                       const iType & n5 ,
01450                       const iType & n6 ,
01451                       const iType & n7 )
01452     {
01453       stride[7] = 0 ;
01454       stride[6] = n7 * (
01455       stride[5] = n6 * (
01456       stride[4] = n5 * (
01457       stride[3] = n4 * (
01458       stride[2] = n3 * (
01459       stride[1] = Tag2::Size * (
01460       stride[0] = Tag1::Size ))))));
01461     }
01462 
01463   template< typename iType >
01464   static void assign( iType * stride ,
01465                       const iType & n2 ,
01466                       const iType & n3 ,
01467                       const iType & n4 ,
01468                       const iType & n5 ,
01469                       const iType & n6 ,
01470                       const iType & n7 )
01471     {
01472       stride[7] = 0 ;
01473       stride[6] = n7 * (
01474       stride[5] = n6 * (
01475       stride[4] = n5 * (
01476       stride[3] = n4 * (
01477       stride[2] = n3 * (
01478       stride[1] = n2 * (
01479       stride[0] = Tag1::Size ))))));
01480     }
01481 
01482   template< typename iType >
01483   static void assign( iType * stride ,
01484                       const iType & n1 ,
01485                       const iType & n2 ,
01486                       const iType & n3 ,
01487                       const iType & n4 ,
01488                       const iType & n5 ,
01489                       const iType & n6 ,
01490                       const iType & n7 )
01491     {
01492       stride[7] = 0 ;
01493       stride[6] = n7 * (
01494       stride[5] = n6 * (
01495       stride[4] = n5 * (
01496       stride[3] = n4 * (
01497       stride[2] = n3 * (
01498       stride[1] = n2 * (
01499       stride[0] = n1 ))))));
01500     }
01501 
01502   template< typename iType >
01503   static void assign( iType * stride ,
01504                       const iType * const dims )
01505     {
01506       stride[7] = 0 ;
01507       stride[6] = dims[6] * (
01508       stride[5] = dims[5] * (
01509       stride[4] = dims[4] * (
01510       stride[3] = dims[3] * (
01511       stride[2] = dims[2] * (
01512       stride[1] = dims[1] * (
01513       stride[0] = dims[0] ))))));
01514    }
01515 };
01516 
01517 //----------------------------------------------------------------------
01520 template< typename Scalar ,
01521           class Tag1 , class Tag2 , class Tag3 , class Tag4 ,
01522           class Tag5 , class Tag6 >
01523 struct Helper<Scalar,NaturalOrder,Tag1,Tag2,Tag3,Tag4,Tag5,Tag6,void,void>
01524 {
01525   typedef
01526     Array<Scalar,FortranOrder,Tag6,Tag5,Tag4,Tag3,Tag2,Tag1,void,void>
01527       reverse ;
01528 
01529   typedef
01530     Array<Scalar,NaturalOrder,Tag2,Tag3,Tag4,Tag5,Tag6,void,void,void>
01531       truncate ;
01532 
01533   template< class TagA >
01534   struct append {
01535     typedef
01536       Array<Scalar,NaturalOrder,TagA,Tag1,Tag2,Tag3,Tag4,Tag5,Tag6,void>
01537         natural ;
01538 
01539     typedef
01540       Array<Scalar,FortranOrder,Tag6,Tag5,Tag4,Tag3,Tag2,Tag1,TagA,void>
01541         fortran ;
01542 
01543     typedef  natural  type ;
01544     typedef  fortran  reverse ;
01545   };
01546 
01547   enum { Rank = 6 };
01548 
01549   static bool verify( int_t rank , const ArrayDimTag * tags[] )
01550     {
01551       return rank == Rank &&
01552              tags[0] == & Tag6::tag() &&
01553              tags[1] == & Tag5::tag() &&
01554              tags[2] == & Tag4::tag() &&
01555              tags[3] == & Tag3::tag() &&
01556              tags[4] == & Tag2::tag() &&
01557              tags[5] == & Tag1::tag();
01558     }
01559 
01560   static void assign_tags( const ArrayDimTag * tags[] )
01561     {
01562       tags[0] = & Tag6::tag();
01563       tags[1] = & Tag5::tag();
01564       tags[2] = & Tag4::tag();
01565       tags[3] = & Tag3::tag();
01566       tags[4] = & Tag2::tag();
01567       tags[5] = & Tag1::tag();
01568       tags[6] = NULL ;
01569       tags[7] = NULL ;
01570     }
01571 
01572   template< typename iType >
01573   static void assign( iType * stride )
01574     {
01575       stride[7] = 0 ;
01576       stride[6] = 0 ;
01577       stride[5] = Tag1::Size * (
01578       stride[4] = Tag2::Size * (
01579       stride[3] = Tag3::Size * (
01580       stride[2] = Tag4::Size * (
01581       stride[1] = Tag5::Size * (
01582       stride[0] = Tag6::Size )))));
01583     }
01584 
01585   template< typename iType >
01586   static void assign( iType * stride ,
01587                       const iType & n1 )
01588     {
01589       stride[7] = 0 ;
01590       stride[6] = 0 ;
01591       stride[5] = n1 * (
01592       stride[4] = Tag2::Size * (
01593       stride[3] = Tag3::Size * (
01594       stride[2] = Tag4::Size * (
01595       stride[1] = Tag5::Size * (
01596       stride[0] = Tag6::Size )))));
01597     }
01598 
01599   template< typename iType >
01600   static void assign( iType * stride ,
01601                       const iType & n1 ,
01602                       const iType & n2 )
01603     {
01604       stride[7] = 0 ;
01605       stride[6] = 0 ;
01606       stride[5] = n1 * (
01607       stride[4] = n2 * (
01608       stride[3] = Tag3::Size * (
01609       stride[2] = Tag4::Size * (
01610       stride[1] = Tag5::Size * (
01611       stride[0] = Tag6::Size )))));
01612     }
01613 
01614   template< typename iType >
01615   static void assign( iType * stride ,
01616                       const iType & n1 ,
01617                       const iType & n2 ,
01618                       const iType & n3 )
01619     {
01620       stride[7] = 0 ;
01621       stride[6] = 0 ;
01622       stride[5] = n1 * (
01623       stride[4] = n2 * (
01624       stride[3] = n3 * (
01625       stride[2] = Tag4::Size * (
01626       stride[1] = Tag5::Size * (
01627       stride[0] = Tag6::Size )))));
01628     }
01629 
01630   template< typename iType >
01631   static void assign( iType * stride ,
01632                       const iType & n1 ,
01633                       const iType & n2 ,
01634                       const iType & n3 ,
01635                       const iType & n4 )
01636     {
01637       stride[7] = 0 ;
01638       stride[6] = 0 ;
01639       stride[5] = n1 * (
01640       stride[4] = n2 * (
01641       stride[3] = n3 * (
01642       stride[2] = n4 * (
01643       stride[1] = Tag5::Size * (
01644       stride[0] = Tag6::Size )))));
01645     }
01646 
01647   template< typename iType >
01648   static void assign( iType * stride ,
01649                       const iType & n1 ,
01650                       const iType & n2 ,
01651                       const iType & n3 ,
01652                       const iType & n4 ,
01653                       const iType & n5 )
01654     {
01655       stride[7] = 0 ;
01656       stride[6] = 0 ;
01657       stride[5] = n1 * (
01658       stride[4] = n2 * (
01659       stride[3] = n3 * (
01660       stride[2] = n4 * (
01661       stride[1] = n5 * (
01662       stride[0] = Tag6::Size )))));
01663     }
01664 
01665   template< typename iType >
01666   static void assign( iType * stride ,
01667                       const iType & n1 ,
01668                       const iType & n2 ,
01669                       const iType & n3 ,
01670                       const iType & n4 ,
01671                       const iType & n5 ,
01672                       const iType & n6 )
01673     {
01674       stride[7] = 0 ;
01675       stride[6] = 0 ;
01676       stride[5] = n1 * (
01677       stride[4] = n2 * (
01678       stride[3] = n3 * (
01679       stride[2] = n4 * (
01680       stride[1] = n5 * (
01681       stride[0] = n6 )))));
01682     }
01683 
01684   template< typename iType >
01685   static void assign( iType * stride ,
01686                       const iType * const dims )
01687     {
01688       stride[7] = 0 ;
01689       stride[6] = 0 ;
01690       stride[5] = dims[0] * (
01691       stride[4] = dims[1] * (
01692       stride[3] = dims[2] * (
01693       stride[2] = dims[3] * (
01694       stride[1] = dims[4] * (
01695       stride[0] = dims[5] )))));
01696     }
01697 };
01698 
01699 template< typename Scalar ,
01700           class Tag1 , class Tag2 , class Tag3 , class Tag4 ,
01701           class Tag5 , class Tag6 >
01702 struct Helper<Scalar,FortranOrder,Tag1,Tag2,Tag3,Tag4,Tag5,Tag6,void,void>
01703 {
01704   typedef
01705     Array<Scalar,NaturalOrder,Tag6,Tag5,Tag4,Tag3,Tag2,Tag1,void,void>
01706       reverse ;
01707 
01708   typedef
01709     Array<Scalar,FortranOrder,Tag1,Tag2,Tag3,Tag4,Tag5,void,void,void>
01710       truncate ;
01711 
01712   template< class TagA >
01713   struct append {
01714     typedef
01715       Array<Scalar,FortranOrder,Tag1,Tag2,Tag3,Tag4,Tag5,Tag6,TagA,void>
01716         fortran ;
01717 
01718     typedef
01719       Array<Scalar,NaturalOrder,TagA,Tag6,Tag5,Tag4,Tag3,Tag2,Tag1,void>
01720         natural ;
01721 
01722     typedef  fortran  type ;
01723     typedef  natural  reverse ;
01724   };
01725 
01726   enum { Rank = 6 };
01727 
01728   static bool verify( int_t rank , const ArrayDimTag * tags[] )
01729     {
01730       return rank == Rank &&
01731              tags[0] == & Tag1::tag() &&
01732              tags[1] == & Tag2::tag() &&
01733              tags[2] == & Tag3::tag() &&
01734              tags[3] == & Tag4::tag() &&
01735              tags[4] == & Tag5::tag() &&
01736              tags[5] == & Tag6::tag();
01737     }
01738 
01739   static void assign_tags( const ArrayDimTag * tags[] )
01740     {
01741       tags[0] = & Tag1::tag();
01742       tags[1] = & Tag2::tag();
01743       tags[2] = & Tag3::tag();
01744       tags[3] = & Tag4::tag();
01745       tags[4] = & Tag5::tag();
01746       tags[5] = & Tag6::tag();
01747       tags[6] = NULL ;
01748       tags[7] = NULL ;
01749     }
01750 
01751   template< typename iType >
01752   static void assign( iType * stride )
01753     {
01754       stride[7] = 0 ;
01755       stride[6] = 0 ;
01756       stride[5] = Tag6::Size * (
01757       stride[4] = Tag5::Size * (
01758       stride[3] = Tag4::Size * (
01759       stride[2] = Tag3::Size * (
01760       stride[1] = Tag2::Size * (
01761       stride[0] = Tag1::Size )))));
01762     }
01763 
01764   template< typename iType >
01765   static void assign( iType * stride ,
01766                       const iType & n6 )
01767     {
01768       stride[7] = 0 ;
01769       stride[6] = 0 ;
01770       stride[5] = n6 * (
01771       stride[4] = Tag5::Size * (
01772       stride[3] = Tag4::Size * (
01773       stride[2] = Tag3::Size * (
01774       stride[1] = Tag2::Size * (
01775       stride[0] = Tag1::Size )))));
01776     }
01777 
01778   template< typename iType >
01779   static void assign( iType * stride ,
01780                       const iType & n5 ,
01781                       const iType & n6 )
01782     {
01783       stride[7] = 0 ;
01784       stride[6] = 0 ;
01785       stride[5] = n6 * (
01786       stride[4] = n5 * (
01787       stride[3] = Tag4::Size * (
01788       stride[2] = Tag3::Size * (
01789       stride[1] = Tag2::Size * (
01790       stride[0] = Tag1::Size )))));
01791     }
01792 
01793   template< typename iType >
01794   static void assign( iType * stride ,
01795                       const iType & n4 ,
01796                       const iType & n5 ,
01797                       const iType & n6 )
01798     {
01799       stride[7] = 0 ;
01800       stride[6] = 0 ;
01801       stride[5] = n6 * (
01802       stride[4] = n5 * (
01803       stride[3] = n4 * (
01804       stride[2] = Tag3::Size * (
01805       stride[1] = Tag2::Size * (
01806       stride[0] = Tag1::Size )))));
01807     }
01808 
01809   template< typename iType >
01810   static void assign( iType * stride ,
01811                       const iType & n3 ,
01812                       const iType & n4 ,
01813                       const iType & n5 ,
01814                       const iType & n6 )
01815     {
01816       stride[7] = 0 ;
01817       stride[6] = 0 ;
01818       stride[5] = n6 * (
01819       stride[4] = n5 * (
01820       stride[3] = n4 * (
01821       stride[2] = n3 * (
01822       stride[1] = Tag2::Size * (
01823       stride[0] = Tag1::Size )))));
01824     }
01825 
01826   template< typename iType >
01827   static void assign( iType * stride ,
01828                       const iType & n2 ,
01829                       const iType & n3 ,
01830                       const iType & n4 ,
01831                       const iType & n5 ,
01832                       const iType & n6 )
01833     {
01834       stride[7] = 0 ;
01835       stride[6] = 0 ;
01836       stride[5] = n6 * (
01837       stride[4] = n5 * (
01838       stride[3] = n4 * (
01839       stride[2] = n3 * (
01840       stride[1] = n2 * (
01841       stride[0] = Tag1::Size )))));
01842     }
01843 
01844   template< typename iType >
01845   static void assign( iType * stride ,
01846                       const iType & n1 ,
01847                       const iType & n2 ,
01848                       const iType & n3 ,
01849                       const iType & n4 ,
01850                       const iType & n5 ,
01851                       const iType & n6 )
01852     {
01853       stride[7] = 0 ;
01854       stride[6] = 0 ;
01855       stride[5] = n6 * (
01856       stride[4] = n5 * (
01857       stride[3] = n4 * (
01858       stride[2] = n3 * (
01859       stride[1] = n2 * (
01860       stride[0] = n1 )))));
01861     }
01862 
01863   template< typename iType >
01864   static void assign( iType * stride ,
01865                       const iType * const dims )
01866     {
01867       stride[7] = 0 ;
01868       stride[6] = 0 ;
01869       stride[5] = dims[5] * (
01870       stride[4] = dims[4] * (
01871       stride[3] = dims[3] * (
01872       stride[2] = dims[2] * (
01873       stride[1] = dims[1] * (
01874       stride[0] = dims[0] )))));
01875    }
01876 };
01877 
01878 //----------------------------------------------------------------------
01881 template< typename Scalar ,
01882           class Tag1 , class Tag2 , class Tag3 , class Tag4 , class Tag5 >
01883 struct Helper<Scalar,NaturalOrder,Tag1,Tag2,Tag3,Tag4,Tag5,void,void,void>
01884 {
01885   typedef
01886     Array<Scalar,FortranOrder,Tag5,Tag4,Tag3,Tag2,Tag1,void,void,void>
01887       reverse ;
01888 
01889   typedef
01890     Array<Scalar,NaturalOrder,Tag2,Tag3,Tag4,Tag5,void,void,void,void>
01891       truncate ;
01892 
01893   template< class TagA >
01894   struct append {
01895     typedef
01896       Array<Scalar,NaturalOrder,TagA,Tag1,Tag2,Tag3,Tag4,Tag5,void,void>
01897         natural ;
01898 
01899     typedef
01900       Array<Scalar,FortranOrder,Tag5,Tag4,Tag3,Tag2,Tag1,TagA,void,void>
01901         fortran ;
01902 
01903     typedef  natural  type ;
01904     typedef  fortran  reverse ;
01905   };
01906 
01907   enum { Rank = 5 };
01908 
01909   static bool verify( int_t rank , const ArrayDimTag * tags[] )
01910     {
01911       return rank == Rank &&
01912              tags[0] == & Tag5::tag() &&
01913              tags[1] == & Tag4::tag() &&
01914              tags[2] == & Tag3::tag() &&
01915              tags[3] == & Tag2::tag() &&
01916              tags[4] == & Tag1::tag();
01917     }
01918 
01919   static void assign_tags( const ArrayDimTag * tags[] )
01920     {
01921       tags[0] = & Tag5::tag();
01922       tags[1] = & Tag4::tag();
01923       tags[2] = & Tag3::tag();
01924       tags[3] = & Tag2::tag();
01925       tags[4] = & Tag1::tag();
01926       tags[5] = NULL ;
01927       tags[6] = NULL ;
01928       tags[7] = NULL ;
01929     }
01930 
01931   template< typename iType >
01932   static void assign( iType * stride )
01933     {
01934       stride[7] = 0 ;
01935       stride[6] = 0 ;
01936       stride[5] = 0 ;
01937       stride[4] = Tag1::Size * (
01938       stride[3] = Tag2::Size * (
01939       stride[2] = Tag3::Size * (
01940       stride[1] = Tag4::Size * (
01941       stride[0] = Tag5::Size ))));
01942     }
01943 
01944   template< typename iType >
01945   static void assign( iType * stride ,
01946                       const iType & n1 )
01947     {
01948       stride[7] = 0 ;
01949       stride[6] = 0 ;
01950       stride[5] = 0 ;
01951       stride[4] = n1 * (
01952       stride[3] = Tag2::Size * (
01953       stride[2] = Tag3::Size * (
01954       stride[1] = Tag4::Size * (
01955       stride[0] = Tag5::Size ))));
01956     }
01957 
01958   template< typename iType >
01959   static void assign( iType * stride ,
01960                       const iType & n1 ,
01961                       const iType & n2 )
01962     {
01963       stride[7] = 0 ;
01964       stride[6] = 0 ;
01965       stride[5] = 0 ;
01966       stride[4] = n1 * (
01967       stride[3] = n2 * (
01968       stride[2] = Tag3::Size * (
01969       stride[1] = Tag4::Size * (
01970       stride[0] = Tag5::Size ))));
01971     }
01972 
01973   template< typename iType >
01974   static void assign( iType * stride ,
01975                       const iType & n1 ,
01976                       const iType & n2 ,
01977                       const iType & n3 )
01978     {
01979       stride[7] = 0 ;
01980       stride[6] = 0 ;
01981       stride[5] = 0 ;
01982       stride[4] = n1 * (
01983       stride[3] = n2 * (
01984       stride[2] = n3 * (
01985       stride[1] = Tag4::Size * (
01986       stride[0] = Tag5::Size ))));
01987     }
01988 
01989   template< typename iType >
01990   static void assign( iType * stride ,
01991                       const iType & n1 ,
01992                       const iType & n2 ,
01993                       const iType & n3 ,
01994                       const iType & n4 )
01995     {
01996       stride[7] = 0 ;
01997       stride[6] = 0 ;
01998       stride[5] = 0 ;
01999       stride[4] = n1 * (
02000       stride[3] = n2 * (
02001       stride[2] = n3 * (
02002       stride[1] = n4 * (
02003       stride[0] = Tag5::Size ))));
02004     }
02005 
02006   template< typename iType >
02007   static void assign( iType * stride ,
02008                       const iType & n1 ,
02009                       const iType & n2 ,
02010                       const iType & n3 ,
02011                       const iType & n4 ,
02012                       const iType & n5 )
02013     {
02014       stride[7] = 0 ;
02015       stride[6] = 0 ;
02016       stride[5] = 0 ;
02017       stride[4] = n1 * (
02018       stride[3] = n2 * (
02019       stride[2] = n3 * (
02020       stride[1] = n4 * (
02021       stride[0] = n5 ))));
02022     }
02023 
02024   template< typename iType >
02025   static void assign( iType * stride ,
02026                       const iType * const dims )
02027     {
02028       stride[7] = 0 ;
02029       stride[6] = 0 ;
02030       stride[5] = 0 ;
02031       stride[4] = dims[0] * (
02032       stride[3] = dims[1] * (
02033       stride[2] = dims[2] * (
02034       stride[1] = dims[3] * (
02035       stride[0] = dims[4] ))));
02036     }
02037 };
02038 
02039 template< typename Scalar ,
02040           class Tag1 , class Tag2 , class Tag3 , class Tag4 , class Tag5 >
02041 struct Helper<Scalar,FortranOrder,Tag1,Tag2,Tag3,Tag4,Tag5,void,void,void>
02042 {
02043   typedef
02044     Array<Scalar,NaturalOrder,Tag5,Tag4,Tag3,Tag2,Tag1,void,void,void>
02045       reverse ;
02046 
02047   typedef
02048     Array<Scalar,FortranOrder,Tag1,Tag2,Tag3,Tag4,void,void,void,void>
02049       truncate ;
02050 
02051   template< class TagA >
02052   struct append {
02053     typedef
02054       Array<Scalar,FortranOrder,Tag1,Tag2,Tag3,Tag4,Tag5,TagA,void,void>
02055         fortran ;
02056 
02057     typedef
02058       Array<Scalar,NaturalOrder,TagA,Tag5,Tag4,Tag3,Tag2,Tag1,void,void>
02059         natural ;
02060 
02061     typedef  fortran  type ;
02062     typedef  natural  reverse ;
02063   };
02064 
02065   enum { Rank = 5 };
02066 
02067   static bool verify( int_t rank , const ArrayDimTag * tags[] )
02068     {
02069       return rank == Rank &&
02070              tags[0] == & Tag1::tag() &&
02071              tags[1] == & Tag2::tag() &&
02072              tags[2] == & Tag3::tag() &&
02073              tags[3] == & Tag4::tag() &&
02074              tags[4] == & Tag5::tag();
02075     }
02076 
02077   static void assign_tags( const ArrayDimTag * tags[] )
02078     {
02079       tags[0] = & Tag1::tag();
02080       tags[1] = & Tag2::tag();
02081       tags[2] = & Tag3::tag();
02082       tags[3] = & Tag4::tag();
02083       tags[4] = & Tag5::tag();
02084       tags[5] = NULL ;
02085       tags[6] = NULL ;
02086       tags[7] = NULL ;
02087     }
02088 
02089   template< typename iType >
02090   static void assign( iType * stride )
02091     {
02092       stride[7] = 0 ;
02093       stride[6] = 0 ;
02094       stride[5] = 0 ;
02095       stride[4] = Tag5::Size * (
02096       stride[3] = Tag4::Size * (
02097       stride[2] = Tag3::Size * (
02098       stride[1] = Tag2::Size * (
02099       stride[0] = Tag1::Size ))));
02100     }
02101 
02102   template< typename iType >
02103   static void assign( iType * stride ,
02104                       const iType & n5 )
02105     {
02106       stride[7] = 0 ;
02107       stride[6] = 0 ;
02108       stride[5] = 0 ;
02109       stride[4] = n5 * (
02110       stride[3] = Tag4::Size * (
02111       stride[2] = Tag3::Size * (
02112       stride[1] = Tag2::Size * (
02113       stride[0] = Tag1::Size ))));
02114     }
02115 
02116   template< typename iType >
02117   static void assign( iType * stride ,
02118                       const iType & n4 ,
02119                       const iType & n5 )
02120     {
02121       stride[7] = 0 ;
02122       stride[6] = 0 ;
02123       stride[5] = 0 ;
02124       stride[4] = n5 * (
02125       stride[3] = n4 * (
02126       stride[2] = Tag3::Size * (
02127       stride[1] = Tag2::Size * (
02128       stride[0] = Tag1::Size ))));
02129     }
02130 
02131   template< typename iType >
02132   static void assign( iType * stride ,
02133                       const iType & n3 ,
02134                       const iType & n4 ,
02135                       const iType & n5 )
02136     {
02137       stride[7] = 0 ;
02138       stride[6] = 0 ;
02139       stride[5] = 0 ;
02140       stride[4] = n5 * (
02141       stride[3] = n4 * (
02142       stride[2] = n3 * (
02143       stride[1] = Tag2::Size * (
02144       stride[0] = Tag1::Size ))));
02145     }
02146 
02147   template< typename iType >
02148   static void assign( iType * stride ,
02149                       const iType & n2 ,
02150                       const iType & n3 ,
02151                       const iType & n4 ,
02152                       const iType & n5 )
02153     {
02154       stride[7] = 0 ;
02155       stride[6] = 0 ;
02156       stride[5] = 0 ;
02157       stride[4] = n5 * (
02158       stride[3] = n4 * (
02159       stride[2] = n3 * (
02160       stride[1] = n2 * (
02161       stride[0] = Tag1::Size ))));
02162     }
02163 
02164   template< typename iType >
02165   static void assign( iType * stride ,
02166                       const iType & n1 ,
02167                       const iType & n2 ,
02168                       const iType & n3 ,
02169                       const iType & n4 ,
02170                       const iType & n5 )
02171     {
02172       stride[7] = 0 ;
02173       stride[6] = 0 ;
02174       stride[5] = 0 ;
02175       stride[4] = n5 * (
02176       stride[3] = n4 * (
02177       stride[2] = n3 * (
02178       stride[1] = n2 * (
02179       stride[0] = n1 ))));
02180     }
02181 
02182   template< typename iType >
02183   static void assign( iType * stride ,
02184                       const iType * const dims )
02185     {
02186       stride[7] = 0 ;
02187       stride[6] = 0 ;
02188       stride[5] = 0 ;
02189       stride[4] = dims[4] * (
02190       stride[3] = dims[3] * (
02191       stride[2] = dims[2] * (
02192       stride[1] = dims[1] * (
02193       stride[0] = dims[0] ))));
02194    }
02195 };
02196 
02197 //----------------------------------------------------------------------
02200 template< typename Scalar , class Tag1 , class Tag2 , class Tag3 , class Tag4 >
02201 struct Helper<Scalar,NaturalOrder,Tag1,Tag2,Tag3,Tag4,void,void,void,void>
02202 {
02203   typedef
02204     Array<Scalar,FortranOrder,Tag4,Tag3,Tag2,Tag1,void,void,void,void>
02205       reverse ;
02206 
02207   typedef
02208     Array<Scalar,NaturalOrder,Tag2,Tag3,Tag4,void,void,void,void,void>
02209       truncate ;
02210 
02211   template< class TagA >
02212   struct append {
02213     typedef
02214       Array<Scalar,NaturalOrder,TagA,Tag1,Tag2,Tag3,Tag4,void,void,void>
02215         natural ;
02216 
02217     typedef
02218       Array<Scalar,FortranOrder,Tag4,Tag3,Tag2,Tag1,TagA,void,void,void>
02219         fortran ;
02220 
02221     typedef  natural  type ;
02222     typedef  fortran  reverse ;
02223   };
02224 
02225   enum { Rank = 4 };
02226 
02227   static bool verify( int_t rank , const ArrayDimTag * tags[] )
02228     {
02229       return rank == Rank &&
02230              tags[0] == & Tag4::tag() &&
02231              tags[1] == & Tag3::tag() &&
02232              tags[2] == & Tag2::tag() &&
02233              tags[3] == & Tag1::tag();
02234     }
02235 
02236   static void assign_tags( const ArrayDimTag * tags[] )
02237     {
02238       tags[0] = & Tag4::tag();
02239       tags[1] = & Tag3::tag();
02240       tags[2] = & Tag2::tag();
02241       tags[3] = & Tag1::tag();
02242       tags[4] = NULL ;
02243       tags[5] = NULL ;
02244       tags[6] = NULL ;
02245       tags[7] = NULL ;
02246     }
02247 
02248   template< typename iType >
02249   static void assign( iType * stride )
02250     {
02251       stride[7] = 0 ;
02252       stride[6] = 0 ;
02253       stride[5] = 0 ;
02254       stride[4] = 0 ;
02255       stride[3] = Tag1::Size * (
02256       stride[2] = Tag2::Size * (
02257       stride[1] = Tag3::Size * (
02258       stride[0] = Tag4::Size )));
02259     }
02260 
02261   template< typename iType >
02262   static void assign( iType * stride ,
02263                       const iType & n1 )
02264     {
02265       stride[7] = 0 ;
02266       stride[6] = 0 ;
02267       stride[5] = 0 ;
02268       stride[4] = 0 ;
02269       stride[3] = n1 * (
02270       stride[2] = Tag2::Size * (
02271       stride[1] = Tag3::Size * (
02272       stride[0] = Tag4::Size )));
02273     }
02274 
02275   template< typename iType >
02276   static void assign( iType * stride ,
02277                       const iType & n1 ,
02278                       const iType & n2 )
02279     {
02280       stride[7] = 0 ;
02281       stride[6] = 0 ;
02282       stride[5] = 0 ;
02283       stride[4] = 0 ;
02284       stride[3] = n1 * (
02285       stride[2] = n2 * (
02286       stride[1] = Tag3::Size * (
02287       stride[0] = Tag4::Size )));
02288     }
02289 
02290   template< typename iType >
02291   static void assign( iType * stride ,
02292                       const iType & n1 ,
02293                       const iType & n2 ,
02294                       const iType & n3 )
02295     {
02296       stride[7] = 0 ;
02297       stride[6] = 0 ;
02298       stride[5] = 0 ;
02299       stride[4] = 0 ;
02300       stride[3] = n1 * (
02301       stride[2] = n2 * (
02302       stride[1] = n3 * (
02303       stride[0] = Tag4::Size )));
02304     }
02305 
02306   template< typename iType >
02307   static void assign( iType * stride ,
02308                       const iType & n1 ,
02309                       const iType & n2 ,
02310                       const iType & n3 ,
02311                       const iType & n4 )
02312     {
02313       stride[7] = 0 ;
02314       stride[6] = 0 ;
02315       stride[5] = 0 ;
02316       stride[4] = 0 ;
02317       stride[3] = n1 * (
02318       stride[2] = n2 * (
02319       stride[1] = n3 * (
02320       stride[0] = n4 )));
02321     }
02322 
02323   template< typename iType >
02324   static void assign( iType * stride ,
02325                       const iType * const dims )
02326     {
02327       stride[7] = 0 ;
02328       stride[6] = 0 ;
02329       stride[5] = 0 ;
02330       stride[4] = 0 ;
02331       stride[3] = dims[0] * (
02332       stride[2] = dims[1] * (
02333       stride[1] = dims[2] * (
02334       stride[0] = dims[3] )));
02335     }
02336 };
02337 
02338 template< typename Scalar , class Tag1 , class Tag2 , class Tag3 , class Tag4 >
02339 struct Helper<Scalar,FortranOrder,Tag1,Tag2,Tag3,Tag4,void,void,void,void>
02340 {
02341   typedef
02342     Array<Scalar,NaturalOrder,Tag4,Tag3,Tag2,Tag1,void,void,void,void>
02343       reverse ;
02344 
02345   typedef
02346     Array<Scalar,FortranOrder,Tag1,Tag2,Tag3,void,void,void,void,void>
02347       truncate ;
02348 
02349   template< class TagA >
02350   struct append {
02351     typedef
02352       Array<Scalar,FortranOrder,Tag1,Tag2,Tag3,Tag4,TagA,void,void,void>
02353         fortran ;
02354 
02355     typedef
02356       Array<Scalar,NaturalOrder,TagA,Tag4,Tag3,Tag2,Tag1,void,void,void>
02357         natural ;
02358 
02359     typedef  fortran  type ;
02360     typedef  natural  reverse ;
02361   };
02362 
02363   enum { Rank = 4 };
02364 
02365   static bool verify( int_t rank , const ArrayDimTag * tags[] )
02366     {
02367       return rank == Rank &&
02368              tags[0] == & Tag1::tag() &&
02369              tags[1] == & Tag2::tag() &&
02370              tags[2] == & Tag3::tag() &&
02371              tags[3] == & Tag4::tag();
02372     }
02373 
02374   static void assign_tags( const ArrayDimTag * tags[] )
02375     {
02376       tags[0] = & Tag1::tag();
02377       tags[1] = & Tag2::tag();
02378       tags[2] = & Tag3::tag();
02379       tags[3] = & Tag4::tag();
02380       tags[4] = NULL ;
02381       tags[5] = NULL ;
02382       tags[6] = NULL ;
02383       tags[7] = NULL ;
02384     }
02385 
02386   template< typename iType >
02387   static void assign( iType * stride )
02388     {
02389       stride[7] = 0 ;
02390       stride[6] = 0 ;
02391       stride[5] = 0 ;
02392       stride[4] = 0 ;
02393       stride[3] = Tag4::Size * (
02394       stride[2] = Tag3::Size * (
02395       stride[1] = Tag2::Size * (
02396       stride[0] = Tag1::Size )));
02397     }
02398 
02399   template< typename iType >
02400   static void assign( iType * stride ,
02401                       const iType & n4 )
02402     {
02403       stride[7] = 0 ;
02404       stride[6] = 0 ;
02405       stride[5] = 0 ;
02406       stride[4] = 0 ;
02407       stride[3] = n4 * (
02408       stride[2] = Tag3::Size * (
02409       stride[1] = Tag2::Size * (
02410       stride[0] = Tag1::Size )));
02411     }
02412 
02413   template< typename iType >
02414   static void assign( iType * stride ,
02415                       const iType & n3 ,
02416                       const iType & n4 )
02417     {
02418       stride[7] = 0 ;
02419       stride[6] = 0 ;
02420       stride[5] = 0 ;
02421       stride[4] = 0 ;
02422       stride[3] = n4 * (
02423       stride[2] = n3 * (
02424       stride[1] = Tag2::Size * (
02425       stride[0] = Tag1::Size )));
02426     }
02427 
02428   template< typename iType >
02429   static void assign( iType * stride ,
02430                       const iType & n2 ,
02431                       const iType & n3 ,
02432                       const iType & n4 )
02433     {
02434       stride[7] = 0 ;
02435       stride[6] = 0 ;
02436       stride[5] = 0 ;
02437       stride[4] = 0 ;
02438       stride[3] = n4 * (
02439       stride[2] = n3 * (
02440       stride[1] = n2 * (
02441       stride[0] = Tag1::Size )));
02442     }
02443 
02444   template< typename iType >
02445   static void assign( iType * stride ,
02446                       const iType & n1 ,
02447                       const iType & n2 ,
02448                       const iType & n3 ,
02449                       const iType & n4 )
02450     {
02451       stride[7] = 0 ;
02452       stride[6] = 0 ;
02453       stride[5] = 0 ;
02454       stride[4] = 0 ;
02455       stride[3] = n4 * (
02456       stride[2] = n3 * (
02457       stride[1] = n2 * (
02458       stride[0] = n1 )));
02459     }
02460 
02461   template< typename iType >
02462   static void assign( iType * stride ,
02463                       const iType * const dims )
02464     {
02465       stride[7] = 0 ;
02466       stride[6] = 0 ;
02467       stride[5] = 0 ;
02468       stride[4] = 0 ;
02469       stride[3] = dims[3] * (
02470       stride[2] = dims[2] * (
02471       stride[1] = dims[1] * (
02472       stride[0] = dims[0] )));
02473    }
02474 };
02475 
02476 //----------------------------------------------------------------------
02479 template< typename Scalar , class Tag1 , class Tag2 , class Tag3 >
02480 struct Helper<Scalar,NaturalOrder,Tag1,Tag2,Tag3,void,void,void,void,void>
02481 {
02482   typedef
02483     Array<Scalar,FortranOrder,Tag3,Tag2,Tag1,void,void,void,void,void>
02484       reverse ;
02485 
02486   typedef
02487     Array<Scalar,NaturalOrder,Tag2,Tag3,void,void,void,void,void,void>
02488       truncate ;
02489 
02490   template< class TagA >
02491   struct append {
02492     typedef
02493       Array<Scalar,NaturalOrder,TagA,Tag1,Tag2,Tag3,void,void,void,void>
02494         natural ;
02495 
02496     typedef
02497       Array<Scalar,FortranOrder,Tag3,Tag2,Tag1,TagA,void,void,void,void>
02498         fortran ;
02499 
02500     typedef  natural  type ;
02501     typedef  fortran  reverse ;
02502   };
02503 
02504   enum { Rank = 3 };
02505 
02506   static bool verify( int_t rank , const ArrayDimTag * tags[] )
02507     {
02508       return rank == Rank &&
02509              tags[0] == & Tag3::tag() &&
02510              tags[1] == & Tag2::tag() &&
02511              tags[2] == & Tag1::tag();
02512     }
02513 
02514   static void assign_tags( const ArrayDimTag * tags[] )
02515     {
02516       tags[0] = & Tag3::tag();
02517       tags[1] = & Tag2::tag();
02518       tags[2] = & Tag1::tag();
02519       tags[3] = NULL ;
02520       tags[4] = NULL ;
02521       tags[5] = NULL ;
02522       tags[6] = NULL ;
02523       tags[7] = NULL ;
02524     }
02525 
02526   template< typename iType >
02527   static void assign( iType * stride )
02528     {
02529       stride[7] = 0 ;
02530       stride[6] = 0 ;
02531       stride[5] = 0 ;
02532       stride[4] = 0 ;
02533       stride[3] = 0 ;
02534       stride[2] = Tag1::Size * (
02535       stride[1] = Tag2::Size * (
02536       stride[0] = Tag3::Size ));
02537     }
02538 
02539   template< typename iType >
02540   static void assign( iType * stride ,
02541                       const iType & n1 )
02542     {
02543       stride[7] = 0 ;
02544       stride[6] = 0 ;
02545       stride[5] = 0 ;
02546       stride[4] = 0 ;
02547       stride[3] = 0 ;
02548       stride[2] = n1 * (
02549       stride[1] = Tag2::Size * (
02550       stride[0] = Tag3::Size ));
02551     }
02552 
02553   template< typename iType >
02554   static void assign( iType * stride ,
02555                       const iType & n1 ,
02556                       const iType & n2 )
02557     {
02558       stride[7] = 0 ;
02559       stride[6] = 0 ;
02560       stride[5] = 0 ;
02561       stride[4] = 0 ;
02562       stride[3] = 0 ;
02563       stride[2] = n1 * (
02564       stride[1] = n2 * (
02565       stride[0] = Tag3::Size ));
02566     }
02567 
02568   template< typename iType >
02569   static void assign( iType * stride ,
02570                       const iType & n1 ,
02571                       const iType & n2 ,
02572                       const iType & n3 )
02573     {
02574       stride[7] = 0 ;
02575       stride[6] = 0 ;
02576       stride[5] = 0 ;
02577       stride[4] = 0 ;
02578       stride[3] = 0 ;
02579       stride[2] = n1 * (
02580       stride[1] = n2 * (
02581       stride[0] = n3 ));
02582     }
02583 
02584   template< typename iType >
02585   static void assign( iType * stride ,
02586                       const iType * const dims )
02587     {
02588       stride[7] = 0 ;
02589       stride[6] = 0 ;
02590       stride[5] = 0 ;
02591       stride[4] = 0 ;
02592       stride[3] = 0 ;
02593       stride[2] = dims[0] * (
02594       stride[1] = dims[1] * (
02595       stride[0] = dims[2] ));
02596     }
02597 };
02598 
02599 template< typename Scalar , class Tag1 , class Tag2 , class Tag3 >
02600 struct Helper<Scalar,FortranOrder,Tag1,Tag2,Tag3,void,void,void,void,void>
02601 {
02602   typedef
02603     Array<Scalar,NaturalOrder,Tag3,Tag2,Tag1,void,void,void,void,void>
02604       reverse ;
02605 
02606   typedef
02607     Array<Scalar,FortranOrder,Tag1,Tag2,void,void,void,void,void,void>
02608       truncate ;
02609 
02610   template< class TagA >
02611   struct append {
02612     typedef
02613       Array<Scalar,FortranOrder,Tag1,Tag2,Tag3,TagA,void,void,void,void>
02614         fortran ;
02615 
02616     typedef
02617       Array<Scalar,NaturalOrder,TagA,Tag3,Tag2,Tag1,void,void,void,void>
02618         natural ;
02619 
02620     typedef  fortran  type ;
02621     typedef  natural  reverse ;
02622   };
02623 
02624   enum { Rank = 3 };
02625 
02626   static bool verify( int_t rank , const ArrayDimTag * tags[] )
02627     {
02628       return rank == Rank &&
02629              tags[0] == & Tag1::tag() &&
02630              tags[1] == & Tag2::tag() &&
02631              tags[2] == & Tag3::tag();
02632     }
02633 
02634   static void assign_tags( const ArrayDimTag * tags[] )
02635     {
02636       tags[0] = & Tag1::tag();
02637       tags[1] = & Tag2::tag();
02638       tags[2] = & Tag3::tag();
02639       tags[3] = NULL ;
02640       tags[4] = NULL ;
02641       tags[5] = NULL ;
02642       tags[6] = NULL ;
02643       tags[7] = NULL ;
02644     }
02645 
02646   template< typename iType >
02647   static void assign( iType * stride )
02648     {
02649       stride[7] = 0 ;
02650       stride[6] = 0 ;
02651       stride[5] = 0 ;
02652       stride[4] = 0 ;
02653       stride[3] = 0 ;
02654       stride[2] = Tag3::Size * (
02655       stride[1] = Tag2::Size * (
02656       stride[0] = Tag1::Size ));
02657     }
02658 
02659   template< typename iType >
02660   static void assign( iType * stride ,
02661                       const iType & n3 )
02662     {
02663       stride[7] = 0 ;
02664       stride[6] = 0 ;
02665       stride[5] = 0 ;
02666       stride[4] = 0 ;
02667       stride[3] = 0 ;
02668       stride[2] = n3 * (
02669       stride[1] = Tag2::Size * (
02670       stride[0] = Tag1::Size ));
02671     }
02672 
02673   template< typename iType >
02674   static void assign( iType * stride ,
02675                       const iType & n2 ,
02676                       const iType & n3 )
02677     {
02678       stride[7] = 0 ;
02679       stride[6] = 0 ;
02680       stride[5] = 0 ;
02681       stride[4] = 0 ;
02682       stride[3] = 0 ;
02683       stride[2] = n3 * (
02684       stride[1] = n2 * (
02685       stride[0] = Tag1::Size ));
02686     }
02687 
02688   template< typename iType >
02689   static void assign( iType * stride ,
02690                       const iType & n1 ,
02691                       const iType & n2 ,
02692                       const iType & n3 )
02693     {
02694       stride[7] = 0 ;
02695       stride[6] = 0 ;
02696       stride[5] = 0 ;
02697       stride[4] = 0 ;
02698       stride[3] = 0 ;
02699       stride[2] = n3 * (
02700       stride[1] = n2 * (
02701       stride[0] = n1 ));
02702     }
02703 
02704   template< typename iType >
02705   static void assign( iType * stride ,
02706                       const iType * const dims )
02707     {
02708       stride[7] = 0 ;
02709       stride[6] = 0 ;
02710       stride[5] = 0 ;
02711       stride[4] = 0 ;
02712       stride[3] = 0 ;
02713       stride[2] = dims[2] * (
02714       stride[1] = dims[1] * (
02715       stride[0] = dims[0] ));
02716    }
02717 };
02718 
02719 //----------------------------------------------------------------------
02722 template< typename Scalar , class Tag1 , class Tag2 >
02723 struct Helper<Scalar,NaturalOrder,Tag1,Tag2,void,void,void,void,void,void>
02724 {
02725   typedef
02726     Array<Scalar,FortranOrder,Tag2,Tag1,void,void,void,void,void,void>
02727       reverse ;
02728 
02729   typedef
02730     Array<Scalar,NaturalOrder,Tag2,void,void,void,void,void,void,void>
02731       truncate ;
02732 
02733   template< class TagA >
02734   struct append {
02735     typedef
02736       Array<Scalar,NaturalOrder,TagA,Tag1,Tag2,void,void,void,void,void>
02737         natural ;
02738 
02739     typedef
02740       Array<Scalar,FortranOrder,Tag2,Tag1,TagA,void,void,void,void,void>
02741         fortran ;
02742 
02743     typedef  natural  type ;
02744     typedef  fortran  reverse ;
02745   };
02746 
02747   enum { Rank = 2 };
02748 
02749   static bool verify( int_t rank , const ArrayDimTag * tags[] )
02750     {
02751       return rank == Rank &&
02752              tags[0] == & Tag2::tag() &&
02753              tags[1] == & Tag1::tag();
02754     }
02755 
02756   static void assign_tags( const ArrayDimTag * tags[] )
02757     {
02758       tags[0] = & Tag2::tag();
02759       tags[1] = & Tag1::tag();
02760       tags[2] = NULL ;
02761       tags[3] = NULL ;
02762       tags[4] = NULL ;
02763       tags[5] = NULL ;
02764       tags[6] = NULL ;
02765       tags[7] = NULL ;
02766     }
02767 
02768   template< typename iType >
02769   static void assign( iType * stride )
02770     {
02771       stride[7] = 0 ;
02772       stride[6] = 0 ;
02773       stride[5] = 0 ;
02774       stride[4] = 0 ;
02775       stride[3] = 0 ;
02776       stride[2] = 0 ;
02777       stride[1] = Tag1::Size * (
02778       stride[0] = Tag2::Size );
02779     }
02780 
02781   template< typename iType >
02782   static void assign( iType * stride ,
02783                       const iType & n1 )
02784     {
02785       stride[7] = 0 ;
02786       stride[6] = 0 ;
02787       stride[5] = 0 ;
02788       stride[4] = 0 ;
02789       stride[3] = 0 ;
02790       stride[2] = 0 ;
02791       stride[1] = n1 * (
02792       stride[0] = Tag2::Size );
02793     }
02794 
02795   template< typename iType >
02796   static void assign( iType * stride ,
02797                       const iType & n1 ,
02798                       const iType & n2 )
02799     {
02800       stride[7] = 0 ;
02801       stride[6] = 0 ;
02802       stride[5] = 0 ;
02803       stride[4] = 0 ;
02804       stride[3] = 0 ;
02805       stride[2] = 0 ;
02806       stride[1] = n1 * (
02807       stride[0] = n2 );
02808     }
02809 
02810   template< typename iType >
02811   static void assign( iType * stride ,
02812                       const iType * const dims )
02813     {
02814       stride[7] = 0 ;
02815       stride[6] = 0 ;
02816       stride[5] = 0 ;
02817       stride[4] = 0 ;
02818       stride[3] = 0 ;
02819       stride[2] = 0 ;
02820       stride[1] = dims[0] * (
02821       stride[0] = dims[1] );
02822     }
02823 };
02824 
02825 template< typename Scalar , class Tag1 , class Tag2 >
02826 struct Helper<Scalar,FortranOrder,Tag1,Tag2,void,void,void,void,void,void>
02827 {
02828   typedef
02829     Array<Scalar,NaturalOrder,Tag2,Tag1,void,void,void,void,void,void>
02830       reverse ;
02831 
02832   typedef
02833     Array<Scalar,FortranOrder,Tag1,void,void,void,void,void,void,void>
02834       truncate ;
02835 
02836   template< class TagA >
02837   struct append {
02838     typedef
02839       Array<Scalar,FortranOrder,Tag1,Tag2,TagA,void,void,void,void,void>
02840         fortran ;
02841 
02842     typedef
02843       Array<Scalar,NaturalOrder,TagA,Tag2,Tag1,void,void,void,void,void>
02844         natural ;
02845 
02846     typedef  fortran  type ;
02847     typedef  natural  reverse ;
02848   };
02849 
02850   enum { Rank = 2 };
02851 
02852   static bool verify( int_t rank , const ArrayDimTag * tags[] )
02853     {
02854       return rank == Rank &&
02855              tags[0] = & Tag1::tag() &&
02856              tags[1] = & Tag2::tag();
02857     }
02858 
02859   static void assign_tags( const ArrayDimTag * tags[] )
02860     {
02861       tags[0] = & Tag1::tag();
02862       tags[1] = & Tag2::tag();
02863       tags[2] = NULL ;
02864       tags[3] = NULL ;
02865       tags[4] = NULL ;
02866       tags[5] = NULL ;
02867       tags[6] = NULL ;
02868       tags[7] = NULL ;
02869     }
02870 
02871   template< typename iType >
02872   static void assign( iType * stride )
02873     {
02874       stride[7] = 0 ;
02875       stride[6] = 0 ;
02876       stride[5] = 0 ;
02877       stride[4] = 0 ;
02878       stride[3] = 0 ;
02879       stride[2] = 0 ;
02880       stride[1] = Tag2::Size * (
02881       stride[0] = Tag1::Size );
02882     }
02883 
02884   template< typename iType >
02885   static void assign( iType * stride ,
02886                       const iType & n2 )
02887     {
02888       stride[7] = 0 ;
02889       stride[6] = 0 ;
02890       stride[5] = 0 ;
02891       stride[4] = 0 ;
02892       stride[3] = 0 ;
02893       stride[2] = 0 ;
02894       stride[1] = n2 * (
02895       stride[0] = Tag1::Size );
02896     }
02897 
02898   template< typename iType >
02899   static void assign( iType * stride ,
02900                       const iType & n1 ,
02901                       const iType & n2 )
02902     {
02903       stride[7] = 0 ;
02904       stride[6] = 0 ;
02905       stride[5] = 0 ;
02906       stride[4] = 0 ;
02907       stride[3] = 0 ;
02908       stride[2] = 0 ;
02909       stride[1] = n2 * (
02910       stride[0] = n1 );
02911     }
02912 
02913   template< typename iType >
02914   static void assign( iType * stride ,
02915                       const iType * const dims )
02916     {
02917       stride[7] = 0 ;
02918       stride[6] = 0 ;
02919       stride[5] = 0 ;
02920       stride[4] = 0 ;
02921       stride[3] = 0 ;
02922       stride[2] = 0 ;
02923       stride[1] = dims[1] * (
02924       stride[0] = dims[0] );
02925     }
02926 };
02927 
02928 //----------------------------------------------------------------------
02931 template< typename Scalar , class Tag1 >
02932 struct Helper<Scalar,NaturalOrder,Tag1,void,void,void,void,void,void,void>
02933 {
02934   typedef
02935     Array<Scalar,FortranOrder,Tag1,void,void,void,void,void,void,void>
02936       reverse ;
02937 
02938   typedef
02939     Array<Scalar,RankZero,void,void,void,void,void,void,void,void>
02940       truncate ;
02941 
02942   template< class TagA >
02943   struct append {
02944     typedef
02945       Array<Scalar,NaturalOrder,TagA,Tag1,void,void,void,void,void,void>
02946         natural ;
02947 
02948     typedef
02949       Array<Scalar,FortranOrder,Tag1,TagA,void,void,void,void,void,void>
02950         fortran ;
02951 
02952     typedef  natural  type ;
02953     typedef  fortran  reverse ;
02954   };
02955 
02956   enum { Rank = 1 };
02957 
02958   static bool verify( int_t rank , const ArrayDimTag * tags[] )
02959     { return rank == Rank && tags[0] == & Tag1::tag(); }
02960 
02961   static void assign_tags( const ArrayDimTag * tags[] )
02962     {
02963       tags[0] = & Tag1::tag();
02964       tags[1] = NULL ;
02965       tags[2] = NULL ;
02966       tags[3] = NULL ;
02967       tags[4] = NULL ;
02968       tags[5] = NULL ;
02969       tags[6] = NULL ;
02970       tags[7] = NULL ;
02971     }
02972 
02973   template< typename iType >
02974   static void assign( iType * stride )
02975     {
02976       stride[7] = 0 ;
02977       stride[6] = 0 ;
02978       stride[5] = 0 ;
02979       stride[4] = 0 ;
02980       stride[3] = 0 ;
02981       stride[2] = 0 ;
02982       stride[1] = 0 ;
02983       stride[0] = Tag1::Size ;
02984     }
02985 
02986   template< typename iType >
02987   static void assign( iType * stride ,
02988                       const iType & n1 )
02989     {
02990       stride[7] = 0 ;
02991       stride[6] = 0 ;
02992       stride[5] = 0 ;
02993       stride[4] = 0 ;
02994       stride[3] = 0 ;
02995       stride[2] = 0 ;
02996       stride[1] = 0 ;
02997       stride[0] = n1 ;
02998     }
02999 
03000   template< typename iType >
03001   static void assign( iType * stride ,
03002                       const iType * const dims )
03003     {
03004       stride[7] = 0 ;
03005       stride[6] = 0 ;
03006       stride[5] = 0 ;
03007       stride[4] = 0 ;
03008       stride[3] = 0 ;
03009       stride[2] = 0 ;
03010       stride[1] = 0 ;
03011       stride[0] = dims[0] ;
03012     }
03013 };
03014 
03015 template< typename Scalar , class Tag1 >
03016 struct Helper<Scalar,FortranOrder,Tag1,void,void,void,void,void,void,void>
03017 {
03018   typedef
03019     Array<Scalar,NaturalOrder,Tag1,void,void,void,void,void,void,void>
03020       reverse ;
03021 
03022   typedef
03023     Array<Scalar,RankZero,void,void,void,void,void,void,void,void>
03024       truncate ;
03025 
03026   template< class TagA >
03027   struct append {
03028     typedef
03029       Array<Scalar,FortranOrder,Tag1,TagA,void,void,void,void,void,void>
03030         fortran ;
03031 
03032     typedef
03033       Array<Scalar,NaturalOrder,TagA,Tag1,void,void,void,void,void,void>
03034         natural ;
03035 
03036     typedef  fortran  type ;
03037     typedef  natural  reverse ;
03038   };
03039 
03040   enum { Rank = 1 };
03041 
03042   static bool verify( int_t rank , const ArrayDimTag * tags[] )
03043     { return rank == Rank && tags[0] == & Tag1::tag(); }
03044 
03045   static void assign_tags( const ArrayDimTag * tags[] )
03046     {
03047       tags[0] = & Tag1::tag();
03048       tags[1] = NULL ;
03049       tags[2] = NULL ;
03050       tags[3] = NULL ;
03051       tags[4] = NULL ;
03052       tags[5] = NULL ;
03053       tags[6] = NULL ;
03054       tags[7] = NULL ;
03055     }
03056 
03057   template< typename iType >
03058   static void assign( iType * stride )
03059     {
03060       stride[7] = 0 ;
03061       stride[6] = 0 ;
03062       stride[5] = 0 ;
03063       stride[4] = 0 ;
03064       stride[3] = 0 ;
03065       stride[2] = 0 ;
03066       stride[1] = 0 ;
03067       stride[0] = Tag1::Size ;
03068     }
03069 
03070   template< typename iType >
03071   static void assign( iType * stride , const iType & n1 )
03072     {
03073       stride[7] = 0 ;
03074       stride[6] = 0 ;
03075       stride[5] = 0 ;
03076       stride[4] = 0 ;
03077       stride[3] = 0 ;
03078       stride[2] = 0 ;
03079       stride[1] = 0 ;
03080       stride[0] = n1 ;
03081     }
03082 
03083   template< typename iType >
03084   static void assign( iType * stride , const iType * const dims )
03085     {
03086       stride[7] = 0 ;
03087       stride[6] = 0 ;
03088       stride[5] = 0 ;
03089       stride[4] = 0 ;
03090       stride[3] = 0 ;
03091       stride[2] = 0 ;
03092       stride[0] = dims[0] ;
03093     }
03094 };
03095 
03096 //----------------------------------------------------------------------
03099 template< typename Scalar >
03100 struct Helper<Scalar,RankZero,void,void,void,void,void,void,void,void>
03101 {
03102   typedef
03103     Array<Scalar,RankZero,void,void,void,void,void,void,void,void>
03104       reverse ;
03105 
03106   template< class TagA >
03107   struct append {
03108     typedef
03109       Array<Scalar,NaturalOrder,TagA,void,void,void,void,void,void,void>
03110         natural ;
03111 
03112     typedef
03113       Array<Scalar,FortranOrder,TagA,void,void,void,void,void,void,void>
03114         fortran ;
03115 
03116     typedef natural type ;
03117     typedef fortran reverse ;
03118   };
03119 
03120   enum { Rank = 0 };
03121 
03122   template< typename iType >
03123   static void assign( iType * ) {}
03124 };
03125 
03126 //----------------------------------------------------------------------
03129 template< typename Scalar >
03130 struct Helper<Scalar,NaturalOrder,void,void,void,void,void,void,void,void>
03131 {
03132   typedef
03133     Array<Scalar,FortranOrder,void,void,void,void,void,void,void,void>
03134       reverse ;
03135 };
03136 
03137 template< typename Scalar >
03138 struct Helper<Scalar,FortranOrder,void,void,void,void,void,void,void,void>
03139 {
03140   typedef
03141     Array<Scalar,NaturalOrder,void,void,void,void,void,void,void,void>
03142       reverse ;
03143 };
03144 
03145 //----------------------------------------------------------------------
03146 
03147 } // namespace array_traits
03148 
03149 template< class ArrayType , class TagA > struct ArrayAppend {};
03150 
03151 template< typename Scalar , ArrayOrder Order ,
03152           class Tag1 , class Tag2 , class Tag3 , class Tag4 ,
03153           class Tag5 , class Tag6 , class Tag7 , class TagA >
03154 struct ArrayAppend<
03155        Array<Scalar,Order,Tag1,Tag2,Tag3,Tag4,Tag5,Tag6,Tag7,void> , TagA >
03156 {
03157 private:
03158   typedef typename
03159     array_traits::Helper<Scalar,Order,Tag1,Tag2,Tag3,Tag4,Tag5,Tag6,Tag7,void>
03160       ::template append<TagA> helper ;
03161 public:
03162   typedef typename helper::type    type ;
03163   typedef typename helper::natural natural ;
03164   typedef typename helper::fortran fortran ;
03165 };
03166 
03167 } // namespace shards
03168 
03169 #endif /* DOXYGEN_COMPILE */
03170 
03171 //----------------------------------------------------------------------
03172 //----------------------------------------------------------------------
03173 
03174 namespace shards {
03175 
03180 //----------------------------------------------------------------------
03193 template< typename Scalar , ArrayOrder array_order >
03194 class Array<Scalar,array_order,void,void,void,void,void,void,void,void>
03195 {
03196 private:
03197   typedef typename array_traits::Offset<array_order> Offset ;
03198 public:
03204   typedef Scalar  value_type ;
03205 
03207   typedef array_traits::int_t size_type ;
03208 
03210   typedef const ArrayDimTag * tag_type ;
03211 
03212   //----------------------------------
03213 
03215   enum { Natural = NaturalOrder == array_order };
03216 
03218   enum { Reverse = FortranOrder == array_order };
03219 
03221   enum { Contiguous = true };
03222 
03224   size_type rank()   const { return m_rank ; }
03225 
03227   bool natural()    const { return Natural ; }
03228 
03230   bool reverse()    const { return Reverse ; }
03231 
03233   bool contiguous() const { return Contiguous ; }
03234 
03235   //----------------------------------
03236 
03238   tag_type tag( size_type ord ) const
03239     {
03240       array_traits::check_range( ord , m_rank );
03241       if ( Natural ) { ord = ( m_rank - 1 ) - ord ; }
03242       return m_tag[ord];
03243     }
03244 
03245   //----------------------------------
03246 
03248   size_type dimension( size_type ord ) const
03249     {
03250       array_traits::check_range( ord , m_rank );
03251       if ( Natural ) { ord = ( m_rank - 1 ) - ord ; }
03252       return ord ? m_stride[ord] / m_stride[ord-1] : m_stride[ord] ;
03253     }
03254 
03256   template< typename iType >
03257   void dimensions( std::vector<iType> & n )
03258     {
03259       n.resize( m_rank );
03260       for ( size_type i = 0 ; i < m_rank ; ++i ) { n[i] = dimension(i); }
03261     }
03262 
03264   size_type size() const { return m_stride[ m_rank - 1 ]; }
03265 
03267   //----------------------------------
03275   template< typename iType >
03276   Array truncate( const iType & i ) const
03277     { return Array( *this , i ); }
03278 
03280   value_type * contiguous_data() const { return m_ptr ; }
03281 
03283   template< typename iType >
03284   value_type & operator[]( const iType & i ) const
03285     {
03286       SHARDS_ARRAY_CHECK( array_traits::check_range(i,size()) );
03287       return m_ptr[ i ];
03288     }
03289 
03290   //----------------------------------
03292   template< typename iType >
03293   value_type & operator()( const iType & i1 , const iType & i2 ,
03294                            const iType & i3 , const iType & i4 ,
03295                            const iType & i5 , const iType & i6 ,
03296                            const iType & i7 , const iType & i8 ) const
03297     {
03298       SHARDS_ARRAY_CHECK( array_traits::check_rank( m_rank , 8 ) );
03299       return m_ptr[ Offset::op(m_stride,i1,i2,i3,i4,i5,i6,i7,i8) ];
03300     }
03301 
03302   template< typename iType >
03303   value_type & operator()( const iType & i1 , const iType & i2 ,
03304                            const iType & i3 , const iType & i4 ,
03305                            const iType & i5 , const iType & i6 ,
03306                            const iType & i7 ) const
03307     {
03308       SHARDS_ARRAY_CHECK( array_traits::check_rank( m_rank , 7 ) );
03309       return m_ptr[ Offset::op(m_stride,i1,i2,i3,i4,i5,i6,i7) ];
03310     }
03311 
03312   template< typename iType >
03313   value_type & operator()( const iType & i1 , const iType & i2 ,
03314                            const iType & i3 , const iType & i4 ,
03315                            const iType & i5 , const iType & i6 ) const
03316     {
03317       SHARDS_ARRAY_CHECK( array_traits::check_rank( m_rank , 6 ) );
03318       return m_ptr[ Offset::op(m_stride,i1,i2,i3,i4,i5,i6) ];
03319     }
03320 
03321   template< typename iType >
03322   value_type & operator()( const iType & i1 , const iType & i2 ,
03323                            const iType & i3 , const iType & i4 ,
03324                            const iType & i5 ) const
03325     {
03326       SHARDS_ARRAY_CHECK( array_traits::check_rank( m_rank , 5 ) );
03327       return m_ptr[ Offset::op(m_stride,i1,i2,i3,i4,i5) ];
03328     }
03329 
03330   template< typename iType >
03331   value_type & operator()( const iType & i1 , const iType & i2 ,
03332                            const iType & i3 , const iType & i4 ) const
03333     {
03334       SHARDS_ARRAY_CHECK( array_traits::check_rank( m_rank , 4 ) );
03335       return m_ptr[ Offset::op(m_stride,i1,i2,i3,i4) ];
03336     }
03337 
03338   template< typename iType >
03339   value_type & operator()( const iType & i1 , const iType & i2 ,
03340                            const iType & i3 ) const
03341     {
03342       SHARDS_ARRAY_CHECK( array_traits::check_rank( m_rank , 3 ) );
03343       return m_ptr[ Offset::op(m_stride,i1,i2,i3) ];
03344     }
03345 
03346   template< typename iType >
03347   value_type & operator()( const iType & i1 , const iType & i2 ) const
03348     {
03349       SHARDS_ARRAY_CHECK( array_traits::check_rank( m_rank , 2 ) );
03350       return m_ptr[ Offset::op(m_stride,i1,i2) ];
03351     }
03352 
03353   template< typename iType >
03354   value_type & operator()( const iType & i1 ) const
03355     {
03356       SHARDS_ARRAY_CHECK( array_traits::check_rank( m_rank , 1 ) );
03357       return m_ptr[ Offset::op(m_stride,i1) ];
03358     }
03359 
03361   //----------------------------------
03366   typedef typename
03367     array_traits::Helper<Scalar,array_order,void,void,void,void,void,void,void,void>
03368       ::reverse  ReverseType ;
03369 
03370   //----------------------------------
03371 
03372   Array()
03373     : m_ptr(NULL), m_rank(0)
03374     {
03375       Copy<8>( m_stride , (size_type) 0 );
03376       Copy<8>( m_tag , (tag_type) NULL );
03377     }
03378 
03379   Array( const Array & rhs )
03380     : m_ptr( rhs.m_ptr ), m_rank( rhs.m_rank )
03381     {
03382       Copy<8>( m_stride , rhs.m_stride );
03383       Copy<8>( m_tag , rhs.m_tag );
03384     }
03385 
03386   Array & operator = ( const Array & rhs )
03387     {
03388       m_ptr = rhs.m_ptr ;
03389       m_rank = rhs.m_rank ;
03390       Copy<8>( m_stride , rhs.m_stride );
03391       Copy<8>( m_tag , rhs.m_tag );
03392       return *this ;
03393     }
03394 
03396   Array( const ReverseType & rhs )
03397     : m_ptr( rhs.m_ptr ), m_rank( rhs.m_rank )
03398     {
03399       Copy<8>( m_stride , rhs.m_stride );
03400       Copy<8>( m_tag , rhs.m_tag );
03401     }
03402 
03404   Array & operator = ( const ReverseType & rhs )
03405     {
03406       m_ptr = rhs.m_ptr ;
03407       m_rank = rhs.m_rank ;
03408       Copy<8>( m_stride , rhs.m_stride );
03409       Copy<8>( m_tag , rhs.m_tag );
03410       return *this ;
03411     }
03412 
03413   //----------------------------------
03414   // Class specific constructors:
03415 
03416   Array( value_type * ptr ,
03417          const size_type rank ,
03418          const size_type * const dims ,
03419          const tag_type  * const tags )
03420     : m_ptr( ptr ), m_rank( rank )
03421     {
03422       array_traits::init_dim( m_stride, dims, rank, Natural);
03423       array_traits::init_tags( m_tag,   tags, rank, Natural);
03424     }
03425 
03428   template< class Tag1 , class Tag2 , class Tag3 , class Tag4 ,
03429             class Tag5 , class Tag6 , class Tag7 , class Tag8 >
03430   Array & assign( value_type * ptr ,
03431                   size_type n1 , size_type n2 , size_type n3 , size_type n4 ,
03432                   size_type n5 , size_type n6 , size_type n7 , size_type n8 )
03433   {
03434     typedef
03435       array_traits::Helper<Scalar,array_order,
03436                            Tag1,Tag2,Tag3,Tag4,Tag5,Tag6,Tag7,Tag8>
03437         helper ;
03438     m_ptr  = ptr ;
03439     m_rank = helper::Rank ;
03440     helper::assign_tags( m_tag );
03441     helper::assign( m_stride, n1, n2, n3, n4, n5, n6, n7, n8 );
03442     return *this ;
03443   }
03444 
03445   template< class Tag1 , class Tag2 , class Tag3 , class Tag4 ,
03446             class Tag5 , class Tag6 , class Tag7 >
03447   Array & assign( value_type * ptr ,
03448                   size_type n1 , size_type n2 , size_type n3 , size_type n4 ,
03449                   size_type n5 , size_type n6 , size_type n7 )
03450   {
03451     typedef
03452       array_traits::Helper<Scalar,array_order,
03453                            Tag1,Tag2,Tag3,Tag4,Tag5,Tag6,Tag7,void>
03454         helper ;
03455     m_ptr = ptr ;
03456     m_rank = helper::Rank ;
03457     helper::assign_tags( m_tag );
03458     helper::assign( m_stride, n1, n2, n3, n4, n5, n6, n7 ); return *this ;
03459   }
03460 
03461   template< class Tag1 , class Tag2 , class Tag3 , class Tag4 ,
03462             class Tag5 , class Tag6 >
03463   Array & assign( value_type * ptr ,
03464                   size_type n1 , size_type n2 , size_type n3 , size_type n4 ,
03465                   size_type n5 , size_type n6 )
03466   {
03467     typedef
03468       array_traits::Helper<Scalar,array_order,
03469                            Tag1,Tag2,Tag3,Tag4,Tag5,Tag6,void,void>
03470         helper ;
03471     m_ptr = ptr ;
03472     m_rank = helper::Rank ;
03473     helper::assign_tags( m_tag );
03474     helper::assign( m_stride, n1, n2, n3, n4, n5, n6 );
03475     return *this ;
03476   }
03477 
03478   template< class Tag1 , class Tag2 , class Tag3 , class Tag4 ,
03479             class Tag5 >
03480   Array & assign( value_type * ptr ,
03481                   size_type n1 , size_type n2 , size_type n3 , size_type n4 ,
03482                   size_type n5 )
03483   {
03484     typedef
03485       array_traits::Helper<Scalar,array_order,
03486                            Tag1,Tag2,Tag3,Tag4,Tag5,void,void,void>
03487         helper ;
03488     m_ptr = ptr ;
03489     m_rank = helper::Rank ;
03490     helper::assign_tags( m_tag );
03491     helper::assign( m_stride, n1, n2, n3, n4, n5 );
03492     return *this ;
03493   }
03494 
03495   template< class Tag1 , class Tag2 , class Tag3 , class Tag4 >
03496   Array & assign( value_type * ptr ,
03497                   size_type n1 , size_type n2 , size_type n3 , size_type n4 )
03498   {
03499     typedef
03500       array_traits::Helper<Scalar,array_order,
03501                            Tag1,Tag2,Tag3,Tag4,void,void,void,void>
03502         helper ;
03503     m_ptr = ptr ;
03504     m_rank = helper::Rank ;
03505     helper::assign_tags( m_tag );
03506     helper::assign( m_stride, n1, n2, n3, n4 );
03507     return *this ;
03508   }
03509 
03510   template< class Tag1 , class Tag2 , class Tag3 >
03511   Array & assign( value_type * ptr ,
03512                   size_type n1 , size_type n2 , size_type n3 )
03513   {
03514     typedef
03515       array_traits::Helper<Scalar,array_order,
03516                            Tag1,Tag2,Tag3,void,void,void,void,void>
03517         helper ;
03518     m_ptr = ptr ;
03519     m_rank = helper::Rank ;
03520     helper::assign_tags( m_tag );
03521     helper::assign( m_stride, n1, n2, n3 );
03522     return *this ;
03523   }
03524 
03525   template< class Tag1 , class Tag2 >
03526   Array & assign( value_type * ptr ,
03527                   size_type n1 , size_type n2 )
03528   {
03529     typedef
03530       array_traits::Helper<Scalar,array_order,
03531                            Tag1,Tag2,void,void,void,void,void,void>
03532         helper ;
03533     m_ptr = ptr ;
03534     m_rank = helper::Rank ;
03535     helper::assign_tags( m_tag );
03536     helper::assign( m_stride, n1, n2 );
03537     return *this ;
03538   }
03539 
03540   template< class Tag1 >
03541   Array & assign( value_type * ptr ,
03542                   size_type n1 )
03543   {
03544     typedef
03545       array_traits::Helper<Scalar,array_order,
03546                            Tag1,void,void,void,void,void,void,void>
03547         helper ;
03548     m_ptr = ptr ;
03549     m_rank = helper::Rank ;
03550     helper::assign_tags( m_tag );
03551     helper::assign( m_stride, n1 );
03552     return *this ;
03553   }
03554 
03555 private:
03556 
03558   Array( const Array & rhs , const size_type i )
03559     : m_ptr( NULL ), m_rank( 0 )
03560     {
03561       if ( 1 < rhs.m_rank ) {
03562         Copy<8>( m_stride , rhs.m_stride );
03563         Copy<8>( m_tag , rhs.m_tag );
03564         m_rank = rhs.m_rank - 1 ;
03565         m_ptr  = rhs.m_ptr + ( m_rank ? m_stride[ m_rank - 1 ] * i : i );
03566         m_stride[ m_rank ] = 0 ;
03567         m_tag[ m_rank ] = 0 ;
03568       }
03569       else {
03570         Copy<8>( m_stride , (size_type) 0 );
03571         Copy<8>( m_tag , (tag_type) NULL );
03572       }
03573     }
03574 
03576   value_type * m_ptr ;
03577 
03579   size_type  m_rank ;
03580 
03582   size_type  m_stride[8];
03583 
03585   tag_type   m_tag[8] ;
03586 
03587   template< typename , ArrayOrder ,
03588             class , class , class , class ,
03589             class , class , class , class >
03590   friend class shards::Array ;
03591 };
03592 
03593 //----------------------------------------------------------------------
03612 template< typename Scalar , ArrayOrder array_order ,
03613           class Tag1 , class Tag2 , class Tag3 , class Tag4 ,
03614           class Tag5 , class Tag6 , class Tag7 , class Tag8 >
03615 class Array
03616 {
03617 private:
03618 
03619 #ifndef DOXYGEN_COMPILE
03620   typedef
03621     array_traits::Helper<Scalar,array_order,
03622                          Tag1,Tag2,Tag3,Tag4,Tag5,Tag6,Tag7,Tag8>
03623       helper ;
03624 #endif /* DOXYGEN_COMPILE */
03625 
03626 public:
03632   typedef Scalar  value_type ;
03633 
03635   typedef array_traits::int_t size_type ;
03636 
03638   typedef const ArrayDimTag * tag_type ;
03639 
03640   //----------------------------------
03641 
03643   enum { Rank = helper::Rank };
03644 
03646   enum { Natural = NaturalOrder == array_order };
03647 
03649   enum { Reverse = FortranOrder == array_order };
03650 
03652   enum { Contiguous = true };
03653 
03655   size_type rank()   const { return Rank ; }
03656 
03658   bool natural()    const { return Natural ; }
03659 
03661   bool reverse()    const { return Reverse ; }
03662 
03664   bool contiguous() const { return Contiguous ; }
03665 
03666   //----------------------------------
03667 
03668 #ifndef DOXYGEN_COMPILE
03669 
03670   template < size_type ordinate >
03671   struct Tag {
03672     typedef typename array_traits::TagAt<Array,ordinate>::type type ;
03673   };
03674 #endif
03675 
03677   tag_type tag( const size_type ordinate ) const
03678     { return m_array.tag( ordinate ); }
03679 
03680   //----------------------------------
03682   template < size_type ordinate > size_type dimension() const
03683     {
03684       typedef array_traits::StrideDim<array_order,Rank,ordinate> StrideDim ;
03685       return StrideDim::dimension(m_array.m_stride);
03686     }
03687 
03689   size_type dimension( const size_type ordinate ) const
03690     {
03691       typedef array_traits::StrideDim<array_order,Rank> StrideDim ;
03692       return StrideDim::dimension(m_array.m_stride,ordinate);
03693     }
03694 
03696   template< typename iType >
03697   void dimensions( std::vector<iType> & n )
03698     { m_array.dimensions<iType>( n ); }
03699 
03701   size_type size() const { return m_array.m_stride[ Rank - 1 ]; }
03702 
03704   //----------------------------------
03712   typedef typename helper::truncate TruncateType ;
03713 
03718   template< typename iType >
03719   TruncateType truncate( const iType & i ) const
03720     { return TruncateType( m_array , i ); }
03721 
03722   //----------------------------------
03724   value_type * contiguous_data() const { return m_array.contiguous_data(); }
03725 
03727   template< typename iType >
03728   value_type & operator[]( const iType & i ) const
03729     { return m_array[i]; }
03730 
03732   template< typename iType >
03733   value_type & operator()( const iType & i1 , const iType & i2 ,
03734                            const iType & i3 , const iType & i4 ,
03735                            const iType & i5 , const iType & i6 ,
03736                            const iType & i7 , const iType & i8 ) const
03737     {
03738       array_traits::CheckRank<8,Rank>::ok();
03739       return m_array(i1,i2,i3,i4,i5,i6,i7,i8);
03740     }
03741 
03743   template< typename iType >
03744   value_type & operator()( const iType & i1 , const iType & i2 ,
03745                            const iType & i3 , const iType & i4 ,
03746                            const iType & i5 , const iType & i6 ,
03747                            const iType & i7 ) const
03748     {
03749       array_traits::CheckRank<7,Rank>::ok();
03750       return m_array(i1,i2,i3,i4,i5,i6,i7);
03751     }
03752 
03754   template< typename iType >
03755   value_type & operator()( const iType & i1 , const iType & i2 ,
03756                            const iType & i3 , const iType & i4 ,
03757                            const iType & i5 , const iType & i6 ) const
03758     {
03759       array_traits::CheckRank<6,Rank>::ok();
03760       return m_array(i1,i2,i3,i4,i5,i6);
03761     }
03762 
03764   template< typename iType >
03765   value_type & operator()( const iType & i1 , const iType & i2 ,
03766                            const iType & i3 , const iType & i4 ,
03767                            const iType & i5 ) const
03768     {
03769       array_traits::CheckRank<5,Rank>::ok();
03770       return m_array(i1,i2,i3,i4,i5);
03771     }
03772 
03774   template< typename iType >
03775   value_type & operator()( const iType & i1 , const iType & i2 ,
03776                            const iType & i3 , const iType & i4 ) const
03777     {
03778       array_traits::CheckRank<4,Rank>::ok();
03779       return m_array(i1,i2,i3,i4);
03780     }
03781 
03783   template< typename iType >
03784   value_type & operator()( const iType & i1 , const iType & i2 ,
03785                            const iType & i3 ) const
03786     {
03787       array_traits::CheckRank<3,Rank>::ok();
03788       return m_array(i1,i2,i3);
03789     }
03790 
03792   template< typename iType >
03793   value_type & operator()( const iType & i1 , const iType & i2 ) const
03794     {
03795       array_traits::CheckRank<2,Rank>::ok();
03796       return m_array(i1,i2);
03797     }
03798 
03800   template< typename iType >
03801   value_type & operator()( const iType & i1 ) const
03802     {
03803       array_traits::CheckRank<1,Rank>::ok();
03804       return m_array(i1);
03805     }
03806 
03808   //----------------------------------
03816   typedef typename helper::reverse  ReverseType ;
03817 
03819   Array() : m_array()
03820     { m_array.m_rank = Rank ; helper::assign_tags( m_array.m_tag ); }
03821 
03823   Array( const Array & rhs ) : m_array( rhs.m_array ) {}
03824 
03826   Array & operator = ( const Array & rhs )
03827     { m_array.operator=(rhs.m_array); return *this ; }
03828 
03830   Array( const ReverseType & rhs ) : m_array( rhs.m_array ) {}
03831 
03833   Array & operator = ( const ReverseType & rhs )
03834     { m_array.operator=(rhs.m_array); return *this ; }
03835 
03837   Array & assign( value_type * arg_ptr , const size_type * const dims )
03838     {
03839       m_array.m_ptr = arg_ptr ;
03840       array_traits::init_dim( m_array.m_stride , dims , Rank , Natural );
03841       return *this ;
03842     }
03843 
03845   Array( value_type * arg_ptr , const size_type * const dims )
03846     : m_array()
03847     {
03848       m_array.m_rank = Rank ;
03849       helper::assign_tags( m_array.m_tag );
03850       assign( arg_ptr , dims );
03851     }
03852 
03854   Array & assign( value_type * arg_ptr ,
03855                   const size_type n1 , const size_type n2 ,
03856                   const size_type n3 , const size_type n4 ,
03857                   const size_type n5 , const size_type n6 ,
03858                   const size_type n7 , const size_type n8 )
03859     {
03860       array_traits::CheckRange<7,Rank>::ok();
03861       m_array.m_ptr  = arg_ptr ;
03862       helper::assign( m_array.m_stride, n1, n2, n3, n4, n5, n6, n7, n8 );
03863       return *this ;
03864     }
03865 
03867   Array( value_type * arg_ptr ,
03868          const size_type n1 , const size_type n2 ,
03869          const size_type n3 , const size_type n4 ,
03870          const size_type n5 , const size_type n6 ,
03871          const size_type n7 , const size_type n8 )
03872     : m_array()
03873     {
03874       m_array.m_rank = Rank ;
03875       helper::assign_tags( m_array.m_tag );
03876       assign( arg_ptr, n1, n2, n3, n4, n5, n6, n7, n8 );
03877     }
03878 
03882   Array& assign( value_type * arg_ptr ,
03883                  const size_type n1 , const size_type n2 ,
03884                  const size_type n3 , const size_type n4 ,
03885                  const size_type n5 , const size_type n6 ,
03886                  const size_type n7 )
03887     {
03888       array_traits::CheckRange<6,Rank>::ok();
03889       m_array.m_ptr = arg_ptr ;
03890       helper::assign( m_array.m_stride, n1, n2, n3, n4, n5, n6, n7 );
03891       return *this ;
03892     }
03893 
03897   Array( value_type * arg_ptr ,
03898          const size_type n1 , const size_type n2 ,
03899          const size_type n3 , const size_type n4 ,
03900          const size_type n5 , const size_type n6 ,
03901          const size_type n7 )
03902     : m_array()
03903     {
03904       m_array.m_rank = Rank ;
03905       helper::assign_tags( m_array.m_tag );
03906       assign( arg_ptr, n1, n2, n3, n4, n5, n6, n7 );
03907     }
03908 
03912   Array & assign( value_type * arg_ptr ,
03913                   const size_type n1 , const size_type n2 ,
03914                   const size_type n3 , const size_type n4 ,
03915                   const size_type n5 , const size_type n6 )
03916     {
03917       array_traits::CheckRange<5,Rank>::ok();
03918       m_array.m_ptr = arg_ptr ;
03919       helper::assign( m_array.m_stride, n1, n2, n3, n4, n5, n6 );
03920       return *this ;
03921     }
03922 
03926   Array( value_type * arg_ptr ,
03927          const size_type n1 , const size_type n2 ,
03928          const size_type n3 , const size_type n4 ,
03929          const size_type n5 , const size_type n6 )
03930     : m_array()
03931     {
03932       m_array.m_rank = Rank ;
03933       helper::assign_tags( m_array.m_tag );
03934       assign( arg_ptr, n1, n2, n3, n4, n5, n6 );
03935     }
03936 
03940   Array & assign( value_type * arg_ptr ,
03941                   const size_type n1 , const size_type n2 ,
03942                   const size_type n3 , const size_type n4 ,
03943                   const size_type n5 )
03944     {
03945       array_traits::CheckRange<4,Rank>::ok();
03946       m_array.m_ptr  = arg_ptr ;
03947       helper::assign( m_array.m_stride, n1, n2, n3, n4, n5 );
03948       return *this ;
03949     }
03950 
03954   Array( value_type * arg_ptr ,
03955          const size_type n1 , const size_type n2 ,
03956          const size_type n3 , const size_type n4 ,
03957          const size_type n5 )
03958     : m_array()
03959     {
03960       m_array.m_rank = Rank ;
03961       helper::assign_tags( m_array.m_tag );
03962       assign( arg_ptr, n1, n2, n3, n4, n5 );
03963     }
03964 
03968   Array & assign( value_type * arg_ptr ,
03969                   const size_type n1 , const size_type n2 ,
03970                   const size_type n3 , const size_type n4 )
03971     {
03972       array_traits::CheckRange<3,Rank>::ok();
03973       m_array.m_ptr  = arg_ptr ;
03974       helper::assign( m_array.m_stride, n1, n2, n3, n4 );
03975       return *this ;
03976     }
03977 
03981   Array( value_type * arg_ptr ,
03982          const size_type n1 , const size_type n2 ,
03983          const size_type n3 , const size_type n4 )
03984     : m_array()
03985     {
03986       m_array.m_rank = Rank ;
03987       helper::assign_tags( m_array.m_tag );
03988       assign( arg_ptr, n1, n2, n3, n4 );
03989     }
03990 
03994   Array & assign( value_type * arg_ptr ,
03995                   const size_type n1 , const size_type n2 ,
03996                   const size_type n3 )
03997     {
03998       array_traits::CheckRange<2,Rank>::ok();
03999       m_array.m_ptr  = arg_ptr ;
04000       helper::assign( m_array.m_stride, n1, n2, n3 );
04001       return *this ;
04002     }
04003 
04007   Array( value_type * arg_ptr ,
04008          const size_type n1 , const size_type n2 ,
04009          const size_type n3 )
04010     : m_array()
04011     {
04012       m_array.m_rank = Rank ;
04013       helper::assign_tags( m_array.m_tag );
04014       assign( arg_ptr , n1, n2, n3 );
04015     }
04016 
04020   Array & assign( value_type * arg_ptr ,
04021                   const size_type n1 , const size_type n2 )
04022     {
04023       array_traits::CheckRange<1,Rank>::ok();
04024       m_array.m_ptr  = arg_ptr ;
04025       helper::assign( m_array.m_stride, n1, n2 );
04026       return *this ;
04027     }
04028 
04032   Array( value_type * arg_ptr , const size_type n1 , const size_type n2 )
04033     : m_array()
04034     {
04035       m_array.m_rank = Rank ;
04036       helper::assign_tags( m_array.m_tag );
04037       assign( arg_ptr, n1, n2 );
04038     }
04039 
04043   Array & assign( value_type * arg_ptr , const size_type n1 )
04044     {
04045       array_traits::CheckRange<0,Rank>::ok();
04046       m_array.m_ptr  = arg_ptr ;
04047       helper::assign( m_array.m_stride, n1 );
04048       return *this ;
04049     }
04050 
04054   Array( value_type * arg_ptr , const size_type n1 )
04055     : m_array()
04056     {
04057       m_array.m_rank = Rank ;
04058       helper::assign_tags( m_array.m_tag );
04059       assign( arg_ptr, n1 );
04060     }
04061 
04063   Array & assign( value_type * arg_ptr )
04064     {
04065       m_array.m_ptr = arg_ptr ;
04066       helper::assign( m_array.m_stride );
04067       return *this ;
04068     }
04069 
04071   Array( value_type * arg_ptr )
04072     : m_array()
04073     {
04074       m_array.m_rank = Rank ;
04075       helper::assign_tags( m_array.m_tag );
04076       assign( arg_ptr );
04077     }
04078 
04080   Array( const Array<Scalar,array_order> & rhs )
04081     : m_array( rhs )
04082     {
04083       if ( ! helper::verify( m_array.m_rank , m_array.m_tag ) ) {
04084         m_array.m_rank = Rank ;
04085         helper::assign_tags( m_array.m_tag );
04086         array_traits::throw_bad_conversion( m_array.m_rank , m_array.m_tag ,
04087                                             rhs.m_rank , rhs.m_tag );
04088       }
04089     }
04090 
04092   operator const Array<Scalar,array_order> & () const { return m_array ; }
04093 
04095   operator typename Array<Scalar,array_order>::ReverseType () const
04096     { return typename Array<Scalar,array_order>::ReverseType( m_array ); }
04097 
04099   void assign_stride( value_type      * arg_ptr ,
04100                       const size_type * arg_stride )
04101     {
04102       m_array.m_ptr = arg_ptr ;
04103       Copy<Rank>(   m_array.m_stride , arg_stride );
04104       Copy<8-Rank>( m_array.m_stride + Rank , size_type(0) );
04105     }
04106 
04108   void assign_stride( value_type      * arg_ptr ,
04109                       const size_type * arg_stride ,
04110                             size_type   arg_final_dim )
04111     {
04112       m_array.m_ptr = arg_ptr ;
04113       Copy<Rank-1>( m_array.m_stride , arg_stride );
04114       m_array.m_stride[Rank-1] = m_array.m_stride[Rank-2] * arg_final_dim ;
04115       Copy<8-Rank>( m_array.m_stride + Rank , size_type(0) );
04116     }
04117 
04119 protected:
04120 
04121   Array( const Array<Scalar,array_order> & rhs , size_type i )
04122     : m_array( rhs , i )
04123     {
04124       if ( ! helper::verify( m_array.m_rank , m_array.m_tag ) ) {
04125         m_array.m_rank = Rank ;
04126         helper::assign_tags( m_array.m_tag );
04127         array_traits::throw_bad_conversion( m_array.m_rank , m_array.m_tag ,
04128                                             rhs.m_rank - 1 , rhs.m_tag );
04129       }
04130     }
04131 
04132   Array<value_type,array_order> m_array ;
04133 
04134   template< typename , ArrayOrder ,
04135             class , class , class , class ,
04136             class , class , class , class >
04137   friend class shards::Array ;
04138 };
04139 
04140 //----------------------------------------------------------------------
04141 
04145 template< typename Scalar >
04146 class Array<Scalar,RankZero,void,void,void,void,void,void,void,void>
04147 {
04148 public:
04154   typedef Scalar  value_type ;
04155 
04157   typedef array_traits::int_t size_type ;
04158 
04160   typedef const ArrayDimTag * tag_type ;
04161 
04162   //----------------------------------
04163 
04165   enum { Rank = 0 };
04166 
04168   enum { Natural = false };
04169 
04171   enum { Reverse = false };
04172 
04174   enum { Contiguous = true };
04175 
04177   size_type rank()   const { return Rank ; }
04178 
04180   bool natural()    const { return Natural ; }
04181 
04183   bool reverse()    const { return Reverse ; }
04184 
04186   bool contiguous() const { return Contiguous ; }
04187 
04188   //----------------------------------
04189 
04191   size_type size() const { return 1 ; }
04192 
04194   //----------------------------------
04200   value_type * contiguous_data() const { return m_ptr ; }
04201 
04203   value_type & operator()() const { return *m_ptr ; }
04204 
04206   //----------------------------------
04211   Array() : m_ptr(NULL) {}
04212 
04213   Array( const Array & rhs ) : m_ptr( rhs.m_ptr ) {}
04214 
04215   Array & operator = ( const Array & rhs )
04216     { m_ptr = rhs.m_ptr ; return *this ; }
04217 
04218   //----------------------------------
04219   // Class specific constructors:
04220 
04221   Array( value_type * arg_ptr ) : m_ptr( arg_ptr ) {}
04222 
04224 protected:
04225 
04226 #ifndef DOXYGEN_COMPILE
04227   value_type * m_ptr ;
04228 
04229   template< typename , ArrayOrder ,
04230             class , class , class , class ,
04231             class , class , class , class >
04232   friend class shards::Array ;
04233 
04234 #endif /* DOXYGEN_COMPILE */
04235 };
04236 
04237 
04238 //----------------------------------------------------------------------
04239 //----------------------------------------------------------------------
04240 
04243 } // namespace shards
04244 
04245 #undef SHARDS_ARRAY_CHECK
04246 
04247 #endif /* Shards_Array_hpp */
04248 
 All Classes Functions Variables Typedefs Enumerator