/** -*- C++ -*- ** ** KAI C++ Compiler ** ** Copyright (C) 1996-2001 Intel Corp. All rights reserved. ** Heavily revised by ADR for speed. Modena's code is almost completely demolished. ** Template metaprogramming is *not* used in order to keep compile-times reasonable. ** Much of the code exploits the "value-return-slot" optimization in the front-end. ** ** Section 26.1p2 of ISO C++ standard says results are undefined if any operation on ** type T is undefined. Thus, in the interest of speed, this implementation is expected ** to be exception safe if operator new or operator delete, but not if any operation ** on type T fails. **/ /** ** Lib++ : The Modena C++ Standard Library, ** Version 2.4, October 1997 ** ** Copyright (c) 1995-1997 Modena Software Inc. **/ #ifndef MSIPL_VALARRAY_H #define MSIPL_VALARRAY_H #include #include #include #include #include #include #include // ISO standard requires that the copy constructor for slice_array (and similar classes) // be private. Unfortunately, this appears to make slice_array nearly useless. // The problem is that the designers of forgot that even if a compiler // can optimize away a copy constructor, the access permissions for the eliminated // copy constructor must still be checked. Define KAI_NONSTD_VALARRAY to a nonzero // value if you want public access (and some older draft features not in the standard). #if KAI_NONSTD_VALARRAY #define __KAI_SLICE_ACCESS public #else #define __KAI_SLICE_ACCESS private #endif namespace __kai { class gslice_generator; } // namespace __kai namespace std { // Section 26.3 -- Numeric Arrays template class valarray; // an array of type T class slice; template class slice_array; // a BLAS-like slice out of array class gslice; template class gslice_array; // a generalized slice out of array template class mask_array; // a masked array template class indirect_array; // an indirect array template class valarray { public: typedef T value_type; valarray() : _len(0), _ptr(0) {} explicit valarray(size_t n) {allocate_and_construct(n);} valarray(const T& t, size_t n) {uninitialized_fill_n(allocate(n), n, t); } valarray(const T* t, size_t n) {uninitialized_copy( t, t+n, allocate(n));} valarray(const valarray& v) { size_t n = v._len; uninitialized_copy( v._ptr, v._ptr+n, allocate(n) ); } valarray(const slice_array& s); valarray(const gslice_array& g ); valarray(const mask_array& m) {construct( m.rep );} valarray(const indirect_array& i) {construct( i );} ~valarray () { destroy_and_deallocate(); } // 26.3.2.2 assignment: valarray& operator=(const valarray&); valarray& operator=(const T&); valarray& operator=(const slice_array&); valarray& operator=(const gslice_array& x); valarray& operator=(const mask_array&); valarray& operator=(const indirect_array&); // 26.3.2.3 element access: T operator[](size_t pos) const { return *(_ptr+pos); } T& operator[](size_t pos) { return *(_ptr+pos); } // 26.3.2.4 subset operations: valarray operator[](slice s) const; slice_array operator[](slice s); valarray operator[](const gslice& g) const; gslice_array operator[](const gslice& g); valarray operator[](const valarray& vb) const; mask_array operator[](const valarray& vb); valarray operator[](const valarray& vi) const; indirect_array operator[](const valarray& vi); // 26.3.2.5 unary operators: valarray operator+() const { return valarray(*this, __kai::unary_plus()); } valarray operator-() const { return valarray(*this, negate()); } valarray operator~() const { return valarray(*this, __kai::complement()); } valarray operator!() const { return valarray(*this, __kai::unary_not()); } // 26.3.2.6 computed assignment: valarray& operator*=(const T& t) {return binary_assign_op< multiplies >(t);} valarray& operator/=(const T& t) {return binary_assign_op< divides >(t);} valarray& operator%=(const T& t) {return binary_assign_op< modulus >(t);} valarray& operator+=(const T& t) {return binary_assign_op< plus >(t);} valarray& operator-=(const T& t) {return binary_assign_op< minus >(t);} valarray& operator^=(const T& t) {return binary_assign_op< __kai::caret >(t);} valarray& operator&=(const T& t) {return binary_assign_op< __kai::bitwise_and >(t);} valarray& operator|=(const T& t) {return binary_assign_op< __kai::bitwise_or >(t);} valarray& operator<<=(const T& t) {return binary_assign_op< __kai::shiftl >(t);} valarray& operator>>=(const T& t) {return binary_assign_op< __kai::shiftr >(t);} valarray& operator*=(const valarray& v) {return binary_assign_op< multiplies >(v);} valarray& operator/=(const valarray& v) {return binary_assign_op< divides >(v);} valarray& operator%=(const valarray& v) {return binary_assign_op< modulus >(v);} valarray& operator+=(const valarray& v) {return binary_assign_op< plus >(v);} valarray& operator-=(const valarray& v) {return binary_assign_op< minus >(v);} valarray& operator^=(const valarray& v) {return binary_assign_op< __kai::caret >(v);} valarray& operator&=(const valarray& v) {return binary_assign_op< __kai::bitwise_and >(v);} valarray& operator|=(const valarray& v) {return binary_assign_op< __kai::bitwise_or >(v);} valarray& operator<<=(const valarray& v) {return binary_assign_op< __kai::shiftl >(v);} valarray& operator>>=(const valarray& v) {return binary_assign_op< __kai::shiftr >(v);} #if KAI_NONSTD_VALARRAY // Method length() removed by KAI. It's been gone from the draft standard // since September 1996. Use size instead. It is expected that length() // will be removed in some future release. size_t length() const { return _len; } #endif /* KAI_NONSTD_VALARRAY */ size_t size() const { return _len; } T sum() const { T total; if (size()) total = *_ptr; else total = T(); return std::accumulate(_ptr+1, _ptr+size(), total); } T min() const; T max() const; valarray shift(int) const; valarray cshift(int) const; valarray apply(T func(T)) const; valarray apply(T func(const T&)) const; void resize(size_t sz) { resize(sz,T()); } void resize(size_t sz, T c); #if KAI_NONSTD_VALARRAY T mult(size_t) const; void fill(const T& t) { fill_n(_ptr, size(), t); } void free() { destroy_and_deallocate() ; } #endif /* KAI_NONSTD_VALARRAY */ private : size_t _len; // Number of elements that have been initialized. T* _ptr; // Pointer to array of elements template friend class valarray; // Added by KAI friend class slice_array; friend class gslice_array; friend class mask_array; friend class indirect_array; private: // These are useful constructors for the various operators that must construct a new valarray. template valarray( const valarray& v, const F ); template valarray( const valarray& u, const valarray& v, const F ); template valarray( const valarray& v, const X& x, const F ); template valarray( const X& x, const valarray& v, const F ); enum grab_t {_grab}; // Constructor used for certain assignment operations. // If new_len differs from the current size, then the constructor grabs v's current // array and allocates a fresh one of the new size. valarray( valarray& v, size_t new_len, grab_t ) { if( v._len!=new_len ) { _ptr = v._ptr; _len = v._len; v.allocate_and_construct( new_len ); } else { _ptr = 0; _len = 0; } } template inline valarray& binary_assign_op( const T& t ) { size_t n = _len; T * p = _ptr; for( size_t k=0; k inline valarray& binary_assign_op( const valarray& v ) { size_t n = std::min(_len, v._len); T * p = _ptr; T * q = v._ptr; for( size_t k=0; k0; ) ptr[--k].T::~T(); _ptr = 0; operator delete( ptr ); } } void trivial_resize( size_t n ); void construct( const indirect_array& i ); void construct( const T * start, const __kai::gslice_generator& g ); template friend valarray operator*(const valarray&, const valarray&); template friend valarray operator*(const valarray&, const TT&); template friend valarray operator*(const TT&, const valarray&); template friend valarray operator/(const valarray&, const valarray&); template friend valarray operator/(const valarray&, const TT&); template friend valarray operator/(const TT&, const valarray&); template friend valarray operator%(const valarray&, const valarray&); template friend valarray operator%(const valarray&, const TT&); template friend valarray operator%(const TT&, const valarray&); template friend valarray operator+(const valarray&, const valarray&); template friend valarray operator+(const valarray&, const TT&); template friend valarray operator+(const TT&, const valarray&); template friend valarray operator-(const valarray&, const valarray&); template friend valarray operator-(const valarray&, const TT&); template friend valarray operator-(const TT&, const valarray&); template friend valarray operator^(const valarray&, const valarray&); template friend valarray operator^(const valarray&, const TT&); template friend valarray operator^(const TT&, const valarray&); template friend valarray operator&(const valarray&, const valarray&); template friend valarray operator&(const valarray&, const TT&); template friend valarray operator&(const TT&, const valarray&); template friend valarray operator|(const valarray&, const valarray&); template friend valarray operator|(const valarray&, const TT&); template friend valarray operator|(const TT&, const valarray&); template friend valarray operator<<(const valarray&, const valarray&); template friend valarray operator<<(const valarray&, const TT&); template friend valarray operator<<(const TT&, const valarray&); template friend valarray operator>>(const valarray&, const valarray&); template friend valarray operator>>(const valarray&, const TT&); template friend valarray operator>>(const TT&, const valarray&); template friend valarray operator&&(const valarray&, const valarray&); template friend valarray operator&&(const valarray&, const TT&); template friend valarray operator&&(const TT&, const valarray&); template friend valarray operator||(const valarray&, const valarray&); template friend valarray operator||(const valarray&, const TT&); template friend valarray operator||(const TT&, const valarray&); template friend valarray operator==(const valarray&, const valarray&); template friend valarray operator==(const valarray&, const TT&); template friend valarray operator==(const TT&, const valarray&); template friend valarray operator!=(const valarray&, const valarray&); template friend valarray operator!=(const valarray&, const TT&); template friend valarray operator!=(const TT&, const valarray&); template friend valarray operator<(const valarray&, const valarray&); template friend valarray operator<(const valarray&, const TT&); template friend valarray operator<(const TT&, const valarray&); template friend valarray operator>(const valarray&, const valarray&); template friend valarray operator>(const valarray&, const TT&); template friend valarray operator>(const TT&, const valarray&); template friend valarray operator<=(const valarray&, const valarray&); template friend valarray operator<=(const valarray&, const TT&); template friend valarray operator<=(const TT&, const valarray&); template friend valarray operator>=(const valarray&, const valarray&); template friend valarray operator>=(const valarray&, const TT&); template friend valarray operator>=(const TT&, const valarray&); template friend valarray abs(const valarray&); template friend valarray acos(const valarray&); template friend valarray asin(const valarray&); template friend valarray atan(const valarray&); template friend valarray cos(const valarray&); template friend valarray cosh(const valarray&); template friend valarray exp(const valarray&); template friend valarray log(const valarray&); template friend valarray log10(const valarray&); template friend valarray sin(const valarray&); template friend valarray sinh(const valarray&); template friend valarray sqrt(const valarray&); template friend valarray tan(const valarray&); template friend valarray tanh(const valarray&); template friend valarray atan2(const valarray&, const TT&); template friend valarray atan2(const TT&, const valarray&); template friend valarray atan2(const valarray&, const valarray&); template friend valarray pow(const valarray&, const TT&); template friend valarray pow(const TT&, const valarray&); template friend valarray pow(const valarray&, const valarray&); template friend TT min(const valarray&); template friend TT max(const valarray&); friend class __kai::gslice_generator; }; template template valarray::valarray( const valarray& v, const F f ) { size_t n = v._len; T * p = allocate(n); T * q = v._ptr; for( size_t k=0; k template valarray::valarray( const valarray& u, const valarray& v, const F f ) { size_t n = std::min(u._len, v._len); T * p = allocate(n); X * q = u._ptr; X * r = v._ptr; for( size_t k=0; k template valarray::valarray(const valarray& v, const X& t, const F f ) { size_t n = v._len; T * p = allocate(n); X * q = v._ptr; for( size_t k=0; k template valarray::valarray(const X& t, const valarray& v, const F f ) { size_t n = v._len; T * p = allocate(n); X * q = v._ptr; for( size_t k=0; k valarray& valarray::operator=( const valarray& v ) { if( this!=&v ) { if( _len != v._len ) trivial_resize( v._len ); std::copy(v._ptr, v._ptr+_len, _ptr); } return *this; } template valarray& valarray::operator=(const T& t) { std::fill_n(_ptr, _len, t); return *this; } template void valarray::trivial_resize( size_t n ) { destroy_and_deallocate(); allocate_and_construct( n ); } #if KAI_NONSTD_VALARRAY template inline T valarray::mult(size_t len) const { T prod = 1; size_t rlen = std::min(len, size()); for (size_t count = 0; count < rlen; ++count) prod *= (*(_ptr+count)); return prod; } #endif /* KAI_NONSTD_VALARRAY */ template inline T valarray::min() const { T min_val = T(); if (size()) min_val = *_ptr; for (size_t count = 1; count < size(); ++count) { if (min_val > (*(_ptr+count))) min_val = (*(_ptr+count)); } return min_val; } template inline T valarray::max() const { T max_val = T(); if (size()) max_val = *_ptr; for (size_t count = 1; count < size(); ++count) { if (max_val < (*(_ptr+count))) max_val = (*(_ptr+count)); } return max_val; } template valarray valarray::shift(int i) const { // Take the absolute value of i in j. int j = i>0 ? i : -i; size_t n = size(); valarray result; T * p = result.allocate( n ); const T * q = _ptr; T * r; const T * q_end = q+n-j; if( i<0 ) { r = p; p += j; } else { r = p+(n-j); q += j; q_end += j; } std::uninitialized_copy( q, q+n-j, p ); std::uninitialized_fill_n( r, j, T() ); return result; } template valarray valarray::cshift(int i) const { size_t n = _len; valarray result; T * p = result.allocate( n ); if ( n>0 ) { const T * q = _ptr; i %= (long)n; T * r = std::uninitialized_copy( q+(n+i)%n, q+n, p ); std::uninitialized_copy( q, q+(n+i)%n, r ); } return result; } template valarray valarray::apply(T func(T)) const { valarray result; size_t n = _len; T * p = result.allocate( n ); T * q = _ptr; for( size_t k=0; k valarray valarray::apply(T func(const T&)) const { valarray result; size_t n = _len; T * p = result.allocate( n ); T * q = _ptr; for( size_t k=0; k void valarray::resize(size_t new_len, T c) { size_t n = _len; if( n!=new_len ) { // Save old array in "old" to guarentee its destruction, even if an exception is thrown. valarray old; T * q = _ptr; old._ptr = q; old._len = n; T * r = allocate( new_len ); if( n>new_len ) { n = new_len; } std::uninitialized_copy( q, q+n, r ); if( new_len!=n ) { std::uninitialized_fill_n( r+n, new_len-n, T() ); } } } //-------------------------------------------------------------------------------- // 26.3.3.1 valarray binary operators //-------------------------------------------------------------------------------- template inline valarray operator*(const valarray& v, const T& t) { return valarray(v, t, multiplies()); } template inline valarray operator*(const T& t, const valarray& v) { return valarray(t, v, multiplies()); } template inline valarray operator*(const valarray& v1, const valarray& v2) { return valarray(v1,v2, multiplies()); } template inline valarray operator/(const valarray& v, const T& t) { return valarray(v, t, divides()); } template inline valarray operator/(const T& t, const valarray& v) { return valarray(t, v, divides()); } template inline valarray operator/(const valarray& v1, const valarray& v2) { return valarray(v1, v2, divides()); } template inline valarray operator%(const valarray& v, const T& t) { return valarray(v, t, modulus()); } template inline valarray operator%(const T& t, const valarray& v) { return valarray(t, v, modulus()); } template inline valarray operator%(const valarray& v1, const valarray& v2) { return valarray(v1, v2, modulus()); } template inline valarray operator+(const valarray& v, const T& t) { return valarray(v, t, plus()); } template inline valarray operator+(const T& t, const valarray& v) { return valarray(t, v, plus()); } template inline valarray operator+(const valarray& v1, const valarray& v2) { return valarray(v1, v2, plus()); } template inline valarray operator-(const valarray& v, const T& t) { return valarray(v, t, minus()); } template inline valarray operator-(const T& t, const valarray& v) { return valarray(t, v, minus()); } template inline valarray operator-(const valarray& v1, const valarray& v2) { return valarray(v1, v2, minus()); } template inline valarray operator^(const valarray& v, const T& t) { return valarray(v, t, __kai::caret()); } template inline valarray operator^(const T& t, const valarray& v) { return valarray(t, v, __kai::caret()); } template inline valarray operator^(const valarray& v1, const valarray& v2){ return valarray(v1,v2,__kai::caret());} template inline valarray operator&(const valarray& v, const T& t) { return valarray(v, t, __kai::bitwise_and()); } template inline valarray operator&(const T& t, const valarray& v) { return valarray(t, v, __kai::bitwise_and()); } template inline valarray operator&(const valarray& v1, const valarray& v2) { return valarray(v1, v2, __kai::bitwise_and()); } template inline valarray operator|(const valarray& v, const T& t) { return valarray(v, t, __kai::bitwise_or()); } template inline valarray operator|(const T& t, const valarray& v) { return valarray(t, v, __kai::bitwise_or()); } template inline valarray operator|(const valarray& v1, const valarray& v2) { return valarray(v1, v2, __kai::bitwise_or()); } template inline valarray operator<<(const valarray& v, const T& t) { return valarray(v, t, __kai::shiftl()); } template inline valarray operator<<(const T& t, const valarray& v) { return valarray(t, v, __kai::shiftl()); } template inline valarray operator<<(const valarray& v1, const valarray& v2) { return valarray(v1, v2, __kai::shiftl()); } template inline valarray operator>>(const valarray& v, const T& t) { return valarray(v, t, __kai::shiftr()); } template inline valarray operator>>(const T& t, const valarray& v) { return valarray(t, v, __kai::shiftr()); } template inline valarray operator>>(const valarray& v1, const valarray& v2) { return valarray(v1, v2, __kai::shiftr()); } template inline valarray operator&&(const valarray& v, const T& t) { return valarray(v, t, __kai::logical_and()); } template inline valarray operator&&(const T& t, const valarray& v) { return valarray(t, v, __kai::logical_and()); } template inline valarray operator&&(const valarray& v1, const valarray& v2) { return valarray(v1, v2, __kai::logical_and()); } template inline valarray operator||(const valarray& v, const T& t) { return valarray(v, t, __kai::logical_or()); } template inline valarray operator||(const T& t, const valarray& v) { return valarray(t, v, __kai::logical_or()); } template inline valarray operator||(const valarray& v1, const valarray& v2) { return valarray(v1, v2, __kai::logical_or()); } template inline valarray operator==(const valarray& v, const T& t) { return valarray(v, t, equal_to()); } template inline valarray operator==(const T& t, const valarray& v) { return valarray(t, v, equal_to()); } template inline valarray operator==(const valarray& v1, const valarray& v2) { return valarray(v1, v2, equal_to()); } template inline valarray operator!=(const valarray& v, const T& t) { return valarray(v, t, not_equal_to()); } template inline valarray operator!=(const T& t, const valarray& v) { return valarray(t, v, not_equal_to()); } template inline valarray operator!=(const valarray& v1, const valarray& v2) { return valarray(v1, v2, not_equal_to()); } template inline valarray operator<(const valarray& v, const T& t) { return valarray(v, t, less()); } template inline valarray operator<(const T& t, const valarray& v) { return valarray(t, v, less()); } template inline valarray operator<(const valarray& v1, const valarray& v2) { return valarray(v1, v2, less()); } template inline valarray operator>(const valarray& v, const T& t) { return valarray(v, t, greater()); } template inline valarray operator>(const T& t, const valarray& v) { return valarray(t, v, greater()); } template inline valarray operator>(const valarray& v1, const valarray& v2) { return valarray(v1, v2, greater()); } template inline valarray operator<=(const valarray& v, const T& t) { return valarray(v, t, less_equal()); } template inline valarray operator<=(const T& t, const valarray& v) { return valarray(t, v, less_equal()); } template inline valarray operator<=(const valarray& v1, const valarray& v2) { return valarray(v1, v2, less_equal()); } template inline valarray operator>=(const valarray& v, const T& t) { return valarray(v, t, greater_equal()); } template inline valarray operator>=(const T& t, const valarray& v) { return valarray(t, v, greater_equal()); } template inline valarray operator>=(const valarray& v1, const valarray& v2) { return valarray(v1, v2, greater_equal()); } template inline valarray abs(const valarray& v) { return valarray(v, __kai::absolute()); } template inline valarray acos(const valarray& v) { return valarray(v, __kai::arccos()); } template inline valarray asin(const valarray& v) { return valarray(v, __kai::arcsin()); } template inline valarray atan(const valarray& v) { return valarray(v, __kai::arctan()); } template inline valarray cos(const valarray& v) { return valarray(v, __kai::cosine()); } template inline valarray cosh(const valarray& v) { return valarray(v, __kai::cosineh()); } template inline valarray exp(const valarray& v) { return valarray(v, __kai::exponential()); } template inline valarray log(const valarray& v) { return valarray(v,__kai::logarithm()); } template inline valarray log10(const valarray& v) { return valarray(v,__kai::logarithm10()); } template inline valarray sin(const valarray& v) { return valarray(v, __kai::sine()); } template inline valarray sinh(const valarray& v) { return valarray(v, __kai::sineh()); } template inline valarray sqrt(const valarray& v) { return valarray(v, __kai::sqroot()); } template inline valarray tan(const valarray& v) { return valarray(v, __kai::tangent()); } template inline valarray tanh(const valarray& v) { return valarray(v, __kai::tangenth()); } template inline valarray atan2(const valarray& v, const T& t) { return valarray(v, t, __kai::arctan2()); } template inline valarray atan2(const T& t, const valarray& v) { return valarray(t, v, __kai::arctan2()); } template inline valarray atan2(const valarray& v1, const valarray& v2) { return valarray(v1, v2, __kai::arctan2()); } template inline valarray pow(const valarray& v, const T& t) { return valarray(v, t, __kai::power()); } template inline valarray pow(const T& t, const valarray& v) { return valarray(t, v, __kai::power()); } template inline valarray pow(const valarray& v1, const valarray& v2) { return valarray(v1, v2, __kai::power()); } template T min(const valarray& v) { T min_val = T(); if (v.size()) min_val = *v._ptr; for (size_t count = 1; count < v.size(); ++count) { if (min_val > (*(v._ptr+count))) min_val = (*(v._ptr+count)); } return min_val; } template T max(const valarray& v) { T max_val = T(); if (v.size()) max_val = *v._ptr; for (size_t count = 1; count < v.size(); ++count) { if (max_val < (*(v._ptr+count))) max_val = (*(v._ptr+count)); } return max_val; } //------------------------------------------------------------------------ // slice //------------------------------------------------------------------------ class slice { public : slice() : _start(0), _len(0), _step(0) {} slice(size_t start, size_t len, size_t step) : _len(len), _step(step), _start(start) {} slice(const slice& s) : _start(s._start), _len(s._len), _step(s._step) {} size_t start() const { return _start; } size_t size() const { return _len; } size_t stride() const { return _step; } #if KAI_NONSTD_VALARRAY // See comments about valarray::length size_t length() const { return _len; } #endif /* KAI_NONSTD_VALARRAY */ private : size_t _start; size_t _len; size_t _step; template friend class valarray; }; //------------------------------------------------------------------------ // slice_array and other methods related to slice_array //------------------------------------------------------------------------ template class slice_array { public : typedef T value_type; void operator=(const valarray&) const; void operator*=(const valarray& v) const {assign_binary_op >(v);}; void operator/=(const valarray& v) const {assign_binary_op >(v);} void operator%=(const valarray& v) const {assign_binary_op >(v);} void operator+=(const valarray& v) const {assign_binary_op >(v);} void operator-=(const valarray& v) const {assign_binary_op >(v);} void operator^=(const valarray& v) const {assign_binary_op< __kai::caret >(v);} void operator&=(const valarray& v) const {assign_binary_op< __kai::bitwise_and >(v);} void operator|=(const valarray& v) const {assign_binary_op< __kai::bitwise_or >(v);} void operator<<=(const valarray& v) const {assign_binary_op< __kai::shiftl >(v);} void operator>>=(const valarray& v) const {assign_binary_op< __kai::shiftr >(v);} void operator=(const T&); ~slice_array() {} __KAI_SLICE_ACCESS: inline slice_array(const slice_array& s) : _start(s._start), _len(s._len), _step(s._step) {} private: slice_array() {} slice_array& operator =(const slice_array&); slice_array(const valarray&, slice); T * _start; size_t _len; size_t _step; template void assign_binary_op( const valarray& v ) const; friend class valarray; }; template inline valarray valarray::operator[](slice s) const { valarray result; T * r = result.allocate( s._len ); T * p = _ptr+s._start; size_t step = s._step; size_t n = s._len; for( size_t k=0; k inline slice_array valarray::operator[](slice s) { slice_array result; result._start = _ptr+s._start; result._len = s._len; result._step = s._step; return result; } template inline void slice_array::operator=(const T& x) { T * p = _start; size_t step = _step; size_t n = _len; for( size_t k=0; k inline void slice_array::operator=(const valarray& v) const { size_t n = std::min(_len, v.size()); T * p = _start; size_t step = _step; T * q = v._ptr; for( size_t k=0; k valarray& valarray::operator=(const slice_array& s) { size_t n = s._len; valarray old(*this,n,_grab); T * q = s._start; T * p = _ptr; size_t step = s._step; for( size_t k=0; k valarray::valarray(const slice_array& s) { size_t len = s._len; T * p = allocate( len ); T * q = s._start; size_t n = len; size_t step = s._step; for( size_t k=0; k template inline void slice_array::assign_binary_op( const valarray& v ) const { size_t n = std::min(_len, v.size()); T * p = _start; size_t step = _step; T * q = v._ptr; for( size_t k=0; k class indirect_array { public : typedef T value_type; void operator=(const valarray&) const; void operator*=(const valarray& v) const {assign_binary_op >(v);}; void operator/=(const valarray& v) const {assign_binary_op >(v);} void operator%=(const valarray& v) const {assign_binary_op >(v);} void operator+=(const valarray& v) const {assign_binary_op >(v);} void operator-=(const valarray& v) const {assign_binary_op >(v);} void operator^=(const valarray& v) const {assign_binary_op< __kai::caret >(v);} void operator&=(const valarray& v) const {assign_binary_op< __kai::bitwise_and >(v);} void operator|=(const valarray& v) const {assign_binary_op< __kai::bitwise_or >(v);} void operator<<=(const valarray& v) const {assign_binary_op< __kai::shiftl >(v);} void operator>>=(const valarray& v) const {assign_binary_op< __kai::shiftr >(v);} void operator=(const T&); ~indirect_array() {if(_ptr_ptr) delete[] _ptr_ptr;} __KAI_SLICE_ACCESS: indirect_array(const indirect_array&); private: indirect_array() {} indirect_array& operator=( const indirect_array& ); size_t _len; T** _ptr_ptr; friend class valarray; T ** allocate( size_t len ) { _len = len; // Clear _ptr_ptr in case "new" throws an exception. _ptr_ptr = 0; return _ptr_ptr = new T*[len]; } template void assign_binary_op( const valarray& v ) const; friend class gslice_array; friend class mask_array; }; template valarray valarray::operator[](const valarray& v) const { size_t n = v.size(); T * p = _ptr; valarray result; T * r = result.allocate(n); const size_t * q = v._ptr; for( size_t k=0; k indirect_array valarray::operator[]( const valarray& v ) { size_t n = v.size(); T * p = _ptr; indirect_array result; T** r = result.allocate(n); const size_t * q = v._ptr; for( size_t k=0; k inline indirect_array::indirect_array(const indirect_array& i) { size_t n = i._len; std::memcpy( allocate(n), i._ptr_ptr, n*sizeof(T*) ); } template inline void indirect_array::operator=(const valarray& v) const { size_t n = std::min(_len, v.size()); T * const * p = _ptr_ptr; const T * q = v._ptr; for( size_t k=0; k template inline void indirect_array::assign_binary_op( const valarray& v ) const { size_t n = std::min(_len, v.size()); T ** p = _ptr_ptr; T * q = v._ptr; for( size_t k=0; k inline void indirect_array::operator=(const T& t) { size_t n = _len; T ** p = _ptr_ptr; for( size_t k=0; k void valarray::construct( const indirect_array& i) { size_t n = i._len; T * p = allocate(n); T * const * q = i._ptr_ptr; for( size_t k=0; k inline valarray& valarray::operator=(const indirect_array& i) { size_t len = i._len; valarray old( *this, len, _grab ); T ** q = i._ptr_ptr; size_t n = _len; T * p = _ptr; for( size_t k=0; k class mask_array { public: typedef T value_type; void operator=(const valarray& y) const {rep=y;} void operator*=(const valarray& y) const {rep*=y;} void operator/=(const valarray& y) const {rep/=y;} void operator%=(const valarray& y) const {rep%=y;} void operator+=(const valarray& y) const {rep+=y;} void operator-=(const valarray& y) const {rep-=y;} void operator^=(const valarray& y) const {rep^=y;} void operator&=(const valarray& y) const {rep&=y;} void operator|=(const valarray& y) const {rep|=y;} void operator<<=(const valarray& y) const {rep<<=y;} void operator>>=(const valarray& y) const {rep>>=y;} void operator=(const T& y) {rep=y;} ~mask_array() {} __KAI_SLICE_ACCESS: mask_array(const mask_array& m) : rep(m.rep) {} private: mask_array() {} mask_array& operator=(const mask_array&); indirect_array rep; friend class valarray; }; template valarray valarray::operator[](const valarray& v) const { size_t rlen = std::min(_len, v._len); const bool * q = v._ptr; size_t n = 0; for( size_t i=0; i result; T * p = result.allocate(n); T * r = _ptr; for( size_t k=0; k mask_array valarray::operator[]( const valarray& v ) { size_t rlen = std::min(_len, v._len); const bool * q = v._ptr; size_t n = 0; for( size_t i=0; i result; T ** p = result.rep.allocate(n); T * r = _ptr; for( size_t k=0; k inline valarray& valarray::operator=(const mask_array& m) { return operator=( m.rep ); } //------------------------------------------------------------------------ // gslice //------------------------------------------------------------------------ class gslice { public : gslice() : _offset(0) {} gslice(size_t offset, const valarray& len, const valarray& step) :_offset(offset), _len(len), _step(step) {} gslice(const gslice& g) :_offset(g._offset), _len(g._len), _step(g._step) {} size_t start() const { return _offset; } valarray size() const { return _len; } valarray stride() const { return _step; } #if !KAI_NONSTD_VALARRAY // See comments about valarray::length valarray length() const { return _len; } #endif /* KAI_NONSTD_VALARRAY */ private : size_t _offset; valarray _len; // min value for any element in _len is 1, otherwise behaviour is undefined. valarray _step; template friend class gslice_array; template friend class valarray; friend class __kai::gslice_generator; }; } // namespace std namespace __kai { class gslice_generator { public: gslice_generator( const std::gslice& g, size_t element_size ); size_t size() const {return length;} void init( std::size_t& m, std::size_t& step ) const { digit_t * d = digits; m = d->modulus; step = d->step; for( size_t r=rank; r>0; --r ) { ++d; d->count = d->modulus; } } static void * inner( const void * p, size_t step ) { return (char*)p + step; } void * outer( const void * p ) const { // Handling of zeroth digit is "unrolled" by client, and not done here. for( digit_t * d = digits; ; ) { ++d; p = inner( p, d->step ); if( --d->count ) break; d->count = d->modulus; } return (void*)p; }; ~gslice_generator() {if( digits!=buffer ) delete[] digits;} gslice_generator( const gslice_generator& g ); private: struct digit_t { size_t step; // Measured in bytes size_t count; // 0 unless actively in use. size_t modulus; }; digit_t* digits; // Points to rank+1 entries. Last entry is dummy to make Purify happy. size_t length; size_t rank; digit_t buffer[5]; void operator=( const gslice_generator& ); // Deny access }; } // namespace __kai namespace std { //------------------------------------------------------------------------ // gslice_array and other methods related to indirect_array //------------------------------------------------------------------------ template class gslice_array { public: typedef T value_type; void operator=(const valarray& y) const; void operator*=(const valarray& v) const {assign_binary_op >(v);}; void operator/=(const valarray& v) const {assign_binary_op >(v);} void operator%=(const valarray& v) const {assign_binary_op >(v);} void operator+=(const valarray& v) const {assign_binary_op >(v);} void operator-=(const valarray& v) const {assign_binary_op >(v);} void operator^=(const valarray& v) const {assign_binary_op< __kai::caret >(v);} void operator&=(const valarray& v) const {assign_binary_op< __kai::bitwise_and >(v);} void operator|=(const valarray& v) const {assign_binary_op< __kai::bitwise_or >(v);} void operator<<=(const valarray& v) const {assign_binary_op< __kai::shiftl >(v);} void operator>>=(const valarray& v) const {assign_binary_op< __kai::shiftr >(v);} void operator=(const T&); ~gslice_array() {} __KAI_SLICE_ACCESS: gslice_array(const gslice_array& g) : _start(g._start), _generator(g._generator) {} private: gslice_array() {} gslice_array& operator=(const gslice&); gslice_array( T * ptr, const gslice& g ) : _start(ptr+g._offset), _generator(g,sizeof(T)) {} T * _start; __kai::gslice_generator _generator; friend class valarray; template void assign_binary_op( const valarray& v ) const; }; template inline gslice_array valarray::operator[](const gslice& g) { return gslice_array( _ptr, g ); } template inline valarray valarray::operator[](const gslice& g) const { __kai::gslice_generator gg(g,sizeof(T)); valarray result; result.construct( _ptr + g._offset, gg ); return result; } template inline valarray::valarray( const gslice_array& g ) { construct( g._start, g._generator ); } template void valarray::construct( const T * q, const __kai::gslice_generator& gg ) { size_t n = gg.size(); T * p = allocate(n); size_t m, stride; gg.init( m, stride ); for(; n>0; n-=m ) { for( int j=m; j>0; --j ) { new( p++ ) T( *q ); q = (const T*)gg.inner(q,stride); } q = (const T*)gg.outer(q); } } template template void gslice_array::assign_binary_op( const valarray& v ) const { size_t n = _generator.size(); // Failure of following assertion indicates that caller is trying to assign arrays of // different sizes. assert( n==v._len ); T * p = _start; T * q = v._ptr; size_t m, stride; _generator.init( m, stride ); for(; n>0; n-=m ) { for( int j=m; j>0; --j ) { *p = F()(*p,*q++); p = (T*)_generator.inner(p,stride); } p = (T*)_generator.outer(p); } } template valarray& valarray::operator=(const gslice_array& g) { valarray old(*this,_len,_grab); size_t n = g._generator.size(); T * p = _ptr; const T * q = g._start; size_t m, stride; g._generator.init( m, stride ); for(; n>0; n-=m ) { for( int j=m; j>0; --j ) { *p++ = *q; q = (const T*)g._generator.inner(q,stride); } q = (const T*)g._generator.outer(q); } return *this; } template void gslice_array::operator=(const T& t) { size_t n = _generator.size(); T * p = _start; size_t m, stride; _generator.init( m, stride ); for(; n>0; n-=m ) { for( int j=m; j>0; --j ) { *p = t; p = (T*)_generator.inner(p,stride); } p = (T*)_generator.outer(p); } } template void gslice_array::operator=(const valarray& v) const { size_t n = _generator.size(); // Failure of following assertion indicates that caller is trying to assign arrays of // different sizes. assert( n==v._len ); T * p = _start; T * q = v._ptr; size_t m, stride; _generator.init( m, stride ); for(; n>0; n-=m ) { for( int j=m; j>0; --j ) { *p = *q++; p = (T*)_generator.inner(p,stride); } p = (T*)_generator.outer(p); } } } // namespace std #endif /* MSIPL_VALARRAY_H */