PHengLEI-NCCR/API/DataStruct/include/DataStruct_Array.h

575 lines
22 KiB
C
Raw Normal View History

2024-10-14 09:32:17 +08:00
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// PPPPP H H EEEEE N N GGGGG L EEEEE III +
// P P H H E NN N G L E I +
// PPPPP HHHHH EEEEE N N N G GG L EEEEE I +
// P H H E N N N G G L E I +
// P H H EEEEE N N GGGGG LLLLL EEEEE III +
//------------------------------------------------------------------------+
// Platform for Hybrid Engineering Simulation of Flows +
// China Aerodynamics Research and Development Center +
// (C) Copyright, Since 2010 +
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//! @file DataStruct_Array.h
//! @brief PHArray defines a multidimensional array class. It is a template class.
//! PHArray<T,N> refers to a N-dimensional T type array
//! We can construct a multidimensional array by specify every dimension's length or range.
//! The way of underlying data's storage follow the example of fortran,
//! e.g. we can construct an 3d RDouble type array by length, PHArray<RDouble,3> array3d = PH<RDouble,3>(10, 20, 30)
//! and access the i,j,k index data by operator(), i.e. array3d(i,j,k).
//! The underlying data's memory storage sequence is from innermost(i) layer to outermost layer(k).
//! So, if we loop over all the data, we recommend you loop from k to i, i.e for(k,...){for(j,...){for(i,...)}}}
//! PHArray class also implement some other array's scalar operatation +=, -=, *=, /=, e.g. array1 *= 0.1.
//! Some other set operator like =, +, -, *, /. We can directly use these operators to PHArray object
//! e.g. dql(I, J, K, M) = MUSCLCoefXb * qr(I, J, K, M)
//! @author He Xin, Zhang Jian, referred from Blitz.
#pragma once
#include <cstddef>
#include <stdexcept>
#include <stdlib.h>
#include "PHSimpleArray.h"
#include "PHStorage.h"
#include "PHMemblock.h"
#include "PHProduct.h"
#include "PHETBase.h"
#include "PHSlice.h" //! Sub-arrays and slicing.
namespace PHSPACE
{
template < typename T, int N >
class PHFastArrayIterator;
template < typename T, int N >
class PHArray : public MemoryBlockReference<T> , public PHETBase< PHArray<T,N> >
{
private:
typedef MemoryBlockReference<T> T_base;
using T_base::data_;
using T_base::changeToNullBlock;
using T_base::numReferences;
GeneralArrayStorage<N> storage_;
SimpleArray<int, N> length_;
SimpleArray<int, N> stride_;
int zeroOffset_;
public:
//! T_numtype is the numeric type stored in the array.
typedef T T_numtype;
//! T_index is a vector type which can be used to access elements
//! of many-dimensional arrays.
typedef SimpleArray<int, N> T_index;
//! T_array is the array type itself -- Array<T_numtype, N_rank>.
typedef PHArray<T, N> T_array;
//! T_iterator is a a fast iterator for the array, used for expression.
//! Templates.
typedef PHFastArrayIterator<T, N> T_iterator;
//! This array's dimension.
static const int ranks = N;
public:
//! Create a reference of another array.
PHArray(const PHArray<T, N> &array);
//! Any missing length arguments will have their value taken from the
//! last argument. For example,
//! Array<int,3> A(32,64);
//! will create a 32x64x64 array. This is handled by setupStorage().
//! Construct an array by each dimension's length.
PHArray(GeneralArrayStorage<N> storage = GeneralArrayStorage<N>());
//! Construct an array by each dimension's length.
explicit PHArray(int length0, GeneralArrayStorage<N> storage = GeneralArrayStorage<N>());
//! Construct an array by each dimension's length.
PHArray(int length0, int length1, GeneralArrayStorage<N> storage = GeneralArrayStorage<N>());
//! Construct an array by each dimension's length.
PHArray(int length0, int length1, int length2,
GeneralArrayStorage<N> storage = GeneralArrayStorage<N>());
//! Construct an array by each dimension's length.
PHArray(int length0, int length1, int length2, int length3,
GeneralArrayStorage<N> storage = GeneralArrayStorage<N>());
//! Construct an array by each dimension's length.
PHArray(int length0, int length1, int length2, int length3, int length4,
GeneralArrayStorage<N> storage = GeneralArrayStorage<N>());
//! This constructor takes an extent (length) vector and storage format.
PHArray(const SimpleArray<int, N> &extent,
GeneralArrayStorage<N> storage = GeneralArrayStorage<N>());
//! This constructor takes a vector of bases (lbounds) and a vector of extents.
PHArray(const SimpleArray<int, N> &lbounds,
const SimpleArray<int, N> &extent,
const GeneralArrayStorage<N> &storage = GeneralArrayStorage<N>());
//! These constructors allow arbitrary bases (starting indices) to be set.
//! e.g. Array<int,2> A(Range(10,20), Range(20,30))
//! will create an 11x11 array whose indices are 10..20 and 20..30
//! Construct an array by each dimension's range.
PHArray(Range r0,
GeneralArrayStorage<N> storage = GeneralArrayStorage<N>());
//! Construct an array by each dimension's range.
PHArray(Range r0, Range r1,
GeneralArrayStorage<N> storage = GeneralArrayStorage<N>());
//! Construct an array by each dimension's range.
PHArray(Range r0, Range r1, Range r2,
GeneralArrayStorage<N> storage = GeneralArrayStorage<N>());
//! Construct an array by each dimension's range.
PHArray(Range r0, Range r1, Range r2, Range r3,
GeneralArrayStorage<N> storage = GeneralArrayStorage<N>());
//! Construct an array by each dimension's range.
PHArray(Range r0, Range r1, Range r2, Range r3, Range r4,
GeneralArrayStorage<N> storage = GeneralArrayStorage<N>());
//! Construct an array by each dimension's range.
PHArray(Range r0, Range r1, Range r2, Range r3, Range r4, Range r5,
GeneralArrayStorage<N> storage = GeneralArrayStorage<N>());
//! Construct an array from an existing block of memory.
PHArray(T *dataFirst,
Range r0,
preexistingMemoryPolicy deletionPolicy,
GeneralArrayStorage<N> storage = GeneralArrayStorage<N>());
//! Construct an array from an existing block of memory.
PHArray(T *dataFirst,
Range r0, Range r1,
preexistingMemoryPolicy deletionPolicy,
GeneralArrayStorage<N> storage = GeneralArrayStorage<N>());
//! Construct an array from an existing block of memory.
PHArray(T *dataFirst,
Range r0, Range r1, Range r2,
preexistingMemoryPolicy deletionPolicy,
GeneralArrayStorage<N> storage = GeneralArrayStorage<N>());
//! Construct an array from an existing block of memory.
PHArray(T *dataFirst,
Range r0, Range r1, Range r2, Range r3,
preexistingMemoryPolicy deletionPolicy,
GeneralArrayStorage<N> storage = GeneralArrayStorage<N>());
//! Construct an array from an existing block of memory.
PHArray(T *dataFirst,
Range r0, Range r1, Range r2, Range r3, Range r4,
preexistingMemoryPolicy deletionPolicy,
GeneralArrayStorage<N> storage = GeneralArrayStorage<N>());
//! These constructors construct an sub-array from another array.
//! Construct an sub-array from another array.
PHArray(PHArray<T, N> &array_in, Range r0);
//! Construct an sub-array from another array.
PHArray(PHArray<T, N> &array_in, Range r0, Range r1);
//! Construct an sub-array from another array.
PHArray(PHArray<T, N> &array_in, Range r0, Range r1, Range r2);
//! Construct an sub-array from another array.
PHArray(PHArray<T, N> &array_in, Range r0, Range r1, Range r2, Range r3);
//! Construct an sub-array from another array.
PHArray(PHArray<T, N> &array_in, Range r0, Range r1, Range r2, Range r3, Range r4);
//! Construct an sub-array from another array.
PHArray(PHArray<T, N> &array_in, Range r0, Range r1, Range r2, Range r3, Range r4, Range r5);
//! Construct an sub-array from another array.
PHArray(PHArray<T, N> &array_in, Range r0, Range r1, Range r2, Range r3, Range r4, Range r5, Range r6);
//! This constructor is invoked by the operator()'s which take
//! a combination of integer and Range arguments.
//! It's not intended for end-user use.
template < int N2, typename gasConstant, typename R1, typename R2, typename R3, typename R4,
typename R5, typename R6, typename R7, typename R8, typename R9, typename R10 >
PHArray(PHArray<T, N2> &array_in, gasConstant r0, R1 r1, R2 r2,
R3 r3, R4 r4, R5 r5, R6 r6, R7 r7, R8 r8, R9 r9, R10 r10);
public:
//! operator() functions:
//! Return constant reference to array[i0].
const T &operator()(int i0) const;
//! Return reference to array[i0].
T & operator()(int i0);
//! Return constant reference to array[i0][i1].
const T & operator()(int i0, int i1) const;
//! Return reference to array[i0][i1].
T & operator()(int i0, int i1);
//! Return constant reference to array[i0][i1][i2].
const T & operator()(int i0, int i1, int i2) const;
//! Return reference to array[i0][i1][i2].
T & operator()(int i0, int i1, int i2);
//! Return constant reference to array[i0][i1][i2][i3].
const T & operator()(int i0, int i1, int i2, int i3) const;
//! Return reference to array[i0][i1][i2][i3].
T & operator()(int i0, int i1, int i2, int i3);
//! Return constant reference to array[i0][i1][i2][i3][i4].
const T & operator()(int i0, int i1, int i2, int i3, int i4) const;
//! Return reference to array[i0][i1][i2][i3][i4].
T & operator()(int i0, int i1, int i2, int i3, int i4);
//! UGKS.
//! Return constant reference to array[i0][i1][i2][i3][i4][i5].
const T & operator()(int i0, int i1, int i2, int i3, int i4, int i5) const;
//! UGKS.
//! Return reference to array[i0][i1][i2][i3][i4][i5]
T & operator()(int i0, int i1, int i2, int i3, int i4,int i5);
//! Return constant reference to underlying data storage at index i,
//! ie. data_[i].
const T & operator[](int i) const;
//! Return reference to underlying data storage at index i,
//! ie. data_[i].
T & operator[](int i);
//! Return const reference to underlying data stored by an index array.
//! e.g index = (10, 20), calculate offset = stride_[0]*10+stride_[1]*20
//! then returns data_[offset].
template<int N_rank2>
const T & operator()(const SimpleArray<int, N_rank2> &index) const;
//! Return reference to underlying data stored by an index array.
//! e.g index = (10, 20), calculate offset = stride_[0]*10+stride_[1]*20
//! then returns data_[offset].
template<int N_rank2>
T & operator()(const SimpleArray<int, N_rank2> &index);
//! These constructors construct an sub-array from this array self.
//! Construct an sub-array from this array self by offering a range.
T_array operator()(Range r0) const;
//! Construct an sub-array from this array self by offering a range.
T_array operator()(Range r0, Range r1) const;
//! Construct an sub-array from this array self by offering a range.
T_array operator()(Range r0, Range r1, Range r2) const;
//! Construct an sub-array from this array self by offering a range.
T_array operator()(Range r0, Range r1, Range r2, Range r3) const;
//! Construct an sub-array from this array self by offering a range.
T_array operator()(Range r0, Range r1, Range r2, Range r3, Range r4) const;
//! Construct an sub-array from this array self by offering a range.
T_array operator()(Range r0, Range r1, Range r2, Range r3, Range r4, Range r5) const;
//! Construct an sub-array from this array self by offering a range.
T_array operator()(Range r0, Range r1, Range r2, Range r3, Range r4, Range r5, Range r6) const;
//! After calling slice(int rank, Range r), the array refers only to the
//! range r of the original array.
//! e.g. Array<int,1> x(100);
//! x.slice(firstRank, Range(25,50));
//! x = 0; //! Sets elements 25..50 of the original array to 0.
template < typename T1, typename T2 >
typename PHSliceInfo<T, T1, T2>::T_slice operator()(T1 r1, T2 r2) const;
template < typename T1, typename T2, typename T3 >
typename PHSliceInfo<T, T1, T2, T3>::T_slice operator()(T1 r1, T2 r2, T3 r3) const;
template < typename T1, typename T2, typename T3, typename T4 >
typename PHSliceInfo<T, T1, T2, T3, T4>::T_slice operator()(T1 r1, T2 r2, T3 r3, T4 r4) const;
template < typename T1, typename T2, typename T3, typename T4, typename T5 >
typename PHSliceInfo<T, T1, T2, T3, T4, T5>::T_slice operator()(T1 r1, T2 r2, T3 r3, T4 r4, T5 r5) const;
template < typename T1, typename T2, typename T3, typename T4, typename T5, typename T6 >
typename PHSliceInfo<T, T1, T2, T3, T4, T5, T6>::T_slice operator()(T1 r1, T2 r2, T3 r3, T4 r4, T5 r5, T6 r6) const;
//! Array expression operands.
//! Scalar operand.
//! NEEDS_WORK : need a precondition check on.
//! isStorageContiguous when operator, is used.
T_array & operator=(T x);
//! operator = expr
template<typename T_expr>
T_array & operator = (const PHETBase<T_expr> &expr);
//! operator = PHArray<T,N>
T_array & operator = (const PHArray<T, N> &rhs);
//! operator +=
template<typename T_expr> T_array & operator += (const T_expr &expr);
//! operator -=
template<typename T_expr> T_array & operator -= (const T_expr &expr);
//! operator *=
template<typename T_expr> T_array & operator *= (const T_expr &expr);
//! operator /=
template<typename T_expr> T_array & operator /= (const T_expr &expr);
//! Member functions.
//! Return index relative to data_, ie. data_[index].
//! index = i0 * stride_[0] + i1 * stride_[1] + i2 * stride_[2] + i3 * stride_[3].
int getindex(int i0, int i1, int i2, int i3) const;
//! Return the rank dimension's lower bound, ie. range's first index, equals base_[rank].
int lbound(int rank) const;
//! Return the rank dimension's upper bound, ie. range's last index, equals base_[rank]+length_[rank]-1.
int ubound(int rank) const;
//! Return the array storing lbound, ie. base_.
SimpleArray<int, N> lbound() const;
//! Return the rank dimension's length, ig length_[rank]
int length(int rank) const;
//! Return the array storing length_.
const SimpleArray<int, N> & length() const;
//! Return the array storing base_.
//! base_ is each dimension's lower bound.
const SimpleArray<int, N> & base() const;
//! Return the rank dimension's base, ie. base_[rank].
int base(int rank) const;
//! Return the rank dimension's stride, ie. stride_[rank].
int stride(int rank) const;
//! Total number of elements in this array.
int numElements() const;
//! data_ always refers to the point (0,0,...,0) which may
//! not be in the array if the base is not zero in each rank.
//! These data() routines return a pointer to the first
//! element in the array (but note that it may not be
//! stored first in memory if some ranks are stored descending).
const T * data() const;
//! data() is the location of the first data member,that is the location of the base.
//! The base array starting subscript of each dimension,ri.first().
//! It is especially important for slice.
//! After slice, the first data point actually is (ifirst, jfirst, ...).
//! The actual location is data_ + dataOffset().
T * data();
//! Judge whether the array's outer dimension's stride equals sum of inner dimension's stride.
//! eg. if outerRank =3 and innerRank =2 , returns true if stride[3] == stride[2]*length[2], otherwise, returns false
bool canCollapse(int outerRank, int innerRank) const;
//! Return the PHFastArrayIterator of this array.
//! It's not intended for end-user use.
T_iterator beginFast() const;
//! Return storage_.ordering(storageRankIndex).
//! It's not intended for end-user use.
int ordering(int storageRankIndex) const;
//! Return storage_.ordering().
//! It's not intended for end-user use.
const SimpleArray<int, N> & ordering() const;
//! True if storage_.ordering(rank) == 0.
//! It's not intended for end-user use.
bool isMajorRank(int rank) const;
//! True if storage_.ordering(rank) != 0.
//! It's not intended for end-user use.
bool isMinorRank(int rank) const;
//! Call storage_.isRankStoredAscending(rank).
//! It's not intended for end-user use.
bool isRankStoredAscending(int rank) const;
//! The underlying data storage(data_) always refers to the point index at (0,0,...,0) which may
//! not be in the array if the base is not zero in each rank.
//! Return the pointer to data.
T * getData() const { return data_; }
protected:
//! Implementation routines.
void computeStrides();
void setupStorage(int rank);
void setupStorage(int rank, T *data, preexistingMemoryPolicy deletionPolicy);
void calculateZeroOffset();
void Reference(const T_array&);
T_array & noConst() const;
void constructSubarray(PHArray<T, N> &array_in, Range r0);
void constructSubarray(PHArray<T, N> &array_in, Range r0, Range r1);
void constructSubarray(PHArray<T, N> &array_in, Range r0, Range r1, Range r2);
void constructSubarray(PHArray<T, N> &array_in, Range r0, Range r1, Range r2, Range r3);
void constructSubarray(PHArray<T, N> &array_in, Range r0, Range r1, Range r2, Range r3, Range r4);
void constructSubarray(PHArray<T, N> &array_in, Range r0, Range r1, Range r2, Range r3, Range r4, Range r5);
void constructSubarray(PHArray<T, N> &array_in, Range r0, Range r1, Range r2, Range r3, Range r4, Range r5, Range r6);
template < int N2, typename gasConstant,
typename R1, typename R2, typename R3, typename R4, typename R5, typename R6, typename R7,
typename R8, typename R9, typename R10 >
void constructSlice(PHArray<T, N2> &array_in,
gasConstant r0, R1 r1, R2 r2, R3 r3, R4 r4, R5 r5, R6 r6, R7 r7, R8 r8, R9 r9, R10 r10);
void slice(int rank, Range r);
template<int N2>
void slice(int &setRank, Range r, PHArray<T, N2> &array_in, SimpleArray<int, N2> &rankMap, int sourceRank);
template<int N2>
void slice(int &setRank, int i, PHArray<T, N2> &array_in, SimpleArray<int, N2> &rankMap, int sourceRank);
template<int N2>
void slice(int &setRank, PHnilArraySection nil, PHArray<T, N2> &array_in, SimpleArray<int, N2> &rankMap, int sourceRank);
T_array & initialize(T x);
int dataOffset() const;
template<typename T_expr, typename T_update>
T_array & evaluate(T_expr expr, T_update);
template<typename T_expr, typename T_update>
T_array & evaluateWithIndexTraversal1(T_expr expr, T_update);
template<typename T_expr, typename T_update>
T_array & evaluateWithIndexTraversalN(T_expr expr, T_update);
template<typename T_expr, typename T_update>
T_array & evaluateWithStackTraversal1(T_expr expr, T_update);
template<typename T_expr, typename T_update>
T_array & evaluateWithStackTraversalN(T_expr expr, T_update);
//! #ifdef USE_SMARTARRY will construct an multi-array pointer to the underlying data_
//! e.g. for a three dimensional T type array with range(r0, r1, r2).
//! We can get and T*** type pointer called datap3 by GetSmartArrayP3() function
//! and access the data at index i, j, k directly by datap3[k][j][i].
//! Remember the way of array storage of range r0, r1, ... corresponding with innermost layer to outermost layer.
//! Moreover, if use operator(i, j, k), will return datap3[k][j][i] instead of data_[i0 * stride_[0] + i1 * stride_[1]+ i2 * stride_[2]].
#ifdef USE_SMARTARRAY
public:
typedef T * TypeP1; //TypeP1 T *
typedef TypeP1 * TypeP2; //TypeP2 T **
typedef TypeP2 * TypeP3; //TypeP3 T ***
typedef TypeP3 * TypeP4; //TypeP4 T ****
typedef TypeP4 * TypeP5; //TypeP5 T *****
typedef TypeP5 * TypeP6; //TypeP6 T ******
private:
TypeP1 data1, datap1; //TypeP1 T *
TypeP2 data2, datap2; //TypeP2 T **
TypeP3 data3, datap3; //TypeP3 T ***
TypeP4 data4, datap4; //TypeP4 T ****
TypeP5 data5, datap5; //TypeP5 T *****
TypeP6 data6, datap6; //TypeP6 T ******
private:
void ZeroAllPointer();
void AllocateRange(int dimension);
void AllocateRange1();
void AllocateRange2();
void AllocateRange3();
void AllocateRange4();
void AllocateRange5();
void AllocateRange6();
public:
~PHArray()
{
if (data1 != NULL) { data1 = NULL; }
if (data2 != NULL) { delete [] data2; data2 = NULL; }
if (data3 != NULL) { delete [] data3; data3 = NULL; }
if (data4 != NULL) { delete [] data4; data4 = NULL; }
if (data5 != NULL) { delete [] data5; data5 = NULL; }
if (data6 != NULL) { delete [] data6; data6 = NULL; }
}
TypeP1 GetSmartArrayP1() const
{
return datap1;
}
TypeP2 GetSmartArrayP2() const
{
return datap2;
}
TypeP3 GetSmartArrayP3() const
{
return datap3;
}
TypeP4 GetSmartArrayP4() const
{
return datap4;
}
TypeP5 GetSmartArrayP5() const
{
return datap5;
}
TypeP6 GetSmartArrayP6() const
{
return datap6;
}
#endif
//! End
};
}
const int firstRank = 0;
const int secondRank = 1;
const int thirdRank = 2;
const int fourthRank = 3;
const int fifthRank = 4;
const int sixthRank = 5;
const int seventhRank = 6;
const int eighthRank = 7;
const int ninthRank = 8;
const int tenthRank = 9;
const int eleventhRank = 10;
const int firstDim = 0;
const int secondDim = 1;
const int thirdDim = 2;
const int fourthDim = 3;
const int fifthDim = 4;
const int sixthDim = 5;
const int seventhDim = 6;
const int eighthDim = 7;
const int ninthDim = 8;
const int tenthDim = 9;
const int eleventhDim = 10;
#include "PHFastArrayIterator.h" //! Fast Array iterators (for et).
#include "PHExpr.h" //! Array expression objects.
#include "PHExprWrap.h"
#include "PHET.h" //! Expression templates.
#include "PHOps.hxx" //! Assignment operators.
#include "PHArray.hxx"
#include "PHSlice.hxx" //! Slicing and sub-arrays.