1
/*------------------------------------------------------------------------*/
2
/* phdMesh : Parallel Heterogneous Dynamic unstructured Mesh */
3
/* Copyright (2008) Sandia Corporation */
5
/* Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive */
6
/* license for use of this work by or on behalf of the U.S. Government. */
8
/* This library is free software; you can redistribute it and/or modify */
9
/* it under the terms of the GNU Lesser General Public License as */
10
/* published by the Free Software Foundation; either version 2.1 of the */
11
/* License, or (at your option) any later version. */
13
/* This library is distributed in the hope that it will be useful, */
14
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
15
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
16
/* Lesser General Public License for more details. */
18
/* You should have received a copy of the GNU Lesser General Public */
19
/* License along with this library; if not, write to the Free Software */
20
/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 */
22
/*------------------------------------------------------------------------*/
24
* @author H. Carter Edwards <hcedwar@sandia.gov>
28
#ifndef util_Array_hpp
29
#define util_Array_hpp
31
//----------------------------------------------------------------------
35
/** \class ArrayNatural
36
* \brief A multidimensional array index mapping into a contiguous storage.
38
* The Scalar template parameter defines the member type of the array.
39
* The Tag? template parameters define the ordinates.
41
* Template parameter for a multi-index mapping class.
42
* This class is required to provide:
43
* - enum { Rank = ... };
44
* which is the rank of the dimension and
45
* - unsigned operator()( unsigned i1 , ... ) const ;
46
* which is the multi-index to offset map.
49
template< typename Scalar ,
50
class Tag1 = void , class Tag2 = void ,
51
class Tag3 = void , class Tag4 = void ,
52
class Tag5 = void , class Tag6 = void ,
53
class Tag7 = void , class Tag8 = void >
56
template< typename Scalar ,
57
class Tag1 = void , class Tag2 = void ,
58
class Tag3 = void , class Tag4 = void ,
59
class Tag5 = void , class Tag6 = void ,
60
class Tag7 = void , class Tag8 = void >
63
template< class Tag1 = void , class Tag2 = void ,
64
class Tag3 = void , class Tag4 = void ,
65
class Tag5 = void , class Tag6 = void ,
66
class Tag7 = void , class Tag8 = void >
67
class ArrayDimension ;
73
//----------------------------------------------------------------------
75
#include <ArrayHelper.hpp>
77
//----------------------------------------------------------------------
82
virtual const char * name() const = 0 ;
84
virtual std::string to_string( size_t , int ) const ;
85
virtual int to_index( size_t , const std::string & ) const ;
87
// A derived type must provide the following static method:
89
// static const Derived_ArrayDimTag_Type & descriptor();
92
virtual ~ArrayDimTag();
95
ArrayDimTag( const ArrayDimTag & );
96
ArrayDimTag & operator = ( const ArrayDimTag & );
99
//----------------------------------------------------------------------
104
class ArrayDimension<void,void,void,void,void,void,void,void> {
108
const ArrayDimTag * tags[8];
111
template< class Tag1 >
112
class ArrayDimension<Tag1,void,void,void,void,void,void,void> {
115
size_t dimension[ Rank ];
118
template< class Tag1 , class Tag2 >
119
class ArrayDimension<Tag1,Tag2,void,void,void,void,void,void> {
122
size_t dimension[ Rank ];
125
template< class Tag1 , class Tag2 , class Tag3 >
126
class ArrayDimension<Tag1,Tag2,Tag3,void,void,void,void,void> {
129
size_t dimension[ Rank ];
132
template< class Tag1 , class Tag2 , class Tag3 , class Tag4 >
133
class ArrayDimension<Tag1,Tag2,Tag3,Tag4,void,void,void,void> {
136
size_t dimension[ Rank ];
139
template< class Tag1 , class Tag2 , class Tag3 , class Tag4 ,
141
class ArrayDimension<Tag1,Tag2,Tag3,Tag4,Tag5,void,void,void> {
144
size_t dimension[ Rank ];
147
template< class Tag1 , class Tag2 , class Tag3 , class Tag4 ,
148
class Tag5 , class Tag6 >
149
class ArrayDimension<Tag1,Tag2,Tag3,Tag4,Tag5,Tag6,void,void> {
152
size_t dimension[ Rank ];
155
template< class Tag1 , class Tag2 , class Tag3 , class Tag4 ,
156
class Tag5 , class Tag6 , class Tag7 >
157
class ArrayDimension<Tag1,Tag2,Tag3,Tag4,Tag5,Tag6,Tag7,void> {
160
size_t dimension[ Rank ];
163
template< class Tag1 , class Tag2 , class Tag3 , class Tag4 ,
164
class Tag5 , class Tag6 , class Tag7 , class Tag8 >
165
class ArrayDimension {
168
size_t dimension[ Rank ];
171
//----------------------------------------------------------------------
173
template< typename Scalar ,
174
class Tag1 , class Tag2 , class Tag3 , class Tag4 ,
175
class Tag5 , class Tag6 , class Tag7 , class Tag8 >
179
// Required by all arrays:
180
typedef Scalar value_type ;
181
typedef int index_type ;
182
typedef size_t size_type ;
183
typedef const ArrayDimTag * tag_type ;
185
// Required by compile-time knowledge arrays:
187
typedef ArrayDimTagList<Tag1,Tag2,Tag3,Tag4,Tag5,Tag6,Tag7,Tag8> TagList ;
189
enum { Rank = TagList::Rank };
190
enum { Natural = true };
191
enum { Reverse = false };
192
enum { Contiguous = true };
194
template < unsigned Ord >
196
typedef typename ArrayDimTagListAt<TagList,Ord>::type type ;
201
typedef ArrayHelper< TagList::Rank > Helper ;
204
size_t m_stride[ TagList::Rank ];
206
template< typename , class , class , class , class ,
207
class , class , class , class >
208
friend class ArrayNatural ;
210
template< typename , class , class , class , class ,
211
class , class , class , class >
212
friend class ArrayFortran ;
216
//----------------------------------
218
unsigned rank() const { return Rank ; }
219
bool natural() const { return Natural ; }
220
bool reverse() const { return Reverse ; }
221
bool contiguous() const { return Contiguous ; }
223
tag_type tag( unsigned ord ) const
225
array_bounds_checking( Rank , ord );
226
return array_tags<TagList>()[ord] ;
229
//----------------------------------
231
size_type size() const { return m_stride[ Rank - 1 ]; }
233
template < unsigned Ord > size_type dimension() const
235
array_bounds_check_ordinal_is_less<Rank,Ord>();
236
enum { I = ( Rank - 1 ) - Ord };
237
return I ? m_stride[I] / m_stride[I-1] : m_stride[I] ;
240
size_type dimension( index_type ord ) const
242
array_bounds_checking( Rank , ord );
243
const int i = ( Rank - 1 ) - ord ;
244
return i ? m_stride[i] / m_stride[i-1] : m_stride[i] ;
247
void dimensions( std::vector<size_type> & n )
250
n[Rank-1] = m_stride[0] ;
251
for ( int i = 1 ; i < Rank ; ++i ) {
252
n[ ( Rank - 1 ) - i ] = m_stride[i] / m_stride[i-1] ;
256
//----------------------------------
257
/** \brief Access member data */
258
value_type * contiguous_data() const { return m_ptr ; }
260
/** \brief Access member via full ordering of members. */
261
value_type & operator[]( size_type i ) const
263
ARRAY_BOUNDS_CHECKING_ORDINAL( size() , i );
267
/** \brief Access member via Rank 8 multi-index */
268
value_type & operator()( index_type i1 , index_type i2 ,
269
index_type i3 , index_type i4 ,
270
index_type i5 , index_type i6 ,
271
index_type i7 , index_type i8 ) const
273
array_bounds_check_rank_is_equal<Rank,8>();
274
ARRAY_BOUNDS_CHECKING_8(i1,i2,i3,i4,i5,i6,i7,i8);
275
return m_ptr[ ARRAY_INDEX_NATURAL_8(m_stride,i1,i2,i3,i4,i5,i6,i7,i8) ];
278
/** \brief Access member via Rank 7 multi-index */
279
value_type & operator()( index_type i1 , index_type i2 ,
280
index_type i3 , index_type i4 ,
281
index_type i5 , index_type i6 ,
282
index_type i7 ) const
284
array_bounds_check_rank_is_equal<Rank,7>();
285
ARRAY_BOUNDS_CHECKING_7(i1,i2,i3,i4,i5,i6,i7);
286
return m_ptr[ ARRAY_INDEX_NATURAL_7(m_stride,i1,i2,i3,i4,i5,i6,i7) ];
289
/** \brief Access member via Rank 6 multi-index */
290
value_type & operator()( index_type i1 , index_type i2 ,
291
index_type i3 , index_type i4 ,
292
index_type i5 , index_type i6 ) const
294
array_bounds_check_rank_is_equal<Rank,6>();
295
ARRAY_BOUNDS_CHECKING_6(i1,i2,i3,i4,i5,i6);
296
return m_ptr[ ARRAY_INDEX_NATURAL_6(m_stride,i1,i2,i3,i4,i5,i6) ];
299
/** \brief Access member via Rank 5 multi-index */
300
value_type & operator()( index_type i1 , index_type i2 ,
301
index_type i3 , index_type i4 ,
302
index_type i5 ) const
304
array_bounds_check_rank_is_equal<Rank,5>();
305
ARRAY_BOUNDS_CHECKING_5(i1,i2,i3,i4,i5);
306
return m_ptr[ ARRAY_INDEX_NATURAL_5(m_stride,i1,i2,i3,i4,i5) ];
309
/** \brief Access member via Rank 4 multi-index */
310
value_type & operator()( index_type i1 , index_type i2 ,
311
index_type i3 , index_type i4 ) const
313
array_bounds_check_rank_is_equal<Rank,4>();
314
ARRAY_BOUNDS_CHECKING_4(i1,i2,i3,i4);
315
return m_ptr[ ARRAY_INDEX_NATURAL_4(m_stride,i1,i2,i3,i4) ];
318
/** \brief Access member via Rank 3 multi-index */
319
value_type & operator()( index_type i1 , index_type i2 ,
320
index_type i3 ) const
322
array_bounds_check_rank_is_equal<Rank,3>();
323
ARRAY_BOUNDS_CHECKING_3(i1,i2,i3);
324
return m_ptr[ ARRAY_INDEX_NATURAL_3(m_stride,i1,i2,i3) ];
327
/** \brief Access member via Rank 2 multi-index */
328
value_type & operator()( index_type i1 , index_type i2 ) const
330
array_bounds_check_rank_is_equal<Rank,2>();
331
ARRAY_BOUNDS_CHECKING_2(i1,i2);
332
return m_ptr[ ARRAY_INDEX_NATURAL_2(m_stride,i1,i2) ];
335
/** \brief Access member via Rank 1 multi-index */
336
value_type & operator()( index_type i1 ) const
338
array_bounds_check_rank_is_equal<Rank,1>();
339
ARRAY_BOUNDS_CHECKING_1(i1);
343
//----------------------------------
344
// Required constructors and assignment operators:
346
ArrayNatural() : m_ptr(NULL) { Helper::zero( m_stride ); }
348
ArrayNatural( const ArrayNatural & rhs )
349
: m_ptr( rhs.m_ptr ) { Helper::copy( m_stride , rhs.m_stride ); }
351
ArrayNatural & operator = ( const ArrayNatural & rhs )
354
Helper::copy( m_stride , rhs.m_stride );
358
//----------------------------------
359
// Copy a reverse-map array
362
ArrayReverse<Scalar,Tag1,Tag2,Tag3,Tag4,Tag5,Tag6,Tag7,Tag8>::fortran_type
365
ArrayNatural( const ReverseType & rhs )
366
: m_ptr( rhs.m_ptr ) { Helper::copy( m_stride , rhs.m_stride ); }
368
ArrayNatural & operator = ( const ReverseType & rhs )
371
Helper::copy( m_stride , rhs.m_stride );
375
//----------------------------------
379
ArrayTruncate<Scalar,Tag1,Tag2,Tag3,Tag4,Tag5,Tag6,Tag7,Tag8>::natural_type
382
TruncatedViewType truncated_view( index_type i ) const
384
return TruncatedViewType( m_ptr + m_stride[ Rank - 2 ] * i ,
385
ArrayStride(), m_stride );
388
// "Power user" constructor, promising a properly strided input
389
ArrayNatural( value_type * arg_ptr ,
390
const ArrayStride & , const size_type * arg_stride )
391
: m_ptr( arg_ptr ) { Helper::copy( m_stride , arg_stride ); }
393
// "Power user" constructor, promising a properly strided input
394
ArrayNatural( value_type * arg_ptr ,
395
const ArrayStride & ,
396
const size_type * arg_stride ,
397
const size_type arg_append )
399
{ Helper::stride_append( m_stride , arg_stride , arg_append ); }
401
//----------------------------------
402
// Take pointer to other compatible array types.
404
template< class OtherArrayType >
405
explicit ArrayNatural( const OtherArrayType & rhs )
406
: m_ptr( rhs.contiguous_data() )
407
{ Helper::stride( m_stride , rhs ); }
409
template< class OtherArrayType >
410
ArrayNatural & operator = ( const OtherArrayType & rhs )
412
m_ptr = rhs.contiguous_data();
413
Helper::stride( m_stride , rhs );
417
//----------------------------------
418
// Class specific constructors:
420
ArrayNatural( value_type * arg_ptr ,
421
size_type n1 , size_type n2 , size_type n3 , size_type n4 ,
422
size_type n5 , size_type n6 , size_type n7 , size_type n8 )
425
array_bounds_check_rank_is_equal<Rank,8>();
426
ARRAY_STRIDE_NATURAL_8( m_stride, n1, n2, n3, n4, n5, n6, n7, n8 );
429
ArrayNatural( value_type * arg_ptr ,
430
size_type n1 , size_type n2 , size_type n3 , size_type n4 ,
431
size_type n5 , size_type n6 , size_type n7 )
434
array_bounds_check_rank_is_equal<Rank,7>();
435
ARRAY_STRIDE_NATURAL_7( m_stride, n1, n2, n3, n4, n5, n6, n7 );
438
ArrayNatural( value_type * arg_ptr ,
439
size_type n1 , size_type n2 , size_type n3 , size_type n4 ,
440
size_type n5 , size_type n6 )
443
array_bounds_check_rank_is_equal<Rank,6>();
444
ARRAY_STRIDE_NATURAL_6( m_stride, n1, n2, n3, n4, n5, n6 );
447
ArrayNatural( value_type * arg_ptr ,
448
size_type n1 , size_type n2 , size_type n3 , size_type n4 ,
452
array_bounds_check_rank_is_equal<Rank,5>();
453
ARRAY_STRIDE_NATURAL_5( m_stride, n1, n2, n3, n4, n5 );
456
ArrayNatural( value_type * arg_ptr ,
457
size_type n1 , size_type n2 , size_type n3 , size_type n4 )
460
array_bounds_check_rank_is_equal<Rank,4>();
461
ARRAY_STRIDE_NATURAL_4( m_stride, n1, n2, n3, n4 );
464
ArrayNatural( value_type * arg_ptr ,
465
size_type n1 , size_type n2 , size_type n3 )
468
array_bounds_check_rank_is_equal<Rank,3>();
469
ARRAY_STRIDE_NATURAL_3( m_stride, n1, n2, n3 );
472
ArrayNatural( value_type * arg_ptr ,
473
size_type n1 , size_type n2 )
476
array_bounds_check_rank_is_equal<Rank,2>();
477
ARRAY_STRIDE_NATURAL_2( m_stride, n1, n2 );
480
ArrayNatural( value_type * arg_ptr , size_type n1 )
483
array_bounds_check_rank_is_equal<Rank,1>();
488
//----------------------------------------------------------------------
490
template< typename Scalar ,
491
class Tag1 , class Tag2 , class Tag3 , class Tag4 ,
492
class Tag5 , class Tag6 , class Tag7 , class Tag8 >
496
// Required by all arrays:
497
typedef Scalar value_type ;
498
typedef int index_type ;
499
typedef size_t size_type ;
500
typedef const ArrayDimTag * tag_type ;
502
// Required by compile-time knowledge arrays:
504
typedef ArrayDimTagList<Tag1,Tag2,Tag3,Tag4,Tag5,Tag6,Tag7,Tag8> TagList ;
506
enum { Rank = TagList::Rank };
507
enum { Natural = false };
508
enum { Reverse = true };
509
enum { Contiguous = true };
511
template < unsigned Ord >
513
typedef typename ArrayDimTagListAt<TagList,Ord>::type type ;
518
typedef ArrayHelper< TagList::Rank > Helper ;
521
size_t m_stride[ TagList::Rank ];
524
class , class , class , class ,
525
class , class , class , class >
526
friend class ArrayNatural ;
529
class , class , class , class ,
530
class , class , class , class >
531
friend class ArrayFortran ;
535
//----------------------------------
537
unsigned rank() const { return Rank ; }
538
bool natural() const { return Natural ; }
539
bool reverse() const { return Reverse ; }
540
bool contiguous() const { return Contiguous ; }
542
tag_type tag( unsigned ord ) const
544
array_bounds_checking( Rank , ord );
545
return array_tags<TagList>()[ord] ;
548
//----------------------------------
550
size_type size() const { return m_stride[ Rank - 1 ]; }
552
template < unsigned Ord > size_type dimension() const
554
array_bounds_check_ordinal_is_less<Rank,Ord>();
555
return Ord ? m_stride[Ord] / m_stride[Ord-1] : m_stride[Ord] ;
558
size_type dimension( index_type ord ) const
560
array_bounds_checking( Rank , ord );
561
return ord ? m_stride[ord] / m_stride[ord-1] : m_stride[ord] ;
564
void dimensions( std::vector<size_type> & n )
568
for ( int i = 1 ; i < Rank ; ++i ) {
569
n[i] = m_stride[i] / m_stride[i-1] ;
573
//----------------------------------
574
/** \brief Access member data */
575
value_type * contiguous_data() const { return m_ptr ; }
577
/** \brief Access member via full ordering of members. */
578
value_type & operator[]( size_type i ) const
580
ARRAY_BOUNDS_CHECKING_ORDINAL( size() , i );
584
/** \brief Access member via Rank 8 multi-index */
585
value_type & operator()( index_type i1 , index_type i2 ,
586
index_type i3 , index_type i4 ,
587
index_type i5 , index_type i6 ,
588
index_type i7 , index_type i8 ) const
590
array_bounds_check_rank_is_equal<Rank,8>();
591
ARRAY_BOUNDS_CHECKING_8(i1,i2,i3,i4,i5,i6,i7,i8);
592
return m_ptr[ ARRAY_INDEX_FORTRAN_8(m_stride,i1,i2,i3,i4,i5,i6,i7,i8) ];
595
/** \brief Access member via Rank 7 multi-index */
596
value_type & operator()( index_type i1 , index_type i2 ,
597
index_type i3 , index_type i4 ,
598
index_type i5 , index_type i6 ,
599
index_type i7 ) const
601
array_bounds_check_rank_is_equal<Rank,7>();
602
ARRAY_BOUNDS_CHECKING_7(i1,i2,i3,i4,i5,i6,i7);
603
return m_ptr[ ARRAY_INDEX_FORTRAN_7(m_stride,i1,i2,i3,i4,i5,i6,i7) ];
606
/** \brief Access member via Rank 6 multi-index */
607
value_type & operator()( index_type i1 , index_type i2 ,
608
index_type i3 , index_type i4 ,
609
index_type i5 , index_type i6 ) const
611
array_bounds_check_rank_is_equal<Rank,6>();
612
ARRAY_BOUNDS_CHECKING_6(i1,i2,i3,i4,i5,i6);
613
return m_ptr[ ARRAY_INDEX_FORTRAN_6(m_stride,i1,i2,i3,i4,i5,i6) ];
616
/** \brief Access member via Rank 5 multi-index */
617
value_type & operator()( index_type i1 , index_type i2 ,
618
index_type i3 , index_type i4 ,
619
index_type i5 ) const
621
array_bounds_check_rank_is_equal<Rank,5>();
622
ARRAY_BOUNDS_CHECKING_5(i1,i2,i3,i4,i5);
623
return m_ptr[ ARRAY_INDEX_FORTRAN_5(m_stride,i1,i2,i3,i4,i5) ];
626
/** \brief Access member via Rank 4 multi-index */
627
value_type & operator()( index_type i1 , index_type i2 ,
628
index_type i3 , index_type i4 ) const
630
array_bounds_check_rank_is_equal<Rank,4>();
631
ARRAY_BOUNDS_CHECKING_4(i1,i2,i3,i4);
632
return m_ptr[ ARRAY_INDEX_FORTRAN_4(m_stride,i1,i2,i3,i4) ];
635
/** \brief Access member via Rank 3 multi-index */
636
value_type & operator()( index_type i1 , index_type i2 ,
637
index_type i3 ) const
639
array_bounds_check_rank_is_equal<Rank,3>();
640
ARRAY_BOUNDS_CHECKING_3(i1,i2,i3);
641
return m_ptr[ ARRAY_INDEX_FORTRAN_3(m_stride,i1,i2,i3) ];
644
/** \brief Access member via Rank 2 multi-index */
645
value_type & operator()( index_type i1 , index_type i2 ) const
647
array_bounds_check_rank_is_equal<Rank,2>();
648
ARRAY_BOUNDS_CHECKING_2(i1,i2);
649
return m_ptr[ ARRAY_INDEX_FORTRAN_2(m_stride,i1,i2) ];
652
/** \brief Access member via Rank 1 multi-index */
653
value_type & operator()( index_type i1 ) const
655
array_bounds_check_rank_is_equal<Rank,1>();
656
ARRAY_BOUNDS_CHECKING_1(i1);
660
//----------------------------------
661
// Required constructors and assignment operators:
663
ArrayFortran() : m_ptr(NULL) { Helper::zero( m_stride ); }
665
ArrayFortran( const ArrayFortran & rhs )
666
: m_ptr( rhs.m_ptr ) { Helper::copy( m_stride , rhs.m_stride ); }
668
ArrayFortran & operator = ( const ArrayFortran & rhs )
671
Helper::copy( m_stride , rhs.m_stride );
675
//----------------------------------
676
// Copy a reverse-map array
679
ArrayReverse<Scalar,Tag1,Tag2,Tag3,Tag4,Tag5,Tag6,Tag7,Tag8>::natural_type
682
ArrayFortran( const ReverseType & rhs )
683
: m_ptr( rhs.m_ptr ) { Helper::copy( m_stride , rhs.m_stride ); }
685
ArrayFortran & operator = ( const ReverseType & rhs )
688
Helper::copy( m_stride , rhs.m_stride );
692
//----------------------------------
696
ArrayTruncate<Scalar,Tag1,Tag2,Tag3,Tag4,Tag5,Tag6,Tag7,Tag8>::fortran_type
699
TruncatedViewType truncated_view( index_type i ) const
701
return TruncatedViewType( m_ptr + m_stride[ Rank - 2 ] * i ,
702
ArrayStride() , m_stride );
705
// "Power user" constructor, promising a properly strided input
706
ArrayFortran( value_type * arg_ptr ,
707
const ArrayStride & , const size_type * arg_stride )
708
: m_ptr( arg_ptr ) { Helper::copy( m_stride , arg_stride ); }
710
// "Power user" constructor, promising a properly strided input
711
ArrayFortran( value_type * arg_ptr ,
712
const ArrayStride & ,
713
const size_type * arg_stride ,
714
const size_type arg_append )
716
{ Helper::stride_append( m_stride , arg_stride , arg_append ); }
718
//----------------------------------
719
// Take pointer to other compatible array types.
721
template< class OtherArrayType >
722
explicit ArrayFortran( const OtherArrayType & rhs )
723
: m_ptr( rhs.contiguous_data() )
724
{ Helper::stride( m_stride , rhs ); }
726
template< class OtherArrayType >
727
ArrayFortran & operator = ( const OtherArrayType & rhs )
729
m_ptr = rhs.contiguous_data();
730
Helper::stride( m_stride , rhs );
734
//----------------------------------
735
// Class specific constructors:
737
ArrayFortran( value_type * arg_ptr ,
738
size_type n1 , size_type n2 , size_type n3 , size_type n4 ,
739
size_type n5 , size_type n6 , size_type n7 , size_type n8 )
742
array_bounds_check_rank_is_equal<Rank,8>();
743
ARRAY_STRIDE_FORTRAN_8( m_stride, n1, n2, n3, n4, n5, n6, n7, n8 );
746
ArrayFortran( value_type * arg_ptr ,
747
size_type n1 , size_type n2 , size_type n3 , size_type n4 ,
748
size_type n5 , size_type n6 , size_type n7 )
751
array_bounds_check_rank_is_equal<Rank,7>();
752
ARRAY_STRIDE_FORTRAN_7( m_stride, n1, n2, n3, n4, n5, n6, n7 );
755
ArrayFortran( value_type * arg_ptr ,
756
size_type n1 , size_type n2 , size_type n3 , size_type n4 ,
757
size_type n5 , size_type n6 )
760
array_bounds_check_rank_is_equal<Rank,6>();
761
ARRAY_STRIDE_FORTRAN_6( m_stride, n1, n2, n3, n4, n5, n6 );
764
ArrayFortran( value_type * arg_ptr ,
765
size_type n1 , size_type n2 , size_type n3 , size_type n4 ,
769
array_bounds_check_rank_is_equal<Rank,5>();
770
ARRAY_STRIDE_FORTRAN_5( m_stride, n1, n2, n3, n4, n5 );
773
ArrayFortran( value_type * arg_ptr ,
774
size_type n1 , size_type n2 , size_type n3 , size_type n4 )
777
array_bounds_check_rank_is_equal<Rank,4>();
778
ARRAY_STRIDE_FORTRAN_4( m_stride, n1, n2, n3, n4 );
781
ArrayFortran( value_type * arg_ptr ,
782
size_type n1 , size_type n2 , size_type n3 )
785
array_bounds_check_rank_is_equal<Rank,3>();
786
ARRAY_STRIDE_FORTRAN_3( m_stride, n1, n2, n3 );
789
ArrayFortran( value_type * arg_ptr ,
790
size_type n1 , size_type n2 )
793
array_bounds_check_rank_is_equal<Rank,2>();
794
ARRAY_STRIDE_FORTRAN_2( m_stride, n1, n2 );
797
ArrayFortran( value_type * arg_ptr ,
801
array_bounds_check_rank_is_equal<Rank,1>();
806
//----------------------------------------------------------------------
807
// Specialization for arrays with rank and dimension tags as runtime info.
809
template< typename Scalar >
810
class ArrayNatural< Scalar, void,void,void,void,void,void,void,void>
814
typedef Scalar value_type ;
815
typedef int index_type ;
816
typedef size_t size_type ;
817
typedef const ArrayDimTag * tag_type ;
819
enum { Natural = true };
820
enum { Reverse = false };
821
enum { Contiguous = true };
827
size_type m_stride[8];
830
typedef ArrayHelper<8> Helper ;
833
class , class , class , class ,
834
class , class , class , class >
835
friend class ArrayNatural ;
838
class , class , class , class ,
839
class , class , class , class >
840
friend class ArrayFortran ;
844
//----------------------------------
846
unsigned rank() const { return m_rank ; }
847
bool natural() const { return Natural ; }
848
bool reverse() const { return Reverse ; }
849
bool contiguous() const { return Contiguous ; }
851
tag_type tag( unsigned ord ) const
853
array_bounds_checking( m_rank , ord );
854
return m_tag[ ( m_rank - 1 ) - ord ];
857
//----------------------------------
859
size_type size() const { return m_stride[ m_rank - 1 ]; }
861
size_type dimension( index_type ord ) const
863
array_bounds_checking( m_rank , ord );
864
const int i = ( m_rank - 1 ) - ord ;
865
return i ? m_stride[i] / m_stride[i-1] : m_stride[i] ;
868
void dimensions( std::vector<size_type> & n )
871
n[m_rank-1] = m_stride[0] ;
872
for ( int i = 1 ; i < m_rank ; ++i ) {
873
n[ ( m_rank - 1 ) - i ] = m_stride[i] / m_stride[i-1] ;
877
//----------------------------------
878
/** \brief Access member data */
879
value_type * contiguous_data() const { return m_ptr ; }
881
/** \brief Access member via full ordering of members. */
882
value_type & operator[]( size_type i ) const
884
ARRAY_BOUNDS_CHECKING_ORDINAL( size() , i );
888
/** \brief Access member via Rank 8 multi-index */
889
value_type & operator()( index_type i1 , index_type i2 ,
890
index_type i3 , index_type i4 ,
891
index_type i5 , index_type i6 ,
892
index_type i7 , index_type i8 ) const
894
ARRAY_BOUNDS_CHECKING_8(i1,i2,i3,i4,i5,i6,i7,i8);
895
return m_ptr[ ARRAY_INDEX_NATURAL_8(m_stride,i1,i2,i3,i4,i5,i6,i7,i8) ];
898
/** \brief Access member via Rank 7 multi-index */
899
value_type & operator()( index_type i1 , index_type i2 ,
900
index_type i3 , index_type i4 ,
901
index_type i5 , index_type i6 ,
902
index_type i7 ) const
904
ARRAY_BOUNDS_CHECKING_7(i1,i2,i3,i4,i5,i6,i7);
905
return m_ptr[ ARRAY_INDEX_NATURAL_7(m_stride,i1,i2,i3,i4,i5,i6,i7) ];
908
/** \brief Access member via Rank 6 multi-index */
909
value_type & operator()( index_type i1 , index_type i2 ,
910
index_type i3 , index_type i4 ,
911
index_type i5 , index_type i6 ) const
913
ARRAY_BOUNDS_CHECKING_6(i1,i2,i3,i4,i5,i6);
914
return m_ptr[ ARRAY_INDEX_NATURAL_6(m_stride,i1,i2,i3,i4,i5,i6) ];
917
/** \brief Access member via Rank 5 multi-index */
918
value_type & operator()( index_type i1 , index_type i2 ,
919
index_type i3 , index_type i4 ,
920
index_type i5 ) const
922
ARRAY_BOUNDS_CHECKING_5(i1,i2,i3,i4,i5);
923
return m_ptr[ ARRAY_INDEX_NATURAL_5(m_stride,i1,i2,i3,i4,i5) ];
926
/** \brief Access member via Rank 4 multi-index */
927
value_type & operator()( index_type i1 , index_type i2 ,
928
index_type i3 , index_type i4 ) const
930
ARRAY_BOUNDS_CHECKING_4(i1,i2,i3,i4);
931
return m_ptr[ ARRAY_INDEX_NATURAL_4(m_stride,i1,i2,i3,i4) ];
934
/** \brief Access member via Rank 3 multi-index */
935
value_type & operator()( index_type i1 , index_type i2 ,
936
index_type i3 ) const
938
ARRAY_BOUNDS_CHECKING_3(i1,i2,i3);
939
return m_ptr[ ARRAY_INDEX_NATURAL_3(m_stride,i1,i2,i3) ];
942
/** \brief Access member via Rank 2 multi-index */
943
value_type & operator()( index_type i1 , index_type i2 ) const
945
ARRAY_BOUNDS_CHECKING_2(i1,i2);
946
return m_ptr[ ARRAY_INDEX_NATURAL_2(m_stride,i1,i2) ];
949
/** \brief Access member via Rank 1 multi-index */
950
value_type & operator()( index_type i1 ) const
952
ARRAY_BOUNDS_CHECKING_1(i1);
956
//----------------------------------
957
/** \brief Truncate view of the array */
959
typedef ArrayNatural<Scalar> TruncateViewType ;
961
TruncateViewType truncated_view( index_type i ) const
963
return TruncateViewType( m_ptr + m_stride[ m_rank - 2 ] * i ,
970
ArrayNatural( value_type * arg_ptr ,
972
const ArrayStride & ,
973
const size_type * arg_stride ,
975
: m_ptr( arg_ptr ), m_rank( arg_rank )
977
Helper::copy( m_stride , arg_stride );
978
Helper::copy( m_tag , arg_tag );
981
//----------------------------------
982
// Required constructors and assignment operators:
985
: m_ptr(NULL), m_rank(0)
987
Helper::zero( m_stride );
988
Helper::zero( m_tag );
991
ArrayNatural( const ArrayNatural & rhs )
992
: m_ptr( rhs.m_ptr ), m_rank( rhs.m_rank )
994
Helper::copy( m_stride , rhs.m_stride );
995
Helper::copy( m_tag , rhs.m_tag );
998
ArrayNatural & operator = ( const ArrayNatural & rhs )
1001
m_rank = rhs.m_rank ;
1002
Helper::copy( m_stride , rhs.m_stride );
1003
Helper::copy( m_tag , rhs.m_tag );
1007
//----------------------------------
1009
ArrayNatural( const ArrayFortran<Scalar> & rhs )
1010
: m_ptr( rhs.m_ptr ), m_rank( rhs.m_rank )
1012
Helper::copy( m_stride , rhs.m_stride );
1013
Helper::copy( m_tag , rhs.m_tag );
1016
ArrayNatural & operator = ( const ArrayFortran<Scalar> & rhs )
1019
m_rank = rhs.m_rank ;
1020
Helper::copy( m_stride , rhs.m_stride );
1021
Helper::copy( m_tag , rhs.m_tag );
1025
//----------------------------------
1026
// Take pointer to other compatible array types.
1028
template< class OtherArrayType >
1029
ArrayNatural( const OtherArrayType & rhs )
1030
: m_ptr( rhs.contiguous_data() ), m_rank( rhs.rank() )
1032
Helper::stride( m_stride , rhs );
1033
Helper::tags( m_tag , rhs );
1036
template< class OtherArrayType >
1037
ArrayNatural & operator = ( const OtherArrayType & rhs )
1039
m_ptr = rhs.contiguous_data();
1040
m_rank = rhs.rank();
1041
Helper::stride( m_stride , rhs );
1042
Helper::tags( m_tag , rhs );
1046
//----------------------------------
1047
// Class specific constructors:
1049
ArrayNatural( value_type * arg_ptr ,
1050
const std::vector<size_type> & arg_size ,
1051
const std::vector<tag_type> & arg_tag )
1053
m_rank( arg_size.size() == arg_tag.size() ? arg_size.size() : 0 )
1055
array_stride_from_natural_sizes( m_rank , m_stride , & arg_size[0] );
1056
array_stride_natural_tag( m_rank , m_tag , & arg_tag[0] );
1060
//----------------------------------------------------------------------
1061
// Specialization for arrays with rank and dimension tags as runtime info.
1063
template< typename Scalar >
1064
class ArrayFortran< Scalar, void,void,void,void,void,void,void,void>
1068
typedef Scalar value_type ;
1069
typedef int index_type ;
1070
typedef size_t size_type ;
1071
typedef const ArrayDimTag * tag_type ;
1073
enum { Natural = false };
1074
enum { Reverse = true };
1075
enum { Contiguous = true };
1081
size_type m_stride[8];
1084
typedef ArrayHelper<8> Helper ;
1086
template< typename ,
1087
class , class , class , class ,
1088
class , class , class , class >
1089
friend class ArrayNatural ;
1091
template< typename ,
1092
class , class , class , class ,
1093
class , class , class , class >
1094
friend class ArrayFortran ;
1098
//----------------------------------
1100
unsigned rank() const { return m_rank ; }
1101
bool natural() const { return Natural ; }
1102
bool reverse() const { return Reverse ; }
1103
bool contiguous() const { return Contiguous ; }
1105
tag_type tag( unsigned ord ) const
1107
array_bounds_checking( m_rank , ord );
1108
return m_tag[ ord ];
1111
//----------------------------------
1113
size_type size() const { return m_stride[ m_rank - 1 ]; }
1115
size_type dimension( index_type ord ) const
1117
array_bounds_checking( m_rank , ord );
1118
return ord ? m_stride[ord] / m_stride[ord-1] : m_stride[ord] ;
1121
void dimensions( std::vector<size_type> & n )
1124
n[0] = m_stride[0] ;
1125
for ( int i = 1 ; i < m_rank ; ++i ) {
1126
n[i] = m_stride[i] / m_stride[i-1] ;
1130
//----------------------------------
1131
/** \brief Access member data */
1132
value_type * contiguous_data() const { return m_ptr ; }
1134
/** \brief Access member via full ordering of members. */
1135
value_type & operator[]( size_type i ) const
1137
ARRAY_BOUNDS_CHECKING_ORDINAL( size() , i );
1141
/** \brief Access member via Rank 8 multi-index */
1142
value_type & operator()( index_type i1 , index_type i2 ,
1143
index_type i3 , index_type i4 ,
1144
index_type i5 , index_type i6 ,
1145
index_type i7 , index_type i8 ) const
1147
ARRAY_BOUNDS_CHECKING_8(i1,i2,i3,i4,i5,i6,i7,i8);
1148
return m_ptr[ ARRAY_INDEX_FORTRAN_8(m_stride,i1,i2,i3,i4,i5,i6,i7,i8) ];
1151
/** \brief Access member via Rank 7 multi-index */
1152
value_type & operator()( index_type i1 , index_type i2 ,
1153
index_type i3 , index_type i4 ,
1154
index_type i5 , index_type i6 ,
1155
index_type i7 ) const
1157
ARRAY_BOUNDS_CHECKING_7(i1,i2,i3,i4,i5,i6,i7);
1158
return m_ptr[ ARRAY_INDEX_FORTRAN_7(m_stride,i1,i2,i3,i4,i5,i6,i7) ];
1161
/** \brief Access member via Rank 6 multi-index */
1162
value_type & operator()( index_type i1 , index_type i2 ,
1163
index_type i3 , index_type i4 ,
1164
index_type i5 , index_type i6 ) const
1166
ARRAY_BOUNDS_CHECKING_6(i1,i2,i3,i4,i5,i6);
1167
return m_ptr[ ARRAY_INDEX_FORTRAN_6(m_stride,i1,i2,i3,i4,i5,i6) ];
1170
/** \brief Access member via Rank 5 multi-index */
1171
value_type & operator()( index_type i1 , index_type i2 ,
1172
index_type i3 , index_type i4 ,
1173
index_type i5 ) const
1175
ARRAY_BOUNDS_CHECKING_5(i1,i2,i3,i4,i5);
1176
return m_ptr[ ARRAY_INDEX_FORTRAN_5(m_stride,i1,i2,i3,i4,i5) ];
1179
/** \brief Access member via Rank 4 multi-index */
1180
value_type & operator()( index_type i1 , index_type i2 ,
1181
index_type i3 , index_type i4 ) const
1183
ARRAY_BOUNDS_CHECKING_4(i1,i2,i3,i4);
1184
return m_ptr[ ARRAY_INDEX_FORTRAN_4(m_stride,i1,i2,i3,i4) ];
1187
/** \brief Access member via Rank 3 multi-index */
1188
value_type & operator()( index_type i1 , index_type i2 ,
1189
index_type i3 ) const
1191
ARRAY_BOUNDS_CHECKING_3(i1,i2,i3);
1192
return m_ptr[ ARRAY_INDEX_FORTRAN_3(m_stride,i1,i2,i3) ];
1195
/** \brief Access member via Rank 2 multi-index */
1196
value_type & operator()( index_type i1 , index_type i2 ) const
1198
ARRAY_BOUNDS_CHECKING_2(i1,i2);
1199
return m_ptr[ ARRAY_INDEX_FORTRAN_2(m_stride,i1,i2) ];
1202
/** \brief Access member via Rank 1 multi-index */
1203
value_type & operator()( index_type i1 ) const
1205
ARRAY_BOUNDS_CHECKING_1(i1);
1209
//----------------------------------
1210
/** \brief Truncate view of the array */
1212
typedef ArrayFortran<Scalar> TruncateViewType ;
1214
TruncateViewType truncated_view( index_type i ) const
1216
return TruncateViewType( m_ptr + m_stride[ m_rank - 2 ] * i ,
1223
ArrayFortran( value_type * arg_ptr ,
1224
size_type arg_rank ,
1225
const ArrayStride & ,
1226
const size_type * arg_stride ,
1227
tag_type * arg_tag )
1228
: m_ptr( arg_ptr ), m_rank( arg_rank )
1230
Helper::copy( m_stride , arg_stride );
1231
Helper::copy( m_tag , arg_tag );
1234
//----------------------------------
1235
// Required constructors and assignment operators:
1238
: m_ptr(NULL), m_rank(0)
1240
Helper::zero( m_stride );
1241
Helper::zero( m_tag );
1244
ArrayFortran( const ArrayFortran & rhs )
1245
: m_ptr( rhs.m_ptr ), m_rank( rhs.m_rank )
1247
Helper::copy( m_stride , rhs.m_stride );
1248
Helper::copy( m_tag , rhs.m_tag );
1251
ArrayFortran & operator = ( const ArrayFortran & rhs )
1254
m_rank = rhs.m_rank ;
1255
Helper::copy( m_stride , rhs.m_stride );
1256
Helper::copy( m_tag , rhs.m_tag );
1260
ArrayFortran( const ArrayNatural<Scalar> & rhs )
1261
: m_ptr( rhs.m_ptr ), m_rank( rhs.m_rank )
1263
Helper::copy( m_stride , rhs.m_stride );
1264
Helper::copy( m_tag , rhs.m_tag );
1267
ArrayFortran & operator = ( const ArrayNatural<Scalar> & rhs )
1270
m_rank = rhs.m_rank ;
1271
Helper::copy( m_stride , rhs.m_stride );
1272
Helper::copy( m_tag , rhs.m_tag );
1276
//----------------------------------
1277
// Take pointer to other compatible array types.
1279
template< class OtherArrayType >
1280
ArrayFortran( const OtherArrayType & rhs )
1281
: m_ptr( rhs.contiguous_data() ), m_rank( rhs.rank() )
1283
Helper::stride( m_stride , rhs );
1284
Helper::tags( m_tag , rhs );
1287
template< class OtherArrayType >
1288
ArrayFortran & operator = ( const OtherArrayType & rhs )
1290
m_ptr = rhs.contiguous_data();
1291
m_rank = rhs.m_rank();
1292
Helper::stride( m_stride , rhs );
1293
Helper::tags( m_tag , rhs );
1297
//----------------------------------
1298
// Class specific constructors:
1300
ArrayFortran( value_type * arg_ptr ,
1301
const std::vector<size_type> & arg_size ,
1302
const std::vector<tag_type> & arg_tag )
1304
m_rank( arg_size.size() == arg_tag.size() ? arg_size.size() : 0 )
1306
array_stride_from_fortran_sizes( m_rank , m_stride , & arg_size[0] );
1307
array_stride_fortran_tag( m_rank , m_tag , & arg_tag[0] );
1311
//----------------------------------------------------------------------