#include "Matrix.h" #include //#include #define _CHECK_INDEX //////////////////////// // Array Constructors // //////////////////////// tcT /*inline*/ Array::Array(int l, int m, int n, T* d/**=0**/) : L(l), M(m), N(n), X(d) { } tcT /*inline*/ Array::Array(int m, int n, T* d/**=0**/) : L(n), M(m), N(n), X(d) { } tcT /*inline*/ Array::Array(int n, T* d/**=0**/) : L(n), M(1), N(n), X(d) { } tcT /*inline*/ Array::Array(const Array& a) : L(a.L), M(a.M), N(a.N), X(a.X) { } tcT /*inline*/ Array::Array() : L(0), M(0), N(0), X(0) { } tcT /*inline*/ /**virtual**/ Array::~Array() { } ///////////////////// // Array selectors // ///////////////////// tcT /*inline*/ int Array::l() const { return L; } tcT /*inline*/ int Array::m() const { return M; } tcT /*inline*/ int Array::n() const { return N; } tcT /*inline*/ T* Array::x() const { return X; } // subArray (without space reallocation) tcT /*inline*/ Array Array::s(int i, int m, int j, int n) const { #ifdef _CHECK_INDEX if ( i<0 ) throw whereOutOfRange( "Array Array::s(int,int,int,int) const","i",i,0,M-1); if ( m<0 || i+m>M ) throw whereOutOfRange( "Array Array::s(int,int,int,int) const","i+m",i+m,0,M-1); if ( j<0 ) throw whereOutOfRange( "Array Array::s(int,int,int,int) const","j",j,0,N-1); if ( n<0 || j+n>N ) throw whereOutOfRange( "Array Array::s(int,int,int,int) const","j+n",j+n,0,N-1); if ( !X ) throw nullArray("Array Array::s(int,int,int,int) const"); #endif return Array(L, m, n, &X[i*L+j]); } tcT /*inline*/ Array Array::s(int i/**=0**/,int m/**=1**/,int j/**=0**/) const { #ifdef _CHECK_INDEX if ( i<0 ) throw whereOutOfRange( "Array Array::s(int=0,int=1,int=0) const","i",i,0,M-1); if ( m<0 || i+m>M ) throw whereOutOfRange( "Array Array::s(int=0,int=1,int=0) const","i+m",i+m,0,M-1); if ( j<0 || j>=N ) throw whereOutOfRange( "Array Array::s(int=0,int=1,int=0) const","j",j,0,N-1); if ( !X ) throw nullArray("Array Array::s(int,int,int,int) const"); #endif return Array(L, m, N-j, &X[i*L+j]); } // subMatrix (with space reallocation) tcT /*inline*/ Matrix Array::_(int i, int m, int j, int n) const { return Matrix(s(i, m, j, n)); } tcT /*inline*/ Matrix Array::_(int i/**=0**/,int m/**=1**/,int j/**=0**/)const { return Matrix(s(i, m, j, N-j)); } // subscripting tcT /*inline*/ T* Array::operator [] (int i) const { #ifdef _CHECK_INDEX if ( i<0 || i>=M ) throw whereOutOfRange( "T* Array::operator[](int) const","i",i,0,M-1); if ( !X ) throw nullArray("T* Array::operator[](int) const"); #endif return &X[i*L]; } tcT /*inline*/ T& Array::operator () (int i) const { #ifdef _CHECK_INDEX if ( i<0 || i>=N ) throw whereOutOfRange( "T& Array::operator()(int) const","i",i,0,N-1); if ( !X ) throw nullArray("T& Array::operator()(int) const"); #endif return X[i]; } tcT /*inline*/ T& Array::operator () (int i, int j) const { #ifdef _CHECK_INDEX if ( i<0 || i>=M ) throw whereOutOfRange( "T& Array::operator()(int,int) const","i",i,0,M-1); if ( j<0 || j>=N ) throw whereOutOfRange( "T& Array::operator()(int,int) const","j",j,0,N-1); if ( !X ) throw nullArray("T& Array::operator()(int,int) const"); #endif return X[i*L+j]; } ////////////////////// // Arrays modifiers // ////////////////////// tcT /*inline*/ Array& Array::resize(const Array& a) { L = a.L; M = a.M; N = a.N; X = a.X; return *this; } tcT /*inline*/ Array& Array::resize(int m, int n, T* d) { L = n; M = m; N = n; X = d; return *this; } tcT /*inline*/ Array& Array::resize(int n, T* d) { L = n; M = 1; N = n; X = d; return *this; } tcT /*inline*/ int& Array::l(int i) { L = i; return L; } tcT /*inline*/ int& Array::m(int j) { M = j; return M; } tcT /*inline*/ int& Array::n(int k) { N = k; return N; } tcT /*inline*/ T*& Array::x(T* u) { X = u; return X; } ////////////////////////// // Assignment of arrays // ////////////////////////// // simple assignment tcT Array& Array::operator = (const T& b) { if ( !N || !M ) return *this; if ( !X ) throw nullArray("Array& Array::operator=(const T&)"); T* s = X; T* t = X + N; do { while (s < t) *s++ = b; s += L - N; } while ((t += L) <= &X[M*L]); return *this; } tcT Array& Array::operator = (const Array& a) { if ( !N || !M ) { if ( N != a.N || M != a.M ) throw whereDimMismatch("Array& Array::operator=(const Array&)",M,N,a.M,a.N); return *this; } if ( !X || !a.X ) throw nullArray("Array& Array::operator=(const Array&)"); if (N == a.N) { if (M == a.M) { // N == a.N && M == a.M T* t = a.X; T* u = X; T* v = X + N; do { while (u < v) *u++ = *t++; t += a.L - a.N; u += L - N; } while ((v += L) <= &X[M*L]); return *this; }; if (a.M == 1) { // N == a.N && M != a.M == 1 T* t; T* u = X; T* v = X + N; do { t = a.X; while (u < v) *u++ = *t++; u += L - N; } while ((v += L) <= &X[M*L]); return *this; } } if (a.N == 1) { if (M == a.M) { // N != a.N == 1 && M == a.M T* t = a.X; T* u = X; T* v = X + N; do { while (u < v) *u++ = *t; t++; u += L - N; } while ((v += L) <= &X[M*L]); return *this; } if (a.M == 1) { // N != a.N == 1 && M != a.M == 1 T* t = a.X; T* u = X; T* v = X + N; do { while (u < v) *u++ = *t; u += L - N; } while ((v += L) <= &X[M*L]); return *this; } } throw whereDimMismatch("Array& Array::operator=(const Array&)",M,N,a.M,a.N); } // add and assign tcT Array& Array::operator += (const T& b) { if ( !N || !M ) return *this; if ( !X ) throw nullArray("Array& Array::operator+=(const T&)"); T* s = X; T* t = X + N; do { while (s < t) *s++ += b; s += L - N; } while ((t += L) <= &X[M*L]); return *this; } tcT Array& Array::operator += (const Array& a) { if ( !N || !M ) { if ( N != a.N || M != a.M ) throw whereDimMismatch( "Array& Array::operator+=(const Array&)",M,N,a.M,a.N); return *this; } if ( !X || !a.X ) throw nullArray("Array& Array::operator+=(const Array&)"); if (N == a.N) { if (M == a.M) { // N == a.N T* t = a.X; T* u = X; T* v = X + N; do { while (u < v) *u++ += *t++; t += a.L - a.N; u += L - N; } while ((v += L) <= &X[M*L]); return *this; }; if (a.M == 1) { // N == a.N && M != a.M T* t; T* u = X; T* v = X + N; do { t = a.X; while (u < v) *u++ += *t++; u += L - N; } while ((v += L) <= &X[M*L]); return *this; }; }; if (a.N == 1) { // N != a.N if (M == a.M) { // N != a.N == 1 T* t = a.X; T* u = X; T* v = X + N; do { while (u < v) *u++ += *t; t++; u += L - N; } while ((v += L) <= &X[M*L]); return *this; }; if (a.M == 1) { // N != a.N == 1 && M != a.M T* t = a.X; T* u = X; T* v = X + N; do { while (u < v) *u++ += *t; u += L - N; } while ((v += L) <= &X[M*L]); return *this; }; }; throw whereDimMismatch( "Array& Array::operator+=(const Array&)",M,N,a.M,a.N); } // substract and assign tcT Array& Array::operator -= (const T& b) { if ( !N || !M ) return *this; if ( !X ) throw nullArray("Array& Array::operator-=(const T&)"); T* s = X; T* t = X + N; do { while (s < t) *s++ -= b; s += L - N; } while ((t += L) <= &X[M*L]); return *this; } tcT Array& Array::operator -= (const Array& a) { if ( !N || !M ) { if ( N != a.N || M != a.M ) throw whereDimMismatch( "Array& Array::operator-=(const Array&)",M,N,a.M,a.N); return *this; } if ( !X || !a.X ) throw nullArray("Array& Array::operator-=(const Array&)"); if (N == a.N) { if (M == a.M) { // N == a.N T* t = a.X; T* u = X; T* v = X + N; do { while (u < v) *u++ -= *t++; t += a.L - a.N; u += L - N; } while ((v += L) <= &X[M*L]); return *this; }; if (a.M == 1) { // N == a.N && M != a.M T* t; T* u = X; T* v = X + N; do { t = a.X; while (u < v) *u++ -= *t++; u += L - N; } while ((v += L) <= &X[M*L]); return *this; }; }; if (a.N == 1) { // N != a.N if (M == a.M) { // N != a.N == 1 T* t = a.X; T* u = X; T* v = X + N; do { while (u < v) *u++ -= *t; t++; u += L - N; } while ((v += L) <= &X[M*L]); return *this; }; if (a.M == 1) { // N != a.N == 1 && M != a.M T* t = a.X; T* u = X; T* v = X + N; do { while (u < v) *u++ -= *t; u += L - N; } while ((v += L) <= &X[M*L]); return *this; }; }; throw whereDimMismatch( "Array& Array::operator-=(const Array&)",M,N,a.M,a.N); } // multiply and assign tcT Array& Array::operator *= (const T& b) { if ( !N || !M ) return *this; if ( !X ) throw nullArray("Array& Array::operator*=(const T&)"); T* s = X; T* t = X + N; do { while (s < t) *s++ *= b; s += L - N; } while ((t += L) <= &X[M*L]); return *this; } tcT Array& Array::operator *= (const Array& a) { if ( !N || !M ) { if ( N != a.N || M != a.M ) throw whereDimMismatch( "Array& Array::operator*=(const Array&)",M,N,a.M,a.N); return *this; } if ( !X || !a.X ) throw nullArray("Array& Array::operator*=(const Array&)"); if (N == a.N) { if (M == a.M) { // N == a.N T* t = a.X; T* u = X; T* v = X + N; do { while (u < v) *u++ *= *t++; t += a.L - a.N; u += L - N; } while ((v += L) <= &X[M*L]); return *this; }; if (a.M == 1) { // N == a.N && M != a.M T* t; T* u = X; T* v = X + N; do { t = a.X; while (u < v) *u++ *= *t++; u += L - N; } while ((v += L) <= &X[M*L]); return *this; }; }; if (a.N == 1) { // N != a.N if (M == a.M) { // N != a.N == 1 T* t = a.X; T* u = X; T* v = X + N; do { while (u < v) *u++ *= *t; t++; u += L - N; } while ((v += L) <= &X[M*L]); return *this; }; if (a.M == 1) { // N != a.N == 1 && M != a.M T* t = a.X; T* u = X; T* v = X + N; do { while (u < v) *u++ *= *t; u += L - N; } while ((v += L) <= &X[M*L]); return *this; }; }; throw whereDimMismatch( "Array& Array::operator*=(const Array&)",M,N,a.M,a.N); } // divide and assign tcT Array& Array::operator /= (const T& b) { if ( !N || !M ) return *this; if ( !X ) throw nullArray("Array& Array::operator/=(const T&)"); T* s = X; T* t = X + N; do { while (s < t) *s++ /= b; s += L - N; } while ((t += L) <= &X[M*L]); return *this; } tcT Array& Array::operator /= (const Array& a) { if ( !N || !M ) { if ( N != a.N || M != a.M ) throw whereDimMismatch( "Array& Array::operator/=(const Array&)",M,N,a.M,a.N); return *this; } if ( !X || !a.X ) throw nullArray("Array& Array::operator/=(const Array&)"); if (N == a.N) { if (M == a.M) { // N == a.N T* t = a.X; T* u = X; T* v = X + N; do { while (u < v) *u++ /= *t++; t += a.L - a.N; u += L - N; } while ((v += L) <= &X[M*L]); return *this; }; if (a.M == 1) { // N == a.N && M != a.M T* t; T* u = X; T* v = X + N; do { t = a.X; while (u < v) *u++ /= *t++; u += L - N; } while ((v += L) <= &X[M*L]); return *this; }; }; if (a.N == 1) { // N != a.N if (M == a.M) { // N != a.N == 1 T* t = a.X; T* u = X; T* v = X + N; do { while (u < v) *u++ /= *t; t++; u += L - N; } while ((v += L) <= &X[M*L]); return *this; }; if (a.M == 1) { // N != a.N == 1 && M != a.M T* t = a.X; T* u = X; T* v = X + N; do { while (u < v) *u++ /= *t; u += L - N; } while ((v += L) <= &X[M*L]); return *this; }; }; throw whereDimMismatch( "Array& Array::operator/=(const Array&)",M,N,a.M,a.N); } // shift right and assign tcT Array& Array::operator >>= (int n) { if ( !N || !M ) return *this; if ( !X ) throw nullArray("Array& Array::operator>>=(int)"); T* t = &X[M*L]; T* u = &X[M*L]; T* v = &X[M*L]; while (X <= (u -= L)) { t -= L - N + n; v -= L - N; while (t > u) *--v = *--t; while (v > u) *--v = *t; }; return *this; } // shift left and assign tcT Array& Array::operator <<= (int n) { if ( !N || !M ) return *this; if ( !X ) throw nullArray("Array& Array::operator<<=(int)"); T* t = X + n; T* u = X; T* v = X + N; do { while (t < v) *u++ = *t++; while (u < v) *u++ = (T)0; t += L - N + n; u += L - N; } while ((v += L) <= &X[M*L]); return *this; } ////////////////////////// // Comparison of arrays // ////////////////////////// // less than tcT boolean Array::operator < (const T& b) const { if ( !X ) throw nullArray("boolean Array::operator<(const T&)"); T* u = X; T* v = X + N; do { while (u < v && *u < b) u++; if (u < v) return false; u += L - N; } while ((v += L) <= &X[M*L]); return true; } tcT /*inline*/ boolean operator < (const T& a, const Array& b) { return b > a; } tcT boolean Array::operator < (const Array& b) const { if ( !X || !b.X ) throw nullArray("boolean Array::operator<(const Array&)"); if (N == b.N) { if (M == b.M) { // N == b.N T* t = X; T* u = b.X; T* v = b.X + b.N; do { while (u < v && *t < *u) { t++; u++; }; if (u < v) return false; t += L - N; u += b.L - b.N; } while ((v += b.L) <= &b.X[b.M*b.L]); return true; }; if (M == 1) { // N == b.N && M != b.M T* u = b.X; T* v = b.X + b.N; do { T* t = X; while (u < v && *t < *u) { t++; u++; }; if (u < v) return false; u += b.L - b.N; } while ((v += b.L) <= &b.X[b.M*b.L]); return true; }; if (b.M == 1) { // N == b.N && M != b.M && M != 1 T* u = X; T* v = X + N; do { T* t = b.X; while (u < v && *u < *t) { t++; u++; }; if (u < v) return false; t += b.L - b.N; u += L - N; } while ((v += L) <= &X[M*L]); return true; }; }; if (N == 1) { // b.N != N if (M == b.M) { // b.N != N == 1 T* t = X; T* u = b.X; T* v = b.X + b.N; do { while (u < v && *t < *u) u++; if (u < v) return false; t++; u += b.L - b.N; } while ((v += b.L) <= &b.X[b.M*b.L]); return true; }; if (M == 1) { // b.N != N == 1 && M != b.M T* u = b.X; T* v = b.X + b.N; do { while (u < v && *X < *u) u++; if (u < v) return false; u += b.L - b.N; } while ((v += b.L) <= &b.X[b.M*b.L]); return true; }; }; if (b.N == 1) { // N != b.N && N != 1 if (M == b.M) { // N != b.N == 1 T* t = b.X; T* u = X; T* v = X + N; do { while (u < v && *u < *t) u++; if (u < v) return false; t++; u += L - N; } while ((v += L) <= &X[M*L]); return true; }; if (b.M == 1) { // N != b.N == 1 && M != b.M T* u = X; T* v = X + N; do { while (u < v && *u < *b.X) u++; if (u < v) return false; u += L - N; } while ((v += L) <= &X[M*L]); return true; }; }; throw whereDimMismatch( "boolean Array::operator<(const Array&)",M,N,b.M,b.N); } // less than or equal tcT boolean Array::operator <= (const T& b) const { if ( !X ) throw nullArray("boolean Array::operator<=(const T&)"); T* u = X; T* v = X + N; do { while (u < v && *u <= b) u++; if (u < v) return false; u += L - N; } while ((v += L) <= &X[M*L]); return true; } tcT /*inline*/ boolean operator <= (const T& a, const Array& b) { return b >= a; } tcT boolean Array::operator <= (const Array& b) const { if ( !X || !b.X ) throw nullArray("boolean Array::operator<=(const Array&)"); if (N == b.N) { if (M == b.M) { // N == b.N T* t = X; T* u = b.X; T* v = b.X + b.N; do { while (u < v && *t <= *u) { t++; u++; }; if (u < v) return false; t += L - N; u += b.L - b.N; } while ((v += b.L) <= &b.X[b.M*b.L]); return true; }; if (M == 1) { // N == b.N && M != b.M T* u = b.X; T* v = b.X + b.N; do { T* t = X; while (u < v && *t <= *u) { t++; u++; }; if (u < v) return false; u += b.L - b.N; } while ((v += b.L) <= &b.X[b.M*b.L]); return true; }; if (b.M == 1) { // N == b.N && M != b.M && M != 1 T* u = X; T* v = X + N; do { T* t = b.X; while (u < v && *u <= *t) { t++; u++; }; if (u < v) return false; t += b.L - b.N; u += L - N; } while ((v += L) <= &X[M*L]); return true; }; }; if (N == 1) { // b.N != N if (M == b.M) { // b.N != N == 1 T* t = X; T* u = b.X; T* v = b.X + b.N; do { while (u < v && *t <= *u) u++; if (u < v) return false; t++; u += b.L - b.N; } while ((v += b.L) <= &b.X[b.M*b.L]); return true; }; if (M == 1) { // b.N != N == 1 && M != b.M T* u = b.X; T* v = b.X + b.N; do { while (u < v && *X <= *u) u++; if (u < v) return false; u += b.L - b.N; } while ((v += b.L) <= &b.X[b.M*b.L]); return true; }; }; if (b.N == 1) { // N != b.N && N != 1 if (M == b.M) { // N != b.N == 1 T* t = b.X; T* u = X; T* v = X + N; do { while (u < v && *u <= *t) u++; if (u < v) return false; t++; u += L - N; } while ((v += L) <= &X[M*L]); return true; }; if (b.M == 1) { // N != b.N == 1 && M != b.M T* u = X; T* v = X + N; do { while (u < v && *u <= *b.X) u++; if (u < v) return false; u += L - N; } while ((v += L) <= &X[M*L]); return true; }; }; throw whereDimMismatch( "boolean Array::operator<=(const Array&)",M,N,b.M,b.N); } // greater than tcT boolean Array::operator > (const T& b) const { if ( !X ) throw nullArray("boolean Array::operator>(const T&)"); T* u = X; T* v = X + N; do { while (u < v && *u > b) u++; if (u < v) return false; u += L - N; } while ((v += L) <= &X[M*L]); return true; } tcT /*inline*/ boolean operator > (const T& a, const Array& b) { return b < a; } tcT boolean Array::operator > (const Array& b) const { if ( !X || !b.X ) throw nullArray("boolean Array::operator>(const Array&)"); if (N == b.N) { if (M == b.M) { // N == b.N T* t = X; T* u = b.X; T* v = b.X + b.N; do { while (u < v && *t > *u) { t++; u++; }; if (u < v) return false; t += L - N; u += b.L - b.N; } while ((v += b.L) <= &b.X[b.M*b.L]); return true; }; if (M == 1) { // N == b.N && M != b.M T* u = b.X; T* v = b.X + b.N; do { T* t = X; while (u < v && *t > *u) { t++; u++; }; if (u < v) return false; u += b.L - b.N; } while ((v += b.L) <= &b.X[b.M*b.L]); return true; }; if (b.M == 1) { // N == b.N && M != b.M && M != 1 T* u = X; T* v = X + N; do { T* t = b.X; while (u < v && *u > *t) { t++; u++; }; if (u < v) return false; t += b.L - b.N; u += L - N; } while ((v += L) <= &X[M*L]); return true; }; }; if (N == 1) { // b.N != N if (M == b.M) { // b.N != N == 1 T* t = X; T* u = b.X; T* v = b.X + b.N; do { while (u < v && *t > *u) u++; if (u < v) return false; t++; u += b.L - b.N; } while ((v += b.L) <= &b.X[b.M*b.L]); return true; }; if (M == 1) { // b.N != N == 1 && M != b.M T* u = b.X; T* v = b.X + b.N; do { while (u < v && *X > *u) u++; if (u < v) return false; u += b.L - b.N; } while ((v += b.L) <= &b.X[b.M*b.L]); return true; }; }; if (b.N == 1) { // N != b.N && N != 1 if (M == b.M) { // N != b.N == 1 T* t = b.X; T* u = X; T* v = X + N; do { while (u < v && *u > *t) u++; if (u < v) return false; t++; u += L - N; } while ((v += L) <= &X[M*L]); return true; }; if (b.M == 1) { // N != b.N == 1 && M != b.M T* u = X; T* v = X + N; do { while (u < v && *u > *b.X) u++; if (u < v) return false; u += L - N; } while ((v += L) <= &X[M*L]); return true; }; }; throw whereDimMismatch( "boolean Array::operator>(const Array&)",M,N,b.M,b.N); } // greater than or equal tcT boolean Array::operator >= (const T& b) const { if ( !X ) throw nullArray("boolean Array::operator>=(const T&)"); T* u = X; T* v = X + N; do { while (u < v && *u >= b) u++; if (u < v) return false; u += L - N; } while ((v += L) <= &X[M*L]); return true; } tcT /*inline*/ boolean operator >= (const T& a, const Array& b) { return b <= a; } tcT boolean Array::operator >= (const Array& b) const { if ( !X || !b.X ) throw nullArray("boolean Array::operator>=(const Array&)"); if (N == b.N) { if (M == b.M) { // N == b.N T* t = X; T* u = b.X; T* v = b.X + b.N; do { while (u < v && *t >= *u) { t++; u++; }; if (u < v) return false; t += L - N; u += b.L - b.N; } while ((v += b.L) <= &b.X[b.M*b.L]); return true; }; if (M == 1) { // N == b.N && M != b.M T* u = b.X; T* v = b.X + b.N; do { T* t = X; while (u < v && *t >= *u) { t++; u++; }; if (u < v) return false; u += b.L - b.N; } while ((v += b.L) <= &b.X[b.M*b.L]); return true; }; if (b.M == 1) { // N == b.N && M != b.M && M != 1 T* u = X; T* v = X + N; do { T* t = b.X; while (u < v && *u >= *t) { t++; u++; }; if (u < v) return false; t += b.L - b.N; u += L - N; } while ((v += L) <= &X[M*L]); return true; }; }; if (N == 1) { // b.N != N if (M == b.M) { // b.N != N == 1 T* t = X; T* u = b.X; T* v = b.X + b.N; do { while (u < v && *t >= *u) u++; if (u < v) return false; t++; u += b.L - b.N; } while ((v += b.L) <= &b.X[b.M*b.L]); return true; }; if (M == 1) { // b.N != N == 1 && M != b.M T* u = b.X; T* v = b.X + b.N; do { while (u < v && *X >= *u) u++; if (u < v) return false; u += b.L - b.N; } while ((v += b.L) <= &b.X[b.M*b.L]); return true; }; }; if (b.N == 1) { // N != b.N && N != 1 if (M == b.M) { // N != b.N == 1 T* t = b.X; T* u = X; T* v = X + N; do { while (u < v && *u >= *t) u++; if (u < v) return false; t++; u += L - N; } while ((v += L) <= &X[M*L]); return true; }; if (b.M == 1) { // N != b.N == 1 && M != b.M T* u = X; T* v = X + N; do { while (u < v && *u >= *b.X) u++; if (u < v) return false; u += L - N; } while ((v += L) <= &X[M*L]); return true; }; }; throw whereDimMismatch( "boolean Array::operator>=(const Array&)",M,N,b.M,b.N); } // equal tcT boolean Array::operator == (const T& b) const { if ( !X ) throw nullArray("boolean Array::operator==(const T&)"); T* u = X; T* v = X + N; do { while (u < v && *u == b) u++; if (u < v) return false; u += L - N; } while ((v += L) <= &X[M*L]); return true; } tcT /*inline*/ boolean operator == (const T& a, const Array& b) { return (b == a); } tcT boolean Array::operator == (const Array& b) const { if ( !X || !b.X ) throw nullArray("boolean Array::operator==(const Array&)"); if (N == b.N) { if (M == b.M) { // N == b.N T* t = X; T* u = b.X; T* v = b.X + b.N; do { while (u < v && *t == *u) { t++; u++; }; if (u < v) return false; t += L - N; u += b.L - b.N; } while ((v += b.L) <= &b.X[b.M*b.L]); return true; }; if (M == 1) { // N == b.N && M != b.M T* u = b.X; T* v = b.X + b.N; do { T* t = X; while (u < v && *t == *u) { t++; u++; }; if (u < v) return false; u += b.L - b.N; } while ((v += b.L) <= &b.X[b.M*b.L]); return true; }; if (b.M == 1) { // N == b.N && M != b.M && M != 1 T* u = X; T* v = X + N; do { T* t = b.X; while (u < v && *u == *t) { t++; u++; }; if (u < v) return false; t += b.L - b.N; u += L - N; } while ((v += L) <= &X[M*L]); return true; }; }; if (N == 1) { // b.N != N if (M == b.M) { // b.N != N == 1 T* t = X; T* u = b.X; T* v = b.X + b.N; do { while (u < v && *t == *u) u++; if (u < v) return false; t++; u += b.L - b.N; } while ((v += b.L) <= &b.X[b.M*b.L]); return true; }; if (M == 1) { // b.N != N == 1 && M != b.M T* u = b.X; T* v = b.X + b.N; do { while (u < v && *X == *u) u++; if (u < v) return false; u += b.L - b.N; } while ((v += b.L) <= &b.X[b.M*b.L]); return true; }; }; if (b.N == 1) { // N != b.N && N != 1 if (M == b.M) { // N != b.N == 1 T* t = b.X; T* u = X; T* v = X + N; do { while (u < v && *u == *t) u++; if (u < v) return false; t++; u += L - N; } while ((v += L) <= &X[M*L]); return true; }; if (b.M == 1) { // N != b.N == 1 && M != b.M T* u = X; T* v = X + N; do { while (u < v && *u == *b.X) u++; if (u < v) return false; u += L - N; } while ((v += L) <= &X[M*L]); return true; }; }; throw whereDimMismatch( "boolean Array::operator==(const Array&)",M,N,b.M,b.N); } // not equal tcT /*inline*/ boolean Array::operator != (const T& b) const { return !(*this == b); } tcT /*inline*/ boolean operator != (const T& a, const Array& b) { return !(b == a); } tcT /*inline*/ boolean Array::operator != (const Array& b) const { return !(*this == b); } /////////////////// // I/O of arrays // /////////////////// //#ifndef _array_output_vars //#define _array_output_vars /*extern*/ int Array_number = 40; /*extern*/ int Array_coefWidth = 6; /*extern*/ int Array_coefPrecision = -1; /*extern*/ boolean Array_charAsChar = false; /*extern*/ boolean Array_longLines = false; //#endif // output tcT ostream& operator << (ostream& s, const Array& b) { if ( !b.X ) throw nullArray( "ostream& operator<<(ostream& s, const Array&)"); T* t = b.X; T* u = b.X; T* v = b.X + b.N; if ( sizeof(T)==1 && !Array_charAsChar ) // T is a char { do { do { t += (0 < Array_number)? Array_number: b.N; t = (t < v)? t: v; while (u < t) if (!(s << coefWidth(Array_coefWidth) << int(*u) && ((++u < t) ? s << "" : s << "\n"))) return s; } while (t < v); t = u += b.L - b.N; } while ((v += b.L) <= &b.X[b.M*b.L]); } else { do { do { t += (0 < Array_number)? Array_number: b.N; t = (t < v)? t: v; while (u < t) { if ( Array_coefPrecision>=0 || *u!=int(*u) ) s << setw(Array_coefWidth) << *u; else s << setw(Array_coefWidth-1+Array_coefPrecision) << int(*u) << setw(-Array_coefPrecision+1) << setfill(' ') << ""; if ( !( s && ((++u < t) ? s << "" : s << "\n"))) return s; } } while (t < v); t = u += b.L - b.N; } while ((v += b.L) <= &b.X[b.M*b.L]); } return s; } // output manipulators ostream& coefWidth(ostream& s, int w) { Array_coefWidth = w; s.width (Array_coefWidth); return s; } OMANIP (int) coefWidth(int w) { return OMANIP (int) (coefWidth, w); } ostream& coefPrecision(ostream& s, int p) { Array_coefPrecision = p; s.unsetf(ios::scientific); s.setf(ios::fixed); if ( p ) s.setf(ios::showpoint); else s.unsetf(ios::showpoint); s.precision(p); return s; } OMANIP (int) coefPrecision(int p) { return OMANIP (int) (coefPrecision, p); } ostream& charAsCharacter (ostream& s) { Array_charAsChar=true; return s; } ostream& charAsNumber (ostream& s) { Array_charAsChar=false; return s; } ostream& coefPerLine (ostream& s, int nbC) { Array_number=nbC; return s; } OMANIP (int) coefPerLine(int nbC) { return OMANIP (int) (coefPerLine, nbC); } // input tcT istream& operator >> (istream& s, const Array& b) { if ( !b.X ) throw nullArray( "istream& operator>>(istream& s, const Array&)"); T* u = b.X; T* v = b.X + b.N; if ( sizeof(T) == 1 && !Array_charAsChar ) // T is a char { int r; do { while (u < v && s >> r) { *u = (T)r; u++; } if (u < v) return s; u += b.L - b.N; } while ((v += b.L) <= &b.X[b.M*b.L]); } else if ( sizeof(T) == 1 && Array_charAsChar ) // T is a char { char r; do { while (u < v && s.get(r)) if (r>31) {*u = r; u++;} if (u < v) return s; u += b.L - b.N; } while ((v += b.L) <= &b.X[b.M*b.L]); } else { do { while (u < v && s >> *u) u++; if (u < v) return s; u += b.L - b.N; } while ((v += b.L) <= &b.X[b.M*b.L]); } return s; } istream& charAsCharacter (istream& s) { Array_charAsChar=true; return s; } istream& charAsNumber (istream& s) { Array_charAsChar=false; return s; } ///////////////////////// // Operators on Arrays // ///////////////////////// // unary plus tcT /*inline*/ Matrix Array::operator + () const { return Matrix(*this); } // unary minus tcT Matrix Array::operator - () const { if ( !X ) throw nullArray("Matrix Array::operator-() const"); T* newX = new T [M*N]; T* t = newX; T* u = X; T* v = X; do while (u < v + N) *t++ = -(*u++); while ((u = v += L) < &X[M*L]); return Matrix(Array(M, N, newX)); } // add (plus) tcT Matrix Array::operator + (const T& b) const { if ( !X ) throw nullArray("Matrix Array::operator+(const T&) const"); T* newx = new T [M*N]; T* t = newx; T* u = X; T* v = X + N; do { while (u < v) *t++ = *u++ + b; u += L - N; } while ((v += L) <= &X[M*L]); return Matrix(Array(M, N, newx)); } tcT Matrix operator + (const T& a, const Array& b) { if ( !b.X ) throw nullArray("Matrix operator+(const T&, const Array&)"); T* newx = new T [b.M*b.N]; T* t = newx; T* u = b.X; T* v = b.X + b.N; do { while (u < v) *t++ = a + *u++; u += b.L - b.N; } while ((v += b.L) <= &b.X[b.M*b.L]); return Matrix(Array(b.M, b.N, newx)); } tcT Matrix Array::operator + (const Array& b) const { if ( !X || !b.X ) throw nullArray("Matrix Array::operator+(const Array&) const"); if (N == b.N) { if (M == b.M) { // N == b.N T* newx = new T [b.M*b.N]; T* s = newx; T* t = newx; T* u = X; T* v = b.X; while ((t += b.N) <= &newx[b.M*b.N]) { while (s < t) *s++ = *u++ + *v++; u += L - N; v += b.L - b.N; }; return Matrix(Array(b.M, b.N, newx)); }; if (M == 1) { // N == b.N && M != b.M T* newx = new T [b.M*b.N]; T* s = newx; T* t = newx; T* v = b.X; while ((t += b.N) <= &newx[b.M*b.N]) { T* u = X; while (s < t) *s++ = *u++ + *v++; v += b.L - b.N; }; return Matrix(Array(b.M, b.N, newx)); }; if (b.M == 1) { // N == b.N && M != b.M && M != 1 T* newx = new T [M*N]; T* s = newx; T* t = newx; T* u = X; while ((t += N) <= &newx[M*N]) { T* v = b.X; while (s < t) *s++ = *u++ + *v++; u += L - N; }; return Matrix(Array(M, N, newx)); }; }; if (N == 1) { // b.N != N if (M == b.M) { // b.N != N == 1 T* newx = new T [b.M*b.N]; T* s = newx; T* t = newx; T* u = X; T* v = b.X; while ((t += b.N) <= &newx[b.M*b.N]) { while (s < t) *s++ = *u + *v++; u++; v += b.L - b.N; }; return Matrix(Array(b.M, b.N, newx)); }; if (M == 1) { // b.N != N == 1 && M != b.M T* newx = new T [b.M*b.N]; T* s = newx; T* t = newx; T* u = X; T* v = b.X; while ((t += b.N) <= &newx[b.M*b.N]) { while (s < t) *s++ = *u + *v++; v += b.L - b.N; }; return Matrix(Array(b.M, b.N, newx)); }; }; if (b.N == 1) { // N != b.N && N != 1 if (M == b.M) { // N != b.N == 1 T* newx = new T [M*N]; T* s = newx; T* t = newx; T* u = X; T* v = b.X; while ((t += N) <= &newx[M*N]) { while (s < t) *s++ = *u++ + *v; u += L - N; v++; }; return Matrix(Array(M, N, newx)); }; if (b.M == 1) { // N != b.N == 1 && M != b.M T* newx = new T [M*N]; T* s = newx; T* t = newx; T* u = X; T* v = b.X; while ((t += N) <= &newx[M*N]) { while (s < t) *s++ = *u++ + *v; u += L - N; }; return Matrix(Array(M, N, newx)); }; }; throw whereDimMismatch( "Matrix Array::operator+(const Array&) const", M,N,b.M,b.N); } // subtract (minus) tcT Matrix Array::operator - (const T& b) const { if ( !X ) throw nullArray("Matrix Array::operator-(const T&) const"); T* newx = new T [M*N]; T* t = newx; T* u = X; T* v = X + N; do { while (u < v) *t++ = *u++ - b; u += L - N; } while ((v += L) <= &X[M*L]); return Matrix(Array(M, N, newx)); } tcT Matrix operator - (const T& a, const Array& b) { if ( !b.X ) throw nullArray("Matrix operator-(const T&, const Array&)"); T* newx = new T [b.M*b.N]; T* t = newx; T* u = b.X; T* v = b.X + b.N; do { while (u < v) *t++ = a - *u++; u += b.L - b.N; } while ((v += b.L) <= &b.X[b.M*b.L]); return Matrix(Array(b.M, b.N, newx)); } tcT Matrix Array::operator - (const Array& b) const { if ( !X || !b.X ) throw nullArray("Matrix Array::operator-(const Array&) const"); if (N == b.N) { if (M == b.M) { // N == b.N T* newx = new T [b.M*b.N]; T* s = newx; T* t = newx; T* u = X; T* v = b.X; while ((t += b.N) <= &newx[b.M*b.N]) { while (s < t) *s++ = *u++ - *v++; u += L - N; v += b.L - b.N; }; return Matrix(Array(b.M, b.N, newx)); }; if (M == 1) { // N == b.N && M != b.M T* newx = new T [b.M*b.N]; T* s = newx; T* t = newx; T* v = b.X; while ((t += b.N) <= &newx[b.M*b.N]) { T* u = X; while (s < t) *s++ = *u++ - *v++; v += b.L - b.N; }; return Matrix(Array(b.M, b.N, newx)); }; if (b.M == 1) { // N == b.N && M != b.M && M != 1 T* newx = new T [M*N]; T* s = newx; T* t = newx; T* u = X; while ((t += N) <= &newx[M*N]) { T* v = b.X; while (s < t) *s++ = *u++ - *v++; u += L - N; }; return Matrix(Array(M, N, newx)); }; }; if (N == 1) { // b.N != N if (M == b.M) { // b.N != N == 1 T* newx = new T [b.M*b.N]; T* s = newx; T* t = newx; T* u = X; T* v = b.X; while ((t += b.N) <= &newx[b.M*b.N]) { while (s < t) *s++ = *u - *v++; u++; v += b.L - b.N; }; return Matrix(Array(b.M, b.N, newx)); }; if (M == 1) { // b.N != N == 1 && M != b.M T* newx = new T [b.M*b.N]; T* s = newx; T* t = newx; T* u = X; T* v = b.X; while ((t += b.N) <= &newx[b.M*b.N]) { while (s < t) *s++ = *u - *v++; v += b.L - b.N; }; return Matrix(Array(b.M, b.N, newx)); }; }; if (b.N == 1) { // N != b.N && N != 1 if (M == b.M) { // N != b.N == 1 T* newx = new T [M*N]; T* s = newx; T* t = newx; T* u = X; T* v = b.X; while ((t += N) <= &newx[M*N]) { while (s < t) *s++ = *u++ - *v; u += L - N; v++; }; return Matrix(Array(M, N, newx)); }; if (b.M == 1) { // N != b.N == 1 && M != b.M T* newx = new T [M*N]; T* s = newx; T* t = newx; T* u = X; T* v = b.X; while ((t += N) <= &newx[M*N]) { while (s < t) *s++ = *u++ - *v; u += L - N; }; return Matrix(Array(M, N, newx)); }; }; throw whereDimMismatch( "Matrix Array::operator-(const Array&) const", M,N,b.M,b.N); } // multiply tcT Matrix Array::operator * (const T& b) const { if ( !X ) throw nullArray("Matrix Array::operator*(const T&) const"); T* newx = new T [M*N]; T* t = newx; T* u = X; T* v = X + N; do { while (u < v) *t++ = *u++ * b; u += L - N; } while ((v += L) <= &X[M*L]); return Matrix(Array(M, N, newx)); } tcT Matrix operator * (const T& a, const Array& b) { if ( !b.X ) throw nullArray("Matrix operator*(const T&, const Array&)"); T* newx = new T [b.M*b.N]; T* t = newx; T* u = b.X; T* v = b.X + b.N; do { while (u < v) *t++ = a * *u++; u += b.L - b.N; } while ((v += b.L) <= &b.X[b.M*b.L]); return Matrix(Array(b.M, b.N, newx)); } tcT Matrix Array::operator * (const Array& b) const { if ( !X || !b.X ) throw nullArray("Matrix Array::operator*(const Array&) const"); if (N == b.N) { if (M == b.M) { // N == b.N T* newx = new T [b.M*b.N]; T* s = newx; T* t = newx; T* u = X; T* v = b.X; while ((t += b.N) <= &newx[b.M*b.N]) { while (s < t) *s++ = *u++ * *v++; u += L - N; v += b.L - b.N; }; return Matrix(Array(b.M, b.N, newx)); }; if (M == 1) { // N == b.N && M != b.M T* newx = new T [b.M*b.N]; T* s = newx; T* t = newx; T* v = b.X; while ((t += b.N) <= &newx[b.M*b.N]) { T* u = X; while (s < t) *s++ = *u++ * *v++; v += b.L - b.N; }; return Matrix(Array(b.M, b.N, newx)); }; if (b.M == 1) { // N == b.N && M != b.M && M != 1 T* newx = new T [M*N]; T* s = newx; T* t = newx; T* u = X; while ((t += N) <= &newx[M*N]) { T* v = b.X; while (s < t) *s++ = *u++ * *v++; u += L - N; }; return Matrix(Array(M, N, newx)); }; }; if (N == 1) { // b.N != N if (M == b.M) { // b.N != N == 1 T* newx = new T [b.M*b.N]; T* s = newx; T* t = newx; T* u = X; T* v = b.X; while ((t += b.N) <= &newx[b.M*b.N]) { while (s < t) *s++ = *u * *v++; u++; v += b.L - b.N; }; return Matrix(Array(b.M, b.N, newx)); }; if (M == 1) { // b.N != N == 1 && M != b.M T* newx = new T [b.M*b.N]; T* s = newx; T* t = newx; T* u = X; T* v = b.X; while ((t += b.N) <= &newx[b.M*b.N]) { while (s < t) *s++ = *u * *v++; v += b.L - b.N; }; return Matrix(Array(b.M, b.N, newx)); }; }; if (b.N == 1) { // N != b.N && N != 1 if (M == b.M) { // N != b.N == 1 T* newx = new T [M*N]; T* s = newx; T* t = newx; T* u = X; T* v = b.X; while ((t += N) <= &newx[M*N]) { while (s < t) *s++ = *u++ * *v; u += L - N; v++; }; return Matrix(Array(M, N, newx)); }; if (b.M == 1) { // N != b.N == 1 && M != b.M T* newx = new T [M*N]; T* s = newx; T* t = newx; T* u = X; T* v = b.X; while ((t += N) <= &newx[M*N]) { while (s < t) *s++ = *u++ * *v; u += L - N; }; return Matrix(Array(M, N, newx)); }; }; throw whereDimMismatch( "Matrix Array::operator*(const Array&) const", M,N,b.M,b.N); } // divide tcT Matrix Array::operator / (const T& b) const { if ( !X ) throw nullArray("Matrix Array::operator/(const T&) const"); T* newx = new T [M*N]; T* t = newx; T* u = X; T* v = X + N; do { while (u < v) *t++ = *u++ / b; u += L - N; } while ((v += L) <= &X[M*L]); return Matrix(Array(M, N, newx)); } tcT Matrix operator / (const T& a, const Array& b) { if ( !b.X ) throw nullArray("Matrix operator/(const T&, const Array&)"); T* newx = new T [b.M*b.N]; T* t = newx; T* u = b.X; T* v = b.X + b.N; do { while (u < v) *t++ = a / *u++; u += b.L - b.N; } while ((v += b.L) <= &b.X[b.M*b.L]); return Matrix(Array(b.M, b.N, newx)); } tcT Matrix Array::operator / (const Array& b) const { if ( !X || !b.X ) throw nullArray("Matrix Array::operator/(const Array&) const"); if (N == b.N) { if (M == b.M) { // N == b.N T* newx = new T [b.M*b.N]; T* s = newx; T* t = newx; T* u = X; T* v = b.X; while ((t += b.N) <= &newx[b.M*b.N]) { while (s < t) *s++ = *u++ / *v++; u += L - N; v += b.L - b.N; }; return Matrix(Array(b.M, b.N, newx)); }; if (M == 1) { // N == b.N && M != b.M T* newx = new T [b.M*b.N]; T* s = newx; T* t = newx; T* v = b.X; while ((t += b.N) <= &newx[b.M*b.N]) { T* u = X; while (s < t) *s++ = *u++ / *v++; v += b.L - b.N; }; return Matrix(Array(b.M, b.N, newx)); }; if (b.M == 1) { // N == b.N && M != b.M && M != 1 T* newx = new T [M*N]; T* s = newx; T* t = newx; T* u = X; while ((t += N) <= &newx[M*N]) { T* v = b.X; while (s < t) *s++ = *u++ / *v++; u += L - N; }; return Matrix(Array(M, N, newx)); }; }; if (N == 1) { // b.N != N if (M == b.M) { // b.N != N == 1 T* newx = new T [b.M*b.N]; T* s = newx; T* t = newx; T* u = X; T* v = b.X; while ((t += b.N) <= &newx[b.M*b.N]) { while (s < t) *s++ = *u / *v++; u++; v += b.L - b.N; }; return Matrix(Array(b.M, b.N, newx)); }; if (M == 1) { // b.N != N == 1 && M != b.M T* newx = new T [b.M*b.N]; T* s = newx; T* t = newx; T* u = X; T* v = b.X; while ((t += b.N) <= &newx[b.M*b.N]) { while (s < t) *s++ = *u / *v++; v += b.L - b.N; }; return Matrix(Array(b.M, b.N, newx)); }; }; if (b.N == 1) { // N != b.N && N != 1 if (M == b.M) { // N != b.N == 1 T* newx = new T [M*N]; T* s = newx; T* t = newx; T* u = X; T* v = b.X; while ((t += N) <= &newx[M*N]) { while (s < t) *s++ = *u++ / *v; u += L - N; v++; }; return Matrix(Array(M, N, newx)); }; if (b.M == 1) { // N != b.N == 1 && M != b.M T* newx = new T [M*N]; T* s = newx; T* t = newx; T* u = X; T* v = b.X; while ((t += N) <= &newx[M*N]) { while (s < t) *s++ = *u++ / *v; u += L - N; }; return Matrix(Array(M, N, newx)); }; }; throw whereDimMismatch( "Matrix Array::operator/(const Array&) const", M,N,b.M,b.N); } // Matrix multiplication(inner product) tcT Matrix Array::operator % (const Array& b) const { if ( !X || !b.X ) throw nullArray("Matrix Array::operator%(const Array&) const"); if (N != b.N) throw whereDimMismatch( "Matrix Array::operator%(const Array&) const", M,N,b.M,b.N); T* newx = new T [M*b.M]; T* s = newx; T* t = X; T* u; T* v; do { v = b.X; while (v < &b.X[b.M*b.L]) { u = t; *s = *u++ * *v++; while (u < t + N) *s += *u++ * *v++; ++s; v += b.L - b.N; }; } while((t += L) < &X[M*L]); return Matrix(Array(M, b.M, newx)); } // Matrix multiplication (outer product) tcT Matrix Array::operator & (const Array& b) const { if ( !X || !b.X ) throw nullArray("Matrix Array::operator&(const Array&) const"); if (M != b.M) throw whereDimMismatch( "Matrix Array::operator&(const Array&) const", M,N,b.M,b.N); T* newx = new T [N*b.N]; T* p = newx; T* s = X; T* t; T* u; T* v; do { t = b.X; do { u = s; v = t; *p = *u * *v; while ((u += L), (v += b.L) < &b.X[b.M*b.L]) *p += *u * *v; p++; } while (++t < &b.X[b.N]); } while (++s < &X[N]); return Matrix(Array(N, b.N, newx)); } // shift left tcT Matrix Array::operator << (int n) const { if ( !X ) throw nullArray("Matrix Array::operator<<(int) const"); T* newx = new T [M*this->N]; T* t = X + n; T* u = newx; T* v = newx; while ((v += this->N) <= &newx[M*this->N]) { while (u < v - n) *u++ = *t++; while (u < v) *u++ = (T)0; t += L - this->N + n; }; return Matrix(Array(M, this->N, newx)); } // shift right tcT Matrix Array::operator >> (int n) const { if ( !X ) throw nullArray("Matrix Array::operator>>(int) const"); T* newx = new T [M*this->N]; T* t = &X[M*L]; T* u = &newx[M*this->N]; T* v = &newx[M*this->N]; while (newx <= (u -= this->N)) { t -= L - this->N + n; while (v > u + n) *--v = *--t; while (v > u) *--v = *t; }; return Matrix(Array(M, this->N, newx)); } // stack tcT Matrix Array::operator ^ (const Array& b) const { if ( !X || !b.X) throw nullArray("Matrix Array::operator^(const Array&) const"); if (N != b.N) throw whereDimMismatch( "Matrix Array::operator^(const Array&) const", M,N,b.M,b.N); T* newx = new T [(M+b.M)*N]; T* t = newx; T* u = X; T* v = X + N; do { while (u < v) *t++ = *u++; u += L - N; } while((v += L) <= &X[M*L]); u = b.X; v = b.X + b.N; do { while (u < v) *t++ = *u++; u += b.L - b.N; } while((v += b.L) <= &b.X[b.M*b.L]); return Matrix(Array(M+b.M, N, newx)); } // adjoin tcT Matrix Array::operator | (const Array& b) const { if ( !X || !b.X) throw nullArray("Matrix Array::operator|(const Array&) const"); if (M != b.M) throw whereDimMismatch( "Matrix Array::operator|(const Array&) const", M,N,b.M,b.N); T* newx = new T [M*(N+b.N)]; T* t = newx; T* u = X; T* v = X + N; do { while (u < v) *t++ = *u++; t += b.N; u += L - N; } while((v += L) <= &X[M*L]); t = newx + N; u = b.X; v = b.X + b.N; do { while (u < v) *t++ = *u++; u += b.L - b.N; t += N; } while((v += b.L) <= &b.X[b.M*b.L]); return Matrix(Array(M, N+b.N, newx)); } // map (return a Matrix given by mapping f to X) tcT Matrix Array::map(T (*f)(T)) const { if ( !X ) throw nullArray("Matrix Array::map(const T (*f)(T))const"); T* newX = new T [M*N]; T* t = newX; T* u = X; T* v = X + N; do { while (u < v) *t++ = f(*u++); u += L - N; } while ((v += L) <= &X[M*L]); return Matrix(Array(M, N, newX)); } // statistical tools tcT Matrix Array::sum() const { if ( !X ) throw nullArray("Matrix Array::sum() const"); T* newX = new T [M]; T* t = newX; T* u = X; T* v = X + N; do { *t = *u; while (++u < v) *t += *u; t++; u += L - N; } while ((v += L) <= &X[M*L]); return Matrix(Array(1, M, newX)); } tcT Matrix Array::sumC() const { if ( !X ) throw nullArray("Matrix Array::sum() const"); T* newX = new T [N]; T* u = X; T* v = X + N; T* t = newX; while (u < v) { *t = *u; t++; u++; } while ((v += L) <= &X[M*L]) { u += L-N; t = newX; while (u < v) { *t += *u; t++; u++; } } return Matrix(Array(1, N, newX)); } tcT Matrix Array::sumsq() const { if ( !X ) throw nullArray("Matrix Array::sumsq() const"); T* newX = new T [M]; T* t = newX; T* u = X; T* v = X + N; do { *t = *u * *u; while (++u < v) *t += *u * *u; t++; u += L - N; } while ((v += L) <= &X[M*L]); return Matrix(Array(1, M, newX)); } tcT Matrix Array::sumsqC() const { if ( !X ) throw nullArray("Matrix Array::sum() const"); T* newX = new T [N]; T* u = X; T* v = X + N; T* t = newX; while (u < v) { *t = *u * *u; t++; u++; } while ((v += L) <= &X[M*L]) { u += L-N; t = newX; while (u < v) { *t += *u * *u; t++; u++; } } return Matrix(Array(1, N, newX)); } tcT Matrix Array::sumabs() const { if ( !X ) throw nullArray("Matrix Array::sumsq() const"); T* newX = new T [M]; T* t = newX; T* u = X; T* v = X + N; do { *t = (*u > T(0) ? *u : -*u); while (++u < v) *t += (*u > T(0) ? *u : -*u); t++; u += L - N; } while ((v += L) <= &X[M*L]); return Matrix(Array(1, M, newX)); } tcT Matrix Array::sumabsC() const { if ( !X ) throw nullArray("Matrix Array::sum() const"); T* newX = new T [N]; T* u = X; T* v = X + N; T* t = newX; while (u < v) { *t = (*u > T(0) ? *u : -*u); t++; u++; } while ((v += L) <= &X[M*L]) { u += L-N; t = newX; while (u < v) { *t += (*u > T(0) ? *u : -*u); t++; u++; } } return Matrix(Array(1, N, newX)); } tcT Matrix Array::min() const { if ( !X ) throw nullArray("Matrix Array::min() const"); T* newX = new T [M]; T* t = newX; T* u = X; T* v = X + N; do { *t = *u; while (++u < v) if (*t > *u) *t = *u; t++; u += L - N; } while ((v += L) <= &X[M*L]); return Matrix(Array(1, M, newX)); } tcT Matrix Array::minC() const { if ( !X ) throw nullArray("Matrix Array::sum() const"); T* newX = new T [N]; T* u = X; T* v = X + N; T* t = newX; while (u < v) { *t = *u; t++; u++; } while ((v += L) <= &X[M*L]) { u += L-N; t = newX; while (u < v) { if (*t > *u) *t = *u; t++; u++; } } return Matrix(Array(1, N, newX)); } tcT Matrix Array::max() const { if ( !X ) throw nullArray("Matrix Array::max() const"); T* newX = new T [M]; T* t = newX; T* u = X; T* v = X + N; do { *t = *u; while (++u < v) if (*t < *u) *t = *u; t++; u += L - N; } while ((v += L) <= &X[M*L]); return Matrix(Array(1, M, newX)); } tcT Matrix Array::maxC() const { if ( !X ) throw nullArray("Matrix Array::sum() const"); T* newX = new T [N]; T* u = X; T* v = X + N; T* t = newX; while (u < v) { *t = *u; t++; u++; } while ((v += L) <= &X[M*L]) { u += L-N; t = newX; while (u < v) { if (*t < *u) *t = *u; t++; u++; } } return Matrix(Array(1, N, newX)); } // algebraic tools tcT Matrix Array::t() const { if ( !X ) throw nullArray("Matrix Array::t() const"); T* newX = new T [N*M]; T* t = newX; T* u; T* v = X; do { u = v; do *t++ = *u; while ((u += L) < &X[M*L]); } while (++v < &X[N]); return Matrix(Array(N, M, newX)); } tcT Array& Array::ta() { if ( !X ) throw nullArray("Array& Array::ta()"); if ( M==1 ) { L=1; M=N; N=1; return *this; } else if ( L==1 && N==1 ) { L=M; N=M; M=1; return *this; } Matrix transpose(t()); L = floor(float(M*L)/float(N)); int temp=M; M=N; N=temp; *this = transpose; return *this; } /*tcT Matrix Array::i(T epsilon) const { if ( !X ) throw nullArray("Matrix Array::i() const"); T* a = new T [N*M]; T* uu = new T [M*N]; T* vv = new T [N*N]; T* w = new T [N]; T** u = new T* [M]; T** v = new T* [N]; void svdcmp(T**, int, int, T*, T**); for (int i = 0; i < M; i++) u[i] = &(uu[N*i]); for (int j = 0; j < N; j++) v[j] = &(vv[N*j]); for (i = 0; i < M; i++) for (j = 0; j < N; j++) u[i][j] = X[i*L+j]; svdcmp(u, M, N, w, v); // Singular value decomposition. T wmax = 0.0; // Maximum singular value. for (j = 0; j < N; j++) if (w[j] > wmax) wmax = w[j]; T wmin = wmax*epsilon; for (int k = 0; k < N; k++) if (w[k] < wmin) w[k] = 0.0; else w[k] = 1.0/w[k]; for (i = 0; i < N; i++) for (j = 0; j < M; j++) { a[M*i+j] = 0.0; for (k = 0; k < N; k++) a[M*i+j] += v[i][k]*w[k]*u[j][k]; }; delete [] w; delete [] u; delete [] v; delete [] uu; delete [] vv; return Matrix(Array(N, M, a)); }*/ // element search in arrays tcT int Array::min_index() const { if ( !X ) throw nullArray("boolean Array::min_index() const"); T* t = X; T* u = X; T* v = X + N; do { do if (*t > *u) t = u; while (++u < v); u += L - N; } while ((v += L) <= &X[M*L]); return (t - X); } tcT int Array::max_index() const { if ( !X ) throw nullArray("boolean Array::max_index() const"); T* t = X; T* u = X; T* v = X + N; do { do if (*t < *u) t = u; while (++u < v); u += L - N; } while ((v += L) <= &X[M*L]); return (t - X); } tcT void fusSort (Array& a, int from, int to) { const int size = to-from+1; switch (size) { case 1: break; case 2: if ( a(from) > a(to) ) { T temp = a(from); a(from) = a(to); a(to) = temp; } break; default: int mid = (from + to)/2; ::fusSort(a,from,mid); ::fusSort(a,mid+1,to); int left = from; int right = mid+1; Matrix temp(size); for (int write = 0; write < size; write++) if ( right > to || ( left <= mid && a(left) < a(right) ) ) temp(write) = a(left++); else temp(write) = a(right++); a.s(0,1,from,size) = temp; } } tcT void Array::fusSortRow (Array& ind, int from, int to) { Array& a = *this; const int size = to-from+1; if ( size > 1 ) { int mid = (from + to)/2; fusSortRow(/*a,*/ind,from,mid); fusSortRow(/*a,*/ind,mid+1,to); int left = from; int right = mid+1; Matrix temp(size); for (int write = 0; write < size; write++) if ( right > to ) temp(write) = ind(left++); else if ( left > mid ) temp(write) = ind(right++); else // ( right<=to && left<=mid ) { for (int i = 0; i < a.n(); i++) if ( a(ind(left),i) < a(ind(right),i) ) { temp(write) = ind(left++); break; } else if ( a(ind(left),i) > a(ind(right),i) ) { temp(write) = ind(right++); break; } if ( i >= a.n() ) temp(write) = ind(left++); } ind.s(0,1,from,size) = temp; } } tcT Array& Array::sort() { if ( !M || !N ) return *this; if ( !X ) throw nullArray("Array& Array::sort()"); if ( M == 1 ) ::fusSort(*this,0,N-1); else { Matrix ind(M); for (int i=0; i used(M); for (i=0; i temp(N); while ( head < M && used(head) ) head++; while ( head < M ) { temp = s(head); hand = head; used(head) = 1; do { s(hand) = s(ind(hand)); hand = ind(hand); used(hand) = 1; } while ( ind(hand) != head ); s(hand) = temp; while ( ++head < M && used(head) ) {} } } return *this; } tcT void Array::fusSort (Array& index, int from, int to, boolean move) { Array& a = *this; const int size = to-from+1; switch (size) { case 1: break; case 2: if ( a(index(from)) > a(index(to)) ) if ( move ) { T temp = a(index(from)); a(index(from)) = a(index(to)); a(index(to)) = temp; } else { int temp = index(from); index(from) = index(to); index(to) = temp; } break; default: int mid = (from + to)/2; fusSort(/*a,*/index,from,mid,move); fusSort(/*a,*/index,mid+1,to,move); int left = from; int right = mid+1; if ( move ) { Matrix temp(size); for (int write = 0; write < size; write++) if ( right > to || ( left <= mid && a(index(left)) < a(index(right)) ) ) temp(write) = a(index(left++)); else temp(write) = a(index(right++)); for (write = 0; write < size; write++) a(index(from+write)) = temp(write); } else { Matrix temp(size); for (int write = 0; write < size; write++) if ( right > to || ( left <= mid && a(index(left)) < a(index(right)) ) ) temp(write) = index(left++); else temp(write) = index(right++); for (write=0; write& Array::sort(Matrix& index, boolean move/**=false**/) { if ( !M || !N ) return *this; if ( !X ) throw nullArray("Array& Array::sort(Matrix,boolean=false)"); // ?? Array& IndexArray = index; int nbIndices = index.n(); if ( M == 1 ) fusSort(/**this,*/IndexArray,0,nbIndices-1,move); else { Matrix ind(index); fusSortRow(/**this,*/IndexArray,0,nbIndices-1); if ( move ) { Matrix used(nbIndices); for (int i=0; i temp(N); while ( head < nbIndices && used(head) ) head++; int hand; while ( head < nbIndices ) { temp = s(ind(head)); hand = head; used(head) = 1; do { s(ind(hand)) = s(index(hand)); hand = xedni[index(hand)]; used(hand) = 1; } while ( xedni[index(hand)] != head ); s(ind(hand)) = temp; while ( ++head < nbIndices && used(head) ); } } } return *this; } // cast (type conversion) tcT /*inline*/ Array::operator T () const { if ( !X ) throw nullArray("Array::operator T () const"); return X[0]; } //tcT /*inline*/ Array::operator T* () const //{ return X; //} ////////////////////////////////////////////////////////////////////////////// /////////////////////////// // Matrices constructors // /////////////////////////// tcT /*inline*/ Matrix::Matrix(int m, int n, T* d) : Array(m, n, d) { if ( !this->m() || !this->n() ) Array::resize(m, n, d); } tcT Matrix::Matrix(int m, int n, const T a) : Array(m, n, new T [m*n]) { if ( !x() ) Array::resize(m, n, new T [m*n]); T* t = x(); while (t < &(x()[m*n])) *t++ = a; } tcT /*inline*/ Matrix::Matrix(int m, int n) : Array(m, n, new T [m*n]) { if ( !x() ) Array::resize(m, n, new T [m*n]); } tcT /*inline*/ Matrix::Matrix(int n) : Array(n, new T [n]) { if ( !x() ) Array::resize(n, new T [n]); } /* ?? */ tcT Matrix::Matrix(const Matrix& a) : Array(a.m(), a.n(), new T [a.m()*a.n()]) { if ( !x() ) Array::resize(a.m(), a.n(), new T [a.m()*a.n()]); if ( a.n() && a.m() ) { T* t = a.x(); T* u = x(); T* v = x(); while ((v += n()) <= &x()[m()*n()]) { while (u < v) *u++ = *t++; t += a.l() - a.n(); } } } tcT Matrix::Matrix(const Array& a) : Array(a.m(), a.n(), new T [a.m()*a.n()]) { if ( !x() ) Array::resize(a.m(), a.n(), new T [a.m()*a.n()]); if ( a.n() && a.m() ) { T* t = a.x(); T* u = x(); T* v = x(); while ((v += n()) <= &x()[m()*n()]) { while (u < v) *u++ = *t++; t += a.l() - a.n(); } } } tcT /*inline*/ Matrix::Matrix() : Array() { } tcT /*inline*/ /**virtual**/ Matrix::~Matrix() { delete [] x(); } //////////////////////// // Matrices modifiers // //////////////////////// tcT /*inline*/ Matrix& Matrix::resize(const Array& a) { delete [] x(); Array::resize(a); x(new T [a.m()*a.n()]); return (*this=a); } tcT /*inline*/ Matrix& Matrix::resize(int m, int n, T* d) { delete [] x(); Array::resize(m,n,d); return *this; } tcT /*inline*/ Matrix& Matrix::resize(int n, T* d) { delete [] x(); Array::resize(n,d); return *this; } tcT Matrix& Matrix::resize(int m, int n, const T& a) { delete [] x(); Array::resize(m, n, new T [m*n]); T* t = x(); while (t < &(x()[m*n])) *t++ = a; return *this; } tcT /*inline*/ Matrix& Matrix::resize(int m, int n) { if ( m==this->m() && n==this->n() ) return *this; delete [] x(); Array::resize(m, n, new T [m*n]); return *this; } tcT /*inline*/ Matrix& Matrix::resize(int n) { if ( this->m()==1 && this->n()==n ) return *this; delete [] x(); Array::resize(n, new T [n]); return *this; } tcT /*inline*/ Matrix& Matrix::resize_(int m, int n) { if ( m==this->m() && n==this->n() ) return *this; Matrix newM(m,n); if ( m && n ) newM.s(0, minimum(m,this->m()), 0, minimum(n,this->n())) = s(0, minimum(m,this->m()), 0, minimum(n,this->n())); delete [] x(); Matrix::resize(newM); return *this; } tcT /*inline*/ Matrix& Matrix::resize_(int n) { return resize_(m(),n); } ///////////////////////////// // Assignement of matrices // ?? ///////////////////////////// // ?? tcT /*inline*/ Matrix& Matrix::operator = (const T& a) { Array::operator = (a); return *this; } // ?? tcT /*inline*/ Matrix& Matrix::operator = (const Array& a) { Array::operator = (a); return *this; } // ?? tcT /*inline*/ Matrix& Matrix::operator = (const Matrix& a) { Array::operator = (a); return *this; } ostream& operator << (ostream& s, const nullArray& e) { s << exceptionHeader << " Null array "; e.whereException::put(s); return (s << exceptionFooter << flush); }