cube.h #ifndef __SW_CUBE_H__ #define __SW_CUBE_H__ #include //#include //#include #include #include #include // Uncomment to disable assert(). // #define NDEBUG #include namespace SW { /* enum fill_type { fill::zeros, fill::ones, fill::eye, fill::randu, fill::randn, fill::none }; */ namespace ORDER_TYPE { enum order_types { CDR, DCR, DRC, CRD, RCD, RDC }; } namespace FILL_TYPE { enum fill_types { ZEROS, // Set all elements to 0. ONES, // Set all elements to 1. TWOS, // Set all elements to 2. EYE, // Set the elements along the main diagonal to 1 and off-diagonal elements to 0. RAND, // Set each element to a random value. RANDU, // Set each element to a random value from a uniform distribution in the [0,1] interval. RANDN, // Set each element to a random value from a normal/Gaussian distribution with zero mean and unit variance. SEQUENTIAL, // Set each element to the next sequential value. HIGHER, // Set each element to a higher value than the previous element. LOWER, // Set each element to a lower value than the previous element. NONE // Do not modify the elements. }; } // Default random engine. int RandRange(int min_value, int max_value) { std::default_random_engine generator; std::uniform_int_distribution distribution(min_value, max_value); auto random_value = distribution(generator); // generates number in the range 1..6 return random_value; } // Default random engine. double RandRangeNormal(double min_value, double max_value) { std::default_random_engine generator; std::uniform_real_distribution distribution(min_value, max_value); auto random_value = distribution(generator); // generates number in the range 1..6 return random_value; } // Mersenne Twister 19937 generator. double RandRangeMersenneTwister(double min_value, double max_value) { std::random_device rd; // only used once to initialise (seed) engine. std::mt19937 rng(rd()); // random-number engine used (Mersenne-Twister in this case). std::uniform_real_distribution uni(min_value, max_value); // guaranteed unbiased. auto random_value = uni(rng); return random_value; } // Mersenne Twister 19937 generator. int RandRange3(int min_value, int max_value) { std::random_device rd; // only used once to initialise (seed) engine. std::mt19937 rng(rd()); // random-number engine used (Mersenne-Twister in this case). std::uniform_int_distribution uni(min_value, max_value); // guaranteed unbiased. auto random_value = uni(rng); return random_value; } // C / C++ standard library generator // The following is the standard C / C++ generator defined in .Beware: on some machines it has // an unacceptably short period!! // Program 1 : http ://www.physics.buffalo.edu/phy410-505/topic2/generators.cpp /* double rand(unsigned& seed, bool set) { if (set) srand(seed); else seed = std::rand(); return seed / (RAND_MAX + 1.0); } */ /* // Park - Miller algorithm. // The following Park - Miller generator is very popular and widely used.It produces sequences of high // quality and has a long period 231 - 1 = 2147483647. The following implementation uses Schrage's // algorithm, which works on old machines with 16 - bit int's. // Program 1: http ://www.physics.buffalo.edu/phy410-505/topic2/generators.cpp double ranf(unsigned& seed, bool set) { const int IA = 16807, IC = 2147483647, IQ = 127773, IR = 2836; int iseed = seed; if (iseed <= 0) iseed += IC; if (!set) { int h = iseed / IQ; int l = iseed % IQ; iseed = IA * l - IR * h; } if (iseed <= 0) iseed += IC; return (seed = iseed) / double(IC); } */ /* // Quick and dirty algorithm // The following implements the Quick and Dirty algorithm from Numerical Recipes[1]. // Program 1: http ://www.physics.buffalo.edu/phy410-505/topic2/generators.cpp double ranq(unsigned& seed, bool set) { static unsigned long idum; const double TWO_POWER_32 = 4294967296.0; if (set) { idum = (unsigned long)seed; return idum / TWO_POWER_32; } idum = 1664525L * idum + 1013904223L; seed = int(idum); return idum / TWO_POWER_32; } */ /* // Marsaglia Xorshift algorithm // The new Third Edition of Numerical Recipes proposes a high-quality generator based on the Xorshift // algorithms of Marsaglia[5]. It uses 64-bit unsigned integer arithmetic that is standard on all modern // machines. It has an extremely long period ~ 3.13857. Note the use of C/C++ bitwise xor (^) and right // shift (>>) operators. // Program 1: http://www.physics.buffalo.edu/phy410-505/topic2/generators.cpp #ifdef _MSC_VER // Microsoft C++ typedef unsigned __int64 Ullong; // 64-bit unsigned integer #else // Macintosh, Linux typedef unsigned long long Ullong; #endif inline Ullong int64(Ullong& u, Ullong& v, Ullong& w) { u = u * 2862933555777941757LL + 7046029254386353087LL; v ^= v >> 17; v ^= v << 31; v ^= v >> 8; w = 4294957665U * (w & 0xffffffff) + (w >> 32); Ullong x = u ^ (u << 21); x ^= x >> 35; x ^= x << 4; return (x + v) ^ w; } double ranx(unsigned& seed, bool set) { static Ullong u = 0, v = 4101842887655102017LL, w = 1; if (set) { Ullong j = seed; v = 4101842887655102017LL; w = 1; u = j ^ v; int64(u, v, w); v = u; int64(u, v, w); w = v; seed = int(int64(u, v, w)); } else { 6Ullong x = int64(u, v, w); seed = unsigned(x); return 5.42101086242752217E-20 * x; } } */ /* #define ranf() ((float) rand() / (float) RAND_MAX) float ranfGauss(int m, float s) { static int pass = 0; static float y2; float x1, x2, w, y1; if (pass) { y1 = y2; } else { do { x1 = 2.0f * ranf() - 1.0f; x2 = 2.0f * ranf() - 1.0f; w = x1 * x1 + x2 * x2; } while (w >= 1.0f); w = (float)sqrt(-2.0 * log(w) / w); y1 = x1 * w; y2 = x2 * w; } pass = !pass; return ((y1 * s + (float)m)); } */ /* // Gaussian White Noise. #define PI 3.1415926536f float R1 = (float) rand() / (float) RAND_MAX; float R2 = (float) rand() / (float) RAND_MAX; float X = (float) sqrt( -2.0f * log( R1 )) * cos( 2.0f * PI * R2 ); */ /* // set the initial seed to whatever you like static int RandSeed = 1; // using rand() (16bit precision) // takes about 110 seconds for 2 billion calls float RandFloat1() { return ((float)rand()/RAND_MAX) * 2.0f - 1.0f; } // direct implementation of rand() (16 bit precision) // takes about 32 seconds for 2 billion calls float RandFloat2() { return ((float)(((RandSeed = RandSeed * 214013L + 2531011L) >> 16) & 0x7fff)/RAND_MAX) * 2.0f - 1.0f; } // fast rand float, using full 32bit precision // takes about 12 seconds for 2 billion calls float Fast_RandFloat() { RandSeed *= 16807; return (float)RandSeed * 4.6566129e-010f; } */ /* // Gaussian random numbers // This algorithm (adapted from "Natur als fraktale Grafik" by // Reinhard Scholl) implements a generation method for gaussian // distributed random numbers with mean=0 and variance=1 // (standard gaussian distribution) mapped to the range of // -1 to +1 with the maximum at 0. // For only positive results you might abs() the return value. // The q variable defines the precision, with q=15 the smallest // distance between two numbers will be 1/(2^q div 3)=1/10922 // which usually gives good results. // Note: the random() function used is the standard random // function from Delphi/Pascal that produces *linear* // distributed numbers from 0 to parameter-1, the equivalent // C function is probably rand(). Code : const q=15; c1=(1 shl q)-1; c2=(c1 div 3)+1; c3=1/c1; function GRandom:single; begin result:=(2*(random(c2)+random(c2)+random(c2))-3*(c2-1))*c3; end; */ // Calculate pseudo-random 32 bit number based on linear congruential method. unsigned long GenerateRandomNumber(void) { // Change this for different random sequences. static unsigned long randSeed = 22222; randSeed = (randSeed * 196314165) + 907633515; return randSeed; } // Mapping of 32768 integers. int RandN(int min_value, int max_value) { int result = min_value + (rand() % (int)(max_value - min_value + 1)); return result; } unsigned long _Randseed = 1; int randN(int seed) { _Randseed = _Randseed * 1103515245 + seed; return ((unsigned int)(_Randseed >> 16) & RAND_MAX); } /* int RandU(int min_value, int max_value) { return min_value + (int)((double)rand() / (RAND_MAX + 1) * (max_value - min_value + 1)); } */ int RandU(int min_value, int max_value) { return ((65539 * rand()) % (2 ^ 31)); //return ((65539 * seed) & 0x7FFFFFFF); } // For 1st result use a random seed. // For next results use prev result as the seed. int RandU(int seed) { int result = (25179 * seed + 13849) % 101; return result; } const int HALF_RAND_MAX = RAND_MAX / 2; float randu() { // Generates a random float uniformly between [-1.0, 1.0) using RAND_MAX return ((float)rand()) / (HALF_RAND_MAX)-1; } int MinMax(int a, int b, int c) { if (b < a) return a; else if (b > c) return c; else return b; } /* // A simple taylor series, but optimized for integer phase. // phase is in 0 -> (2^32)-1 range and maps to 0 -> ~2PI float fastsin(UINT32 phase) { const float frf3 = -1.0f / 6.0f; const float frf5 = 1.0f / 120.0f; const float frf7 = -1.0f / 5040.0f; const float frf9 = 1.0f / 362880.0f; const float f0pi5 = 1.570796327f; float x, x2, asin; UINT32 tmp = 0x3f800000 | (phase >> 7); if (phase & 0x40000000) tmp ^= 0x007fffff; x = (*((float*)&tmp) - 1.0f) * f0pi5; x2 = x * x; asin = ((((frf9 * x2 + frf7) * x2 + frf5) * x2 + frf3) * x2 + 1.0f) * x; return (phase & 0x80000000) ? -asin : asin; } // A simple taylor series, but optimized for integer phase. // fastsin2 is less accurate than fastsin. // phase is in 0 -> (2^32)-1 range and maps to 0 -> ~2PI float fastsin2(UINT32 phase) { const float frf3 = -1.0f / 6.0f; const float frf5 = 1.0f / 120.0f; const float frf7 = -1.0f / 5040.0f; const float f0pi5 = 1.570796327f; float x, x2, asin; UINT32 tmp = 0x3f800000 | (phase >> 7); if (phase & 0x40000000) tmp ^= 0x007fffff; x = (*((float*)&tmp) - 1.0f) * f0pi5; x2 = x * x; asin = (((frf7 * x2 + frf5) * x2 + frf3) * x2 + 1.0f) * x; return (phase & 0x80000000) ? -asin : asin; } */ /* // C++ gaussian noise generation #include #include // Generate a new random seed from system time - do this once in your constructor. srand(time(0)); // Setup constants. const static int q = 15; const static float c1 = (1 << q) - 1; const static float c2 = ((int)(c1 / 3)) + 1; const static float c3 = 1.f / c1; // random number in range 0 - 1 not including 1. float random = 0.f; // the white noise. float noise = 0.f; for (int i = 0; i < numSamples; i++) { random = ((float)rand() / (float)(RAND_MAX + 1)); noise = (2.f * ((random * c2) + (random * c2) + (random * c2)) - 3.f * (c2 - 1.f)) * c3; } */ /* // intended for 32-bit floating point numbers only and should work a bit faster than the regular ones. // fastabs() gives you the absolute value of a float float fastabs(float f) {int i=((*(int*)&f)&0x7fffffff);return (*(float*)&i);} // fastneg() gives you the negative number (faster than multiplying with -1) float fastneg(float f) {int i=((*(int*)&f)^0x80000000);return (*(float*)&i);} // fastsgn() gives back +1 for 0 or positive numbers, -1 for negative numbers int fastsgn(float f) {return 1+(((*(int*)&f)>>31)<<1);} */ /* // uses IEEE 32-bit floating point representation to // quickly compute approximations to the log2 of a value. // // Both functions return under-estimates of the actual value, although the second flavour is less of an under-estimate than the first. // // Try examples of 0.1, 1, 2, 5, 100. int floorOfLn2( float f ) { assert( f > 0. ); assert( sizeof(f) == sizeof(int) ); assert( sizeof(f) == 4 ); return (((*(int *)&f)&0x7f800000)>>23)-0x7f; } float approxLn2( float f ) { assert( f > 0. ); assert( sizeof(f) == sizeof(int) ); assert( sizeof(f) == 4 ); int i = (*(int *)&f); return (((i&0x7f800000)>>23)-0x7f)+(i&0x007fffff)/(float)0x800000; } */ /* // fastpow(f,n) gives a rather *rough* estimate of a float number f to the power of an integer number n (y=f^n). It is fast but result can be quite a bit off, since we directly mess with the floating point exponent.-> use it only for getting rough estimates of the values and where precision is not that important. float fastpower(float f,int n) { long *lp,l; lp=(long*)(&f); l=*lp;l-=0x3F800000l;l<<=(n-1);l+=0x3F800000l; *lp=l; return f; } // fastroot(f,n) gives the n-th root of f. Same thing concerning precision applies here. float fastroot(float f,int n) { long *lp,l; lp=(long*)(&f); l=*lp;l-=0x3F800000l;l>>=(n-1);l+=0x3F800000l; *lp=l; return f; } */ template class Cube { private: std::vector > > data; mutable unsigned rows; // Width. mutable unsigned cols; // Height. mutable unsigned depth; // Depth. FILL_TYPE::fill_types fill_type; ORDER_TYPE::order_types order_type; public: Cube(); Cube(unsigned _rows, unsigned _cols, unsigned _depth); Cube(unsigned _rows, unsigned _cols, unsigned _depth, FILL_TYPE::fill_types _fill_type); Cube(unsigned _rows, unsigned _cols, unsigned _depth, FILL_TYPE::fill_types _fill_type, ORDER_TYPE::order_types _order_type); Cube(unsigned _rows, unsigned _cols, unsigned _depth, ORDER_TYPE::order_types _order_type); ~Cube(); Cube(const Cube& rhs); // Arithmetic operators and Relational operators const Cube& operator = (const Cube &); // Assignment operator. // Operator overloading, for comparitive operations. bool operator==(const Cube& rhs) const; // Comparison operator. bool operator!=(const Cube& rhs) const; // bool operator<(const Cube& rhs) const; bool operator<=(const Cube& rhs) const; bool operator>(const Cube& rhs) const; bool operator>=(const Cube& rhs) const; // Arithmetic operators. Cube operator - () const; // Negate operator. Cube operator ++ (); // Prefix increment operator. Cube operator ++ (int); // Postfix increment operator. Cube operator -- (); // Prefix decrement operator. Cube operator -- (int); // Postfix decrement operator. // Mathematical operations. Cube operator + (const Cube &); Cube operator += (const Cube &); Cube operator - (const Cube &); Cube operator -= (const Cube &); Cube operator * (const Cube &); Cube operator *= (const Cube &); Cube operator / (const Cube &); Cube operator /= (const Cube &); Cube operator % (const Cube &); Cube operator %= (const Cube &); Cube operator ^ (const Cube &); Cube operator ^= (const Cube &); // Scalar operations. Cube operator+(const T& rhs); Cube operator+=(const T& rhs); Cube operator-(const T& rhs); Cube operator-=(const T& rhs); Cube operator*(const T& rhs); Cube operator*=(const T& rhs); Cube operator/(const T& rhs); Cube operator/=(const T& rhs); Cube operator%(const T& rhs); Cube operator%=(const T& rhs); Cube operator^(const T& rhs); Cube operator^=(const T& rhs); // Access the individual elements. T& operator()(const unsigned& row, const unsigned& col, const unsigned& depth); const T& operator()(const unsigned& row, const unsigned& col, const unsigned& depth) const; void fill(); void fill(T value); void fill_higher(T seq = 0, T min_inc = 1); void fill_lower(T seq = 0, T min_inc = 1); void fill_sequentially(T seq = 0, T inc = 1); // Access the row, column and depth sizes. unsigned getCols() const; unsigned getDepth() const; FILL_TYPE::fill_types getFillType() const; ORDER_TYPE::order_types getOrderType() const; unsigned getRows() const; unsigned getSize() const; unsigned getVolume(); T& max(); T& min(); void print(std::ostream& os = cout); void randomize(); void read(std::istream& is = cin); void sequence(T seq, T inc=1); T& sum(); friend Cube operator + (const Cube &, const Cube &); friend Cube operator - (const Cube &, const Cube &); friend Cube operator * (const Cube &, const Cube &); friend Cube operator / (const Cube &, const Cube &); friend Cube operator % (const Cube &, const Cube &); friend Cube operator ^ (const Cube &, const Cube &); friend int operator == (const Cube &, const Cube &); friend int operator != (const Cube &, const Cube &); friend int operator < (const Cube &, const Cube &); friend int operator <= (const Cube &, const Cube &); friend int operator > (const Cube &, const Cube &); friend int operator >= (const Cube &, const Cube &); // Other functions friend Cube abs(const Cube &); friend double div(const Cube &, const Cube &); friend unsigned size(const Cube &); friend Cube sqrt(const Cube &); friend Cube pow(const Cube &, const Cube &); // I/O stream functions //template friend std::ostream & operator << (std::ostream &, const Cube &); //template friend std::istream & operator >> (std::istream &, Cube &); }; // Basic Constructor. template Cube::Cube() { rows = 0; cols = 0; depth = 0; fill_type = FILL_TYPE::NONE; order_type = ORDER_TYPE::CDR; } // Parameter Constructor. template Cube::Cube(unsigned _rows, unsigned _cols, unsigned _depth) { data.resize(_rows); for (unsigned i = 0; i Cube::Cube(unsigned _rows, unsigned _cols, unsigned _depth, FILL_TYPE::fill_types _fill_type) { data.resize(_rows); for (unsigned i = 0; i Cube::Cube(unsigned _rows, unsigned _cols, unsigned _depth, FILL_TYPE::fill_types _fill_type, ORDER_TYPE::order_types _order_type) { data.resize(_rows); for (unsigned i = 0; i Cube::Cube(unsigned _rows, unsigned _cols, unsigned _depth, ORDER_TYPE::order_types _order_type) { data.resize(_rows); for (unsigned i = 0; i Cube::~Cube() { // does nothing } // Copy Constructor. template Cube::Cube(const Cube& rhs) { data = rhs.data; rows = rhs.getRows(); cols = rhs.getCols(); depth = rhs.getDepth(); fill_type = rhs.getFillType(); order_type = rhs.getOrderype(); } // Assignment Operator. template const Cube& Cube::operator=(const Cube& rhs) { if (&rhs == this) return *this; unsigned new_cols = rhs.getCols(); unsigned new_depth = rhs.getDepth(); unsigned new_rows = rhs.getRows(); bool new_fill_type = rhs.getFillType(); bool new_order_type = rhs.getOrderType(); data.resize(new_rows); for (unsigned i = 0; i < data.size(); i++) { data[i].resize(new_cols); for (unsigned i = 0; i < data.size(); i++) { data[i][j].resize(new_depth); } } /* for (unsigned i = 0; i bool Cube::operator==(const Cube& rhs) const { unsigned cols = rhs.getCols(); unsigned depth = rhs.getDepth(); unsigned rows = rhs.getRows(); fill_types fill_type = rhs.getFillType(); order_types order_type = rhs.getOrderType(); if (getCols() != cols) return false; if (getDepth() != depth) return false; if (getRows() != rows) return false; if (getFillType() != fill_type) return false; if (getOrderType() != order_type) return false; for (unsigned i = 0; idata[i][j][k] != rhs(i, j, k)) return false; } } } return true; } // Comparison Operator !=. template bool Cube::operator!=(const Cube& rhs) const { unsigned rows = rhs.getRows(); unsigned cols = rhs.getCols(); unsigned depth = rhs.getDepth(); fill_types fill_type = rhs.getFillType(); order_types order_type = rhs.getOrderType(); if (getCols() != cols) return true; if (getDepth() != depth) return true; if (getRows() != rows) return true; if (getFillType() != fill_type) return true; if (getOrderType() != order_type) return true; for (unsigned i = 0; idata[i][j][k] == rhs(i, j, k)) return false; } } } return false; } // Comparison Operator <. // // If every cell is < than rhs. template bool Cube::operator<(const Cube& rhs) const { unsigned rows = rhs.getRows(); unsigned cols = rhs.getCols(); unsigned depth = rhs.getDepth(); if (getCols() != cols) return false; if (getDepth() != depth) return false; if (getRows() != rows) return false; for (unsigned i = 0; idata[i][j][k] >= rhs(i, j, k)) return false; } } } return true; } // Comparison Operator <=. // // If every cell is <= than rhs. template bool Cube::operator<=(const Cube& rhs) const { unsigned rows = rhs.getRows(); unsigned cols = rhs.getCols(); unsigned depth = rhs.getDepth(); if (getRows() != rows) return false; if (getCols() != cols) return false; if (getDepth() != depth) return false; for (unsigned i = 0; idata[i][j][k] > rhs(i, j, k)) return false; } } } return true; } // Comparison Operator <. // // If every cell is > than rhs. template bool Cube::operator>(const Cube& rhs) const { unsigned rows = rhs.getRows(); unsigned cols = rhs.getCols(); unsigned depth = rhs.getDepth(); if (getRows() != rows) return false; if (getCols() != cols) return false; if (getDepth() != depth) return false; for (unsigned i = 0; idata[i][j][k] <= rhs(i, j, k)) return false; } } } return true; } // Comparison Operator >=. // // If every cell is >= than rhs. template bool Cube::operator>=(const Cube& rhs) const { unsigned rows = rhs.getRows(); unsigned cols = rhs.getCols(); unsigned depth = rhs.getDepth(); if (getRows() != rows) return false; if (getCols() != cols) return false; if (getDepth() != depth) return false; for (unsigned i = 0; idata[i][j][k] < rhs(i, j, k)) return false; } } } return true; } // Unary - operator. template Cube Cube::operator -() const { Cube result(rows, cols, depth); for (unsigned i = 0; idata[i][j][k]; } } } return result; } // Prefix increment operator. template Cube Cube::operator ++ () { Cube result(rows, cols, depth); for (unsigned i = 0; idata[i][j][k] + 1; } } } return *this = result; } // Postfix increment operator. template Cube Cube::operator ++ (int) { Cube result(rows, cols, depth); for (unsigned i = 0; idata[i][j][k] + 1; } } } return result; } // Prefix decrement operator. template Cube Cube::operator -- () { Cube result(rows, cols, depth); for (unsigned i = 0; idata[i][j][k] - 1; } } } return *this = result; } // Postfix decrement operator. template Cube Cube::operator -- (int) { Cube result(rows, cols, depth); for (unsigned i = 0; idata[i][j][k] - 1; } } } return result; } // Addition of two Cubes. template Cube Cube::operator+(const Cube& rhs) { float new_rows = (x > rhs.getRows()) ? x : rhs.getRows(); float new_cols = (y > rhs.getCols()) ? y : rhs.getCols(); float new_depth = z + rhs.getDepth(); Cube result(new_rows, new_cols, new_depth); for (unsigned i = 0; idata[i][j][k] + rhs(i, j, k); } } } return result; } // Cumulative addition of this Cube and another. template Cube Cube::operator+=(const Cube& rhs) { unsigned rows = rhs.getRows(); unsigned cols = rhs.getCols(); unsigned depth = rhs.getDepth(); for (unsigned i = 0; idata[i][j][k] += rhs(i, j, k); } } } return *this; } // Subtraction of this Cube and another. template Cube Cube::operator-(const Cube& rhs) { unsigned rows = rhs.getRows(); unsigned cols = rhs.getCols(); unsigned depth = rhs.getDepth(); Cube result(rows, cols, depth); for (unsigned i = 0; idata[i][j][k] - rhs(i, j, k); } } } return result; } // Cumulative subtraction of this Cube and another. template Cube Cube::operator-=(const Cube& rhs) { unsigned rows = rhs.getRows(); unsigned cols = rhs.getCols(); unsigned depth = rhs.getDepth(); for (unsigned i = 0; idata[i][j][k] -= rhs(i, j, k); } } } return *this; } // Left multiplication of this Cube and another. template Cube Cube::operator*(const Cube& rhs) { unsigned rows = rhs.getRows(); unsigned cols = rhs.getCols(); unsigned depth = rhs.getDepth(); Cube result(rows, cols, depth); for (unsigned i = 0; idata[i][j][k] * rhs(i, j, k); } } } return result; } // Cumulative left multiplication of this Cube and another. template Cube Cube::operator*=(const Cube& rhs) { Cube result = (*this) * rhs; (*this) = result; return *this; } // Left division of this Cube and another. template Cube Cube::operator/(const Cube& rhs) { unsigned rows = rhs.getRows(); unsigned cols = rhs.getCols(); unsigned depth = rhs.getDepth(); Cube result(rows, cols, depth); for (unsigned i = 0; idata[i][j][k] / rhs(i, j, k); } } } return result; } // Cumulative left division of this Cube and another. template Cube Cube::operator/=(const Cube& rhs) { Cube result = (*this) / rhs; (*this) = result; return *this; } // Left mod of this Cube and another. template Cube Cube::operator%(const Cube& rhs) { unsigned rows = rhs.getRows(); unsigned cols = rhs.getCols(); unsigned depth = rhs.getDepth(); Cube result(rows, cols, depth); for (unsigned i = 0; idata[i][j][k] % rhs(i, j, k); } } } return result; } // Cumulative left mod of this Cube and another. template Cube Cube::operator%=(const Cube& rhs) { Cube result = (*this) % rhs; (*this) = result; return *this; } // Left raise of this Cube and another. template Cube Cube::operator^(const Cube& rhs) { // unsigned rows = rhs.get_rows(); // unsigned cols = rhs.get_cols(); Matrix result(rows, cols, depth); for (unsigned i = 0; idata[i][j][k] ^ rhs(i, j, k); } } } return result; } // Cumulative left raise of this Cube and another. template Cube Cube::operator^=(const Cube& rhs) { Cube result = (*this) ^ rhs; (*this) = result; return *this; } // Addition of this Cube and a value. template Cube Cube::operator+(const T& rhs) { Cube result(rows, cols, depth); for (unsigned i = 0; idata[i][j][k] + rhs; } } } return result; } // Cumulative addition of this Cube and a value. template Cube Cube::operator+=(const T& rhs) { Cube result = (*this) + rhs; (*this) = result; return *this; } // Subtraction of this Cube and a value. template Cube Cube::operator-(const T& rhs) { unsigned rows = rhs.getRows(); unsigned cols = rhs.getCols(); unsigned depth = rhs.getDepth(); Cube result(rows, cols, depth); for (unsigned i = 0; idata[i][j][k] - rhs; } } } return result; } // Cumulative subtraction of a valye from this Cube. template Cube Cube::operator-=(const T& rhs) { Cube result = (*this) - rhs; (*this) = result; return *this; } // Left multiplication of this Cube and a value. template Cube Cube::operator*(const T& rhs) { unsigned rows = rhs.getRows(); unsigned cols = rhs.getCols(); unsigned depth = rhs.getDepth(); Cube result(rows, cols, depth); for (unsigned i = 0; idata[i][j][k] * rhs; } } } return result; } // Cumulative multiplication from this Cube and a value. template Cube Cube::operator*=(const T& rhs) { Cube result = (*this) * rhs; (*this) = result; return *this; } // Left division of this Cube and a value. template Cube Cube::operator/(const T& rhs) { unsigned rows = rhs.getRows(); unsigned cols = rhs.getCols(); unsigned depth = rhs.getDepth(); Cube result(rows, cols, depth); for (unsigned i = 0; idata[i][j][k] / rhs; } } } return result; } // Cumulative division from this Cube and a value. template Cube Cube::operator/=(const T& rhs) { if (rhs != 0) { Cube result = (*this) / rhs; (*this) = result; } return *this; } // Left mod of this Cube and a value. template Cube Cube::operator%(const T& rhs) { unsigned rows = rhs.getRows(); unsigned cols = rhs.getCols(); unsigned depth = rhs.getDepth(); Cube result(rows, cols, depth); for (unsigned i = 0; idata[i][j][k] % rhs; } } } return result; } // Cumulative left mod of this Cube and a value. template Cube Cube::operator%=(const T& rhs) { if (rhs != 0) { Cube result = (*this) % rhs; (*this) = result; } return *this; } // Left raise of this Cube and a value. template Cube Cube::operator^(const T& rhs) { // unsigned rows = rhs.get_rows(); // unsigned cols = rhs.get_cols(); Matrix result(rows, cols, depth); for (unsigned i = 0; idata[i][j][k] ^ rhs; } } } return result; } // Cumulative left raise of this Cube and a value.. template Cube Cube::operator^=(const T& rhs) { Cube result = (*this) ^ rhs; (*this) = result; return *this; } // Access the individual elements. template T& Cube::operator()(const unsigned& row, const unsigned& col, const unsigned& depth) { assert(row >= 0); assert(col >= 0); assert(depth >= 0); assert(row < this->rows); assert(col < this->cols); assert(depth < this->depth); return this->data[row][col][depth]; } // Access the individual elements (const). template const T& Cube::operator()(const unsigned& row, const unsigned& col, const unsigned& depth) const { assert(row >= 0); assert(col >= 0); assert(depth >= 0); assert(row < this->rows); assert(col < this->cols); assert(depth < this->depth); return this->data[row][col][depth]; } // Populates every cell with a specific value which is dependant on the FILL_TYPE. template void Cube::fill() { std::srand(std::time(0)); // use current time as seed for random generator. for (unsigned i = 0; i void Cube::fill(T value) { for (unsigned i = 0; i void Cube::fill_higher(T seq = 0, T min_inc = 1) { T tmp; switch (order_type) { case 0: // CDR. for (unsigned j = 0; j < cols; j++) { for (unsigned k = 0; k < depth; k++) { for (unsigned i = 0; i < rows; i++) { data[i][j][k] = seq; tmp = rand(); while (tmp <= seq + min_inc) tmp = rand(); seq = tmp; } } } break; case 1: // DCR. for (unsigned k = 0; k < depth; k++) { for (unsigned j = 0; j < cols; j++) { for (unsigned i = 0; i < rows; i++) { data[i][j][k] = seq; tmp = rand(); while (tmp <= seq + min_inc) tmp = rand(); seq = tmp; } } } break; case 2: // DRC. for (unsigned k = 0; k < depth; k++) { for (unsigned i = 0; i < rows; i++) { for (unsigned j = 0; j < cols; j++) { data[i][j][k] = seq; tmp = rand(); while (tmp <= seq + min_inc) tmp = rand(); seq = tmp; } } } break; case 3: // CRD. for (unsigned j = 0; j < cols; j++) { for (unsigned i = 0; i < rows; i++) { for (unsigned k = 0; k < depth; k++) { data[i][j][k] = seq; tmp = rand(); while (tmp <= seq + min_inc) tmp = rand(); seq = tmp; } } } break; case 4: // RCD. for (unsigned i = 0; i < rows; i++) { for (unsigned j = 0; j < cols; j++) { for (unsigned k = 0; k < depth; k++) { data[i][j][k] = seq; tmp = rand(); while (tmp <= seq + min_inc) tmp = rand(); seq = tmp; } } } break; case 5: // RDC. for (unsigned i = 0; i < rows; i++) { for (unsigned k = 0; k < depth; k++) { for (unsigned j = 0; j < cols; j++) { data[i][j][k] = seq; tmp = rand(); while (tmp <= seq + min_inc) tmp = rand(); seq = tmp; } } } break; default: // CDR. for (unsigned j = 0; j < cols; j++) { for (unsigned k = 0; k < depth; k++) { for (unsigned i = 0; i < rows; i++) { data[i][j][k] = seq; tmp = rand(); while (tmp <= seq + min_inc) tmp = rand(); seq = tmp; } } } } } // Populates every cell with the a lower number than the previous cell. // // seq is the starting sequence. // min_inc is the minimum increment to the next number. template void Cube::fill_lower(T seq = 0, T min_inc = 1) { T tmp; switch (order_type) { case 0: // CDR. for (unsigned j = 0; j < cols; j++) { for (unsigned k = 0; k < depth; k++) { for (unsigned i = 0; i < rows; i++) { data[i][j][k] = seq; tmp = rand(); while (tmp >= seq + min_inc) tmp = rand(); seq = tmp; } } } break; case 1: // DCR. for (unsigned k = 0; k < depth; k++) { for (unsigned j = 0; j < cols; j++) { for (unsigned i = 0; i < rows; i++) { data[i][j][k] = seq; tmp = rand(); while (tmp >= seq + min_inc) tmp = rand(); seq = tmp; } } } break; case 2: // DRC. for (unsigned k = 0; k < depth; k++) { for (unsigned i = 0; i < rows; i++) { for (unsigned j = 0; j < cols; j++) { data[i][j][k] = seq; tmp = rand(); while (tmp >= seq + min_inc) tmp = rand(); seq = tmp; } } } break; case 3: // CRD. for (unsigned j = 0; j < cols; j++) { for (unsigned i = 0; i < rows; i++) { for (unsigned k = 0; k < depth; k++) { data[i][j][k] = seq; tmp = rand(); while (tmp >= seq + min_inc) tmp = rand(); seq = tmp; } } } break; case 4: // RCD. for (unsigned i = 0; i < rows; i++) { for (unsigned j = 0; j < cols; j++) { for (unsigned k = 0; k < depth; k++) { data[i][j][k] = seq; tmp = rand(); while (tmp >= seq + min_inc) tmp = rand(); seq = tmp; } } } break; case 5: // RDC. for (unsigned i = 0; i < rows; i++) { for (unsigned k = 0; k < depth; k++) { for (unsigned j = 0; j < cols; j++) { data[i][j][k] = seq; tmp = rand(); while (tmp >= seq + min_inc) tmp = rand(); seq = tmp; } } } break; default: // CDR. for (unsigned j = 0; j < cols; j++) { for (unsigned k = 0; k < depth; k++) { for (unsigned i = 0; i < rows; i++) { data[i][j][k] = seq; tmp = rand(); while (tmp >= seq + min_inc) tmp = rand(); seq = tmp; } } } } } // Populates every cell with the a sequential number. // // seq is the starting sequence. // inc is the increment to the next number. template void Cube::fill_sequentially(T seq = 0, T inc = 1) { switch (order_type) { case 0: // CDR. for (unsigned j = 0; j < cols; j++) { for (unsigned k = 0; k < depth; k++) { for (unsigned i = 0; i < rows; i++) { data[i][j][k] = seq; seq += inc; } } } break; case 1: // DCR. for (unsigned k = 0; k < depth; k++) { for (unsigned j = 0; j < cols; j++) { for (unsigned i = 0; i < rows; i++) { data[i][j][k] = seq; seq += inc; } } } break; case 2: // DRC. for (unsigned k = 0; k < depth; k++) { for (unsigned i = 0; i < rows; i++) { for (unsigned j = 0; j < cols; j++) { data[i][j][k] = seq; seq += inc; } } } break; case 3: // CRD. for (unsigned j = 0; j < cols; j++) { for (unsigned i = 0; i < rows; i++) { for (unsigned k = 0; k < depth; k++) { data[i][j][k] = seq; seq += inc; } } } break; case 4: // RCD. for (unsigned i = 0; i < rows; i++) { for (unsigned j = 0; j < cols; j++) { for (unsigned k = 0; k < depth; k++) { data[i][j][k] = seq; seq += inc; } } } break; case 5: // RDC. for (unsigned i = 0; i < rows; i++) { for (unsigned k = 0; k < depth; k++) { for (unsigned j = 0; j < cols; j++) { data[i][j][k] = seq; seq += inc; } } } break; default: // CDR. for (unsigned j = 0; j < cols; j++) { for (unsigned k = 0; k < depth; k++) { for (unsigned i = 0; i < rows; i++) { data[i][j][k] = seq; seq += inc; } } } } } // Get the number of columns. template unsigned Cube::getCols() const { return this->cols; } // Get the number of columns. template unsigned Cube::getDepth() const { return this->depth; } // Gets the fill_type. // // Cells are populated using the fill_type. template FILL_TYPE::fill_types Cube::getFillType() const { return this->fill_type; } // Gets the fill_type. // // Cells are populated in the order determined by the order_type. template ORDER_TYPE::order_types Cube::getOrderType() const { return this->order_type; } // Get the number of rows. template unsigned Cube::getRows() const { return this->rows; } // Returns the size. // // Returns the volume. template unsigned Cube::getSize() const { return rows * cols * depth; } // Returns the volume. template unsigned Cube::getVolume() { return rows * cols * depth; } // Returns the maximum value. template T& Cube::max() { T result = data[0][0][0]; for (unsigned i = 0; i result) result = data[i][j][k]; } } } return result; } // Returns the minimum value. template T& Cube::min() { T result = data[0][0][0]; for (unsigned i = 0; i void Cube::print(std::ostream& os) { unsigned rows = getRows(); unsigned cols = getCols(); unsigned depth = getDepth(); for (unsigned j = 0; j < cols; j++) { for (unsigned k = 0; k < depth; k++) { for (unsigned i = 0; i < rows; i++) { os << data[i][j][k]; //if ((i*j) < (((rows - 1)*(cols - 1)) - 1)) //if ((i*j*k) < (((rows - 1)*(cols - 1)*(depth -1)) - 1)) if ((i < rows - 1) || (j < cols - 1) || (k < depth -1)) os << ","; } os << " "; } os << std::endl; } } // Randomizes every cell. template void Cube::randomize() { for (unsigned i = 0; i void Cube::read(std::istream& is) { is >> data; } // Populates every cell with the a sequential number. // // seq is the starting sequence. // inc is the increment to the next number. template void Cube::sequence(T seq = 0, T inc = 1) { switch (order_type) { case 0: // CDR. for (unsigned j = 0; j < cols; j++) { for (unsigned k = 0; k < depth; k++) { for (unsigned i = 0; i < rows; i++) { data[i][j][k] = seq; seq += inc; } } } break; case 1: // DCR. for (unsigned k = 0; k < depth; k++) { for (unsigned j = 0; j < cols; j++) { for (unsigned i = 0; i < rows; i++) { data[i][j][k] = seq; seq += inc; } } } break; case 2: // DRC. for (unsigned k = 0; k < depth; k++) { for (unsigned i = 0; i < rows; i++) { for (unsigned j = 0; j < cols; j++) { data[i][j][k] = seq; seq += inc; } } } break; case 3: // CRD. for (unsigned j = 0; j < cols; j++) { for (unsigned i = 0; i < rows; i++) { for (unsigned k = 0; k < depth; k++) { data[i][j][k] = seq; seq += inc; } } } break; case 4: // RCD. for (unsigned i = 0; i < rows; i++) { for (unsigned j = 0; j < cols; j++) { for (unsigned k = 0; k < depth; k++) { data[i][j][k] = seq; seq += inc; } } } break; case 5: // RDC. for (unsigned i = 0; i < rows; i++) { for (unsigned k = 0; k < depth; k++) { for (unsigned j = 0; j < cols; j++) { data[i][j][k] = seq; seq += inc; } } } break; default: // CDR. for (unsigned j = 0; j < cols; j++) { for (unsigned k = 0; k < depth; k++) { for (unsigned i = 0; i < rows; i++) { data[i][j][k] = seq; seq += inc; } } } } } // Returns the sum of all cells. template T& Cube::sum() { T result = 0; for (unsigned i = 0; i Cube operator + (const Cube &u, const Cube &v) { Cube result(rows, cols, depth); for (unsigned i = 0; i Cube operator - (const Cube &u, const Cube &v) { Cube result(rows, cols, depth); for (unsigned i = 0; i Cube operator * (const Cube &u, const Cube &v) { Cube result(rows, cols, depth); for (unsigned i = 0; i Cube operator / (const Cube &u, const Cube &v) { Cube result(rows, cols, depth); for (unsigned i = 0; i Cube operator % (const Cube &u, const Cube &v) { Cube result(rows, cols, depth); for (unsigned i = 0; i Cube operator ^ (const Cube &u, const Cube &v) { Cube result(rows, cols, depth); for (unsigned i = 0; i int operator == (const Cube &u, const Cube &v) { return (u == v); } template int operator != (const Cube &u, const Cube &v) { return !(u == v); } template int operator < (const Cube &u, const Cube &v) { return (u < v); } template int operator <= (const Cube &u, const Cube &v) { return (u <= v); } template int operator >(const Cube &u, const Cube &v) { return (u > v); } template int operator >= (const Cube &u, const Cube &v) { return (u >= v); } // Calculate the absolute value of a number. template Cube abs(const Cube &v) { Cube result(rows, cols, depth); for (unsigned i = 0; i double div(const Cube &u, const Cube &v) { Cube result(rows, cols, depth); for (unsigned i = 0; i unsigned size(const Cube &c) { return c.rows * c.cols * c.depth; } // Calculate the integer square root of a number // based on the formula (a+b)^2 = a^2 + 2ab + b^2 template Cube sqrt(const Cube &v) { Cube result(rows, cols, depth); for (unsigned i = 0; i Cube pow(const Cube &X, const Cube °ree) { Cube result(rows, cols, depth); for (unsigned i = 0; i //std::ostream & operator << (std::ostream &s, const Cube &m) std::ostream & operator << (std::ostream &s, Cube &m) { m.print(s); return s; /* unsigned rows = m.getRows(); unsigned cols = m.getCols(); unsigned depth = m.getDepth(); for (unsigned i = 0; i std::ostream & operator << (std::ostream &s, const Cube &m) { unsigned rows = m.getRows(); unsigned cols = m.getCols(); unsigned depth = m.getDepth(); for (unsigned i = 0; i std::ostream & operator << (std::ostream &s, const Cube &m) { m.print(s); return s; } */ /* template std::istream & operator >> (std::istream &s, Cube &v) { std::string temp(10000, ' '); s >> temp; return s; } */ template std::istream & operator >> (std::istream &s, Cube &m) { m.read(s); return s; } } // end namespace SW. #endif