Chombo + EB + MF  3.2
CHArray.H
Go to the documentation of this file.
1 #ifdef CH_LANG_CC
2 /*
3  * _______ __
4  * / ___/ / ___ __ _ / / ___
5  * / /__/ _ \/ _ \/ V \/ _ \/ _ \
6  * \___/_//_/\___/_/_/_/_.__/\___/
7  * Please refer to Copyright.txt, in Chombo's root directory.
8  */
9 #endif
10 
11 #ifndef _CHARRAY_H_
12 #define _CHARRAY_H_
13 
14 /******************************************************************************/
15 /**
16  * \file
17  *
18  * \brief A multi-dimensional array class for Chombo
19  *
20  *//***************************************************************************/
21 // search for 'class CHArray'
22 
23 #include <iomanip>
24 
25 #include "CHArray_fwd.H"
26 
27 #ifdef CH_SPACEDIM
28 // In Chombo land
29  #include "REAL.H"
30  #include "Misc.H"
31  #include "Box.H"
32  #include "NamespaceHeader.H"
33 #else
34 // Probably testing land
35  #include <cassert>
36 // #define CH_assert(cond) (void)0
37  #define CH_assert(cond) assert(cond)
38  #define SpaceDim 2
39  #define D_DECL6(a,b,c,d,e,f) a,b
40  #define D_TERM6(a,b,c,d,e,f) a b
41  typedef double Real;
42  class IntVect
43  {
44  public:
45  IntVect(D_DECL6(const int i0, const int i1, const int i2,
46  const int i3, const int i4, const int i5))
47  {
48  D_TERM6(vec[0] = i0;, vec[1] = i1;, vec[2] = i2;,
49  vec[3] = i3;, vec[4] = i4;, vec[5] = i5;)
50  }
51  IntVect(const IntVect &iv)
52  {
53  D_TERM6(vec[0] = iv.vec[0];, vec[1] = iv.vec[1];, vec[2] = iv.vec[2];,
54  vec[3] = iv.vec[3];, vec[4] = iv.vec[4];, vec[5] = iv.vec[5];)
55  }
56  int &operator[](const int i)
57  {
58  return vec[i];
59  }
60  const int &operator[](const int i) const
61  {
62  return vec[i];
63  }
64  int product() const
65  {
66  int prod = 1;
67  for (int i = 0; i != SpaceDim; ++i) prod *= vec[i];
68  return prod;
69  }
70  int vec[SpaceDim];
71  };
72  class Box
73  {
74  public:
75  Box(const IntVect &lb, const IntVect &ub)
76  : m_lb(lb), m_ub(ub)
77  { }
78  int smallEnd(const int dir) const
79  {
80  return m_lb[dir];
81  }
82  int bigEnd(const int dir) const
83  {
84  return m_ub[dir];
85  }
86  IntVect size() const
87  {
88  return IntVect(D_DECL6(m_ub[0] - m_lb[0] + 1,
89  m_ub[1] - m_lb[1] + 1,
90  m_ub[2] - m_lb[2] + 1,
91  m_ub[3] - m_lb[3] + 1,
92  m_ub[4] - m_lb[4] + 1,
93  m_ub[5] - m_lb[5] + 1));
94  }
97  };
98  // Test for class type
99  namespace Misc {
100  template <typename T>
101  class TypeTr
102  {
103  private:
104  typedef char One;
105  typedef struct
106  {
107  char a[2];
108  } Two;
109  template <typename C> static One test(int C::*);
110  template <typename C> static Two test(...);
111  public:
112  enum
113  {
114  IsClass = sizeof(TypeTr<T>::template test<T>(0)) == 1
115  };
116  };
117  }
118 #endif
119 
120 // How to index an IntVect. May evaluate to, e.g., iv[0], iv[1], iv[2] or
121 // iv[2], iv[1], iv[0]
122 # define D_DEFIV D_DECL6(DimT(iv[Indexer::ixIV(0)]), \
123  DimT(iv[Indexer::ixIV(1)]), \
124  DimT(iv[Indexer::ixIV(2)]), \
125  DimT(iv[Indexer::ixIV(3)]), \
126  DimT(iv[Indexer::ixIV(4)]), \
127  DimT(iv[Indexer::ixIV(5)]))
128 
129 // How to index a Box. Same as above but determines a range.
130 # define D_DEFBOX D_DECL6(DimT(box.smallEnd(Indexer::ixIV(0)), \
131  box.bigEnd(Indexer::ixIV(0))), \
132  DimT(box.smallEnd(Indexer::ixIV(1)), \
133  box.bigEnd(Indexer::ixIV(1))), \
134  DimT(box.smallEnd(Indexer::ixIV(2)), \
135  box.bigEnd(Indexer::ixIV(2))), \
136  DimT(box.smallEnd(Indexer::ixIV(3)), \
137  box.bigEnd(Indexer::ixIV(3))), \
138  DimT(box.smallEnd(Indexer::ixIV(4)), \
139  box.bigEnd(Indexer::ixIV(4))), \
140  DimT(box.smallEnd(Indexer::ixIV(5)), \
141  box.bigEnd(Indexer::ixIV(5))))
142 
143 // How to index an IntVect. May evaluate to, e.g., iv[0], iv[1], iv[2] or
144 // iv[2], iv[1], iv[0]
145 # define D_IXIV D_DECL6(iv[Indexer::ixIV(0)], \
146  iv[Indexer::ixIV(1)], \
147  iv[Indexer::ixIV(2)], \
148  iv[Indexer::ixIV(3)], \
149  iv[Indexer::ixIV(4)], \
150  iv[Indexer::ixIV(5)])
151 
152 /* These sizes are in CHArray_fwd.H
153 namespace ArSp // CHArray support
154 {
155 
156 // An index refers to a single dimension and a size to the overall
157 // size of the array. Except for 1D arrays, indexes are smaller than
158 // sizes by division by at least 1 stride.
159 
160 typedef int IIx_t; ///< Type of int for an index. Must be
161  ///< signed to allow for lower bounds
162  ///< != 0
163 typedef unsigned USz_t; ///< Type of unsigned int for a size
164 }
165  */
166 
167 /* This enum had to be put in CHArray_fwd.H because it is used for default
168  * template parameters. Repeated here for informational purposes
169 /|/ Array configuration parameters
170 enum
171 {
172  ArZeroRow, /|/< Zero lower bound and row-storage
173  ArZeroCol, /|/< Zero lower bound and column-storage
174  ArRangeRow, /|/< Range of subscripts and row-storage
175  ArRangeCol /|/< Range of subscripts and column-
176  /|/< storage
177 };
178  */
179 
180 /*====================================================================*/
181 /// Defines a range of subscripts
182 /*====================================================================*/
183 
184 struct CHRange
185 {
186  CHRange(const ArSp::IIx_t a_dimE)
187  : dimB(0), dimE(a_dimE - 1)
188  {
189  CH_assert(a_dimE >= 0);
190  }
191  CHRange(const ArSp::IIx_t a_dimB, const ArSp::IIx_t a_dimE)
192  : dimB(a_dimB), dimE(a_dimE)
193  {
194  CH_assert(a_dimE >= a_dimB);
195  }
198 };
199 
200 /*====================================================================*/
201 /** \name Support for describing dimensions by a range of subscripts
202  *//*=================================================================*/
203 //@{
204 
205 namespace ArSp // CHArray support
206 {
207 
208 /// Get the size of a dimension
209 template <typename T>
210 inline USz_t sizeOfDim(const T &dim)
211 {
212  return (USz_t)dim;
213 }
214 
215 ///
216 template <>
218 {
219  return (USz_t)(dim.dimE - dim.dimB + 1);
220 }
221 }
222 
223 /// Multiply two dimensions
224 inline ArSp::USz_t operator*(const CHRange &a, const CHRange &b)
225 {
226  return (ArSp::sizeOfDim(a)*ArSp::sizeOfDim(b));
227 }
228 
229 ///
230 inline ArSp::USz_t operator*(const ArSp::USz_t &i, const CHRange &a)
231 {
232  return i*ArSp::sizeOfDim(a);
233 }
234 
235 ///
236 inline ArSp::USz_t operator*(const CHRange &a, const ArSp::USz_t &i)
237 {
238  return ArSp::sizeOfDim(a)*i;
239 }
240 //@}
241 
242 namespace ArSp // CHArray support
243 {
244 
245 /*====================================================================*/
246 /** \name Raw address allocation policy
247  *//*=================================================================*/
248 //@{
249 
250 template <typename T, bool IsClass = Misc::TypeTr<T>::IsClass>
252 
253 /// If elements are class type, allocate using placement new
254 template <typename T>
255 struct AllocRawPolicy<T, true>
256 {
257  static T *eval(void *const addr, const USz_t size)
258  {
259  return new(addr) T[size];
260  }
261 };
262 
263 /// If element are not class type, just assign the address
264 template <typename T>
265 struct AllocRawPolicy<T, false>
266 {
267  static T *eval(void *const addr, const USz_t size)
268  {
269  return static_cast<T*>(addr);
270  }
271 };
272 //@}
273 
274 /*====================================================================*/
275 /** \name Raw address release policy
276  *//*=================================================================*/
277 //@{
278 
279 template <typename T, bool IsClass = Misc::TypeTr<T>::IsClass>
281 
282 /// If elements are class type, invoke destructor on each element
283 template <typename T>
284 struct ReleaseRawPolicy<T, true>
285 {
286  static void eval(T *p, USz_t size)
287  {
288  while (size--) p++->~T();
289  }
290 };
291 
292 /// If elements are not class type, do nothing
293 template <typename T>
294 struct ReleaseRawPolicy<T, false>
295 {
296  static void eval(T *p, USz_t size)
297  {
298  }
299 };
300 //@}
301 
302 /*====================================================================*/
303 /// Default allocator
304 /** Allocators used by class array are simplified versions of the
305  * std::allocator and may contain member data.
306  * The following members are required:
307  * <ul>
308  * <li> allocate(const USz_t size)
309  * - Allocate and construct 'size' objects
310  * <li> deallocate(void *const addr, const USz_t size)
311  * - Deallocate and destroy 'size' objects at 'addr'
312  * </ul>
313  * The following members are optional:
314  * <ul>
315  * <li> allocate(void *const addr, const USz_t size)
316  * - Construct 'size' objects at 'addr'. If provided,
317  * CHArray::define(void *const addr, ...) can be used to
318  * construct on preallocated memory. In this case,
319  * deallocate should only destroy the created objects,
320  * not delete the memory.
321  * </ul>
322  *//*=================================================================*/
323 
324 template <typename T>
326 {
327 private:
328  enum AllocBy
329  {
332  AllocRaw
333  };
335 
336 public:
338  : m_allocBy(AllocUndefined)
339  { }
340 
341  T* allocate(const USz_t size)
342  {
343  T *const p = new(std::nothrow) T[size];
344  CH_assert(p != 0);
345  m_allocBy = AllocNew;
346  return p;
347  }
348 
349  T* allocate(void *const addr, const USz_t size)
350  {
351  m_allocBy = AllocRaw;
352  return AllocRawPolicy<T>::eval(addr, size);
353  }
354 
355  void deallocate(T *p, const USz_t size)
356  {
357  switch (m_allocBy)
358  {
359  case AllocNew:
360  delete[] p;
361  break;
362  case AllocRaw:
363  ReleaseRawPolicy<T>::eval(p, size);
364  break;
365  case AllocUndefined:
366  break;
367  }
368  }
369 };
370 
371 /*====================================================================*/
372 /** \name Data for the indexer classes. This may vary in size
373  * depending on if the subscripts are zero-based or ranges.
374  *//*=================================================================*/
375 //@{
376 
377 /*--------------------------------------------------------------------*/
378 /// Any rank and a zero-based subscript
379 /*--------------------------------------------------------------------*/
380 
381 template <unsigned Rank, typename DimT>
383 {
384 protected:
386  : m_ixStride(0)
387  { }
388  IndexerData(const USz_t stride, const DimT &dim)
389  : m_ixStride(stride)
390  { }
391  void ixDefineLowerBound(const DimT &dim)
392  { }
394  {
395  return 0;
396  }
397  bool ixValidBounds(const IIx_t i, const USz_t size) const
398  {
399  return (((USz_t)i) < size/m_ixStride);
400  }
402  {
403  return 0;
404  }
405  USz_t m_ixStride; ///< Stride for this dimension
406 };
407 
408 /*--------------------------------------------------------------------*/
409 /// Any rank and a subscript range
410 /*--------------------------------------------------------------------*/
411 
412 template <unsigned Rank>
413 class IndexerData<Rank, CHRange>
414 {
415 protected:
417  : m_ixStride(0), m_ixIB(0)
418  { }
419  IndexerData(const USz_t stride, const CHRange &dim)
420  : m_ixStride(stride), m_ixIB(dim.dimB)
421  { }
423  {
424  m_ixIB = dim.dimB;
425  }
427  {
428  return m_ixIB;
429  }
430  bool ixValidBounds(const IIx_t i, const USz_t size) const
431  {
432  return (i >= m_ixIB && i < m_ixIB + (IIx_t)(size/m_ixStride));
433  }
435  {
436  return m_ixIB*m_ixStride;
437  }
438  USz_t m_ixStride; ///< Stride for this dimension
439 private:
440  IIx_t m_ixIB; ///< Lower bound for this dimension
441 };
442 
443 /*--------------------------------------------------------------------*/
444 /// Rank 1 and a zero-based subscript (no data)
445 /*--------------------------------------------------------------------*/
446 
447 template <typename DimT>
448 class IndexerData<1, DimT>
449 {
450 protected:
452  { }
453  IndexerData(const DimT &dim)
454  { }
455  void ixDefineLowerBound(const DimT &dim)
456  { }
458  {
459  return 0;
460  }
461  bool ixValidBounds(const IIx_t i, const USz_t size) const
462  {
463  return (((USz_t)i) < size);
464  }
465  void ixDefineTotalOffset(const IIx_t offset)
466  { }
468  {
469  return 0;
470  }
471 };
472 
473 /*--------------------------------------------------------------------*/
474 /// Rank 1 and a subscript range
475 /*--------------------------------------------------------------------*/
476 
477 template <>
479 {
480 protected:
482  : m_ixIB(0)
483  { }
485  : m_ixIB(dim.dimB)
486  { }
488  {
489  m_ixIB = dim.dimB;
490  }
492  {
493  return m_ixIB;
494  }
495  bool ixValidBounds(const IIx_t i, const USz_t size) const
496  {
497  return (i >= m_ixIB && i < m_ixIB + (IIx_t)size);
498  }
499  void ixDefineTotalOffset(const IIx_t offset)
500  {
501  m_ixOffset = offset;
502  }
504  {
505  return m_ixOffset;
506  }
507 private:
508  IIx_t m_ixIB; ///< Lower bound for this dimension
509  IIx_t m_ixOffset; ///< Total offset to an index because of
510  ///< non-zero lower bounds for this and
511  ///< all higher dimensions
512 };
513 
514 /*====================================================================*/
515 /** \name Provides indexing for row ordered (C) storage.
516  *//*=================================================================*/
517 //@{
518 
519 /*--------------------------------------------------------------------*/
520 /// Rank > 2 for zero-based subscripts and > 1 for subscript ranges
521 /*--------------------------------------------------------------------*/
522 
523 template <unsigned Rank, typename DimT>
524 class RSIndexer : private IndexerData<Rank, DimT>
525 {
527 public:
529  : IxData(), m_ixNext()
530  { }
531 
532  RSIndexer(const IIx_t offset,
533  const DimT &dim6, const DimT &dim5, const DimT &dim4,
534  const DimT &dim3, const DimT &dim2, const DimT &dim1,
535  const DimT &dim0)
536  : IxData(dim5*dim4*dim3*dim2*dim1*dim0, dim6),
537  m_ixNext(offset - IxData::ixDimOffset(),
538  dim5, dim4, dim3, dim2, dim1, dim0)
539  { }
540  RSIndexer(const IIx_t offset,
541  const DimT &dim5, const DimT &dim4, const DimT &dim3,
542  const DimT &dim2, const DimT &dim1, const DimT &dim0)
543  : IxData(dim4*dim3*dim2*dim1*dim0, dim5),
544  m_ixNext(offset - IxData::ixDimOffset(), dim4, dim3, dim2, dim1, dim0)
545  { }
546  RSIndexer(const IIx_t offset,
547  const DimT &dim4, const DimT &dim3, const DimT &dim2,
548  const DimT &dim1, const DimT &dim0)
549  : IxData(dim3*dim2*dim1*dim0, dim4),
550  m_ixNext(offset - IxData::ixDimOffset(), dim3, dim2, dim1, dim0)
551  { }
552  RSIndexer(const IIx_t offset,
553  const DimT &dim3, const DimT &dim2, const DimT &dim1,
554  const DimT &dim0)
555  : IxData(dim2*dim1*dim0, dim3),
556  m_ixNext(offset - IxData::ixDimOffset(), dim2, dim1, dim0)
557  { }
558  RSIndexer(const IIx_t offset,
559  const DimT &dim2, const DimT &dim1, const DimT &dim0)
560  : IxData(dim1*dim0, dim2),
561  m_ixNext(offset - IxData::ixDimOffset(), dim1, dim0)
562  { }
563  RSIndexer(const IIx_t offset,
564  const DimT &dim1, const DimT &dim0)
565  : IxData(sizeOfDim(dim0), dim1),
566  m_ixNext(offset - IxData::ixDimOffset(), dim0)
567  { }
568 
569  void ixDefine(const IIx_t offset,
570  const DimT &dim6, const DimT &dim5, const DimT &dim4,
571  const DimT &dim3, const DimT &dim2, const DimT &dim1,
572  const DimT &dim0)
573  {
574  IxData::m_ixStride = dim5*dim4*dim3*dim2*dim1*dim0;
575  IxData::ixDefineLowerBound(dim6);
576  m_ixNext.ixDefine(offset - IxData::ixDimOffset(),
577  dim5, dim4, dim3, dim2, dim1, dim0);
578  }
579  void ixDefine(const IIx_t offset,
580  const DimT &dim5, const DimT &dim4, const DimT &dim3,
581  const DimT &dim2, const DimT &dim1, const DimT &dim0)
582  {
583  IxData::m_ixStride = dim4*dim3*dim2*dim1*dim0;
584  IxData::ixDefineLowerBound(dim5);
585  m_ixNext.ixDefine(offset - IxData::ixDimOffset(),
586  dim4, dim3, dim2, dim1, dim0);
587  }
588  void ixDefine(const IIx_t offset,
589  const DimT &dim4, const DimT &dim3, const DimT &dim2,
590  const DimT &dim1, const DimT &dim0)
591  {
592  IxData::m_ixStride = dim3*dim2*dim1*dim0;
593  IxData::ixDefineLowerBound(dim4);
594  m_ixNext.ixDefine(offset - IxData::ixDimOffset(), dim3, dim2, dim1, dim0);
595  }
596  void ixDefine(const IIx_t offset,
597  const DimT &dim3, const DimT &dim2, const DimT &dim1,
598  const DimT &dim0)
599  {
600  IxData::m_ixStride = dim2*dim1*dim0;
601  IxData::ixDefineLowerBound(dim3);
602  m_ixNext.ixDefine(offset - IxData::ixDimOffset(), dim2, dim1, dim0);
603  }
604  void ixDefine(const IIx_t offset,
605  const DimT &dim2, const DimT &dim1, const DimT &dim0)
606  {
607  IxData::m_ixStride = dim1*dim0;
608  IxData::ixDefineLowerBound(dim2);
609  m_ixNext.ixDefine(offset - IxData::ixDimOffset(), dim1, dim0);
610  }
611  void ixDefine(const IIx_t offset,
612  const DimT &dim1, const DimT &dim0)
613  {
614  IxData::m_ixStride = sizeOfDim(dim0);
615  IxData::ixDefineLowerBound(dim1);
616  m_ixNext.ixDefine(offset - IxData::ixDimOffset(), dim0);
617  }
618 
619  USz_t ixIndex1D(const USz_t size,
620  const IIx_t i6, const IIx_t i5, const IIx_t i4,
621  const IIx_t i3, const IIx_t i2, const IIx_t i1,
622  const IIx_t i0) const
623  {
624  CH_assert((IxData::ixValidBounds(i6, size)));
625  return IxData::m_ixStride*i6 +
626  m_ixNext.ixIndex1D(IxData::m_ixStride, i5, i4, i3, i2, i1, i0);
627  }
628  USz_t ixIndex1D(const USz_t size,
629  const IIx_t i5, const IIx_t i4, const IIx_t i3,
630  const IIx_t i2, const IIx_t i1, const IIx_t i0) const
631  {
632  CH_assert((IxData::ixValidBounds(i5, size)));
633  return IxData::m_ixStride*i5 +
634  m_ixNext.ixIndex1D(IxData::m_ixStride, i4, i3, i2, i1, i0);
635  }
636  USz_t ixIndex1D(const USz_t size,
637  const IIx_t i4, const IIx_t i3, const IIx_t i2,
638  const IIx_t i1, const IIx_t i0) const
639  {
640  CH_assert((IxData::ixValidBounds(i4, size)));
641  return IxData::m_ixStride*i4 +
642  m_ixNext.ixIndex1D(IxData::m_ixStride, i3, i2, i1, i0);
643  }
644  USz_t ixIndex1D(const USz_t size,
645  const IIx_t i3, const IIx_t i2, const IIx_t i1,
646  const IIx_t i0) const
647  {
648  CH_assert((IxData::ixValidBounds(i3, size)));
649  return IxData::m_ixStride*i3 +
650  m_ixNext.ixIndex1D(IxData::m_ixStride, i2, i1, i0);
651  }
652  USz_t ixIndex1D(const USz_t size,
653  const IIx_t i2, const IIx_t i1, const IIx_t i0) const
654  {
655  CH_assert((IxData::ixValidBounds(i2, size)));
656  return IxData::m_ixStride*i2 +
657  m_ixNext.ixIndex1D(IxData::m_ixStride, i1, i0);
658  }
659  USz_t ixIndex1D(const USz_t size,
660  const IIx_t i1, const IIx_t i0) const
661  {
662  CH_assert((IxData::ixValidBounds(i1, size)));
663  return IxData::m_ixStride*i1 +
664  m_ixNext.ixIndex1D(IxData::m_ixStride, i0);
665  }
666 
667  USz_t ixDimSize(const USz_t size, const unsigned dim) const
668  {
669  return (dim == Rank) ?
670  size/IxData::m_ixStride :
671  m_ixNext.ixDimSize(IxData::m_ixStride, dim);
672  }
673  IIx_t ixLowerBound(const unsigned dim) const
674  {
675  return (dim == Rank) ?
676  IxData::ixLowerBound() :
677  m_ixNext.ixLowerBound(dim);
678  }
679  IIx_t ixUpperBound(const USz_t size, const unsigned dim) const
680  {
681  return (dim == Rank) ?
682  IxData::ixLowerBound() + size/IxData::m_ixStride - 1 :
683  m_ixNext.ixUpperBound(IxData::m_ixStride, dim);
684  }
686  {
687  return m_ixNext.ixTotalOffset();
688  }
689 
690  unsigned ixIV(const unsigned i) const
691  {
692  return SpaceDim - 1 - i;
693  }
694 
695 private:
696  RSIndexer<Rank-1, DimT> m_ixNext; ///< Next lower rank
697 };
698 
699 /*--------------------------------------------------------------------*/
700 /// Specialization for Rank 1 (any type of subscript)
701 /*--------------------------------------------------------------------*/
702 
703 template <typename DimT>
704 class RSIndexer<1, DimT> : private IndexerData<1, DimT>
705 {
707 public:
709  : IxData()
710  { }
711 
712  RSIndexer(const IIx_t offset,
713  const DimT &dim0)
714  : IxData(dim0)
715  {
716  IxData::ixDefineTotalOffset(offset - IxData::ixLowerBound());
717  }
718 
719  void ixDefine(const IIx_t offset,
720  const DimT &dim0)
721  {
722  IxData::ixDefineLowerBound(dim0);
723  IxData::ixDefineTotalOffset(offset - IxData::ixLowerBound());
724  }
725 
726  USz_t ixIndex1D(const USz_t size,
727  const IIx_t i0) const
728  {
729  CH_assert((IxData::ixValidBounds(i0, size)));
730  return i0 + IxData::ixTotalOffset();
731  }
732 
733  USz_t ixDimSize(const USz_t size, const unsigned dim) const
734  {
735  return size;
736  }
737  IIx_t ixLowerBound(const unsigned dim) const
738  {
739  return IxData::ixLowerBound();
740  }
741  IIx_t ixUpperBound(const USz_t size, const unsigned dim) const
742  {
743  return IxData::ixLowerBound() + size - 1;
744  }
746  {
747  return IxData::ixTotalOffset();
748  }
749 
750  unsigned ixIV(const unsigned i) const
751  {
752  return SpaceDim - 1 - i;
753  }
754 };
755 
756 /*--------------------------------------------------------------------*/
757 /// Full specialization for Rank 2 and zero-based subscripts
758 /** Saves the byte required to store the rank1 indexer (which itself
759  * holds no data if DimT=USz_t)
760  *//*-----------------------------------------------------------------*/
761 
762 template <>
763 class RSIndexer<2, USz_t> : private IndexerData<2, USz_t>
764 {
766 public:
768  : IxData()
769  { }
770 
771  RSIndexer(const IIx_t offset,
772  const USz_t &dim1, const USz_t &dim0)
773  : IxData(dim0, dim1)
774  { }
775 
776  void ixDefine(const IIx_t offset,
777  const USz_t &dim1, const USz_t &dim0)
778  {
779  IxData::m_ixStride = dim0;
780  }
781 
782  USz_t ixIndex1D(const USz_t size,
783  const IIx_t i1, const IIx_t i0) const
784  {
785  CH_assert((IxData::ixValidBounds(i1, size)));
786  CH_assert((i0 < IxData::m_ixStride));
787  return IxData::m_ixStride*i1 + i0;
788  }
789 
790  USz_t ixDimSize(const USz_t size, const unsigned dim) const
791  {
792  return (dim == 2) ? size/IxData::m_ixStride :
793  IxData::m_ixStride;
794  }
795  IIx_t ixLowerBound(const unsigned dim) const
796  {
797  return 0;
798  }
799  IIx_t ixUpperBound(const USz_t size, const unsigned dim) const
800  {
801  return ixDimSize(size, dim) - 1;
802  }
804  {
805  return 0;
806  }
807 
808  unsigned ixIV(const unsigned i) const
809  {
810  return SpaceDim - 1 - i;
811  }
812 };
813 //@}
814 
815 /*====================================================================*/
816 /** \name Provides indexing for column ordered (Fortran) storage.
817  *//*=================================================================*/
818 //@{
819 
820 /*--------------------------------------------------------------------*/
821 /// Rank > 2 for zero-based subscripts and > 1 for subscript ranges
822 /*--------------------------------------------------------------------*/
823 
824 template <unsigned Rank, typename DimT>
825 class CSIndexer : private IndexerData<Rank, DimT>
826 {
828 public:
830  : IxData(), m_ixNext()
831  { }
832 
833  CSIndexer(const IIx_t offset,
834  const DimT &dim0, const DimT &dim1, const DimT &dim2,
835  const DimT &dim3, const DimT &dim4, const DimT &dim5,
836  const DimT &dim6)
837  : IxData(dim0*dim1*dim2*dim3*dim4*dim5, dim6),
838  m_ixNext(offset - IxData::ixDimOffset(),
839  dim0, dim1, dim2, dim3, dim4, dim5)
840  { }
841  CSIndexer(const IIx_t offset,
842  const DimT &dim0, const DimT &dim1, const DimT &dim2,
843  const DimT &dim3, const DimT &dim4, const DimT &dim5)
844  : IxData(dim0*dim1*dim2*dim3*dim4, dim5),
845  m_ixNext(offset - IxData::ixDimOffset(), dim0, dim1, dim2, dim3, dim4)
846  { }
847  CSIndexer(const IIx_t offset,
848  const DimT &dim0, const DimT &dim1, const DimT &dim2,
849  const DimT &dim3, const DimT &dim4)
850  : IxData(dim0*dim1*dim2*dim3, dim4),
851  m_ixNext(offset - IxData::ixDimOffset(), dim0, dim1, dim2, dim3)
852  { }
853  CSIndexer(const IIx_t offset,
854  const DimT &dim0, const DimT &dim1, const DimT &dim2,
855  const DimT &dim3)
856  : IxData(dim0*dim1*dim2, dim3),
857  m_ixNext(offset - IxData::ixDimOffset(), dim0, dim1, dim2)
858  { }
859  CSIndexer(const IIx_t offset,
860  const DimT &dim0, const DimT &dim1, const DimT &dim2)
861  : IxData(dim0*dim1, dim2),
862  m_ixNext(offset - IxData::ixDimOffset(), dim0, dim1)
863  { }
864  CSIndexer(const IIx_t offset,
865  const DimT &dim0, const DimT &dim1)
866  : IxData(sizeOfDim(dim0), dim1),
867  m_ixNext(offset - IxData::ixDimOffset(), dim0)
868  { }
869 
870  void ixDefine(const IIx_t offset,
871  const DimT &dim0, const DimT &dim1, const DimT &dim2,
872  const DimT &dim3, const DimT &dim4, const DimT &dim5,
873  const DimT &dim6)
874  {
875  IxData::m_ixStride = dim0*dim1*dim2*dim3*dim4*dim5;
876  IxData::ixDefineLowerBound(dim6);
877  m_ixNext.ixDefine(offset - IxData::ixDimOffset(),
878  dim0, dim1, dim2, dim3, dim4, dim5);
879  }
880  void ixDefine(const IIx_t offset,
881  const DimT &dim0, const DimT &dim1, const DimT &dim2,
882  const DimT &dim3, const DimT &dim4, const DimT &dim5)
883  {
884  IxData::m_ixStride = dim0*dim1*dim2*dim3*dim4;
885  IxData::ixDefineLowerBound(dim5);
886  m_ixNext.ixDefine(offset - IxData::ixDimOffset(),
887  dim0, dim1, dim2, dim3, dim4);
888  }
889  void ixDefine(const IIx_t offset,
890  const DimT &dim0, const DimT &dim1, const DimT &dim2,
891  const DimT &dim3, const DimT &dim4)
892  {
893  IxData::m_ixStride = dim0*dim1*dim2*dim3;
894  IxData::ixDefineLowerBound(dim4);
895  m_ixNext.ixDefine(offset - IxData::ixDimOffset(), dim0, dim1, dim2, dim3);
896  }
897  void ixDefine(const IIx_t offset,
898  const DimT &dim0, const DimT &dim1, const DimT &dim2,
899  const DimT &dim3)
900  {
901  IxData::m_ixStride = dim0*dim1*dim2;
902  IxData::ixDefineLowerBound(dim3);
903  m_ixNext.ixDefine(offset - IxData::ixDimOffset(), dim0, dim1, dim2);
904  }
905  void ixDefine(const IIx_t offset,
906  const DimT &dim0, const DimT &dim1, const DimT &dim2)
907  {
908  IxData::m_ixStride = dim0*dim1;
909  IxData::ixDefineLowerBound(dim2);
910  m_ixNext.ixDefine(offset - IxData::ixDimOffset(), dim0, dim1);
911  }
912  void ixDefine(const IIx_t offset,
913  const DimT &dim0, const DimT &dim1)
914  {
915  IxData::m_ixStride = sizeOfDim(dim0);
916  IxData::ixDefineLowerBound(dim1);
917  m_ixNext.ixDefine(offset - IxData::ixDimOffset(), dim0);
918  }
919 
920  USz_t ixIndex1D(const USz_t size,
921  const IIx_t i0, const IIx_t i1, const IIx_t i2,
922  const IIx_t i3, const IIx_t i4, const IIx_t i5,
923  const IIx_t i6) const
924  {
925  CH_assert((IxData::ixValidBounds(i6, size)));
926  return IxData::m_ixStride*i6 +
927  m_ixNext.ixIndex1D(IxData::m_ixStride, i0, i1, i2, i3, i4, i5);
928  }
929  USz_t ixIndex1D(const USz_t size,
930  const IIx_t i0, const IIx_t i1, const IIx_t i2,
931  const IIx_t i3, const IIx_t i4, const IIx_t i5) const
932  {
933  CH_assert((IxData::ixValidBounds(i5, size)));
934  return IxData::m_ixStride*i5 +
935  m_ixNext.ixIndex1D(IxData::m_ixStride, i0, i1, i2, i3, i4);
936  }
937  USz_t ixIndex1D(const USz_t size,
938  const IIx_t i0, const IIx_t i1, const IIx_t i2,
939  const IIx_t i3, const IIx_t i4) const
940  {
941  CH_assert((IxData::ixValidBounds(i4, size)));
942  return IxData::m_ixStride*i4 +
943  m_ixNext.ixIndex1D(IxData::m_ixStride, i0, i1, i2, i3);
944  }
945  USz_t ixIndex1D(const USz_t size,
946  const IIx_t i0, const IIx_t i1, const IIx_t i2,
947  const IIx_t i3) const
948  {
949  CH_assert((IxData::ixValidBounds(i3, size)));
950  return IxData::m_ixStride*i3 +
951  m_ixNext.ixIndex1D(IxData::m_ixStride, i0, i1, i2);
952  }
953  USz_t ixIndex1D(const USz_t size,
954  const IIx_t i0, const IIx_t i1, const IIx_t i2) const
955  {
956  CH_assert((IxData::ixValidBounds(i2, size)));
957  return IxData::m_ixStride*i2 +
958  m_ixNext.ixIndex1D(IxData::m_ixStride, i0, i1);
959  }
960  USz_t ixIndex1D(const USz_t size,
961  const IIx_t i0, const IIx_t i1) const
962  {
963  CH_assert((IxData::ixValidBounds(i1, size)));
964  return IxData::m_ixStride*i1 +
965  m_ixNext.ixIndex1D(IxData::m_ixStride, i0);
966  }
967 
968  USz_t ixDimSize(const USz_t size, const unsigned dim) const
969  {
970  return (dim == Rank) ?
971  size/IxData::m_ixStride :
972  m_ixNext.ixDimSize(IxData::m_ixStride, dim);
973  }
974  IIx_t ixLowerBound(const unsigned dim) const
975  {
976  return (dim == Rank) ?
977  IxData::ixLowerBound() :
978  m_ixNext.ixLowerBound(dim);
979  }
980  IIx_t ixUpperBound(const USz_t size, const unsigned dim) const
981  {
982  return (dim == Rank) ?
983  IxData::ixLowerBound() + size/IxData::m_ixStride - 1 :
984  m_ixNext.ixUpperBound(IxData::m_ixStride, dim);
985  }
987  {
988  return m_ixNext.ixTotalOffset();
989  }
990 
991  unsigned ixIV(const unsigned i) const
992  {
993  return i;
994  }
995 
996 private:
997  CSIndexer<Rank-1, DimT> m_ixNext; ///< Next lower rank
998 };
999 
1000 /*--------------------------------------------------------------------*/
1001 /// Specialization for Rank 1 (any type of subscript)
1002 /*--------------------------------------------------------------------*/
1003 
1004 template <typename DimT>
1005 class CSIndexer<1, DimT> : private IndexerData<1, DimT>
1006 {
1008 public:
1010  : IxData()
1011  { }
1012 
1013  CSIndexer(const IIx_t offset,
1014  const DimT &dim0)
1015  : IxData(dim0)
1016  {
1017  IxData::ixDefineTotalOffset(offset - IxData::ixLowerBound());
1018  }
1019 
1020  void ixDefine(const IIx_t offset, const DimT &dim0)
1021  {
1022  IxData::ixDefineLowerBound(dim0);
1023  IxData::ixDefineTotalOffset(offset - IxData::ixLowerBound());
1024  }
1025 
1026  USz_t ixIndex1D(const USz_t size,
1027  const IIx_t i0) const
1028  {
1029  CH_assert((IxData::ixValidBounds(i0, size)));
1030  return i0 + IxData::ixTotalOffset();
1031  }
1032 
1033  USz_t ixDimSize(const USz_t size, const unsigned dim) const
1034  {
1035  return size;
1036  }
1037  IIx_t ixLowerBound(const unsigned dim) const
1038  {
1039  return IxData::ixLowerBound();
1040  }
1041  IIx_t ixUpperBound(const USz_t size, const unsigned dim) const
1042  {
1043  return IxData::ixLowerBound() + size - 1;
1044  }
1046  {
1047  return IxData::ixTotalOffset();
1048  }
1049 
1050  unsigned ixIV(const unsigned i) const
1051  {
1052  return i;
1053  }
1054 };
1055 
1056 /*--------------------------------------------------------------------*/
1057 /// Full specialization for Rank 2 and zero-based subscripts
1058 /** Saves the byte required to store the rank1 indexer (which itself
1059  * holds no data if DimT=USz_t)
1060  *//*-----------------------------------------------------------------*/
1061 
1062 template <>
1063 class CSIndexer<2, USz_t> : private IndexerData<2, USz_t>
1064 {
1066 public:
1068  : IxData()
1069  { }
1070 
1071  CSIndexer(const IIx_t offset,
1072  const USz_t dim0, const USz_t dim1)
1073  : IxData(dim0, dim1)
1074  { }
1075 
1076  void ixDefine(const IIx_t offset,
1077  const USz_t dim0, const USz_t dim1)
1078  {
1079  IxData::m_ixStride = dim0;
1080  }
1081 
1082  USz_t ixIndex1D(const USz_t size,
1083  const IIx_t i0, const IIx_t i1) const
1084  {
1085  CH_assert((IxData::ixValidBounds(i1, size)));
1086  CH_assert((i0 < IxData::m_ixStride));
1087  return IxData::m_ixStride*i1 + i0;
1088  }
1089 
1090  IIx_t ixDimSize(const USz_t size, const unsigned dim) const
1091  {
1092  return (dim == 2) ? size/IxData::m_ixStride :
1093  IxData::m_ixStride;
1094  }
1095  IIx_t ixLowerBound(const unsigned dim) const
1096  {
1097  return 0;
1098  }
1099  IIx_t ixUpperBound(const USz_t size, const unsigned dim) const
1100  {
1101  return ixDimSize(size, dim) - 1;
1102  }
1104  {
1105  return 0;
1106  }
1107 
1108  unsigned ixIV(const unsigned i) const
1109  {
1110  return i;
1111  }
1112 };
1113 //@}
1114 
1115 /*====================================================================*/
1116 /** \name Array configuration. Select types based on 'ArConf'
1117  *//*=================================================================*/
1118 //@{
1119 
1120 template <unsigned Rank, int ArConf>
1121 struct ArTr;
1122 template <unsigned Rank>
1123 struct ArTr<Rank, ArZeroRow>
1124 {
1127 };
1128 template <unsigned Rank>
1129 struct ArTr<Rank, ArZeroCol>
1130 {
1133 };
1134 template <unsigned Rank>
1135 struct ArTr<Rank, ArRangeRow>
1136 {
1137  typedef CHRange DimT;
1139  typedef int BoxAllowed;
1140 };
1141 template <unsigned Rank>
1142 struct ArTr<Rank, ArRangeCol>
1143 {
1144  typedef CHRange DimT;
1146  typedef int BoxAllowed;
1147 };
1148 //@}
1149 
1150 } // End of namespace ArSp
1151 
1152 /*******************************************************************************
1153  */
1154 /// Multidimensional array class
1155 /**
1156  * \tparam T Type of element
1157  * \tparam Rank Rank of the array
1158  * \tparam ArConf Configuration of the indexing. Allowable values are:
1159  * ArZeroRow - Row-ordered indexing with lower bound = 0
1160  * ArZeroCol - Column-ordered indexing with lower
1161  * bound = 0 (DEFAULT)
1162  * ArRangeRow - Row-ordered indexing with subscript ranges
1163  * ArRangeCol - Column-ordered indexing with subscript
1164  * ranges
1165  * \tparam Alloc Allocator for the array
1166  *
1167  * \note
1168  * <ul>
1169  * <li> Default template arguments specify column-ordered arrays since it
1170  * is expected that this class will be mostly used as storage for
1171  * data used in Fortran routines.
1172  * <li> When an assertion fails, note that the indexers label the contiguous
1173  * dimension as i0 or dim0 and the others from there. This class
1174  * labels all dimensions assuming row-ordered (C) storage.
1175  * <li> Currently supports up to rank 7, matching the maximum permitted by
1176  * the Fortran 2003 standard (the 2008 standard extends this to 15 and
1177  * this class will be extended once that is commonplace). With
1178  * IntVects or Boxes used to specify some of the dimensions, 2 extra
1179  * dimensions are supported, allowing a matrix in each cell. This
1180  * implies a rank of SpaceDim+2 so you can only add 1 extra dimension
1181  * if you want to support SpaceDim=6.
1182  * <li> Empty base-class optimizations are frequently used. On 32-bit arch,
1183  * sizeof(CHArray<int, 1, ArZeroRow, ArSp::NewArrayAlloc<int> >) = 8
1184  * sizeof(CHArray<int, 2, ArZeroRow, ArSp::NewArrayAlloc<int> >) = 12
1185  * <li> There is support for passing these arrays to Fortran -- see Chombo
1186  * design doc
1187  * <li> CHMatrix will define a real, rank 2, column-ordered matrix
1188  * <li> You can also allocate an array of matrices, continguous in memory,
1189  * using the ArrayOfMatrixAlloc allocator.
1190  * </ul>
1191  *
1192  * Example \verbatim
1193  *
1194  * CHArray<int, 3> A(2, 2, 2);
1195  * A = 2;
1196  * A(0, 0, 0) = 4;
1197  * std::cout << A << std::endl;
1198  * CHArray<double, 2> B;
1199  * B.define(3, 4);
1200  * B(2, 3) = 5.5;
1201  * \endverbatim
1202  * One can also use subscript ranges but the array has to be configured to
1203  * support this. Ranges are specified with CHRange in place of a size. Any
1204  * integer types are converted to CHRange(0, int-1). E.g.,
1205  * \verbatim
1206  * CHArray<int, 3, ArRangeRow> C(CHRange(-1,0), 2, 2);
1207  * C = 2;
1208  * C(-1, 0, 0) = 4;
1209  * \endverbatim
1210  * IntVects are allowed for specifying some of the dimensions so that this
1211  * class can be used with boxes, e.g: \verbatim
1212  *
1213  * CHArray<int, SpaceDim+1> A(box.size(), 1)
1214  * \endverbatim
1215  * The indices of the IntVect are rearranged so that the first index is always
1216  * closest to contiguous memory no matter if the actual memory layout is row-
1217  * ordered or column-ordered. In other words, the first index of the IntVect
1218  * always has the lowest stride. As such, the allocated memory can be
1219  * accessed by iterating over the box in Chombo Fortran. Whether the
1220  * remaining indices (or components) are left or right of the IntVect and the
1221  * storage order determine if the components are distributed across the
1222  * IntVects (like with a BaseFab) or are contiguous in each IntVect. The
1223  * effect is natural; for row storage, components on the right will lead to
1224  * contigous memory. E.g.,
1225  * \verbatim
1226  * typedef CHArray<int, SpaceDim+1, ArZeroRow> CHArrayRS;
1227  * typedef CHArray<int, SpaceDim+1, ArZeroCol> CHArrayCS;
1228  * const IntVect iv(2, 2);
1229  * CHArrayRS ARS_IVComp(iv, 2);
1230  * CHArrayRS ARS_CompIV(2, iv);
1231  * CHArrayCS ACS_IVComp(iv, 2);
1232  * CHArrayCS ACS_CompIV(2, iv);
1233  * int ic = 1;
1234  * for (int j = 0; j != 2; ++j)
1235  * for (int i = 0; i != 2; ++i) // Column storage!
1236  * {
1237  * const IntVect ixv(i, j);
1238  * ARS_IVComp(ixv, 0) = ic;
1239  * ARS_IVComp(ixv, 1) = -ic;
1240  * ARS_CompIV(0, ixv) = ic;
1241  * ARS_CompIV(1, ixv) = -ic;
1242  * ACS_IVComp(ixv, 0) = ic;
1243  * ACS_IVComp(ixv, 1) = -ic;
1244  * ACS_CompIV(0, ixv) = ic;
1245  * ACS_CompIV(1, ixv) = -ic;
1246  * ++ic;
1247  * }
1248  *
1249  * std::cout << "ARS_IVComp: " << ARS_IVComp << std::endl;
1250  * std::cout << "ARS_CompIV: " << ARS_CompIV << std::endl;
1251  * std::cout << "ACS_IVComp: " << ACS_IVComp << std::endl;
1252  * std::cout << "ACS_CompIV: " << ACS_CompIV << std::endl;
1253  * \endverbatim
1254  * will produce
1255  * \verbatim
1256  * $ ARS_IVComp: 1 -1 2 -2 3 -3 4 -4
1257  * $ ARS_CompIV: 1 2 3 4 -1 -2 -3 -4
1258  * $ ACS_IVComp: 1 2 3 4 -1 -2 -3 -4
1259  * $ ACS_CompIV: 1 -1 2 -2 3 -3 4 -4
1260  * \endverbatim
1261  * Note that the IntVects simply expand to dimensions and there is nothing to
1262  * ensure that you access in the array in the same manner you defined it
1263  * (i.e., switching the order of the IntVect and the component)!
1264  *
1265  * IntVects are always zero-based and there is no way to specify a range of
1266  * IntVects. However, one can use Boxes instead of IntVects to define the
1267  * array but only if the array is configured with subscript ranges
1268  * (ArConf = ArRangeRow or ArRangeCol)
1269  * \verbatim
1270  * Box box(IntVect(-1,-1), IntVect(1, 1));
1271  * CHArray<int, SpaceDim+1, ArRangeRow> AB(box, 2);
1272  * AB = 1;
1273  * AB(IntVect(-1, -1), 0) = 2;
1274  * std::cout << AB << std::endl;
1275  * \endverbatim
1276  *
1277  ******************************************************************************/
1278 
1279 template <typename T,
1280  unsigned Rank,
1281  int ArConf, // Default ArZeroCol
1282  typename Alloc> // Default ArSp::DefaultArrayAlloc<T>
1283 class CHArray : private ArSp::ArTr<Rank, ArConf>::IndexerT
1284 {
1287  typedef T value_type; ///< Type of element
1288 public:
1289 
1290  /// Default constructor
1292  : Indexer(), m_arrayImpl()
1293  { }
1294 
1295  /// Construct with dimensions
1296  CHArray(const DimT &dim6, const DimT &dim5, const DimT &dim4,
1297  const DimT &dim3, const DimT &dim2, const DimT &dim1,
1298  const DimT &dim0)
1299  : Indexer(0, dim6, dim5, dim4, dim3, dim2, dim1, dim0),
1300  m_arrayImpl(dim6*dim5*dim4*dim3*dim2*dim1*dim0)
1301  { }
1302  CHArray(const DimT &dim5, const DimT &dim4, const DimT &dim3,
1303  const DimT &dim2, const DimT &dim1, const DimT &dim0)
1304  : Indexer(0, dim5, dim4, dim3, dim2, dim1, dim0),
1305  m_arrayImpl(dim5*dim4*dim3*dim2*dim1*dim0)
1306  { }
1307  CHArray(const DimT &dim4, const DimT &dim3, const DimT &dim2,
1308  const DimT &dim1, const DimT &dim0)
1309  : Indexer(0, dim4, dim3, dim2, dim1, dim0),
1310  m_arrayImpl(dim4*dim3*dim2*dim1*dim0)
1311  { }
1312  CHArray(const DimT &dim3, const DimT &dim2, const DimT &dim1,
1313  const DimT &dim0)
1314  : Indexer(0, dim3, dim2, dim1, dim0), m_arrayImpl(dim3*dim2*dim1*dim0)
1315  { }
1316  CHArray(const DimT &dim2, const DimT &dim1, const DimT &dim0)
1317  : Indexer(0, dim2, dim1, dim0), m_arrayImpl(dim2*dim1*dim0)
1318  { }
1319  CHArray(const DimT &dim1, const DimT &dim0)
1320  : Indexer(0, dim1, dim0), m_arrayImpl(dim1*dim0)
1321  { }
1322  CHArray(const DimT &dim0)
1323  : Indexer(0, dim0), m_arrayImpl(ArSp::sizeOfDim(dim0))
1324  { }
1325  // With IntVect
1326  CHArray(const IntVect &iv, const DimT &dimc1, const DimT &dimc0)
1327  : Indexer(0, D_DEFIV, dimc1, dimc0), m_arrayImpl(iv.product()*dimc1*dimc0)
1328  { }
1329  CHArray(const IntVect &iv, const DimT &dimc0)
1330  : Indexer(0, D_DEFIV, dimc0), m_arrayImpl(iv.product()*dimc0)
1331  { }
1332  CHArray(const DimT &dimc1, const DimT &dimc0, const IntVect &iv)
1333  : Indexer(0, dimc1, dimc0, D_DEFIV), m_arrayImpl(dimc1*dimc0*iv.product())
1334  { }
1335  CHArray(const DimT &dimc0, const IntVect &iv)
1336  : Indexer(0, dimc0, D_DEFIV), m_arrayImpl(dimc0*iv.product())
1337  { }
1338  // With Box
1339  CHArray(const Box &box, const DimT &dimc1, const DimT &dimc0)
1340  : Indexer(0, D_DEFBOX, dimc1, dimc0),
1341  m_arrayImpl(box.size().product()*dimc1*dimc0)
1342  {
1343  // Any error with "BoxAllowed" means you are not allowed to use boxes with
1344  // zero-based lower bounds. Use ArConf=ArRangeRow or ArConf=ArRangeCol.
1345  typedef typename ArSp::ArTr<Rank, ArConf>::BoxAllowed Check;
1346  }
1347  CHArray(const Box &box, const DimT &dimc0)
1348  : Indexer(0, D_DEFBOX, dimc0), m_arrayImpl(box.size().product()*dimc0)
1349  {
1350  // Any error with "BoxAllowed" means you are not allowed to use boxes with
1351  // zero-based lower bounds. Use ArConf=ArRangeRow or ArConf=ArRangeCol.
1352  typedef typename ArSp::ArTr<Rank, ArConf>::BoxAllowed Check;
1353  }
1354  CHArray(const DimT &dimc1, const DimT &dimc0, const Box &box)
1355  : Indexer(0, dimc1, dimc0, D_DEFBOX),
1356  m_arrayImpl(dimc1*dimc0*box.size().product())
1357  {
1358  // Any error with "BoxAllowed" means you are not allowed to use boxes with
1359  // zero-based lower bounds. Use ArConf=ArRangeRow or ArConf=ArRangeCol.
1360  typedef typename ArSp::ArTr<Rank, ArConf>::BoxAllowed Check;
1361  }
1362  CHArray(const DimT &dimc0, const Box &box)
1363  : Indexer(0, dimc0, D_DEFBOX), m_arrayImpl(dimc0*box.size().product())
1364  {
1365  // Any error with "BoxAllowed" means you are not allowed to use boxes with
1366  // zero-based lower bounds. Use ArConf=ArRangeRow or ArConf=ArRangeCol.
1367  typedef typename ArSp::ArTr<Rank, ArConf>::BoxAllowed Check;
1368  }
1369 
1370  /// Define the dimensions
1371  void define(const DimT &dim6, const DimT &dim5, const DimT &dim4,
1372  const DimT &dim3, const DimT &dim2, const DimT &dim1,
1373  const DimT &dim0)
1374  {
1375  Indexer::ixDefine(0, dim6, dim5, dim4, dim3, dim2, dim1, dim0);
1376  m_arrayImpl.define(dim6*dim5*dim4*dim3*dim2*dim1*dim0);
1377  }
1378  void define(const DimT &dim5, const DimT &dim4, const DimT &dim3,
1379  const DimT &dim2, const DimT &dim1, const DimT &dim0)
1380  {
1381  Indexer::ixDefine(0, dim5, dim4, dim3, dim2, dim1, dim0);
1382  m_arrayImpl.define(dim5*dim4*dim3*dim2*dim1*dim0);
1383  }
1384  void define(const DimT &dim4, const DimT &dim3, const DimT &dim2,
1385  const DimT &dim1, const DimT &dim0)
1386  {
1387  Indexer::ixDefine(0, dim4, dim3, dim2, dim1, dim0);
1388  m_arrayImpl.define(dim4*dim3*dim2*dim1*dim0);
1389  }
1390  void define(const DimT &dim3, const DimT &dim2, const DimT &dim1,
1391  const DimT &dim0)
1392  {
1393  Indexer::ixDefine(0, dim3, dim2, dim1, dim0);
1394  m_arrayImpl.define(dim3*dim2*dim1*dim0);
1395  }
1396  void define(const DimT &dim2, const DimT &dim1, const DimT &dim0)
1397  {
1398  Indexer::ixDefine(0, dim2, dim1, dim0);
1399  m_arrayImpl.define(dim2*dim1*dim0);
1400  }
1401  void define(const DimT &dim1, const DimT &dim0)
1402  {
1403  Indexer::ixDefine(0, dim1, dim0);
1404  m_arrayImpl.define(dim1*dim0);
1405  }
1406  void define(const DimT &dim0)
1407  {
1408  Indexer::ixDefine(0, dim0);
1409  m_arrayImpl.define(ArSp::sizeOfDim(dim0));
1410  }
1411  // With IntVect
1412  void define(const IntVect &iv, const DimT &dimc1, const DimT &dimc0)
1413  {
1414  Indexer::ixDefine(0, D_DEFIV, dimc1, dimc0);
1415  m_arrayImpl.define(iv.product()*dimc1*dimc0);
1416  }
1417  void define(const IntVect &iv, const DimT &dimc0)
1418  {
1419  Indexer::ixDefine(0, D_DEFIV, dimc0);
1420  m_arrayImpl.define(iv.product()*dimc0);
1421  }
1422  void define(const DimT &dimc1, const DimT &dimc0, const IntVect &iv)
1423  {
1424  Indexer::ixDefine(0, dimc1, dimc0, D_DEFIV);
1425  m_arrayImpl.define(dimc1*dimc0*iv.product());
1426  }
1427  void define(const DimT &dimc0, const IntVect &iv)
1428  {
1429  Indexer::ixDefine(0, dimc0, D_DEFIV);
1430  m_arrayImpl.define(dimc0*iv.product());
1431  }
1432  // With Box
1433  void define(const Box &box, const DimT &dimc1, const DimT &dimc0)
1434  {
1435  // Any error with "BoxAllowed" means you are not allowed to use boxes with
1436  // zero-based lower bounds. Use ArConf=ArRangeRow or ArConf=ArRangeCol.
1437  typedef typename ArSp::ArTr<Rank, ArConf>::BoxAllowed Check;
1438  Indexer::ixDefine(0, D_DEFBOX, dimc1, dimc0);
1439  m_arrayImpl.define(box.size().product()*dimc1*dimc0);
1440  }
1441  void define(const Box &box, const DimT &dimc0)
1442  {
1443  // Any error with "BoxAllowed" means you are not allowed to use boxes with
1444  // zero-based lower bounds. Use ArConf=ArRangeRow or ArConf=ArRangeCol.
1445  typedef typename ArSp::ArTr<Rank, ArConf>::BoxAllowed Check;
1446  Indexer::ixDefine(0, D_DEFBOX, dimc0);
1447  m_arrayImpl.define(box.size().product()*dimc0);
1448  }
1449  void define(const DimT &dimc1, const DimT &dimc0, const Box &box)
1450  {
1451  // Any error with "BoxAllowed" means you are not allowed to use boxes with
1452  // zero-based lower bounds. Use ArConf=ArRangeRow or ArConf=ArRangeCol.
1453  typedef typename ArSp::ArTr<Rank, ArConf>::BoxAllowed Check;
1454  Indexer::ixDefine(0, dimc1, dimc0, D_DEFBOX);
1455  m_arrayImpl.define(dimc1*dimc0*box.size().product());
1456  }
1457  void define(const DimT &dimc0, const Box &box)
1458  {
1459  // Any error with "BoxAllowed" means you are not allowed to use boxes with
1460  // zero-based lower bounds. Use ArConf=ArRangeRow or ArConf=ArRangeCol.
1461  typedef typename ArSp::ArTr<Rank, ArConf>::BoxAllowed Check;
1462  Indexer::ixDefine(0, dimc0, D_DEFBOX);
1463  m_arrayImpl.define(dimc0*box.size().product());
1464  }
1465 
1466  /// Define the dimensions and allocate on 'addr'
1467  void define(void *const addr,
1468  const DimT &dim6, const DimT &dim5, const DimT &dim4,
1469  const DimT &dim3, const DimT &dim2, const DimT &dim1,
1470  const DimT &dim0)
1471  {
1472  Indexer::ixDefine(0, dim6, dim5, dim4, dim3, dim2, dim1, dim0);
1473  m_arrayImpl.define(addr, dim6*dim5*dim4*dim3*dim2*dim1*dim0);
1474  }
1475  void define(void *const addr,
1476  const DimT &dim5, const DimT &dim4, const DimT &dim3,
1477  const DimT &dim2, const DimT &dim1, const DimT &dim0)
1478  {
1479  Indexer::ixDefine(0, dim5, dim4, dim3, dim2, dim1, dim0);
1480  m_arrayImpl.define(addr, dim5*dim4*dim3*dim2*dim1*dim0);
1481  }
1482  void define(void *const addr,
1483  const DimT &dim4, const DimT &dim3, const DimT &dim2,
1484  const DimT &dim1, const DimT &dim0)
1485  {
1486  Indexer::ixDefine(0, dim4, dim3, dim2, dim1, dim0);
1487  m_arrayImpl.define(addr, dim4*dim3*dim2*dim1*dim0);
1488  }
1489  void define(void *const addr,
1490  const DimT &dim3, const DimT &dim2, const DimT &dim1,
1491  const DimT &dim0)
1492  {
1493  Indexer::ixDefine(0, dim3, dim2, dim1, dim0);
1494  m_arrayImpl.define(addr, dim3*dim2*dim1*dim0);
1495  }
1496  void define(void *const addr,
1497  const DimT &dim2, const DimT &dim1, const DimT &dim0)
1498  {
1499  Indexer::ixDefine(0, dim2, dim1, dim0);
1500  m_arrayImpl.define(addr, dim2*dim1*dim0);
1501  }
1502  void define(void *const addr,
1503  const DimT &dim1, const DimT &dim0)
1504  {
1505  Indexer::ixDefine(0, dim1, dim0);
1506  m_arrayImpl.define(addr, dim1*dim0);
1507  }
1508  void define(void *const addr,
1509  const DimT &dim0)
1510  {
1511  Indexer::ixDefine(0, dim0);
1512  m_arrayImpl.define(addr, ArSp::sizeOfDim(dim0));
1513  }
1514  // With IntVect
1515  void define(void *const addr, const IntVect &iv,
1516  const DimT &dimc1, const DimT &dimc0)
1517  {
1518  Indexer::ixDefine(0, D_DEFIV, dimc1, dimc0);
1519  m_arrayImpl.define(addr, iv.product()*dimc1*dimc0);
1520  }
1521  void define(void *const addr, const IntVect &iv, const DimT &dimc0)
1522  {
1523  Indexer::ixDefine(0, D_DEFIV, dimc0);
1524  m_arrayImpl.define(addr, iv.product()*dimc0);
1525  }
1526  void define(void *const addr, const DimT &dimc1, const DimT &dimc0,
1527  const IntVect &iv)
1528  {
1529  Indexer::ixDefine(0, dimc1, dimc0, D_DEFIV);
1530  m_arrayImpl.define(addr, dimc1*dimc0*iv.product());
1531  }
1532  void define(void *const addr, const DimT &dimc0, const IntVect &iv)
1533  {
1534  Indexer::ixDefine(0, dimc0, D_DEFIV);
1535  m_arrayImpl.define(addr, dimc0*iv.product());
1536  }
1537  // With Box
1538  void define(void *const addr, const Box &box,
1539  const DimT &dimc1, const DimT &dimc0)
1540  {
1541  // Any error with "BoxAllowed" means you are not allowed to use boxes with
1542  // zero-based lower bounds. Use ArConf=ArRangeRow or ArConf=ArRangeCol.
1543  typedef typename ArSp::ArTr<Rank, ArConf>::BoxAllowed Check;
1544  Indexer::ixDefine(0, D_DEFBOX, dimc1, dimc0);
1545  m_arrayImpl.define(addr, box.size().product()*dimc1*dimc0);
1546  }
1547  void define(void *const addr, const Box &box, const DimT &dimc0)
1548  {
1549  // Any error with "BoxAllowed" means you are not allowed to use boxes with
1550  // zero-based lower bounds. Use ArConf=ArRangeRow or ArConf=ArRangeCol.
1551  typedef typename ArSp::ArTr<Rank, ArConf>::BoxAllowed Check;
1552  Indexer::ixDefine(0, D_DEFBOX, dimc0);
1553  m_arrayImpl.define(addr, box.size().product()*dimc0);
1554  }
1555  void define(void *const addr, const DimT &dimc1, const DimT &dimc0,
1556  const Box &box)
1557  {
1558  // Any error with "BoxAllowed" means you are not allowed to use boxes with
1559  // zero-based lower bounds. Use ArConf=ArRangeRow or ArConf=ArRangeCol.
1560  typedef typename ArSp::ArTr<Rank, ArConf>::BoxAllowed Check;
1561  Indexer::ixDefine(0, dimc1, dimc0, D_DEFBOX);
1562  m_arrayImpl.define(addr, dimc1*dimc0*box.size().product());
1563  }
1564  void define(void *const addr, const DimT &dimc0, const Box &box)
1565  {
1566  // Any error with "BoxAllowed" means you are not allowed to use boxes with
1567  // zero-based lower bounds. Use ArConf=ArRangeRow or ArConf=ArRangeCol.
1568  typedef typename ArSp::ArTr<Rank, ArConf>::BoxAllowed Check;
1569  Indexer::ixDefine(0, dimc0, D_DEFBOX);
1570  m_arrayImpl.define(addr, dimc0*box.size().product());
1571  }
1572 
1573  /// Deallocate the array
1574  void undefine()
1575  {
1576  CH_assert(isAllocated());
1577  m_arrayImpl.undefine();
1578  }
1579 
1580  /// Assign a constant to the array
1581  template <typename T2>
1582  CHArray &operator=(const T2 &val)
1583  {
1584  CH_assert(isAllocated());
1585  T Tval = val;
1586  const T *const pEnd = end();
1587  for (T *p = begin(); p != pEnd;) *p++ = Tval;
1588  return *this;
1589  }
1590 
1591  /// Access an element
1592  T &operator()(const ArSp::IIx_t i6, const ArSp::IIx_t i5,
1593  const ArSp::IIx_t i4, const ArSp::IIx_t i3,
1594  const ArSp::IIx_t i2, const ArSp::IIx_t i1,
1595  const ArSp::IIx_t i0)
1596  {
1597  CH_assert(isUsable());
1598  return m_arrayImpl.data[
1599  Indexer::ixIndex1D(size(), i6, i5, i4, i3, i2, i1, i0)];
1600  }
1601  T &operator()(const ArSp::IIx_t i5, const ArSp::IIx_t i4,
1602  const ArSp::IIx_t i3, const ArSp::IIx_t i2,
1603  const ArSp::IIx_t i1, const ArSp::IIx_t i0)
1604  {
1605  CH_assert(isUsable());
1606  return m_arrayImpl.data[
1607  Indexer::ixIndex1D(size(), i5, i4, i3, i2, i1, i0)];
1608  }
1609  T &operator()(const ArSp::IIx_t i4, const ArSp::IIx_t i3,
1610  const ArSp::IIx_t i2, const ArSp::IIx_t i1,
1611  const ArSp::IIx_t i0)
1612  {
1613  CH_assert(isUsable());
1614  return m_arrayImpl.data[Indexer::ixIndex1D(size(), i4, i3, i2, i1, i0)];
1615  }
1616  T &operator()(const ArSp::IIx_t i3, const ArSp::IIx_t i2,
1617  const ArSp::IIx_t i1, const ArSp::IIx_t i0)
1618  {
1619  CH_assert(isUsable());
1620  return m_arrayImpl.data[Indexer::ixIndex1D(size(), i3, i2, i1, i0)];
1621  }
1622  T &operator()(const ArSp::IIx_t i2, const ArSp::IIx_t i1,
1623  const ArSp::IIx_t i0)
1624  {
1625  CH_assert(isUsable());
1626  return m_arrayImpl.data[Indexer::ixIndex1D(size(), i2, i1, i0)];
1627  }
1628  T &operator()(const ArSp::IIx_t i1, const ArSp::IIx_t i0)
1629  {
1630  CH_assert(isUsable());
1631  return m_arrayImpl.data[Indexer::ixIndex1D(size(), i1, i0)];
1632  }
1634  {
1635  CH_assert(isUsable());
1636  return m_arrayImpl.data[Indexer::ixIndex1D(size(), i0)];
1637  }
1638  T &operator()(const IntVect& iv, const ArSp::IIx_t c1, const ArSp::IIx_t c0)
1639  {
1640  CH_assert(isUsable());
1641  return m_arrayImpl.data[Indexer::ixIndex1D(size(), D_IXIV, c1, c0)];
1642  }
1643  T &operator()(const IntVect& iv, const ArSp::IIx_t c0)
1644  {
1645  CH_assert(isUsable());
1646  return m_arrayImpl.data[Indexer::ixIndex1D(size(), D_IXIV, c0)];
1647  }
1648  T &operator()(const ArSp::IIx_t c1, const ArSp::IIx_t c0, const IntVect& iv)
1649  {
1650  CH_assert(isUsable());
1651  return m_arrayImpl.data[Indexer::ixIndex1D(size(), c1, c0, D_IXIV)];
1652  }
1653  T &operator()(const ArSp::IIx_t c0, const IntVect& iv)
1654  {
1655  CH_assert(isUsable());
1656  return m_arrayImpl.data[Indexer::ixIndex1D(size(), c0, D_IXIV)];
1657  }
1658 
1659  /// Constant access to an element
1660  const T &operator()(const ArSp::IIx_t i6, const ArSp::IIx_t i5,
1661  const ArSp::IIx_t i4, const ArSp::IIx_t i3,
1662  const ArSp::IIx_t i2, const ArSp::IIx_t i1,
1663  const ArSp::IIx_t i0) const
1664  {
1665  CH_assert(isUsable());
1666  return m_arrayImpl.data[
1667  Indexer::ixIndex1D(size(), i6, i5, i4, i3, i2, i1, i0)];
1668  }
1669  const T &operator()(const ArSp::IIx_t i5, const ArSp::IIx_t i4,
1670  const ArSp::IIx_t i3, const ArSp::IIx_t i2,
1671  const ArSp::IIx_t i1, const ArSp::IIx_t i0) const
1672  {
1673  CH_assert(isUsable());
1674  return m_arrayImpl.data[
1675  Indexer::ixIndex1D(size(), i5, i4, i3, i2, i1, i0)];
1676  }
1677  const T &operator()(const ArSp::IIx_t i4, const ArSp::IIx_t i3,
1678  const ArSp::IIx_t i2, const ArSp::IIx_t i1,
1679  const ArSp::IIx_t i0) const
1680  {
1681  CH_assert(isUsable());
1682  return m_arrayImpl.data[Indexer::ixIndex1D(size(), i4, i3, i2, i1, i0)];
1683  }
1684  const T &operator()(const ArSp::IIx_t i3, const ArSp::IIx_t i2,
1685  const ArSp::IIx_t i1, const ArSp::IIx_t i0) const
1686  {
1687  CH_assert(isUsable());
1688  return m_arrayImpl.data[Indexer::ixIndex1D(size(), i3, i2, i1, i0)];
1689  }
1690  const T &operator()(const ArSp::IIx_t i2, const ArSp::IIx_t i1,
1691  const ArSp::IIx_t i0) const
1692  {
1693  CH_assert(isUsable());
1694  return m_arrayImpl.data[Indexer::ixIndex1D(size(), i2, i1, i0)];
1695  }
1696  const T &operator()(const ArSp::IIx_t i1, const ArSp::IIx_t i0) const
1697  {
1698  CH_assert(isUsable());
1699  return m_arrayImpl.data[Indexer::ixIndex1D(size(), i1, i0)];
1700  }
1701  const T &operator()(const ArSp::IIx_t i0) const
1702  {
1703  CH_assert(isUsable());
1704  return m_arrayImpl.data[Indexer::ixIndex1D(size(), i0)];
1705  }
1706  const T &operator()(const IntVect& iv,
1707  const ArSp::IIx_t c1, const ArSp::IIx_t c0) const
1708  {
1709  CH_assert(isUsable());
1710  return m_arrayImpl.data[Indexer::ixIndex1D(size(), D_IXIV, c1, c0)];
1711  }
1712  const T &operator()(const IntVect& iv, const ArSp::IIx_t c0) const
1713  {
1714  CH_assert(isUsable());
1715  return m_arrayImpl.data[Indexer::ixIndex1D(size(), D_IXIV, c0)];
1716  }
1717  const T &operator()(const ArSp::IIx_t c1, const ArSp::IIx_t c0,
1718  const IntVect& iv) const
1719  {
1720  CH_assert(isUsable());
1721  return m_arrayImpl.data[Indexer::ixIndex1D(size(), c1, c0, D_IXIV)];
1722  }
1723  const T &operator()(const ArSp::IIx_t c0, const IntVect& iv) const
1724  {
1725  CH_assert(isUsable());
1726  return m_arrayImpl.data[Indexer::ixIndex1D(size(), c0, D_IXIV)];
1727  }
1728 
1729  /// Get the allocator
1730  Alloc& getAllocator()
1731  {
1732  return *static_cast<Alloc*>(&m_arrayImpl);
1733  }
1734 
1735  /// Access extents of the memory allocated for the array
1736  T* begin()
1737  {
1738  return m_arrayImpl.data;
1739  }
1740  const T* begin() const
1741  {
1742  return m_arrayImpl.data;
1743  }
1744  T* end()
1745  {
1746  return m_arrayImpl.data + size();
1747  }
1748  const T* end() const
1749  {
1750  return m_arrayImpl.data + size();
1751  }
1752 
1753  /// Rank of the array
1754  static constexpr unsigned rank() noexcept
1755  {
1756  return Rank;
1757  }
1758 
1759  /// Overall size of the array
1761  {
1762  return m_arrayImpl.size;
1763  }
1764 
1765  /// Size of a dimension (0 is dimension with contiguous storage)
1766  ArSp::USz_t size(const unsigned dim) const
1767  {
1768  CH_assert(isUsable());
1769  CH_assert(dim < Rank);
1770  return Indexer::ixDimSize(size(), dim+1);
1771  }
1772 
1773  /// Lower bound of a dimension (0 is dimension with contiguous storage)
1774  ArSp::IIx_t lowerBound(const unsigned dim) const
1775  {
1776  CH_assert(isUsable());
1777  CH_assert(dim < Rank);
1778  return Indexer::ixLowerBound(dim+1);
1779  }
1780 
1781  /// Upper bound of a dimension (0 is dimension with contiguous storage)
1782  ArSp::IIx_t upperBound(const unsigned dim) const
1783  {
1784  CH_assert(isUsable());
1785  CH_assert(dim < Rank);
1786  return Indexer::ixUpperBound(size(), dim+1);
1787  }
1788 
1789  /// Offset from non-zero lower bound
1791  {
1792  CH_assert(isUsable());
1793  return Indexer::ixTotalOffset();
1794  }
1795 
1796  /// Memory has been allocated
1797  bool isAllocated() const
1798  {
1799  return (m_arrayImpl.data != 0);
1800  }
1801 
1802  /// Memory has been allocated and size is > 0
1803  bool isUsable() const
1804  {
1805  return isAllocated() && size() > 0;
1806  }
1807 
1808 private:
1809 
1810  CHArray(const CHArray&);
1811  CHArray &operator=(const CHArray&);
1812 
1813  struct Array_impl : public Alloc
1814  {
1816  : size(0), data(0)
1817  { }
1818  Array_impl(const ArSp::USz_t a_size)
1819  : size(a_size), data(0)
1820  {
1821  data = Alloc::allocate(size);
1822  }
1824  {
1825  if (data != 0) undefine();
1826  }
1827  void define(const ArSp::USz_t a_size)
1828  {
1829  if (data != 0) undefine();
1830  size = a_size;
1831  data = Alloc::allocate(size);
1832  }
1833  void define(void *const addr, const ArSp::USz_t a_size)
1834  {
1835  if (data != 0) undefine();
1836  size = a_size;
1837  data = Alloc::allocate(addr, size);
1838  }
1839  void undefine()
1840  {
1841  Alloc::deallocate(data, size);
1842  data = 0;
1843  size = 0;
1844  }
1845  ArSp::USz_t size; ///< Overall size of the array
1846  T *data; ///< Data for the array
1847  };
1848 
1849  Array_impl m_arrayImpl; ///< Data + allocation/deallocation
1850 };
1851 
1852 /// Vector definition
1854 
1855 /// Matrix defined with column-ordered storage
1857 
1858 /// Output of an array
1859 template<typename T, unsigned Rank, int ArConf, typename Alloc>
1860 std::ostream &operator<<(std::ostream &os,
1862 {
1863  CH_assert(A.isAllocated());
1864  const T *p = A.begin();
1865  const T *const pEnd = A.end();
1866  if (p != pEnd) os << *p++;
1867  while (p != pEnd) os << ' ' << *p++;
1868  return os;
1869 }
1870 
1871 /// Pretty output of a matrix (should be in .cpp)
1872 template<>
1873 inline std::ostream &operator<<(std::ostream &os, const CHMatrix &M)
1874 {
1875  CH_assert(M.isAllocated());
1876  const int prec = 2;
1877  os.setf(std::ios_base::scientific, std::ios_base::floatfield);
1878  os.precision(prec);
1879  const ArSp::USz_t iMax = M.size(0);
1880  const ArSp::USz_t jMax = M.size(1);
1881  for (ArSp::USz_t i = 0; i != iMax; ++i)
1882  {
1883  if (jMax > 0)
1884  {
1885  os << std::setw(prec+7) << M(i, 0);
1886  for (ArSp::USz_t j = 1; j != jMax; ++j)
1887  {
1888  os << ' ' << std::setw(prec+7) << M(i, j);
1889  }
1890  os << std::endl;
1891  }
1892  }
1893  os.setf(std::ios_base::fmtflags(0), std::ios_base::floatfield);
1894  os.precision(6);
1895  return os;
1896 }
1897 
1898 namespace ArSp
1899 {
1900 
1901 /*====================================================================*/
1902 /** \name Special allocators
1903  *//*=================================================================*/
1904 //@{
1905 
1906 /*--------------------------------------------------------------------*/
1907 /// Allocator that only permits allocation by new
1908 /** Use of CHArray::define(void *const addr, ...) will cause an error
1909  *//*-----------------------------------------------------------------*/
1910 
1911 template <typename T>
1913 {
1914 public:
1915  T* allocate(const USz_t size)
1916  {
1917  T *const p = new(std::nothrow) T[size];
1918  CH_assert(p != 0);
1919  return p;
1920  }
1921 
1922  void deallocate(T *p, const USz_t size)
1923  {
1924  delete[] p;
1925  }
1926 };
1927 
1928 /*--------------------------------------------------------------------*/
1929 /// Allocator for an array of vectors contiguous in memory
1930 /** Useful for allocating an array of vectors which can be easily
1931  * passed to Fortran, etc.
1932  *
1933  * Example - 1D Array of 2 size 3 vectors \verbatim
1934  *
1935  * CHArray<CHVector, 1, ArZeroRow, ArSp::ArrayOfVectorAlloc> AV;
1936  * AV.getAllocator().define(3);
1937  * AV.define(2);
1938  * AV(0) = 1.1;
1939  * AV(1) = 1.9;
1940  * std::cout << AV << std::endl;
1941  * \endverbatim
1942  *//*-----------------------------------------------------------------*/
1943 
1945 {
1946  public:
1948  : defined(false)
1949  { }
1950  void define(const USz_t a_n)
1951  {
1952  n = a_n;
1953  defined = true;
1954  }
1955  CHVector* allocate(const USz_t size)
1956  {
1957  CH_assert(defined);
1958  CHVector *const V = new(std::nothrow) CHVector[size];
1959  CH_assert(V != 0);
1960  vectorData = new(std::nothrow) Real[size*n];
1961  CH_assert(vectorData != 0);
1962  for (USz_t i = 0; i != size; ++i)
1963  {
1964  V[i].define(vectorData + i*n, n);
1965  }
1966  return V;
1967  }
1968  void deallocate(CHVector *p, const USz_t size)
1969  {
1970  delete[] p;
1971  delete[] vectorData;
1972  }
1973 private:
1976  bool defined;
1977 };
1978 
1979 /*--------------------------------------------------------------------*/
1980 /// Allocator for an array of matrices contiguous in memory
1981 /** Useful for allocating an array of matrices which can be easily
1982  * passed to Fortran, etc.
1983  *
1984  * Example - 1D Array of 2 3x3 matrices \verbatim
1985  *
1986  * CHArray<CHMatrix, 1, ArZeroRow, ArSp::ArrayOfMatrixAlloc> AM;
1987  * AM.getAllocator().define(3, 3);
1988  * AM.define(2);
1989  * AM(0) = 1.1;
1990  * AM(1) = 1.9;
1991  * std::cout << AM << std::endl;
1992  * \endverbatim
1993  *//*-----------------------------------------------------------------*/
1994 
1996 {
1997  public:
1999  : defined(false)
2000  { }
2001  void define(const USz_t a_m, const USz_t a_n)
2002  {
2003  m = a_m;
2004  n = a_n;
2005  defined = true;
2006  }
2007  CHMatrix* allocate(const USz_t size)
2008  {
2009  CH_assert(defined);
2010  CHMatrix *const M = new(std::nothrow) CHMatrix[size];
2011  CH_assert(M != 0);
2012  const USz_t stride = m*n;
2013  matrixData = new(std::nothrow) Real[size*stride];
2014  CH_assert(matrixData != 0);
2015  for (USz_t i = 0; i != size; ++i)
2016  {
2017  M[i].define(matrixData + i*stride, m, n);
2018  }
2019  return M;
2020  }
2021  void deallocate(CHMatrix *p, const USz_t size)
2022  {
2023  delete[] p;
2024  delete[] matrixData;
2025  }
2026 private:
2030  bool defined;
2031 };
2032 //@}
2033 } // End of namespace ArSp
2034 
2035 //--Row ordered speed test
2036 
2037 // StopWatchLinux sw1;
2038 // CHArray<int, 3, ArZeroRow> AR1;
2039 // const unsigned nr = 200;
2040 // AR1.define(nr, nr, nr);
2041 // AR1 = 1;
2042 // sw1.start();
2043 // for (int i = 1; i != nr; ++i)
2044 // for (int j = 0; j != nr; ++j)
2045 // for (int k = 0; k != nr; ++k)
2046 // AR1(i, j, k) += AR1(i-1, j, k);
2047 // sw1.stop();
2048 // std::cout << AR1((int)AR1(1, 0, 0), (int)AR1(0, 1, 0), (int)AR1(0, 0, 1))
2049 // << std::endl;
2050 // std::cout << "Time: " << sw1.getTime() << std::endl;
2051 
2052 //--Column ordered speed test
2053 
2054 // StopWatchLinux sw2;
2055 // CHArray<int, 3, ArZeroCol> AC1;
2056 // const unsigned nc = 200;
2057 // AC1.define(nc, nc, nc);
2058 // AC1 = 1;
2059 // sw2.start();
2060 // for (int i = 1; i != nc; ++i)
2061 // for (int j = 0; j != nc; ++j)
2062 // for (int k = 0; k != nc; ++k)
2063 // AC1(k, j, i) += AC1(k, j, i-1);
2064 // sw2.stop();
2065 // std::cout << AC1((int)AC1(1, 0, 0), (int)AC1(0, 1, 0), (int)AC1(0, 0, 1))
2066 // << std::endl;
2067 // std::cout << "Time: " << sw2.getTime() << std::endl;
2068 
2069 #ifdef CH_SPACEDIM
2070  #include "NamespaceFooter.H"
2071 #endif
2072 #endif
Multidimensional array class.
Definition: CHArray.H:1283
CHArray(const Box &box, const DimT &dimc0)
Definition: CHArray.H:1347
#define D_DECL6(a, b, c, d, e, f)
Definition: CHArray.H:39
USz_t ixIndex1D(const USz_t size, const IIx_t i0, const IIx_t i1, const IIx_t i2, const IIx_t i3, const IIx_t i4) const
Definition: CHArray.H:937
USz_t ixDimSize(const USz_t size, const unsigned dim) const
Definition: CHArray.H:733
IIx_t m_ixIB
Lower bound for this dimension.
Definition: CHArray.H:508
IIx_t ixLowerBound(const unsigned dim) const
Definition: CHArray.H:795
bool isUsable() const
Memory has been allocated and size is > 0.
Definition: CHArray.H:1803
void define(void *const addr, const IntVect &iv, const DimT &dimc0)
Definition: CHArray.H:1521
Rank > 2 for zero-based subscripts and > 1 for subscript ranges.
Definition: CHArray.H:825
CHArray(const DimT &dim3, const DimT &dim2, const DimT &dim1, const DimT &dim0)
Definition: CHArray.H:1312
IIx_t ixDimOffset() const
Definition: CHArray.H:401
Allocator for an array of matrices contiguous in memory.
Definition: CHArray.H:1995
ArSp::IIx_t dimB
Definition: CHArray.H:196
#define D_DEFIV
Definition: CHArray.H:122
void define(const DimT &dimc1, const DimT &dimc0, const IntVect &iv)
Definition: CHArray.H:1422
void deallocate(CHVector *p, const USz_t size)
Definition: CHArray.H:1968
USz_t m_ixStride
Stride for this dimension.
Definition: CHArray.H:438
void ixDefine(const IIx_t offset, const DimT &dim6, const DimT &dim5, const DimT &dim4, const DimT &dim3, const DimT &dim2, const DimT &dim1, const DimT &dim0)
Definition: CHArray.H:569
IIx_t ixLowerBound(const unsigned dim) const
Definition: CHArray.H:974
T & operator()(const ArSp::IIx_t i2, const ArSp::IIx_t i1, const ArSp::IIx_t i0)
Definition: CHArray.H:1622
#define D_DEFBOX
Definition: CHArray.H:130
int vec[SpaceDim]
Definition: CHArray.H:70
void define(void *const addr, const DimT &dim4, const DimT &dim3, const DimT &dim2, const DimT &dim1, const DimT &dim0)
Definition: CHArray.H:1482
Rank 1 and a zero-based subscript (no data)
Definition: CHArray.H:448
T & operator()(const ArSp::IIx_t c0, const IntVect &iv)
Definition: CHArray.H:1653
Allocator that only permits allocation by new.
Definition: CHArray.H:1912
#define D_TERM6(a, b, c, d, e, f)
Definition: CHArray.H:40
static void eval(T *p, USz_t size)
Definition: CHArray.H:296
void ixDefine(const IIx_t offset, const DimT &dim0, const DimT &dim1, const DimT &dim2, const DimT &dim3, const DimT &dim4, const DimT &dim5, const DimT &dim6)
Definition: CHArray.H:870
IIx_t ixLowerBound(const unsigned dim) const
Definition: CHArray.H:1095
#define CH_assert(cond)
Definition: CHArray.H:37
void define(void *const addr, const DimT &dim1, const DimT &dim0)
Definition: CHArray.H:1502
const T & operator()(const ArSp::IIx_t i6, const ArSp::IIx_t i5, const ArSp::IIx_t i4, const ArSp::IIx_t i3, const ArSp::IIx_t i2, const ArSp::IIx_t i1, const ArSp::IIx_t i0) const
Constant access to an element.
Definition: CHArray.H:1660
void define(const DimT &dim2, const DimT &dim1, const DimT &dim0)
Definition: CHArray.H:1396
IndexerData< 1, DimT > IxData
Definition: CHArray.H:1007
void ixDefineTotalOffset(const IIx_t offset)
Definition: CHArray.H:465
Array_impl()
Definition: CHArray.H:1815
#define SpaceDim
Definition: CHArray.H:38
CSIndexer(const IIx_t offset, const DimT &dim0, const DimT &dim1, const DimT &dim2, const DimT &dim3)
Definition: CHArray.H:853
const T & operator()(const ArSp::IIx_t i2, const ArSp::IIx_t i1, const ArSp::IIx_t i0) const
Definition: CHArray.H:1690
const T & operator()(const ArSp::IIx_t i5, const ArSp::IIx_t i4, const ArSp::IIx_t i3, const ArSp::IIx_t i2, const ArSp::IIx_t i1, const ArSp::IIx_t i0) const
Definition: CHArray.H:1669
bool ixValidBounds(const IIx_t i, const USz_t size) const
Definition: CHArray.H:461
IIx_t ixLowerBound() const
Definition: CHArray.H:491
IIx_t ixUpperBound(const USz_t size, const unsigned dim) const
Definition: CHArray.H:799
Definition: CHArray_fwd.H:37
CHArray(const Box &box, const DimT &dimc1, const DimT &dimc0)
Definition: CHArray.H:1339
IIx_t ixTotalOffset() const
Definition: CHArray.H:467
T * allocate(void *const addr, const USz_t size)
Definition: CHArray.H:349
unsigned ixIV(const unsigned i) const
Definition: CHArray.H:1108
const T & operator()(const ArSp::IIx_t i4, const ArSp::IIx_t i3, const ArSp::IIx_t i2, const ArSp::IIx_t i1, const ArSp::IIx_t i0) const
Definition: CHArray.H:1677
IIx_t ixUpperBound(const USz_t size, const unsigned dim) const
Definition: CHArray.H:741
bool defined
Definition: CHArray.H:2030
static constexpr unsigned rank() noexcept
Rank of the array.
Definition: CHArray.H:1754
CHArray< Real, 2, ArZeroCol, ArSp::DefaultArrayAlloc< Real > > CHMatrix
Matrix defined with column-ordered storage.
Definition: CHArray.H:1856
int product() const
Definition: CHArray.H:64
void ixDefine(const IIx_t offset, const DimT &dim3, const DimT &dim2, const DimT &dim1, const DimT &dim0)
Definition: CHArray.H:596
T & operator()(const ArSp::IIx_t c1, const ArSp::IIx_t c0, const IntVect &iv)
Definition: CHArray.H:1648
IIx_t ixUpperBound(const USz_t size, const unsigned dim) const
Definition: CHArray.H:679
IndexerData< 1, DimT > IxData
Definition: CHArray.H:706
CSIndexer(const IIx_t offset, const DimT &dim0, const DimT &dim1, const DimT &dim2)
Definition: CHArray.H:859
USz_t ixIndex1D(const USz_t size, const IIx_t i0) const
Definition: CHArray.H:1026
IntVect(const IntVect &iv)
Definition: CHArray.H:51
void ixDefine(const IIx_t offset, const USz_t dim0, const USz_t dim1)
Definition: CHArray.H:1076
USz_t ixIndex1D(const USz_t size, const IIx_t i2, const IIx_t i1, const IIx_t i0) const
Definition: CHArray.H:652
void deallocate(CHMatrix *p, const USz_t size)
Definition: CHArray.H:2021
const int & operator[](const int i) const
Definition: CHArray.H:60
void define(const DimT &dimc0, const Box &box)
Definition: CHArray.H:1457
T & operator()(const IntVect &iv, const ArSp::IIx_t c0)
Definition: CHArray.H:1643
void define(void *const addr, const Box &box, const DimT &dimc1, const DimT &dimc0)
Definition: CHArray.H:1538
USz_t ixIndex1D(const USz_t size, const IIx_t i0, const IIx_t i1, const IIx_t i2, const IIx_t i3, const IIx_t i4, const IIx_t i5, const IIx_t i6) const
Definition: CHArray.H:920
void define(void *const addr, const DimT &dim2, const DimT &dim1, const DimT &dim0)
Definition: CHArray.H:1496
AllocBy m_allocBy
Definition: CHArray.H:334
void ixDefineLowerBound(const DimT &dim)
Definition: CHArray.H:391
IntVect size() const
Definition: CHArray.H:86
const T & operator()(const ArSp::IIx_t i3, const ArSp::IIx_t i2, const ArSp::IIx_t i1, const ArSp::IIx_t i0) const
Definition: CHArray.H:1684
int BoxAllowed
Definition: CHArray.H:1146
void define(void *const addr, const DimT &dim3, const DimT &dim2, const DimT &dim1, const DimT &dim0)
Definition: CHArray.H:1489
double Real
Definition: CHArray.H:41
USz_t ixDimSize(const USz_t size, const unsigned dim) const
Definition: CHArray.H:667
const T * begin() const
Definition: CHArray.H:1740
CHArray & operator=(const T2 &val)
Assign a constant to the array.
Definition: CHArray.H:1582
CHArray(const DimT &dim0)
Definition: CHArray.H:1322
RSIndexer(const IIx_t offset, const USz_t &dim1, const USz_t &dim0)
Definition: CHArray.H:771
USz_t ixIndex1D(const USz_t size, const IIx_t i0, const IIx_t i1, const IIx_t i2) const
Definition: CHArray.H:953
T & operator()(const IntVect &iv, const ArSp::IIx_t c1, const ArSp::IIx_t c0)
Definition: CHArray.H:1638
CHRange(const ArSp::IIx_t a_dimE)
Definition: CHArray.H:186
CSIndexer< Rank-1, DimT > m_ixNext
Next lower rank.
Definition: CHArray.H:997
Array_impl(const ArSp::USz_t a_size)
Definition: CHArray.H:1818
RSIndexer(const IIx_t offset, const DimT &dim2, const DimT &dim1, const DimT &dim0)
Definition: CHArray.H:558
void undefine()
Definition: CHArray.H:1839
USz_t ixIndex1D(const USz_t size, const IIx_t i4, const IIx_t i3, const IIx_t i2, const IIx_t i1, const IIx_t i0) const
Definition: CHArray.H:636
void ixDefine(const IIx_t offset, const DimT &dim1, const DimT &dim0)
Definition: CHArray.H:611
RSIndexer()
Definition: CHArray.H:767
IndexerData< Rank, DimT > IxData
Definition: CHArray.H:827
IIx_t ixTotalOffset() const
Definition: CHArray.H:803
void ixDefineLowerBound(const CHRange &dim)
Definition: CHArray.H:422
RSIndexer(const IIx_t offset, const DimT &dim0)
Definition: CHArray.H:712
int IIx_t
Definition: CHArray_fwd.H:54
void define(const DimT &dim4, const DimT &dim3, const DimT &dim2, const DimT &dim1, const DimT &dim0)
Definition: CHArray.H:1384
ArSp::USz_t size
Overall size of the array.
Definition: CHArray.H:1845
void ixDefine(const IIx_t offset, const DimT &dim0, const DimT &dim1, const DimT &dim2)
Definition: CHArray.H:905
int smallEnd(const int dir) const
Definition: CHArray.H:78
ArSp::ArTr< Rank, ArConf >::DimT DimT
Definition: CHArray.H:1285
USz_t ixIndex1D(const USz_t size, const IIx_t i1, const IIx_t i0) const
Definition: CHArray.H:782
IIx_t ixLowerBound(const unsigned dim) const
Definition: CHArray.H:737
CHArray(const DimT &dim1, const DimT &dim0)
Definition: CHArray.H:1319
IIx_t ixLowerBound() const
Definition: CHArray.H:426
void ixDefineLowerBound(const DimT &dim)
Definition: CHArray.H:455
IIx_t ixTotalOffset() const
Definition: CHArray.H:1045
const T & operator()(const IntVect &iv, const ArSp::IIx_t c0) const
Definition: CHArray.H:1712
bool ixValidBounds(const IIx_t i, const USz_t size) const
Definition: CHArray.H:430
bool ixValidBounds(const IIx_t i, const USz_t size) const
Definition: CHArray.H:397
Alloc & getAllocator()
Get the allocator.
Definition: CHArray.H:1730
void define(void *const addr, const DimT &dimc0, const Box &box)
Definition: CHArray.H:1564
void define(const DimT &dim0)
Definition: CHArray.H:1406
Any rank and a zero-based subscript.
Definition: CHArray.H:382
ArSp::RSIndexer< Rank, DimT > IndexerT
Definition: CHArray.H:1138
AllocBy
Definition: CHArray.H:328
USz_t m
Definition: CHArray.H:2028
void ixDefineLowerBound(const CHRange &dim)
Definition: CHArray.H:487
CSIndexer()
Definition: CHArray.H:1067
ArSp::IIx_t lowerBound(const unsigned dim) const
Lower bound of a dimension (0 is dimension with contiguous storage)
Definition: CHArray.H:1774
void define(const DimT &dimc1, const DimT &dimc0, const Box &box)
Definition: CHArray.H:1449
USz_t ixIndex1D(const USz_t size, const IIx_t i0, const IIx_t i1) const
Definition: CHArray.H:960
const T & operator()(const ArSp::IIx_t i1, const ArSp::IIx_t i0) const
Definition: CHArray.H:1696
Definition: EBInterface.H:45
unsigned USz_t
Type of unsigned int for a size.
Definition: CHArray_fwd.H:57
RSIndexer(const IIx_t offset, const DimT &dim6, const DimT &dim5, const DimT &dim4, const DimT &dim3, const DimT &dim2, const DimT &dim1, const DimT &dim0)
Definition: CHArray.H:532
void const char const int const int const int const Real const Real const int const Real const int const Real Real * C
Definition: Lapack.H:83
USz_t ixIndex1D(const USz_t size, const IIx_t i0) const
Definition: CHArray.H:726
ArSp::USz_t size(const unsigned dim) const
Size of a dimension (0 is dimension with contiguous storage)
Definition: CHArray.H:1766
CHArray(const IntVect &iv, const DimT &dimc0)
Definition: CHArray.H:1329
IIx_t ixLowerBound() const
Definition: CHArray.H:393
IndexerData(const USz_t stride, const DimT &dim)
Definition: CHArray.H:388
T & operator()(const ArSp::IIx_t i3, const ArSp::IIx_t i2, const ArSp::IIx_t i1, const ArSp::IIx_t i0)
Definition: CHArray.H:1616
void ixDefine(const IIx_t offset, const DimT &dim2, const DimT &dim1, const DimT &dim0)
Definition: CHArray.H:604
RSIndexer(const IIx_t offset, const DimT &dim4, const DimT &dim3, const DimT &dim2, const DimT &dim1, const DimT &dim0)
Definition: CHArray.H:546
IndexerData()
Definition: CHArray.H:416
T & operator()(const ArSp::IIx_t i1, const ArSp::IIx_t i0)
Definition: CHArray.H:1628
CHRange(const ArSp::IIx_t a_dimB, const ArSp::IIx_t a_dimE)
Definition: CHArray.H:191
T * end()
Definition: CHArray.H:1744
IntVect m_lb
Definition: CHArray.H:95
IIx_t ixDimOffset() const
Definition: CHArray.H:434
ArSp::USz_t DimT
Definition: CHArray.H:1131
void const char const int const int const int const Real const Real * A
Definition: Lapack.H:83
Box(const IntVect &lb, const IntVect &ub)
Definition: CHArray.H:75
CSIndexer()
Definition: CHArray.H:829
USz_t sizeOfDim< CHRange >(const CHRange &dim)
Definition: CHArray.H:217
ArSp::ArTr< Rank, ArConf >::IndexerT Indexer
Definition: CHArray.H:1286
IntVect(D_DECL6(const int i0, const int i1, const int i2, const int i3, const int i4, const int i5))
Definition: CHArray.H:45
void define(const USz_t a_m, const USz_t a_n)
Definition: CHArray.H:2001
IIx_t m_ixIB
Lower bound for this dimension.
Definition: CHArray.H:440
Definition: CHArray.H:1813
T * data
Data for the array.
Definition: CHArray.H:1846
RSIndexer(const IIx_t offset, const DimT &dim5, const DimT &dim4, const DimT &dim3, const DimT &dim2, const DimT &dim1, const DimT &dim0)
Definition: CHArray.H:540
Real * matrixData
Definition: CHArray.H:2027
IndexerData(const CHRange &dim)
Definition: CHArray.H:484
IndexerData< 2, USz_t > IxData
Definition: CHArray.H:765
USz_t ixIndex1D(const USz_t size, const IIx_t i0, const IIx_t i1, const IIx_t i2, const IIx_t i3) const
Definition: CHArray.H:945
~Array_impl()
Definition: CHArray.H:1823
RSIndexer()
Definition: CHArray.H:528
Array_impl m_arrayImpl
Data + allocation/deallocation.
Definition: CHArray.H:1849
DefaultArrayAlloc()
Definition: CHArray.H:337
void define(const ArSp::USz_t a_size)
Definition: CHArray.H:1827
bool ixValidBounds(const IIx_t i, const USz_t size) const
Definition: CHArray.H:495
IIx_t ixUpperBound(const USz_t size, const unsigned dim) const
Definition: CHArray.H:980
void ixDefine(const IIx_t offset, const DimT &dim0, const DimT &dim1, const DimT &dim2, const DimT &dim3)
Definition: CHArray.H:897
IndexerData< Rank, DimT > IxData
Definition: CHArray.H:526
friend std::ostream & operator<<(std::ostream &os, const IntVect &iv)
void define(void *const addr, const DimT &dimc0, const IntVect &iv)
Definition: CHArray.H:1532
T & operator()(const ArSp::IIx_t i4, const ArSp::IIx_t i3, const ArSp::IIx_t i2, const ArSp::IIx_t i1, const ArSp::IIx_t i0)
Definition: CHArray.H:1609
Forward declarations for class CHArray.
void define(const IntVect &iv, const DimT &dimc1, const DimT &dimc0)
Definition: CHArray.H:1412
RSIndexer< Rank-1, DimT > m_ixNext
Next lower rank.
Definition: CHArray.H:696
double Real
Definition: REAL.H:33
IndexerData(const USz_t stride, const CHRange &dim)
Definition: CHArray.H:419
void ixDefine(const IIx_t offset, const DimT &dim0)
Definition: CHArray.H:719
USz_t ixIndex1D(const USz_t size, const IIx_t i0, const IIx_t i1, const IIx_t i2, const IIx_t i3, const IIx_t i4, const IIx_t i5) const
Definition: CHArray.H:929
T * allocate(const USz_t size)
Definition: CHArray.H:1915
Definition: CHArray.H:280
IntVect m_ub
Definition: CHArray.H:96
RSIndexer()
Definition: CHArray.H:708
unsigned ixIV(const unsigned i) const
Definition: CHArray.H:690
USz_t m_ixStride
Stride for this dimension.
Definition: CHArray.H:405
void ixDefine(const IIx_t offset, const DimT &dim0, const DimT &dim1, const DimT &dim2, const DimT &dim3, const DimT &dim4, const DimT &dim5)
Definition: CHArray.H:880
Real * vectorData
Definition: CHArray.H:1974
IIx_t ixLowerBound(const unsigned dim) const
Definition: CHArray.H:673
int & operator[](const int i)
Definition: CHArray.H:56
CHArray(const DimT &dim4, const DimT &dim3, const DimT &dim2, const DimT &dim1, const DimT &dim0)
Definition: CHArray.H:1307
Range of subscripts and row-storage.
Definition: CHArray_fwd.H:36
void define(const IntVect &iv, const DimT &dimc0)
Definition: CHArray.H:1417
void define(void *const addr, const DimT &dim6, const DimT &dim5, const DimT &dim4, const DimT &dim3, const DimT &dim2, const DimT &dim1, const DimT &dim0)
Define the dimensions and allocate on 'addr'.
Definition: CHArray.H:1467
CSIndexer(const IIx_t offset, const DimT &dim0, const DimT &dim1, const DimT &dim2, const DimT &dim3, const DimT &dim4, const DimT &dim5, const DimT &dim6)
Definition: CHArray.H:833
IIx_t ixTotalOffset() const
Definition: CHArray.H:1103
IIx_t ixUpperBound(const USz_t size, const unsigned dim) const
Definition: CHArray.H:1099
ArSp::RSIndexer< Rank, DimT > IndexerT
Definition: CHArray.H:1126
IIx_t ixTotalOffset() const
Definition: CHArray.H:745
CHMatrix * allocate(const USz_t size)
Definition: CHArray.H:2007
unsigned ixIV(const unsigned i) const
Definition: CHArray.H:1050
void ixDefine(const IIx_t offset, const DimT &dim0)
Definition: CHArray.H:1020
int BoxAllowed
Definition: CHArray.H:1139
void ixDefine(const IIx_t offset, const DimT &dim0, const DimT &dim1)
Definition: CHArray.H:912
void deallocate(T *p, const USz_t size)
Definition: CHArray.H:355
CSIndexer(const IIx_t offset, const DimT &dim0, const DimT &dim1, const DimT &dim2, const DimT &dim3, const DimT &dim4, const DimT &dim5)
Definition: CHArray.H:841
unsigned ixIV(const unsigned i) const
Definition: CHArray.H:808
CHArray(const DimT &dimc0, const IntVect &iv)
Definition: CHArray.H:1335
CHArray(const DimT &dimc1, const DimT &dimc0, const IntVect &iv)
Definition: CHArray.H:1332
void ixDefine(const IIx_t offset, const DimT &dim5, const DimT &dim4, const DimT &dim3, const DimT &dim2, const DimT &dim1, const DimT &dim0)
Definition: CHArray.H:579
void define(void *const addr, const DimT &dim0)
Definition: CHArray.H:1508
T * begin()
Access extents of the memory allocated for the array.
Definition: CHArray.H:1736
IIx_t ixLowerBound(const unsigned dim) const
Definition: CHArray.H:1037
bool defined
Definition: CHArray.H:1976
Definition: CHArray.H:331
ArSp::CSIndexer< Rank, DimT > IndexerT
Definition: CHArray.H:1145
void define(const Box &box, const DimT &dimc1, const DimT &dimc0)
Definition: CHArray.H:1433
void define(void *const addr, const DimT &dimc1, const DimT &dimc0, const IntVect &iv)
Definition: CHArray.H:1526
ArrayOfMatrixAlloc()
Definition: CHArray.H:1998
T value_type
Type of element.
Definition: CHArray.H:1287
A Rectangular Domain on an Integer Lattice.
Definition: Box.H:469
Test for class type.
Definition: Misc.H:136
const T & operator()(const ArSp::IIx_t c1, const ArSp::IIx_t c0, const IntVect &iv) const
Definition: CHArray.H:1717
bool isAllocated() const
Memory has been allocated.
Definition: CHArray.H:1797
CHArray()
Default constructor.
Definition: CHArray.H:1291
void define(const DimT &dim1, const DimT &dim0)
Definition: CHArray.H:1401
void define(const USz_t a_n)
Definition: CHArray.H:1950
Zero lower bound and column-storage.
Definition: CHArray_fwd.H:35
T & operator()(const ArSp::IIx_t i6, const ArSp::IIx_t i5, const ArSp::IIx_t i4, const ArSp::IIx_t i3, const ArSp::IIx_t i2, const ArSp::IIx_t i1, const ArSp::IIx_t i0)
Access an element.
Definition: CHArray.H:1592
IIx_t ixTotalOffset() const
Definition: CHArray.H:986
void define(const DimT &dimc0, const IntVect &iv)
Definition: CHArray.H:1427
void ixDefine(const IIx_t offset, const DimT &dim4, const DimT &dim3, const DimT &dim2, const DimT &dim1, const DimT &dim0)
Definition: CHArray.H:588
CSIndexer()
Definition: CHArray.H:1009
USz_t ixIndex1D(const USz_t size, const IIx_t i5, const IIx_t i4, const IIx_t i3, const IIx_t i2, const IIx_t i1, const IIx_t i0) const
Definition: CHArray.H:628
CSIndexer(const IIx_t offset, const DimT &dim0)
Definition: CHArray.H:1013
IIx_t ixTotalOffset() const
Definition: CHArray.H:503
IIx_t ixLowerBound() const
Definition: CHArray.H:457
Definition: CHArray.H:251
static void eval(T *p, USz_t size)
Definition: CHArray.H:286
const T & operator()(const ArSp::IIx_t c0, const IntVect &iv) const
Definition: CHArray.H:1723
int bigEnd(const int dir) const
Definition: CHArray.H:82
IIx_t ixDimSize(const USz_t size, const unsigned dim) const
Definition: CHArray.H:1090
An integer Vector in SpaceDim-dimensional space.
Definition: CHArray.H:42
void define(const DimT &dim5, const DimT &dim4, const DimT &dim3, const DimT &dim2, const DimT &dim1, const DimT &dim0)
Definition: CHArray.H:1378
USz_t ixDimSize(const USz_t size, const unsigned dim) const
Definition: CHArray.H:1033
IndexerData(const DimT &dim)
Definition: CHArray.H:453
CHArray(const DimT &dim2, const DimT &dim1, const DimT &dim0)
Definition: CHArray.H:1316
ArrayOfVectorAlloc()
Definition: CHArray.H:1947
void ixDefine(const IIx_t offset, const DimT &dim0, const DimT &dim1, const DimT &dim2, const DimT &dim3, const DimT &dim4)
Definition: CHArray.H:889
CHArray< Real, 1, ArZeroCol, ArSp::DefaultArrayAlloc< Real > > CHVector
Vector definition.
Definition: CHArray.H:1853
void define(const Box &box, const DimT &dimc0)
Definition: CHArray.H:1441
void const char const int * M
Definition: Lapack.H:83
IndexerData< 2, USz_t > IxData
Definition: CHArray.H:1065
void p() const
Zero lower bound and row-storage.
Definition: CHArray_fwd.H:34
IIx_t ixTotalOffset() const
Definition: CHArray.H:685
ArSp::IIx_t totalOffset() const
Offset from non-zero lower bound.
Definition: CHArray.H:1790
IIx_t m_ixOffset
Definition: CHArray.H:509
USz_t ixDimSize(const USz_t size, const unsigned dim) const
Definition: CHArray.H:968
T & operator()(const ArSp::IIx_t i5, const ArSp::IIx_t i4, const ArSp::IIx_t i3, const ArSp::IIx_t i2, const ArSp::IIx_t i1, const ArSp::IIx_t i0)
Definition: CHArray.H:1601
RSIndexer(const IIx_t offset, const DimT &dim1, const DimT &dim0)
Definition: CHArray.H:563
T & operator()(const ArSp::IIx_t i0)
Definition: CHArray.H:1633
unsigned ixIV(const unsigned i) const
Definition: CHArray.H:750
CHVector * allocate(const USz_t size)
Definition: CHArray.H:1955
IndexerData()
Definition: CHArray.H:481
ArSp::USz_t size() const
Overall size of the array.
Definition: CHArray.H:1760
CHArray(const DimT &dimc0, const Box &box)
Definition: CHArray.H:1362
ArSp::IIx_t dimE
Definition: CHArray.H:197
IntVect operator*(const IntVect &p) const
Definition: IntVect.H:1102
Default allocator.
Definition: CHArray.H:325
RSIndexer(const IIx_t offset, const DimT &dim3, const DimT &dim2, const DimT &dim1, const DimT &dim0)
Definition: CHArray.H:552
void ixDefineTotalOffset(const IIx_t offset)
Definition: CHArray.H:499
void ixDefine(const IIx_t offset, const USz_t &dim1, const USz_t &dim0)
Definition: CHArray.H:776
ArSp::USz_t DimT
Definition: CHArray.H:1125
void deallocate(T *p, const USz_t size)
Definition: CHArray.H:1922
void define(void *const addr, const ArSp::USz_t a_size)
Definition: CHArray.H:1833
CSIndexer(const IIx_t offset, const DimT &dim0, const DimT &dim1)
Definition: CHArray.H:864
void define(void *const addr, const IntVect &iv, const DimT &dimc1, const DimT &dimc0)
Definition: CHArray.H:1515
ArSp::IIx_t upperBound(const unsigned dim) const
Upper bound of a dimension (0 is dimension with contiguous storage)
Definition: CHArray.H:1782
ArSp::CSIndexer< Rank, DimT > IndexerT
Definition: CHArray.H:1132
unsigned ixIV(const unsigned i) const
Definition: CHArray.H:991
Definition: CHArray.H:1121
static T * eval(void *const addr, const USz_t size)
Definition: CHArray.H:267
const T & operator()(const IntVect &iv, const ArSp::IIx_t c1, const ArSp::IIx_t c0) const
Definition: CHArray.H:1706
CSIndexer(const IIx_t offset, const USz_t dim0, const USz_t dim1)
Definition: CHArray.H:1071
int dim
Definition: EBInterface.H:146
USz_t ixIndex1D(const USz_t size, const IIx_t i6, const IIx_t i5, const IIx_t i4, const IIx_t i3, const IIx_t i2, const IIx_t i1, const IIx_t i0) const
Definition: CHArray.H:619
void undefine()
Deallocate the array.
Definition: CHArray.H:1574
USz_t n
Definition: CHArray.H:1975
USz_t ixIndex1D(const USz_t size, const IIx_t i1, const IIx_t i0) const
Definition: CHArray.H:659
void define(const DimT &dim6, const DimT &dim5, const DimT &dim4, const DimT &dim3, const DimT &dim2, const DimT &dim1, const DimT &dim0)
Define the dimensions.
Definition: CHArray.H:1371
#define D_IXIV
Definition: CHArray.H:145
USz_t ixIndex1D(const USz_t size, const IIx_t i3, const IIx_t i2, const IIx_t i1, const IIx_t i0) const
Definition: CHArray.H:644
USz_t ixDimSize(const USz_t size, const unsigned dim) const
Definition: CHArray.H:790
char One
Definition: CHArray.H:104
const T & operator()(const ArSp::IIx_t i0) const
Definition: CHArray.H:1701
USz_t sizeOfDim(const T &dim)
Get the size of a dimension.
Definition: CHArray.H:210
IndexerData()
Definition: CHArray.H:385
CHArray(const IntVect &iv, const DimT &dimc1, const DimT &dimc0)
Definition: CHArray.H:1326
CHArray(const DimT &dimc1, const DimT &dimc0, const Box &box)
Definition: CHArray.H:1354
CSIndexer(const IIx_t offset, const DimT &dim0, const DimT &dim1, const DimT &dim2, const DimT &dim3, const DimT &dim4)
Definition: CHArray.H:847
Allocator for an array of vectors contiguous in memory.
Definition: CHArray.H:1944
CHArray(const DimT &dim6, const DimT &dim5, const DimT &dim4, const DimT &dim3, const DimT &dim2, const DimT &dim1, const DimT &dim0)
Construct with dimensions.
Definition: CHArray.H:1296
void define(void *const addr, const DimT &dim5, const DimT &dim4, const DimT &dim3, const DimT &dim2, const DimT &dim1, const DimT &dim0)
Definition: CHArray.H:1475
T * allocate(const USz_t size)
Definition: CHArray.H:341
CHRange DimT
Definition: CHArray.H:1137
const T * end() const
Definition: CHArray.H:1748
IndexerData()
Definition: CHArray.H:451
static T * eval(void *const addr, const USz_t size)
Definition: CHArray.H:257
Defines a range of subscripts.
Definition: CHArray.H:184
void define(const DimT &dim3, const DimT &dim2, const DimT &dim1, const DimT &dim0)
Definition: CHArray.H:1390
CHRange DimT
Definition: CHArray.H:1144
USz_t ixIndex1D(const USz_t size, const IIx_t i0, const IIx_t i1) const
Definition: CHArray.H:1082
IIx_t ixUpperBound(const USz_t size, const unsigned dim) const
Definition: CHArray.H:1041
Rank > 2 for zero-based subscripts and > 1 for subscript ranges.
Definition: CHArray.H:524
void define(void *const addr, const DimT &dimc1, const DimT &dimc0, const Box &box)
Definition: CHArray.H:1555
CHArray(const DimT &dim5, const DimT &dim4, const DimT &dim3, const DimT &dim2, const DimT &dim1, const DimT &dim0)
Definition: CHArray.H:1302
IntVect()
Definition: IntVect.H:67
void define(void *const addr, const Box &box, const DimT &dimc0)
Definition: CHArray.H:1547
USz_t n
Definition: CHArray.H:2029