///////////////////////////////////////////////////////////////////////////// // // // Array class // // // // Burkhard Militzer Urbana 4-1-99 // // Updated later Livermore 01-11-03 // // // ///////////////////////////////////////////////////////////////////////////// #ifndef _ARRAY_ #define _ARRAY_ #include "Standard.h" // Define SLOW_WARNING to warn if arrays are copied or [][] are used. // #define SLOW_WARNING // Array1, Array2, and Array3 are template classes for 1, 2, and 3 // dimensional arrays storing elements contiguously in memory. Array // boundary checking as well as resizing functions are implemented. // Array1 can accessed by () or []. [] make it somewhat // compatible with STL's class but does not show its // performance problems. // If you access Array2 a[i][j] then a temporary Array1 must be // generated. It works but is slower than a(i,j) // We could define a virtual base class Array providing a universal access to rank // and GetDims(). However, we have not had much use for it. // RArray get be read from a stream e.g. cin >> mat but Array cannot because // many template elements do not provide stream handling. // Constraints of this class: // (1) Reading must be as fast as possible: // a(i) <- a.v+i and not "a.v+i+shift" // a(i,j) <- a.v+i*step+j and not "a.v+i*step+j*step2" nor "a[i][j]" // a(i,j,k) <- a.v+i*step+j*step2+k and not "a.v+i*step+j*step2+k*step3" nor "a[i][j][k]" // (2) Can have arrays that own and some that do not own the memory, see "bool b". // Functions that work for all arrays: // Copy constructor // Constructor with given dimensions // Constructor with given dimensions and initialization // Constructor with given dimensions and external pointer (do not deallocate memory later) // Read and write elements (...) // CopyElements(const Array & a) // Assignment operator=(const Array & a) A=B // Assignment operator=(const T & x) A=x // A += x // A += B // A -= x // A -= B // A *= x // A /= x // A == B // A != B // Max(), Min(), Sum() // Resize(...) // Resize(...,mn) // CopyResize(...) // CopyResize(...,mn) // Free() // SetPointer(v,...,bool b=true); // T* GetPointer() // Check() template class Array1; template class Array2; template class Array3; const int stInc=10; // Default increment for PushBack const int notFound = -1; template class Array1 { public: int size; // logical boundary of array: 0<= index < size int mSize; // physical boundary of allocated memory int inc; // current increment for pushback T* v; // pointer to the elements bool b; // true if the objects owns the memory and mst deallocated memory at the end //default constructor Array1(): size(0), mSize(0), inc(stInc), v(0), b(true) {}; // What should never be done: Make a copy of the pointer and prevent // allocation and copyingL fast but NOT SAFE because copy and original share the // same memory indicate by v. Do never use this!!! // Array1(const Array1& a):size(a.size),mSize(a.mSize),v(a.v),b(false) { // } // Make a real copy in the standard way, slow and safe. Copy also the extra memory // so that Array keeps 'all' its properties when copied. Array1(const Array1 & a): size(a.size), mSize(a.mSize), inc(a.inc), b(a.b) { // warning("do not copy Array1",a.Size()); if (b) { v = new T[mSize]; if (mSize>0 && v==0) error("Could not allocate memory",mSize); for(int i=0; i0 && v==0) error("Could not allocate memory",n); } // Create with certain size and initialize Array1(const int n, const T & x):size(0),mSize(0),inc(stInc),v(0),b(true) { Resize(n); for(int i=0;i & a1, const int n1, const int n2); inline Array1(const Array2 & a2, const int n1); inline Array1(const Array2 & a2, const int n1, const int n21, const int n22); inline Array1(const Array3 & a3, const int n1, const int n2); ~Array1() { if (v && b) delete[] v; }; const T& operator() (int n) const { // Read element Limits(n,size); return v[n]; }; const T& operator[] (int n) const { // Read element Limits(n,size); return v[n]; }; T& operator() (int n) { // Access element Limits(n,size); return v[n]; }; T& operator[] (int n) { // Access element Limits(n,size); return v[n]; }; const T& First() const { // Read first element return (*this)[0]; } T& First() { // Access first element return (*this)[0]; } const T& Last() const { // Read last element return (*this)[size-1]; } T& Last() { // Access last element return (*this)[size-1]; } // Copy all elements and do not check size unless RANGE_CHECKING is defined void CopyElements(const Array1 & x) { EqualLimits(size,x.size); for(int i=0;i & a) { // Add array of equal dimensions for(int i=0;i & a) { // Subtract array of equal dimensions for(int i=0;i & a, const T & x) { Array1 b(a); b += x; return b; } friend Array1 operator-(const Array1 & a, const T & x) { Array1 b(a); b -= x; return b; } friend Array1 operator*(const Array1 & a, const T & x) { Array1 b(a); b *= x; return b; } friend Array1 operator/(const Array1 & a, const T & x) { Array1 b(a); b /= x; return b; } friend Array1 operator*(const T & x, const Array1 & a) { return a*x; } friend Array1 operator+(const T & x, const Array1 & a) { return a+x; } bool operator==(const Array1 & a) const { // Are Array identical? if (size != a.Size()) return false; for(int i=0;i & a) const { // Are Array identical? return !(*this==a); } T Max() const { return Max(0,size); } T Max(const int i2) const { return Max(0,i2); } T Max(const int i1, const int i2) const { Limits(i1,i2); Limits(i1,size); LimitsInclusive(i2,size); T x=v[i1]; for(int i=i1; ix) x=v[i]; } return x; } T Min() const { return Min(0,size); } T Min(const int i2) const { return Min(0,i2); } T Min(const int i1, const int i2) const { Limits(i1,i2); Limits(i1,size); LimitsInclusive(i2,size); T x=v[i1]; for(int i=i1; iv[ii]) ii=i; } return ii; } int MinIndex() const { Limits(0,size); int ii=0; for(int i=1; i0 && v==0) error("Could not allocate memory",mSize); } size = n; } void Set(const T & x) { // Set all elements, equivalent to for(int i=0; imSize we would lose some memory but no memory leak. mSize=nm; T* vv = new T[mSize]; if (mSize>0 && vv==0) error("Could not allocate memory",mSize); for(int i=0;i0 && v) { delete[] v; // Must set to zero because otherwise deallocation is tried again (for egcs at least) v = 0; mSize = size = 0; } } int Size() const { return size;} int Rank() const { return 1; } // Assume the memory has be allocated by some other routine // if (b1==true) take over the ownership and deallocated the memory at the end void SetPointer(T* vv, const int n, const bool b1=true) { if (v && b) delete[] v; size=n; mSize=n; v=vv; b=b1; } // Return the point but do not give up the ownership T* GetPointer() const { return v; } int Find(const T & x) const { for(int i=0; i MakeArray2(const int n1); inline const Array2 MakeConstArray2(const int n1); void Check() const { if (size<0) error("in Array dimension",size); if (mSize & a) { os << "[" << a.size << "] ("; for(int i=0; i0) os << ","; os << a[i]; } os << ")"; return os; } // ii==0 means insert at the beginning. If x[0] exists it is moved up. // ii==size-1 means x[size-1] is moved up. // in==size would mean to append nn elements BUT THIS IS NOT ALLOWED void Insert(const int ii, const int nn=1) { LimitsInclusive(ii,size); if (!b) error ("Cannot copy and resize fixed-size array."); if (nn<0) error("Insert limit error",ii,nn); const int newSize = size+nn; if (newSize>mSize) { // yes, we must reallocate mSize=newSize; T* vv = new T[mSize]; if (mSize>0 && vv==0) error("Could not allocate memory",mSize); for(int i=0; i=ii; i--) v[i+nn] = v[i]; } size = newSize; } void Insert(const T & x, const int ii, const int nn=1) { Insert(ii,nn); for(int i=ii; i class Array2 { public: int size; // == dim[0]*dim[1], logical memory int mSize; // >=size, physical memory T* v; bool b; int dim[2]; // array dimensions: Array2(i,j) with idim[1]) // because this definition associates "Limits(n1,dim[0]); Limits(n2,dim[1]);" Array2(): size(0), mSize(0), v(0), b(true) { dim[0]=dim[1]=0; }; // Make a real copy; slow and save in the standard way Array2(const Array2 & a): size(a.size), mSize(a.mSize), b(a.b) { if (b) { #ifdef SLOW_WARNING warning("Avoid copying Array2",size); #endif v = new T[mSize]; if (mSize>0 && v==0) error("Could not allocate memory",mSize); for(int i=0; i0 && v==0) error("Could not allocate memory",mSize); dim[0] = n1; dim[1] = n2; } // Create with initialization Array2(const int n1, const int n2, const T & x):size(0),mSize(0),v(0),b(true) { Resize(n1,n2); for(int i=0;i & a1):size(a1.size),mSize(a1.size),v(a1.v),b(false) { dim[0] = a1.size; dim[1] = 1; } // Create from existing 3d array inline Array2(const Array3 & a3, const int n); ~Array2() { if (v && b) delete[] v; } int Size() const { return size; } int Rank() const { return 2; } int GetDim(const int i) const { Limits(i,Rank()); return dim[i]; } const T& operator() (const int n1, const int n2) const { // Read element Limits(n1,dim[0]); Limits(n2,dim[1]); return v[n1*dim[1]+n2]; }; T& operator() (const int n1, const int n2) { // Access element Limits(n1,dim[0]); Limits(n2,dim[1]); return v[n1*dim[1]+n2]; }; const Array1 operator[](const int n1) const { #ifdef SLOW_WARNING warning("Avoid C style access Array2 a[i][j]"); #endif Limits(n1,dim[0]); Array1 a(*this,n1); return a; } Array1 operator[](const int n1) { #ifdef SLOW_WARNING warning("Avoid C style access of Array2 a[i][j]"); #endif Limits(n1,dim[0]); Array1 a(*this,n1); return a; } // Copy array like 1D in predefined array void CopyElements(const Array2 & a) { EqualLimits(a.dim[0],dim[0]); EqualLimits(a.dim[1],dim[1]); for(int i=0;i & a) { // Add array of equal dimensions for(int i=0;i & a) { // Add array of equal dimensions for(int i=0;i & a, const T & x) { Array2 b(a); b += x; return b; } friend Array2 operator-(const Array2 & a, const T & x) { Array2 b(a); b -= x; return b; } friend Array2 operator*(const Array2 & a, const T & x) { Array2 b(a); b *= x; return b; } friend Array2 operator/(const Array2 & a, const T & x) { Array2 b(a); b /= x; return b; } friend Array2 operator*(const T & x, const Array2 & a) { return a*x; } friend Array2 operator+(const T & x, const Array2 & a) { return a+x; } bool operator==(const Array2 & a) const { // Are Array identical? if (dim[0]!=a.dim[0] || dim[1]!=a.dim[1]) return false; for(int i=0;i & a) const { // Are Array identical? return !(*this==a); } T Max() const { Limits(0,size); T x=v[0]; for(int i=1; ix) x=v[i]; } return x; } T Min() const { Limits(0,size); T x=v[0]; for(int i=1; i0 && v==0) error("Could not allocate memory",mSize); } size = n1*n2; dim[0] = n1; dim[1] = n2; } // CopyResize with extra memory has not been implemented void CopyResize(const int n1, const int n2) { CopyResize(n1,n2,max(n1*n2,mSize)); } // Resize and copy elements and reserve memory for exactly nm elements (for later CopyResize) void CopyResize(const int n1, const int n2, const int nm) { if (!b) error ("Cannot resize fixed-size array"); int nn= n1*n2; if (nn>nm) error("Copy resize limit error",n1,n2,nm); if (n2!=dim[1] || nm!=mSize) { mSize = nm; T* vv=new T[mSize]; if (mSize>0 && vv==0) error("Could not allocate memory",mSize); for(int i1=0;i10 && v) { delete[] v; v = 0; mSize = size = dim[0] = dim[1] = 0; } } // Assume the memory has be allocated by some other routine // if (b1==true) take over the ownership and deallocated the memory at the end void SetPointer(T* vv, const int n1, const int n2, const bool b1=true) { if (v && b) delete[] v; int nn=n1*n2; size = mSize = nn; v = vv; b = b1; dim[0]= n1; dim[1]= n2; } // Return the point but do not give up the ownership T* GetPointer() { return v; } void Check() const { int nn=1; for(int i=0; i=ii; i--) { for(int j=0; j=ii; j--) { (*this).operator()(i,j+nn) = (*this).operator()(i,j); } } } } void Insert(const T & x, const int d, const int ii, const int nn=1) { Insert(d,ii,nn); if (d==0) { for(int i=ii; i class Array3 { public: int size; // == dim[0]*dim[1]*dim[2], logical memory int mSize; // >= size, physical memory T* v; bool b; int dim[3]; // array dimensions: Array3(i,j,k) with i0 && v==0) error("Could not allocate memory",mSize); for(int i=0; i0 && v==0) error("Could not allocate memory",mSize); dim[0] = n1; dim[1] = n2; dim[2] = n3; } // Create with initialization Array3(const int n1, const int n2, const int n3, const T & vv):size(0),mSize(size),v(0),b(true) { Resize(n1,n2,n3); for(int i=0;i operator[](const int n1) const { #ifdef SLOW_WARNING warning("Avoid C style access Array3 a[i][j][k]"); #endif Limits(n1,dim[0]); Array2 a(*this,n1); return a; } Array2 operator[](const int n1) { #ifdef SLOW_WARNING warning("Avoid C style access Array3 a[i][j][k]"); #endif Limits(n1,dim[0]); Array2 a(*this,n1); return a; } void CopyElements(const Array3 & a) { // Copy array like 1D EqualLimits(a.dim[0],dim[0]); EqualLimits(a.dim[1],dim[1]); EqualLimits(a.dim[2],dim[2]); for(int i=0;i & a) { // Add array of equal dimensions for(int i=0;i & a) { // Add array of equal dimensions for(int i=0;i & a) const { // Are Array identical? if (dim[0]!=a.dim[0] || dim[1]!=a.dim[1] || dim[2]!=a.dim[2]) return false; for(int i=0;i & a) const { // Are Array identical? return !(*this==a); } friend Array3 operator+(const Array3 & a, const T & x) { Array3 b(a); b += x; return b; } friend Array3 operator-(const Array3 & a, const T & x) { Array3 b(a); b -= x; return b; } friend Array3 operator*(const Array3 & a, const T & x) { Array3 b(a); b *= x; return b; } friend Array3 operator/(const Array3 & a, const T & x) { Array3 b(a); b /= x; return b; } friend Array3 operator*(const T & x, const Array3 & a) { return a*x; } friend Array3 operator+(const T & x, const Array3 & a) { return a+x; } T Max() const { Limits(0,size); T x=v[0]; for(int i=1; ix) x=v[i]; } return x; } T Min() const { Limits(0,size); T x=v[0]; for(int i=1; i0 && v==0) error("Could not allocate memory",mSize); } size = n1*n2*n3; dim[0] = n1; dim[1] = n2; dim[2] = n3; } // CopyResize with extra memory has not been implemented void CopyResize(const int n1, const int n2, const int n3) { CopyResize(n1,n2,n3,max(n1*n2*n3,mSize)); } // Resize and copy elements and reserve memory for exactly nm elements (for later CopyResize) void CopyResize(const int n1, const int n2, const int n3, const int nm) { if (!b) error ("Cannot resize fixed-size array"); int nn= n1*n2*n3; if (nn>nm) error("Copy resize limit error",n1,n2,n3,nm); if (n3!=dim[2] || n2!=dim[1] || nm!=mSize) { mSize = nm; T* vv=new T[mSize]; if (mSize>0 && vv==0) error("Could not allocate memory",mSize); for(int i1=0;i10 && v) { delete[] v; v = 0; size = dim[0] = dim[1] = dim[2] = 0; } } // Assume the memory has be allocated by some other routine // if (b1==true) take over the ownership and deallocated the memory at the end void SetPointer(T* vv, const int n1, const int n2, const int n3, const bool b1=true) { if (v && b) delete[] v; int nn=n1*n2*n3; size = mSize = nn; v = vv; b = b1; dim[0]= n1; dim[1]= n2; dim[2]= n3; } // Return the point but do not give up the ownership T* GetPointer() { return v; } void Check() const { int nn=1; for(int i=0; i=ii; i--) { for(int j=0; j=ii; j--) { for(int k=0; k=ii; k--) { (*this).operator()(i,j,k+nn) = (*this).operator()(i,j,k); } } } } } void Insert(const T & x, const int d, const int ii, const int nn=1) { Insert(d,ii,nn); if (d==0) { for(int i=ii; i Array2 Array1::MakeArray2(const int n1) { const int n2=size/n1; return Array2(n1,n2,v); } template const Array2 Array1::MakeConstArray2(const int n1) { const int n2=size/n1; return Array2(n1,n2,v); } // create from section of 1d array template inline Array1::Array1(const Array1 & a1, const int n1, const int n2): size(n2-n1), mSize(size), inc(stInc), v(a1.v+n1), b(false) { BiggerLimit(n1,n2); Limits(n1,a1.size); Limits(n2,a1.size); } // create from 1d vector in 2d array template inline Array1::Array1(const Array2 & a2, const int n1): size(a2.dim[1]), mSize(size), inc(stInc), v(a2.v+n1*a2.dim[1]), b(false) { Limits(n1,a2.dim[0]); } // create from section of 1d vector in 2d array template inline Array1::Array1(const Array2 & a2, const int n1, const int n21, const int n22): size(n22-n21), mSize(size), inc(stInc), v(a2.v+n1*a2.dim[1]+n21), b(false) { Limits(n1,a2.dim[0]); Limits(n21,a2.dim[1]); LimitsInclusive(n22,a2.dim[1]); BiggerLimit(n21,n22); } // create from 1d vector in 3d array template inline Array1::Array1(const Array3 & a3, const int n1, const int n2): size(a3.dim[2]), mSize(size), inc(stInc), v(a3.v+(n1*a3.dim[1]+n2)*a3.dim[2]), b(false) { Limits(n1,a3.dim[0]); Limits(n2,a3.dim[1]); } // create from 2d array in 3d array template inline Array2::Array2(const Array3 & a3, const int n1): size(a3.dim[1]*a3.dim[2]), mSize(size), v(a3.v+n1*a3.dim[1]*a3.dim[2]), b(false) { dim[0] = a3.dim[1]; dim[1] = a3.dim[2]; Limits(n1,a3.dim[0]); } template void WriteArray1(const Array1 & a) { cout << "[ "; for(int i=0; i void WriteArray2(const Array2 & a, const string & s="") { if (s.length()==0) cout << "2D array of size " << a.dim[0] << " x " << a.dim[1] << endl; for(int i=0; i a1(a,i); WriteArray1(a1); cout << endl; } } template void WriteArray3(const Array3 & a) { cout << "3D array of size " << a.dim[0] << " x " << a.dim[1] << " x " << a.dim[2] << endl; for(int i=0; i a2(a,i); WriteArray2(a2,s); } } /////////////////////////////////////////////////////////////////////////////////////////////////////// #ifdef _MAINXXX_ template void Equal(const Array1 & a, const Array1 & b) { a.Check(); b.Check(); if (a!=b) { WriteArray1(a); cout << endl; WriteArray1(b); cout << endl; error("Array1's not equal"); } if (a.mSize != b.mSize) error("mSize problem"); if (a.b != b.b) error("b problem"); if (a.inc != b.inc) error("inc problem"); } template void Equal(const Array2 & a, const Array2 & b) { a.Check(); b.Check(); if (a!=b) error("Array2's not equal"); if (a.mSize != b.mSize) error("mSize problem"); if (a.b != b.b) error("b problem"); } template void Equal(const Array3 & a, const Array3 & b) { a.Check(); b.Check(); if (a!=b) error("Array3's not equal"); if (a.mSize != b.mSize) error("mSize problem"); if (a.b != b.b) error("b problem"); } /////////////////////////////////////////////////////////////////////////////////////////////////////// template void Equal(const Array1 & a, const Array1 & b, const T & tol) { a.Check(); b.Check(); for(int i=0; itol) { WriteArray1(a); cout << endl; WriteArray1(b); cout << endl; error("Array1's not equal",i); } } if (a.size != b.size) error("size problem"); if (a.mSize != b.mSize) error("mSize problem"); if (a.b != b.b) error("b problem"); if (a.inc != b.inc) error("inc problem"); } template void Equal(const Array2 & a, const Array2 & b, const T & tol) { a.Check(); b.Check(); for(int i=0; itol) { WriteArray2(a); cout << endl; WriteArray2(b); cout << endl; error("Array2's not equal",i,j); } } } if (a.dim[0] != b.dim[0]) error("dim 0 problem"); if (a.dim[1] != b.dim[1]) error("dim 1 problem"); if (a.mSize != b.mSize) error("mSize problem"); if (a.b != b.b) error("b problem"); } template void Equal(const Array3 & a, const Array3 & b, const T & tol) { a.Check(); b.Check(); for(int i=0; itol) { WriteArray3(a); cout << endl; WriteArray3(b); cout << endl; error("Array3's not equal",i,j,k); } } } } if (a.dim[0] != b.dim[0]) error("dim 0 problem"); if (a.dim[1] != b.dim[1]) error("dim 1 problem"); if (a.dim[2] != b.dim[2]) error("dim 2 problem"); if (a.mSize != b.mSize) error("mSize problem"); if (a.b != b.b) error("b problem"); } /////////////////////////////////////////////////////////////////////////////////////////////////////// int main() { Array1 a,b; Equal(a,b); int n=10; int x=314; a.Resize(n); a=x; Array1 c(n); c=x; Array1 d(n,x); Equal(a,c); Equal(a,d); a += 1; c = x+1; Equal(a,c); d = 2*c[0]; d -= a; Equal(a,d); Array1 e; for (int i=0; i<2*n; i++) { e.PushBack(e.Size()); } if (e.Min()!=0) error(); if (e.Max()!=e.Size()-1) error(); Write2(e.Sum(),(e.Size()*(e.Size()-1))/2); if (e.Sum()!=(e.Size()*(e.Size()-1))/2) error(); int nn=4*n; Array1 f(nn); f.Last() = 5; Write2(f.v,f.Last()); f = e; Equal(e,f); // if (f.Last() != 5) error(); f.CopyResize(e.Size()); Equal(e,f); f.CopyResize(e.Size(),nn); if (f!=e) error(); f.CopyResize(nn,nn); int *v = f.GetPointer(); f.CopyResize(e.Size()); if (e!=f) error(); f.CopyResize(nn,nn); if (v != f.GetPointer()) error(); f.PushBack(4); if (v == f.GetPointer()) error(); v = f.GetPointer(); f.PushBack(4); f.PushBack(4); f.PushBack(4); if (v != f.GetPointer()) error(); f.CopyResize(e.Size()); if (e!=f) error(); cout << "Non-fixed Array1 tests passed" << endl; Array1 g(e.Size(),e.GetPointer()); Array1 g2(g); if (e[0]!=g2[0]) error(); if (e.GetPointer()!=g2.GetPointer()) error(); if (e.Sum()!=g2.Sum()) error(); if (e!=g2) error(); cout << "Fixed Array1 tests passed" << endl; // Test making Array2 by sub-dividing Array1 Array2 e2 = e.MakeArray2(2); Array2 e2c(e2); Array2 e2cc; e2cc = e2c; if (e2cc.b) error(); if (e.Last()!=e2cc(e2cc.dim[0]-1,e2cc.dim[1]-1)) error(); // Make a new Array1 containing a section of the old one Array1 ef(e,3,5); if (ef.Size()!=2) error(); if (ef[0]!=e[3]) error(); if (ef.b) error(); ef[1]=100; if (ef[1]!=e[4]) error(); cout << "--- all Array1 tests completed ---" << endl << endl; int n1=6; int n2=13; Array2 h1(n1,n2,2); Array2 h2(h1); for(int i=0; i h3; h3 = h2; Equal(h2,h3); h3.CopyResize(h2.dim[0]*2,h2.dim[1]*3); h3.CopyResize(h2.dim[0],h2.dim[1]); if (h2!=h3) error(); if (h2.Sum()!=h3.Sum()) error(); if (h2.Min()!=h3.Min()) error(); if (h2.Min()!=0) error(); Write(h2.Max()); if (h2.Max()!=h2.size-1) error(); if (h2.Max()!=h3.Max()) error(); Array1 hh(h3,3); if (hh.Last()!=h3(3,h3.dim[1]-1)) error(); Array1 hhh(h3,3,3,5); if (hhh.Last()!=h3(3,4)) error(); if (h2[5][4] != h2(5,4)) error(); Array1 qx(h2[5]); qx[4]=-21; (h2[5])[4] = -21; h2(5,4) = -21; if (h2[5][4] != h2(5,4)) error(); if (h2[5][4] == h2(4,5)) error(); h2[4][5] = -15; if (h2[4][5] != -15 || h2[4][5] != h2(4,5) ) error("[][]"); cout << "--- all Array2 tests completed ---" << endl << endl; int n3=21; Array3 m0(n1,n2,n3); m0.Check(); m0 = 3; Array3 m(n1,n2,n3,3); Equal(m0,m); Array3 m2(m); Array3 m3; m3 = m; for(int i=0; i q(nnn); for(int i=0; i qq(nx,ny); for(int i=0; i qq2; qq2 = qq+2.0; qq2 /= 2.0; Array2 qq3 = qq2 - 1.0; Array2 qq4; qq4 = 2.0*qq3; Equal(qq,qq4,1e-10); cout << "Array2 arithmetic finished ok." << endl; int nz=20; Array3 qqq(nx,ny,nz); for(int i=0; i qqq2; qqq2 = qqq+10.0; qqq2 /= 10.0; Array3 qqq3 = qqq2 - 1.0; Array3 qqq4; qqq4 = 10.0*qqq3; Equal(qqq,qqq4,1e-10); cout << "Array3 arithmetic finished ok." << endl; cout << "Program finished properly." << endl; } #endif #endif // _ARRAY_