Advanced Multi-Physics (AMP)
On-Line Documentation
ArraySize.h
Go to the documentation of this file.
1#ifndef included_AMP_ArraySizeClass
2#define included_AMP_ArraySizeClass
3
4
5#include <array>
6#include <cmath>
7#include <complex>
8#include <cstdint>
9#include <cstdlib>
10#include <cstring>
11#include <initializer_list>
12#include <stdexcept>
13#include <vector>
14
15#include "AMP/utils/Memory.h"
16
17#if defined( __CUDA_ARCH__ )
18 #include <cuda.h>
19 #define HOST_DEVICE __host__ __device__
20#elif defined( __HIP_DEVICE_COMPILE__ )
21 #include "hip/hip_runtime.h"
22 #define HOST_DEVICE __host__ __device__
23#else
24 #define HOST_DEVICE
25#endif
26#if defined( __NVCC__ )
27 #define CONSTEXPR HOST_DEVICE constexpr
28 #define CONSTEXPR_IF
29#elif defined( __HIPCC__ )
30 #define CONSTEXPR HOST_DEVICE constexpr
31 #define CONSTEXPR_IF constexpr
32#else
33 #define CONSTEXPR HOST_DEVICE constexpr
34 #define CONSTEXPR_IF constexpr
35#endif
36#if defined( __GNUC__ ) || defined( __clang__ )
37 #define ARRAY_INLINE HOST_DEVICE inline __attribute__( ( always_inline ) )
38#elif defined( _MSC_VER )
39 #define ARRAY_INLINE HOST_DEVICE __forceinline
40#else
41 #define ARRAY_INLINE HOST_DEVICE inline
42#endif
43#if ( defined( DEBUG ) || defined( _DEBUG ) ) && !defined( NDEBUG ) && !defined( __NVCC__ ) && \
44 !defined( __HIP_DEVICE_COMPILE__ )
45 #define CHECK_ARRAY_LENGTH( i, length ) \
46 do { \
47 if ( i >= length ) \
48 throw std::out_of_range( "Index exceeds array bounds" ); \
49 } while ( 0 )
50 #define ARRAY_INSIST( test, msg ) \
51 do { \
52 if ( !( test ) ) \
53 throw std::out_of_range( msg ); \
54 } while ( 0 )
55#else
56 #define CHECK_ARRAY_LENGTH( i, length ) \
57 do { \
58 } while ( 0 )
59 #define ARRAY_INSIST( test, msg ) \
60 do { \
61 } while ( 0 )
62#endif
63
64namespace AMP {
65
66
67// Forward declerations
68template<class TYPE>
69class FunctionTable;
70template<class TYPE>
71class GPUFunctionTable;
72template<class TYPE, class FUN = FunctionTable<TYPE>, class Allocator = AMP::HostAllocator<void>>
73class Array;
74
75
77template<class TYPE = size_t>
78class Range final
79{
80public:
82 CONSTEXPR Range() : i( 0 ), j( 0 ), k( 1 ) {}
83
90 CONSTEXPR Range( const TYPE &i_, const TYPE &j_, const TYPE &k_ = 1 )
91 : i( i_ ), j( j_ ), k( k_ )
92 {
93 }
94
96 CONSTEXPR size_t size() const
97 {
98 if CONSTEXPR_IF ( std::is_integral_v<TYPE> ) {
99 int64_t tmp = ( static_cast<int64_t>( j ) - static_cast<int64_t>( i ) ) /
100 static_cast<int64_t>( k );
101 return tmp + 1;
102 } else if CONSTEXPR_IF ( std::is_floating_point_v<TYPE> ) {
103 double tmp = static_cast<double>( ( j - i ) ) / static_cast<double>( k );
104 return static_cast<size_t>( floor( tmp + 1e-12 ) + 1 );
105 } else if CONSTEXPR_IF ( std::is_same_v<TYPE, std::complex<float>> ||
106 std::is_same_v<TYPE, std::complex<double>> ) {
107 double tmp = std::real( ( j - i ) / ( k ) );
108 return static_cast<size_t>( floor( tmp + 1e-12 ) + 1 );
109 } else {
110 static_assert( !std::is_integral_v<TYPE>, "Unsupported type for range" );
111 return 0;
112 }
113 }
114
116 CONSTEXPR TYPE get( size_t index ) const
117 {
118 if CONSTEXPR_IF ( std::is_integral_v<TYPE> ) {
119 return static_cast<TYPE>( i + index * k );
120 } else if CONSTEXPR_IF ( std::is_floating_point_v<TYPE> ) {
121 return static_cast<TYPE>( k * ( i / k + index ) );
122 } else if CONSTEXPR_IF ( std::is_same_v<TYPE, std::complex<float>> ||
123 std::is_same_v<TYPE, std::complex<double>> ) {
124 return static_cast<TYPE>( k * ( i / k + static_cast<TYPE>( index ) ) );
125 } else {
126 static_assert( !std::is_integral_v<TYPE>, "Unsupported type for range" );
127 return static_cast<TYPE>( index );
128 }
129 }
130
131public:
132 TYPE i, j, k;
133};
134
135
137class ArraySize final
138{
139public:
141 CONSTEXPR ArraySize() : d_ndim( 1 ), d_length( 0 ), d_N{ 0, 1, 1, 1, 1 } {}
142
147 CONSTEXPR ArraySize( size_t N1 ) : d_ndim( 1 ), d_length( N1 ), d_N{ N1, 1, 1, 1, 1 } {}
148
154 CONSTEXPR ArraySize( size_t N1, size_t N2 )
155 : d_ndim( 2 ), d_length( N1 * N2 ), d_N{ N1, N2, 1, 1, 1 }
156 {
157 }
158
165 CONSTEXPR ArraySize( size_t N1, size_t N2, size_t N3 )
166 : d_ndim( 3 ), d_length( N1 * N2 * N3 ), d_N{ N1, N2, N3, 1, 1 }
167 {
168 }
169
177 CONSTEXPR ArraySize( size_t N1, size_t N2, size_t N3, size_t N4 )
178 : d_ndim( 4 ), d_length( N1 * N2 * N3 * N4 ), d_N{ N1, N2, N3, N4, 1 }
179 {
180 }
181
190 CONSTEXPR ArraySize( size_t N1, size_t N2, size_t N3, size_t N4, size_t N5 )
191 : d_ndim( 5 ), d_length( N1 * N2 * N3 * N4 * N5 ), d_N{ N1, N2, N3, N4, N5 }
192 {
193 }
194
200 template<class TYPE>
201 CONSTEXPR ArraySize( std::initializer_list<TYPE> N, int ndim = -1 )
202 : d_ndim( 0 ), d_length( 0 ), d_N{ 0, 1, 1, 1, 1 }
203 {
204 if ( ndim >= 0 ) {
205 d_ndim = ndim;
206 } else {
207 int ndim2 = 0;
208 for ( auto it = N.begin(); ndim2 < (int) N.size(); ndim2++, ++it ) {
209 if ( *it == (TYPE) -1 )
210 break;
211 }
212 d_ndim = std::min<int>( ndim2, maxDim() );
213 }
214 if ( d_ndim == 0 )
215 return;
216 ARRAY_INSIST( d_ndim <= maxDim(), "Maximum number of dimensions exceeded" );
217 auto it = N.begin();
218 d_length = 1;
219 for ( size_t i = 0; i < d_ndim; i++, ++it ) {
220 d_N[i] = *it;
221 d_length *= d_N[i];
222 }
223 }
224
230 CONSTEXPR ArraySize( size_t ndim, const size_t *dims )
231 : d_ndim( ndim ), d_length( 0 ), d_N{ 0, 1, 1, 1, 1 }
232 {
233 ARRAY_INSIST( d_ndim <= maxDim(), "Maximum number of dimensions exceeded" );
234 for ( size_t i = 0; i < ndim; i++ )
235 d_N[i] = dims[i];
236 d_length = 1;
237 for ( unsigned long i : d_N )
238 d_length *= i;
239 if ( d_ndim == 0 )
240 d_length = 0;
241 }
242
247 template<std::size_t NDIM>
248 CONSTEXPR ArraySize( const std::array<size_t, NDIM> &N ) : ArraySize( NDIM, N.data() )
249 {
250 }
251
256 inline ArraySize( const std::vector<size_t> &N ) : ArraySize( N.size(), N.data() ) {}
257
262 CONSTEXPR size_t operator[]( size_t i ) const { return d_N[i]; }
263
265 CONSTEXPR uint8_t ndim() const { return d_ndim; }
266
268 CONSTEXPR size_t size() const { return d_ndim; }
269
271 CONSTEXPR size_t length() const { return d_length; }
272
274 CONSTEXPR void resize( uint8_t dim, size_t N )
275 {
276 ARRAY_INSIST( dim < d_ndim, "Invalid dimension" );
277 d_N[dim] = N;
278 d_length = 1;
279 for ( unsigned long i : d_N )
280 d_length *= i;
281 }
282
288 constexpr void setNdim( uint8_t ndim ) { d_ndim = std::max( ndim, d_ndim ); }
289
291 CONSTEXPR const size_t *begin() const { return d_N; }
292
294 CONSTEXPR const size_t *end() const { return d_N + d_ndim; }
295
296 // Check if two array sizes are equal
297 CONSTEXPR bool operator==( const ArraySize &rhs ) const
298 {
299 return d_ndim == rhs.d_ndim && d_N[0] == rhs.d_N[0] && d_N[1] == rhs.d_N[1] &&
300 d_N[2] == rhs.d_N[2] && d_N[3] == rhs.d_N[3] && d_N[4] == rhs.d_N[4];
301 }
302
303 // Check if two array sizes are equal (ignoring the dimension)
304 CONSTEXPR bool approxEqual( const ArraySize &rhs ) const
305 {
306 return ( length() == 0 && rhs.length() == 0 ) || memcmp( d_N, rhs.d_N, sizeof( d_N ) ) == 0;
307 }
308
310 CONSTEXPR bool operator!=( const ArraySize &rhs ) const { return !operator==( rhs ); }
311
313 CONSTEXPR static uint8_t maxDim() { return 5u; }
314
316 CONSTEXPR size_t index( size_t i ) const
317 {
319 return i;
320 }
321
323 CONSTEXPR size_t index( size_t i1, size_t i2 ) const
324 {
325 size_t index = i1 + i2 * d_N[0];
327 return index;
328 }
329
331 CONSTEXPR size_t index( size_t i1, size_t i2, size_t i3 ) const
332 {
333 size_t index = i1 + d_N[0] * ( i2 + d_N[1] * i3 );
335 return index;
336 }
337
339 CONSTEXPR size_t index( size_t i1, size_t i2, size_t i3, size_t i4 ) const
340 {
341 size_t index = i1 + d_N[0] * ( i2 + d_N[1] * ( i3 + d_N[2] * i4 ) );
343 return index;
344 }
345
347 CONSTEXPR size_t index( size_t i1, size_t i2, size_t i3, size_t i4, size_t i5 ) const
348 {
349 size_t index = i1 + d_N[0] * ( i2 + d_N[1] * ( i3 + d_N[2] * ( i4 + d_N[3] * i5 ) ) );
351 return index;
352 }
353
355 constexpr size_t index( const std::array<size_t, 5> &i ) const
356 {
357 size_t j = 0;
358 for ( size_t m = 0, N = 1; m < 5; m++ ) {
359 j += i[m] * N;
360 N *= d_N[m];
361 }
362 return j;
363 }
364
366 constexpr size_t index( std::initializer_list<size_t> i ) const
367 {
368 size_t N = 1;
369 size_t j = 0;
370 size_t m = 0;
371 for ( size_t k : i ) {
372 j += k * N;
373 N *= d_N[m++];
374 }
375 return j;
376 }
377
379 constexpr std::array<size_t, 5> ijk( size_t index ) const
380 {
382 size_t i0 = index % d_N[0];
383 index = index / d_N[0];
384 size_t i1 = index % d_N[1];
385 index = index / d_N[1];
386 size_t i2 = index % d_N[2];
387 index = index / d_N[2];
388 size_t i3 = index % d_N[3];
389 index = index / d_N[3];
390 return { i0, i1, i2, i3, index };
391 }
392
394 CONSTEXPR void ijk( size_t index, size_t *x ) const
395 {
397 x[0] = index % d_N[0];
398 index = index / d_N[0];
399 x[1] = index % d_N[1];
400 index = index / d_N[1];
401 x[2] = index % d_N[2];
402 index = index / d_N[2];
403 x[3] = index % d_N[3];
404 index = index / d_N[3];
405 x[4] = index;
406 }
407
408private:
409 uint8_t d_ndim;
410 size_t d_length;
411 size_t d_N[5];
412};
413
414
415// Function to concatenate dimensions of two array sizes
417{
418 ARRAY_INSIST( x.ndim() + y.ndim() <= ArraySize::maxDim(),
419 "Maximum number of dimensions exceeded" );
420 size_t N[ArraySize::maxDim()] = { 0 };
421 for ( int i = 0; i < x.ndim(); i++ )
422 N[i] = x[i];
423 for ( int i = 0; i < y.ndim(); i++ )
424 N[i + x.ndim()] = y[i];
425 return ArraySize( x.ndim() + y.ndim(), N );
426}
427
428
429// Function to pop the first dimension and return the resulting array size
431{
432 int ndim = x.ndim() == 1 ? 1 : x.ndim() - 1;
433 size_t dims[] = { x[1], x[2], x[3], x[4] };
434 return AMP::ArraySize( ndim, dims );
435}
436
437
438// Remove singleton dimensions
439constexpr ArraySize squeeze( const ArraySize &x )
440{
441 int Nd = 0;
442 size_t N[5] = { 1 };
443 for ( size_t i = 0; i < x.maxDim(); i++ ) {
444 if ( x[i] != 1 )
445 N[Nd++] = x[i];
446 }
447 return ArraySize( std::max( Nd, 1 ), N );
448}
449
450
451// Operator overloads
453{
454 size_t N[5] = { v * x[0], v * x[1], v * x[2], v * x[3], v * x[4] };
455 return ArraySize( x.ndim(), N );
456}
458{
459 size_t N[5] = { v * x[0], v * x[1], v * x[2], v * x[3], v * x[4] };
460 return ArraySize( x.ndim(), N );
461}
463{
464 int ndim = std::max( x.ndim(), y.ndim() );
465 size_t N[5] = { x[0] * y[0], x[1] * y[1], x[2] * y[2], x[3] * y[3], x[4] * y[4] };
466 return ArraySize( ndim, N );
467}
469{
470 size_t N[5] = { x[0] - v, x[1] - v, x[2] - v, x[3] - v, x[4] - v };
471 return ArraySize( x.ndim(), N );
472}
474{
475 size_t N[5] = { x[0] + v, x[1] + v, x[2] + v, x[3] + v, x[4] + v };
476 return ArraySize( x.ndim(), N );
477}
479{
480 size_t N[5] = { x[0] + v, x[1] + v, x[2] + v, x[3] + v, x[4] + v };
481 return ArraySize( x.ndim(), N );
482}
483
484
485// Get the resulting array size from multiplying two arrays
486constexpr ArraySize multiplySize( const ArraySize &sa, const ArraySize &sb )
487{
488 if ( sa[1] != sb[0] )
489 throw std::logic_error( "Inner dimensions must match" );
490 if ( sa.ndim() == 2 && sb.ndim() == 1 ) {
491 return { sa[0] };
492 } else if ( sa.ndim() <= 2 && sb.ndim() <= 2 ) {
493 return { sa[0], sb[1] };
494 } else {
495 throw std::logic_error( "Not finished yet" );
496 }
497}
498
499
500} // namespace AMP
501
502
503#endif
#define CONSTEXPR_IF
Definition ArraySize.h:34
#define ARRAY_INSIST(test, msg)
Definition ArraySize.h:59
#define CONSTEXPR
Definition ArraySize.h:33
#define CHECK_ARRAY_LENGTH(i, length)
Definition ArraySize.h:56
Simple class to store the array dimensions.
Definition ArraySize.h:138
constexpr size_t index(const std::array< size_t, 5 > &i) const
Get the index.
Definition ArraySize.h:355
constexpr ArraySize(size_t ndim, const size_t *dims)
Definition ArraySize.h:230
constexpr const size_t * end() const
Returns an iterator to the end.
Definition ArraySize.h:294
constexpr ArraySize(size_t N1)
Definition ArraySize.h:147
constexpr ArraySize(size_t N1, size_t N2, size_t N3, size_t N4)
Definition ArraySize.h:177
constexpr ArraySize(size_t N1, size_t N2, size_t N3)
Definition ArraySize.h:165
constexpr ArraySize(size_t N1, size_t N2)
Definition ArraySize.h:154
ArraySize(const std::vector< size_t > &N)
Definition ArraySize.h:256
constexpr size_t index(size_t i1, size_t i2, size_t i3) const
Get the index.
Definition ArraySize.h:331
size_t d_length
Definition ArraySize.h:410
constexpr void setNdim(uint8_t ndim)
Definition ArraySize.h:288
constexpr ArraySize()
Empty constructor.
Definition ArraySize.h:141
constexpr size_t size() const
Return the number of dimensions.
Definition ArraySize.h:268
constexpr size_t index(size_t i1, size_t i2) const
Get the index.
Definition ArraySize.h:323
constexpr std::array< size_t, 5 > ijk(size_t index) const
Convert the index to ijk values.
Definition ArraySize.h:379
constexpr size_t index(size_t i1, size_t i2, size_t i3, size_t i4, size_t i5) const
Get the index.
Definition ArraySize.h:347
constexpr size_t index(std::initializer_list< size_t > i) const
Get the index.
Definition ArraySize.h:366
constexpr bool operator==(const ArraySize &rhs) const
Definition ArraySize.h:297
constexpr uint8_t ndim() const
Return the number of dimensions.
Definition ArraySize.h:265
constexpr ArraySize(std::initializer_list< TYPE > N, int ndim=-1)
Definition ArraySize.h:201
constexpr size_t index(size_t i) const
Get the index.
Definition ArraySize.h:316
constexpr size_t operator[](size_t i) const
Definition ArraySize.h:262
constexpr void ijk(size_t index, size_t *x) const
Convert the index to ijk values.
Definition ArraySize.h:394
constexpr size_t index(size_t i1, size_t i2, size_t i3, size_t i4) const
Get the index.
Definition ArraySize.h:339
constexpr bool approxEqual(const ArraySize &rhs) const
Definition ArraySize.h:304
constexpr size_t length() const
Return the total number of elements in the array.
Definition ArraySize.h:271
constexpr ArraySize(size_t N1, size_t N2, size_t N3, size_t N4, size_t N5)
Definition ArraySize.h:190
uint8_t d_ndim
Definition ArraySize.h:409
constexpr const size_t * begin() const
Returns an iterator to the beginning.
Definition ArraySize.h:291
constexpr bool operator!=(const ArraySize &rhs) const
Check if two matrices are not equal.
Definition ArraySize.h:310
constexpr ArraySize(const std::array< size_t, NDIM > &N)
Definition ArraySize.h:248
static constexpr uint8_t maxDim()
Maximum supported dimension.
Definition ArraySize.h:313
constexpr void resize(uint8_t dim, size_t N)
Resize the dimension.
Definition ArraySize.h:274
size_t d_N[5]
Definition ArraySize.h:411
Simple range class.
Definition ArraySize.h:79
constexpr TYPE get(size_t index) const
Get the ith values in the range.
Definition ArraySize.h:116
constexpr size_t size() const
Get the number of values in the range.
Definition ArraySize.h:96
constexpr Range()
Empty constructor.
Definition ArraySize.h:82
constexpr Range(const TYPE &i_, const TYPE &j_, const TYPE &k_=1)
Definition ArraySize.h:90
Array< TYPE, FUN, Allocator > operator-(const Array< TYPE, FUN, Allocator > &a, const Array< TYPE, FUN, Allocator > &b)
Definition Array.h:889
constexpr ArraySize multiplySize(const ArraySize &sa, const ArraySize &sb)
Definition ArraySize.h:486
constexpr ArraySize pop(const ArraySize &x)
Definition ArraySize.h:430
constexpr ArraySize squeeze(const ArraySize &x)
Definition ArraySize.h:439
constexpr ArraySize cat(const ArraySize &x, const ArraySize &y)
Definition ArraySize.h:416
Array< TYPE, FUN, Allocator > operator*(const Array< TYPE, FUN, Allocator > &a, const Array< TYPE, FUN, Allocator > &b)
Definition Array.h:897
Array< TYPE, FUN, Allocator > operator+(const Array< TYPE, FUN, Allocator > &a, const Array< TYPE, FUN, Allocator > &b)
Definition Array.h:881



Advanced Multi-Physics (AMP)
Oak Ridge National Laboratory
Idaho National Laboratory
Los Alamos National Laboratory
This page automatically produced from the
source code by doxygen
Last updated: Tue Mar 10 2026 13:06:41.
Comments on this page