/* Metrowerks Standard Library
 * Copyright  1995-2004 Metrowerks Corporation.  All rights reserved.
 *
 * $Date: 2004/06/15 14:20:26 $
 * $Revision: 1.32.2.1 $
 */

// valarray

#ifndef _VALARRAY
#define _VALARRAY

/*  valarray synopsis

namespace std
{

template<class T>
class valarray
{
public:
	typedef T value_type;

	//  lib.valarray.cons construct/destroy:
	valarray();
	explicit valarray(size_t);
	valarray(const T&, size_t);
	valarray(const T*, size_t);
	valarray(const valarray&);
	valarray(const slice_array<T>&);
	valarray(const gslice_array<T>&);
	valarray(const mask_array<T>&);
	valarray(const indirect_array<T>&);
	~valarray();

	//  lib.valarray.assign assignment:
	valarray<T>& operator=(const valarray<T>&);
	valarray<T>& operator=(const T&);
	valarray<T>& operator=(const slice_array<T>&);
	valarray<T>& operator=(const gslice_array<T>&);
	valarray<T>& operator=(const mask_array<T>&);
	valarray<T>& operator=(const indirect_array<T>&);

	//  lib.valarray.access element access:
	T                 operator[](size_t) const;
	T&                operator[](size_t);

	//  lib.valarray.sub subset operations:
	valarray<T>       operator[](slice) const;
	slice_array<T>    operator[](slice);
	valarray<T>       operator[](const gslice&) const;
	gslice_array<T>   operator[](const gslice&);
	valarray<T>       operator[](const valarray<bool>&) const;
	mask_array<T>     operator[](const valarray<bool>&);
	valarray<T>       operator[](const valarray<size_t>&) const;
	indirect_array<T> operator[](const valarray<size_t>&);

	//  lib.valarray.unary unary operators:
	valarray<T> operator+() const;
	valarray<T> operator-() const;
	valarray<T> operator~() const;
	valarray<T> operator!() const;

	//  lib.valarray.cassign computed assignment:
	valarray<T>& operator*= (const T&);
	valarray<T>& operator/= (const T&);
	valarray<T>& operator%= (const T&);
	valarray<T>& operator+= (const T&);
	valarray<T>& operator-= (const T&);
	valarray<T>& operator^= (const T&);
	valarray<T>& operator&= (const T&);
	valarray<T>& operator|= (const T&);
	valarray<T>& operator<<=(const T&);
	valarray<T>& operator>>=(const T&);

	valarray<T>& operator*= (const valarray<T>&);
	valarray<T>& operator/= (const valarray<T>&);
	valarray<T>& operator%= (const valarray<T>&);
	valarray<T>& operator+= (const valarray<T>&);
	valarray<T>& operator-= (const valarray<T>&);
	valarray<T>& operator^= (const valarray<T>&);
	valarray<T>& operator|= (const valarray<T>&);
	valarray<T>& operator&= (const valarray<T>&);
	valarray<T>& operator<<=(const valarray<T>&);
	valarray<T>& operator>>=(const valarray<T>&);

	//  lib.valarray.members member functions:
	size_t size() const;

	T    sum() const;
	T    min() const;
	T    max() const;

	valarray<T> shift (int) const;
	valarray<T> cshift(int) const;
	valarray<T> apply(T func(T)) const;
	valarray<T> apply(T func(const T&)) const;
	void resize(size_t sz, T c = T());
};

class slice
{
public:
	slice();
	slice(size_t start, size_t length, size_t stride);

	size_t start() const;
	size_t size() const;
	size_t stride() const;
};

template <class T>
class slice_array
{
public:
	typedef T value_type;

	void operator=  (const valarray<T>&) const;
	void operator*= (const valarray<T>&) const;
	void operator/= (const valarray<T>&) const;
	void operator%= (const valarray<T>&) const;
	void operator+= (const valarray<T>&) const;
	void operator-= (const valarray<T>&) const;
	void operator^= (const valarray<T>&) const;
	void operator&= (const valarray<T>&) const;
	void operator|= (const valarray<T>&) const;
	void operator<<=(const valarray<T>&) const;
	void operator>>=(const valarray<T>&) const;

	void operator=(const T&) const;
	~slice_array();
private:
	slice_array();
	slice_array(const slice_array&);
	slice_array& operator=(const slice_array&);
};

class gslice
{
public:
	gslice();
	gslice(size_t s, const valarray<size_t>& l, const valarray<size_t>& d);

	size_t           start() const;
	valarray<size_t> size() const;
	valarray<size_t> stride() const;
};

template <class T>
class gslice_array
{
public:
	typedef T value_type;

	void operator=  (const valarray<T>&) const;
	void operator*= (const valarray<T>&) const;
	void operator/= (const valarray<T>&) const;
	void operator%= (const valarray<T>&) const;
	void operator+= (const valarray<T>&) const;
	void operator-= (const valarray<T>&) const;
	void operator^= (const valarray<T>&) const;
	void operator&= (const valarray<T>&) const;
	void operator|= (const valarray<T>&) const;
	void operator<<=(const valarray<T>&) const;
	void operator>>=(const valarray<T>&) const;

	void operator=(const T&) const;
	~gslice_array();
private:
	gslice_array();
	gslice_array(const gslice_array&);
	gslice_array& operator=(const gslice_array&);
};

template <class T>
class mask_array
{
public:
	typedef T value_type;

	void operator=  (const valarray<T>&) const;
	void operator*= (const valarray<T>&) const;
	void operator/= (const valarray<T>&) const;
	void operator%= (const valarray<T>&) const;
	void operator+= (const valarray<T>&) const;
	void operator-= (const valarray<T>&) const;
	void operator^= (const valarray<T>&) const;
	void operator&= (const valarray<T>&) const;
	void operator|= (const valarray<T>&) const;
	void operator<<=(const valarray<T>&) const;
	void operator>>=(const valarray<T>&) const;

	void operator=(const T&) const;
	~mask_array();
private:
	mask_array();
	mask_array(const mask_array&);
	mask_array& operator=(const mask_array&);
};

template <class T>
class indirect_array
{
public:
	typedef T value_type;

	void operator=  (const valarray<T>&) const;
	void operator*= (const valarray<T>&) const;
	void operator/= (const valarray<T>&) const;
	void operator%= (const valarray<T>&) const;
	void operator+= (const valarray<T>&) const;
	void operator-= (const valarray<T>&) const;
	void operator^= (const valarray<T>&) const;
	void operator&= (const valarray<T>&) const;
	void operator|= (const valarray<T>&) const;
	void operator<<=(const valarray<T>&) const;
	void operator>>=(const valarray<T>&) const;

	void operator=(const T&) const;
	~indirect_array();
private:
	indirect_array();
	indirect_array(const indirect_array&);
	indirect_array& operator=(const indirect_array&);
};

template<class T> valarray<T> operator*(const valarray<T>&, const valarray<T>&);
template<class T> valarray<T> operator*(const valarray<T>&, const T&);
template<class T> valarray<T> operator*(const T&, const valarray<T>&);

template<class T> valarray<T> operator/(const valarray<T>&, const valarray<T>&);
template<class T> valarray<T> operator/(const valarray<T>&, const T&);
template<class T> valarray<T> operator/(const T&, const valarray<T>&);

template<class T> valarray<T> operator%(const valarray<T>&, const valarray<T>&);
template<class T> valarray<T> operator%(const valarray<T>&, const T&);
template<class T> valarray<T> operator%(const T&, const valarray<T>&);

template<class T> valarray<T> operator+(const valarray<T>&, const valarray<T>&);
template<class T> valarray<T> operator+(const valarray<T>&, const T&);
template<class T> valarray<T> operator+(const T&, const valarray<T>&);

template<class T> valarray<T> operator-(const valarray<T>&, const valarray<T>&);
template<class T> valarray<T> operator-(const valarray<T>&, const T&);
template<class T> valarray<T> operator-(const T&, const valarray<T>&);

template<class T> valarray<T> operator^(const valarray<T>&, const valarray<T>&);
template<class T> valarray<T> operator^(const valarray<T>&, const T&);
template<class T> valarray<T> operator^(const T&, const valarray<T>&);

template<class T> valarray<T> operator&(const valarray<T>&, const valarray<T>&);
template<class T> valarray<T> operator&(const valarray<T>&, const T&);
template<class T> valarray<T> operator&(const T&, const valarray<T>&);

template<class T> valarray<T> operator|(const valarray<T>&, const valarray<T>&);
template<class T> valarray<T> operator|(const valarray<T>&, const T&);
template<class T> valarray<T> operator|(const T&, const valarray<T>&);

template<class T> valarray<T> operator<<(const valarray<T>&, const valarray<T>&);
template<class T> valarray<T> operator<<(const valarray<T>&, const T&);
template<class T> valarray<T> operator<<(const T&, const valarray<T>&);

template<class T> valarray<T> operator>>(const valarray<T>&, const valarray<T>&);
template<class T> valarray<T> operator>>(const valarray<T>&, const T&);
template<class T> valarray<T> operator>>(const T&, const valarray<T>&);

template<class T> valarray<bool> operator&&(const valarray<T>&, const valarray<T>&);
template<class T> valarray<bool> operator&&(const valarray<T>&, const T&);
template<class T> valarray<bool> operator&&(const T&, const valarray<T>&);

template<class T> valarray<bool> operator||(const valarray<T>&, const valarray<T>&);
template<class T> valarray<bool> operator||(const valarray<T>&, const T&);
template<class T> valarray<bool> operator||(const T&, const valarray<T>&);

template<class T> valarray<bool> operator==(const valarray<T>&, const valarray<T>&);
template<class T> valarray<bool> operator==(const valarray<T>&, const T&);
template<class T> valarray<bool> operator==(const T&, const valarray<T>&);

template<class T> valarray<bool> operator!=(const valarray<T>&, const valarray<T>&);
template<class T> valarray<bool> operator!=(const valarray<T>&, const T&);
template<class T> valarray<bool> operator!=(const T&, const valarray<T>&);

template<class T> valarray<bool> operator< (const valarray<T>&, const valarray<T>&);
template<class T> valarray<bool> operator< (const valarray<T>&, const T&);
template<class T> valarray<bool> operator< (const T&, const valarray<T>&);

template<class T> valarray<bool> operator> (const valarray<T>&, const valarray<T>&);
template<class T> valarray<bool> operator> (const valarray<T>&, const T&);
template<class T> valarray<bool> operator> (const T&, const valarray<T>&);

template<class T> valarray<bool> operator<=(const valarray<T>&, const valarray<T>&);
template<class T> valarray<bool> operator<=(const valarray<T>&, const T&);
template<class T> valarray<bool> operator<=(const T&, const valarray<T>&);

template<class T> valarray<bool> operator>=(const valarray<T>&, const valarray<T>&);
template<class T> valarray<bool> operator>=(const valarray<T>&, const T&);
template<class T> valarray<bool> operator>=(const T&, const valarray<T>&);

template<class T> valarray<T> abs  (const valarray<T>&);
template<class T> valarray<T> acos (const valarray<T>&);
template<class T> valarray<T> asin (const valarray<T>&);
template<class T> valarray<T> atan (const valarray<T>&);

template<class T> valarray<T> atan2(const valarray<T>&, const valarray<T>&);
template<class T> valarray<T> atan2(const valarray<T>&, const T&);
template<class T> valarray<T> atan2(const T&, const valarray<T>&);

template<class T> valarray<T> cos  (const valarray<T>&);
template<class T> valarray<T> cosh (const valarray<T>&);
template<class T> valarray<T> exp  (const valarray<T>&);
template<class T> valarray<T> log  (const valarray<T>&);
template<class T> valarray<T> log10(const valarray<T>&);

template<class T> valarray<T> pow(const valarray<T>&, const valarray<T>&);
template<class T> valarray<T> pow(const valarray<T>&, const T&);
template<class T> valarray<T> pow(const T&, const valarray<T>&);

template<class T> valarray<T> sin  (const valarray<T>&);
template<class T> valarray<T> sinh (const valarray<T>&);
template<class T> valarray<T> sqrt (const valarray<T>&);
template<class T> valarray<T> tan  (const valarray<T>&);
template<class T> valarray<T> tanh (const valarray<T>&);

}  // std
*/

#include <mslconfig>
#include <msl_utility>
#include <algorithm>
#include <cmath>

#ifndef RC_INVOKED // hh 971230

#ifdef __MWERKS__
#pragma options align=native
#endif

#ifdef _MSL_FORCE_ENUMS_ALWAYS_INT
	#if _MSL_FORCE_ENUMS_ALWAYS_INT
		#pragma enumsalwaysint on
	#else
		#pragma enumsalwaysint off
	#endif
#endif  // _MSL_FORCE_ENUMS_ALWAYS_INT

#ifdef _MSL_FORCE_ENABLE_BOOL_SUPPORT
	#if _MSL_FORCE_ENABLE_BOOL_SUPPORT
		#pragma bool on
	#else
		#pragma bool off
	#endif
#endif  // _MSL_FORCE_ENABLE_BOOL_SUPPORT

#ifdef min
#undef min
#endif

#ifdef max
#undef max
#endif

#ifndef _MSL_NO_CPP_NAMESPACE
	namespace std {
#endif

// slice

class slice
{
public:
	slice() : start_(0), size_(0), stride_(0) {}
	slice(size_t start, size_t size, size_t stride)
		: start_(start), size_(size), stride_(stride) {}

	size_t start() const {return start_;}
	size_t size() const {return size_;}
	size_t stride() const {return stride_;}
	size_t length() const {return size_;}
private:
	size_t start_;
	size_t size_;
	size_t stride_;
};

template<class T> class valarray;         //  An array of type  T
template<class T> class slice_array;
class gslice;                             //  a generalized slice out of an array
template<class T> class gslice_array;
template<class T> class mask_array;       //  a masked array
template<class T> class indirect_array;   //  an indirected array

template<class T> valarray<T> operator* (const valarray<T>&, const valarray<T>&);
template<class T> valarray<T> operator* (const valarray<T>&, const T&);
template<class T> valarray<T> operator* (const T&, const valarray<T>&);

template<class T> valarray<T> operator/ (const valarray<T>&, const valarray<T>&);
template<class T> valarray<T> operator/ (const valarray<T>&, const T&);
template<class T> valarray<T> operator/ (const T&, const valarray<T>&);

template<class T> valarray<T> operator% (const valarray<T>&, const valarray<T>&);
template<class T> valarray<T> operator% (const valarray<T>&, const T&);
template<class T> valarray<T> operator% (const T&, const valarray<T>&);

template<class T> valarray<T> operator+ (const valarray<T>&, const valarray<T>&);
template<class T> valarray<T> operator+ (const valarray<T>&, const T&);
template<class T> valarray<T> operator+ (const T&, const valarray<T>&);

template<class T> valarray<T> operator- (const valarray<T>&, const valarray<T>&);
template<class T> valarray<T> operator- (const valarray<T>&, const T&);
template<class T> valarray<T> operator- (const T&, const valarray<T>&);

template<class T> valarray<T> operator^ (const valarray<T>&, const valarray<T>&);
template<class T> valarray<T> operator^ (const valarray<T>&, const T&);
template<class T> valarray<T> operator^ (const T&, const valarray<T>&);

template<class T> valarray<T> operator& (const valarray<T>&, const valarray<T>&);
template<class T> valarray<T> operator& (const valarray<T>&, const T&);
template<class T> valarray<T> operator& (const T&, const valarray<T>&);

template<class T> valarray<T> operator| (const valarray<T>&, const valarray<T>&);
template<class T> valarray<T> operator| (const valarray<T>&, const T&);
template<class T> valarray<T> operator| (const T&, const valarray<T>&);

template<class T> valarray<T> operator<< (const valarray<T>&, const valarray<T>&);
template<class T> valarray<T> operator<< (const valarray<T>&, const T&);
template<class T> valarray<T> operator<< (const T&, const valarray<T>&);

template<class T> valarray<T> operator>> (const valarray<T>&, const valarray<T>&);
template<class T> valarray<T> operator>> (const valarray<T>&, const T&);
template<class T> valarray<T> operator>> (const T&, const valarray<T>&);

template<class T> valarray<bool> operator&& (const valarray<T>&, const valarray<T>&);
template<class T> valarray<bool> operator&& (const valarray<T>&, const T&);
template<class T> valarray<bool> operator&& (const T&, const valarray<T>&);

template<class T> valarray<bool> operator|| (const valarray<T>&, const valarray<T>&);
template<class T> valarray<bool> operator|| (const valarray<T>&, const T&);
template<class T> valarray<bool> operator|| (const T&, const valarray<T>&);

template<class T> valarray<bool> operator== (const valarray<T>&, const valarray<T>&);
template<class T> valarray<bool> operator== (const valarray<T>&, const T&);
template<class T> valarray<bool> operator== (const T&, const valarray<T>&);
template<class T> valarray<bool> operator!= (const valarray<T>&, const valarray<T>&);
template<class T> valarray<bool> operator!= (const valarray<T>&, const T&);
template<class T> valarray<bool> operator!= (const T&, const valarray<T>&);

template<class T> valarray<bool> operator<  (const valarray<T>&, const valarray<T>&);
template<class T> valarray<bool> operator<  (const valarray<T>&, const T&);
template<class T> valarray<bool> operator<  (const T&, const valarray<T>&);
template<class T> valarray<bool> operator>  (const valarray<T>&, const valarray<T>&);
template<class T> valarray<bool> operator>  (const valarray<T>&, const T&);
template<class T> valarray<bool> operator>  (const T&, const valarray<T>&);
template<class T> valarray<bool> operator<= (const valarray<T>&, const valarray<T>&);
template<class T> valarray<bool> operator<= (const valarray<T>&, const T&);
template<class T> valarray<bool> operator<= (const T&, const valarray<T>&);
template<class T> valarray<bool> operator>= (const valarray<T>&, const valarray<T>&);
template<class T> valarray<bool> operator>= (const valarray<T>&, const T&);
template<class T> valarray<bool> operator>= (const T&, const valarray<T>&);

template<class T> valarray<T> abs (const valarray<T>&);
template<class T> valarray<T> acos(const valarray<T>&);
template<class T> valarray<T> asin(const valarray<T>&);
template<class T> valarray<T> atan(const valarray<T>&);

template<class T> valarray<T> atan2(const valarray<T>&, const valarray<T>&);
template<class T> valarray<T> atan2(const valarray<T>&, const T&);
template<class T> valarray<T> atan2(const T&, const valarray<T>&);

template<class T> valarray<T> cos  (const valarray<T>&);
template<class T> valarray<T> cosh (const valarray<T>&);
template<class T> valarray<T> exp  (const valarray<T>&);
template<class T> valarray<T> log  (const valarray<T>&);
template<class T> valarray<T> log10(const valarray<T>&);

template<class T> valarray<T> pow(const valarray<T>&, const valarray<T>&);
template<class T> valarray<T> pow(const valarray<T>&, const T&);
template<class T> valarray<T> pow(const T&, const valarray<T>&);

template<class T> valarray<T> sin (const valarray<T>&);
template<class T> valarray<T> sinh(const valarray<T>&);
template<class T> valarray<T> sqrt(const valarray<T>&);
template<class T> valarray<T> tan (const valarray<T>&);
template<class T> valarray<T> tanh(const valarray<T>&);

template<class T>
class valarray
{
public:
	typedef T value_type;

	//  lib.valarray.cons construct/destroy:
	valarray();
	explicit valarray(size_t);
	valarray(const T&, size_t);
	valarray(const T*, size_t);
	valarray(const valarray&);
	valarray(const slice_array<T>&);
	valarray(const gslice_array<T>&);
	valarray(const mask_array<T>&);
	valarray(const indirect_array<T>&);
	~valarray();

	//  lib.valarray.assign assignment:
	valarray<T>& operator=(const valarray<T>&);
	valarray<T>& operator=(const T&);
	valarray<T>& operator=(const slice_array<T>&);
	valarray<T>& operator=(const gslice_array<T>&);
	valarray<T>& operator=(const mask_array<T>&);
	valarray<T>& operator=(const indirect_array<T>&);

	//  lib.valarray.access element access:
	T                 operator[](size_t) const;
	T&                operator[](size_t);

	//  lib.valarray.sub subset operations:
	valarray<T>       operator[](slice) const;
	slice_array<T>    operator[](slice);
	valarray<T>       operator[](const gslice&) const;
	gslice_array<T>   operator[](const gslice&);
	valarray<T>       operator[](const valarray<bool>&) const;
	mask_array<T>     operator[](const valarray<bool>&);
	valarray<T>       operator[](const valarray<size_t>&) const;
	indirect_array<T> operator[](const valarray<size_t>&);

	//  lib.valarray.unary unary operators:
	valarray<T> operator+() const;
	valarray<T> operator-() const;
	valarray<T> operator~() const;
	valarray<bool> operator!() const;

	//  lib.valarray.cassign computed assignment:
	valarray<T>& operator*= (const T&);
	valarray<T>& operator/= (const T&);
	valarray<T>& operator%= (const T&);
	valarray<T>& operator+= (const T&);
	valarray<T>& operator-= (const T&);
	valarray<T>& operator^= (const T&);
	valarray<T>& operator&= (const T&);
	valarray<T>& operator|= (const T&);
	valarray<T>& operator<<=(const T&);
	valarray<T>& operator>>=(const T&);

	valarray<T>& operator*= (const valarray<T>&);
	valarray<T>& operator/= (const valarray<T>&);
	valarray<T>& operator%= (const valarray<T>&);
	valarray<T>& operator+= (const valarray<T>&);
	valarray<T>& operator-= (const valarray<T>&);
	valarray<T>& operator^= (const valarray<T>&);
	valarray<T>& operator|= (const valarray<T>&);
	valarray<T>& operator&= (const valarray<T>&);
	valarray<T>& operator<<=(const valarray<T>&);
	valarray<T>& operator>>=(const valarray<T>&);

	//  lib.valarray.members member functions:
	size_t size() const;

	T    sum() const;
	T    min() const;
	T    max() const;

	valarray<T> shift (int) const;
	valarray<T> cshift(int) const;
	valarray<T> apply(T func(T)) const;
	valarray<T> apply(T func(const T&)) const;
	void resize(size_t sz, T c = T());

private:
	T* data_;
	size_t size_;

	void change_size(size_t newsize);
	void init(size_t newsize);

	template <class U> friend class valarray;

	friend valarray operator*<T>(const valarray&, const valarray&);
	friend valarray operator*<T>(const valarray&, const T&);
	friend valarray operator*<T>(const T&, const valarray&);

	friend valarray operator/<T>(const valarray&, const valarray&);
	friend valarray operator/<T>(const valarray&, const T&);
	friend valarray operator/<T>(const T&, const valarray&);

	friend valarray operator%<T>(const valarray&, const valarray&);
	friend valarray operator%<T>(const valarray&, const T&);
	friend valarray operator%<T>(const T&, const valarray&);

	friend valarray operator+<T>(const valarray&, const valarray&);
	friend valarray operator+<T>(const valarray&, const T&);
	friend valarray operator+<T>(const T&, const valarray&);

	friend valarray operator-<T>(const valarray&, const valarray&);
	friend valarray operator-<T>(const valarray&, const T&);
	friend valarray operator-<T>(const T&, const valarray&);

	friend valarray operator^<T>(const valarray&, const valarray&);
	friend valarray operator^<T>(const valarray&, const T&);
	friend valarray operator^<T>(const T&, const valarray&);

	friend valarray operator&<T>(const valarray&, const valarray&);
	friend valarray operator&<T>(const valarray&, const T&);
	friend valarray operator&<T>(const T&, const valarray&);

	friend valarray operator|<T>(const valarray&, const valarray&);
	friend valarray operator|<T>(const valarray&, const T&);
	friend valarray operator|<T>(const T&, const valarray&);

	friend valarray operator<< <T>(const valarray&, const valarray&);
	friend valarray operator<< <T>(const valarray&, const T&);
	friend valarray operator<< <T>(const T&, const valarray&);

	friend valarray operator>> <T>(const valarray&, const valarray&);
	friend valarray operator>> <T>(const valarray&, const T&);
	friend valarray operator>> <T>(const T&, const valarray&);

	template <class U> friend valarray<bool> operator&&(const valarray<U>&, const valarray<U>&);
	template <class U> friend valarray<bool> operator&&(const valarray<U>&, const U&);
	template <class U> friend valarray<bool> operator&&(const U&, const valarray<U>&);

	template <class U> friend valarray<bool> operator||(const valarray<U>&, const valarray<U>&);
	template <class U> friend valarray<bool> operator||(const valarray<U>&, const U&);
	template <class U> friend valarray<bool> operator||(const U&, const valarray<U>&);

	template <class U> friend valarray<bool> operator==(const valarray<U>&, const valarray<U>&);
	template <class U> friend valarray<bool> operator==(const valarray<U>&, const U&);
	template <class U> friend valarray<bool> operator==(const U&, const valarray<U>&);

	template <class U> friend valarray<bool> operator!=(const valarray<U>&, const valarray<U>&);
	template <class U> friend valarray<bool> operator!=(const valarray<U>&, const U&);
	template <class U> friend valarray<bool> operator!=(const U&, const valarray<U>&);

	template <class U> friend valarray<bool> operator< (const valarray<U>&, const valarray<U>&);
	template <class U> friend valarray<bool> operator< (const valarray<U>&, const U&);
	template <class U> friend valarray<bool> operator< (const U&, const valarray<U>&);

	template <class U> friend valarray<bool> operator<=(const valarray<U>&, const valarray<U>&);
	template <class U> friend valarray<bool> operator<=(const valarray<U>&, const U&);
	template <class U> friend valarray<bool> operator<=(const U&, const valarray<U>&);

	template <class U> friend valarray<bool> operator> (const valarray<U>&, const valarray<U>&);
	template <class U> friend valarray<bool> operator> (const valarray<U>&, const U&);
	template <class U> friend valarray<bool> operator> (const U&, const valarray<U>&);

	template <class U> friend valarray<bool> operator>=(const valarray<U>&, const valarray<U>&);
	template <class U> friend valarray<bool> operator>=(const valarray<U>&, const U&);
	template <class U> friend valarray<bool> operator>=(const U&, const valarray<U>&);

	friend valarray abs<T>(const valarray&);
	friend valarray acos<T>(const valarray&);
	friend valarray asin<T>(const valarray&);
	friend valarray atan<T>(const valarray&);
	friend valarray atan2<T>(const valarray&, const valarray&);
	friend valarray atan2<T>(const valarray&, const T&);
	friend valarray atan2<T>(const T&, const valarray&);
	friend valarray cos<T>(const valarray&);
	friend valarray cosh<T>(const valarray&);
	friend valarray exp<T>(const valarray&);
	friend valarray log<T>(const valarray&);
	friend valarray log10<T>(const valarray&);
	friend valarray pow<T>(const valarray&, const valarray&);
	friend valarray pow<T>(const valarray&, const T&);
	friend valarray pow<T>(const T&, const valarray&);
	friend valarray sin<T>(const valarray&);
	friend valarray sinh<T>(const valarray&);
	friend valarray sqrt<T>(const valarray&);
	friend valarray tan<T>(const valarray&);
	friend valarray tanh<T>(const valarray&);
};

// gslice

class gslice
{
public:
	gslice();
	gslice(size_t start, const valarray<size_t>& sizes, const valarray<size_t>& strides);

	size_t start() const;
	const valarray<size_t>& size() const;
	const valarray<size_t>& stride() const;
	size_t length() const;
private:
	size_t start_;
	valarray<size_t> size_;
	valarray<size_t> stride_;
	size_t length_;
};

// gslice Implementation

inline
gslice::gslice()
	: start_(0),
	  length_(0)
{
}

inline
gslice::gslice(size_t start, const valarray<size_t>& sizes, const valarray<size_t>& strides)
	: start_(start),
	  size_(sizes),
	  stride_(strides),
	  length_(0)
{
	if (size_.size() > 0)
	{
		length_ = 1;
		for (size_t i = 0; i < size_.size(); ++i)
			length_ *= size_[i];
	}
}

inline
size_t
gslice::start() const
{
	return start_;
}

inline
const valarray<size_t>&
gslice::size() const
{
	return size_;
}

inline
const valarray<size_t>&
gslice::stride() const
{
	return stride_;
}

inline
size_t
gslice::length() const
{
	return length_;
}

// valarray Implementation

template<class T>
inline
void
valarray<T>::init(size_t newsize)
{
	data_ = new T [newsize];
#ifdef _MSL_NO_EXCEPTIONS
	if (data_ == 0)
		__msl_error("valarray<T>::change_size out of memory");
#endif  // _MSL_NO_EXCEPTIONS
	size_ = newsize;
}

template<class T>
inline
void
valarray<T>::change_size(size_t newsize)
{
	T* newdata = new T [newsize];
#ifdef _MSL_NO_EXCEPTIONS
	if (newdata == 0)
		__msl_error("valarray<T>::change_size out of memory");
#endif  // _MSL_NO_EXCEPTIONS
	delete [] data_;
	data_ = newdata;
	size_ = newsize;
}

template<class T>
inline
valarray<T>::valarray()
	:	data_(0),
		size_(0)
{
}

template<class T>
valarray<T>::valarray(size_t n)
	:	data_(0),
		size_(n)
{
	if (size_ > 0)
	{
		data_ = new T [size_];
	#ifdef _MSL_NO_EXCEPTIONS
		if (data_ == 0)
			__msl_error("valarray<T>::valarray out of memory");
	#endif  // _MSL_NO_EXCEPTIONS
		if (Metrowerks::is_scalar<T>::value)
			_STD::fill_n(data_, size_, T());
	}
}

template<class T>
valarray<T>::valarray(const T& t, size_t n)
	:	data_(0),
		size_(n)
{
	if (size_ > 0)
	{
		data_ = new T [size_];
	#ifdef _MSL_NO_EXCEPTIONS
		if (data_ == 0)
			__msl_error("valarray<T>::valarray out of memory");
	#endif  // _MSL_NO_EXCEPTIONS
		_STD::fill_n(data_, size_, t);
	}
}

template<class T>
valarray<T>::valarray(const T* t, size_t n)
	:	data_(0),
		size_(n)
{
	if (size_ > 0)
	{
		data_ = new T [size_];
	#ifdef _MSL_NO_EXCEPTIONS
		if (data_ == 0)
			__msl_error("valarray<T>::valarray out of memory");
	#endif  // _MSL_NO_EXCEPTIONS
		_STD::copy(t, t + size_, data_);
	}
}

template<class T>
valarray<T>::valarray(const valarray& v)
	:	data_(0),
		size_(v.size_)
{
	if (size_ > 0)
	{
		data_ = new T [size_];
	#ifdef _MSL_NO_EXCEPTIONS
		if (data_ == 0)
			__msl_error("valarray<T>::valarray out of memory");
	#endif  // _MSL_NO_EXCEPTIONS
		_STD::copy(v.data_, v.data_ + size_, data_);
	}
}

template<class T>
valarray<T>::valarray(const slice_array<T>& sa)
	:	data_(0),
		size_(sa.get_slice().length())
{
	if (size_ > 0)
	{
		data_ = new T [size_];
	#ifdef _MSL_NO_EXCEPTIONS
		if (data_ == 0)
			__msl_error("valarray<T>::valarray out of memory");
	#endif  // _MSL_NO_EXCEPTIONS
		typename slice_array<T>::iterator k = sa.begin();
		for (size_t i = 0; i < size_; ++i, ++k)
			data_[i] = *k;
	}
}

template<class T>
valarray<T>::valarray(const gslice_array<T>& gsa)
	:	data_(0),
		size_(gsa.get_gslice().length())
{
	if (size_ > 0)
	{
		data_ = new T [size_];
	#ifdef _MSL_NO_EXCEPTIONS
		if (data_ == 0)
			__msl_error("valarray<T>::valarray out of memory");
	#endif  // _MSL_NO_EXCEPTIONS
		typename gslice_array<T>::iterator k = gsa.begin();
		for (size_t i = 0; i < size_; ++i, ++k)
			data_[i] = *k;
	}
}

template<class T>
valarray<T>::valarray(const mask_array<T>& ma)
	:	data_(0),
		size_(ma.length())
{
	if (size_ > 0)
	{
		data_ = new T [size_];
	#ifdef _MSL_NO_EXCEPTIONS
		if (data_ == 0)
			__msl_error("valarray<T>::valarray out of memory");
	#endif  // _MSL_NO_EXCEPTIONS
		typename mask_array<T>::iterator k = ma.begin();
		for (size_t i = 0; i < size_; ++i, ++k)
			data_[i] = *k;
	}
}

template<class T>
valarray<T>::valarray(const indirect_array<T>& ia)
	:	data_(0),
		size_(ia.length())
{
	if (size_ > 0)
	{
		data_ = new T [size_];
	#ifdef _MSL_NO_EXCEPTIONS
		if (data_ == 0)
			__msl_error("valarray<T>::valarray out of memory");
	#endif  // _MSL_NO_EXCEPTIONS
		typename indirect_array<T>::iterator k = ia.begin();
		for (size_t i = 0; i < size_; ++i, ++k)
			data_[i] = *k;
	}
}

template<class T>
inline
valarray<T>::~valarray()
{
	delete [] data_;
}

template<class T>
valarray<T>&
valarray<T>::operator=(const valarray<T>& v)
{
	if (this == &v)
		return *this;
	if (size() != v.size())
		change_size(v.size());
	_STD::copy(v.data_, v.data_ + size_, data_);
	return *this;
}

template<class T>
inline
valarray<T>&
valarray<T>::operator=(const T& t)
{
	_STD::fill_n(data_, size_, t);
	return *this;
}

template<class T>
valarray<T>&
valarray<T>::operator=(const slice_array<T>& sa)
{
	const valarray& v = sa.array();
	if (this == &v)
		return *this = valarray(sa);
	const slice& s = sa.get_slice();
	if (size() != s.length())
		change_size(s.length());
	if (size() > 0)
	{
		typename slice_array<T>::iterator k = sa.begin();
		for (size_t i = 0; i < size_; ++i, ++k)
			data_[i] = *k;
	}
	return *this;
}

template<class T>
valarray<T>&
valarray<T>::operator=(const gslice_array<T>& gsa)
{
	const valarray& v = gsa.array();
	if (this == &v)
		return *this = valarray(gsa);
	const gslice& gs = gsa.get_gslice();
	if (size() != gs.length())
		change_size(gs.length());
	if (size() > 0)
	{
		typename gslice_array<T>::iterator k = gsa.begin();
		for (size_t i = 0; i < size_; ++i, ++k)
			data_[i] = *k;
	}
	return *this;
}

template<class T>
valarray<T>&
valarray<T>::operator=(const mask_array<T>& ma)
{
	const valarray& v = ma.array();
	if (this == &v)
		return *this = valarray(ma);
	if (size() != ma.length())
		change_size(ma.length());
	if (size() > 0)
	{
		typename mask_array<T>::iterator k = ma.begin();
		for (size_t i = 0; i < size_; ++i, ++k)
			data_[i] = *k;
	}
	return *this;
}

template<class T>
valarray<T>&
valarray<T>::operator=(const indirect_array<T>& ia)
{
	const valarray& v = ia.array();
	if (this == &v)
		return *this = valarray(ia);
	if (size() != ia.length())
		change_size(ia.length());
	if (size() > 0)
	{
		typename indirect_array<T>::iterator k = ia.begin();
		for (size_t i = 0; i < size_; ++i, ++k)
			data_[i] = *k;
	}
	return *this;
}

template<class T>
inline
T
valarray<T>::operator[](size_t i) const
{
	return data_[i];
}

template<class T>
inline
T&
valarray<T>::operator[](size_t i)
{
	return data_[i];
}

template<class T>
inline
valarray<T>
valarray<T>::operator[](slice s) const
{
	return slice_array<T>(const_cast<valarray<T>&>(*this), s);
}

template<class T>
inline
slice_array<T>
valarray<T>::operator[](slice s)
{
	return slice_array<T>(*this, s);
}

template<class T>
inline
valarray<T>
valarray<T>::operator[](const gslice& gs) const
{
	return gslice_array<T>(const_cast<valarray<T>&>(*this), gs);
}

template<class T>
inline
gslice_array<T>
valarray<T>::operator[](const gslice& gs)
{
	return gslice_array<T>(*this, gs);
}

template<class T>
inline
valarray<T>
valarray<T>::operator[](const valarray<bool>& b) const
{
	return mask_array<T>(const_cast<valarray<T>&>(*this), b);
}

template<class T>
inline
mask_array<T>
valarray<T>::operator[](const valarray<bool>& b)
{
	return mask_array<T>(*this, b);
}

template<class T>
inline
valarray<T>
valarray<T>::operator[](const valarray<size_t>& ia) const
{
	return indirect_array<T>(const_cast<valarray<T>&>(*this), ia);
}

template<class T>
inline
indirect_array<T>
valarray<T>::operator[](const valarray<size_t>& ia)
{
	return indirect_array<T>(*this, ia);
}

template<class T>
valarray<T>
valarray<T>::operator+() const
{
	valarray result;
	result.init(size_);
	for (size_t i = 0; i < size_; ++i)
		result[i] = static_cast<T>(+data_[i]);
	return result;
}

template<class T>
valarray<T>
valarray<T>::operator-() const
{
	valarray result;
	result.init(size_);
	for (size_t i = 0; i < size_; ++i)
		result[i] = static_cast<T>(-data_[i]);
	return result;
}

template<class T>
valarray<bool>
valarray<T>::operator!() const
{
	valarray<bool> result;
	result.init(size_);
	for (size_t i = 0; i < size_; ++i)
		result[i] = static_cast<bool>(!data_[i]);
	return result;
}

template<class T>
valarray<T>
valarray<T>::operator~() const
{
	valarray result;
	result.init(size_);
	for (size_t i = 0; i < size_; ++i)
		result[i] = static_cast<T>(~data_[i]);
	return result;
}

template<class T>
inline
valarray<T>&
valarray<T>::operator*= (const T& t)
{
	for (size_t i = 0; i < size_; ++i)
		data_[i] *= t;
	return *this;
}

template<class T>
inline
valarray<T>&
valarray<T>::operator/= (const T& t)
{
	for (size_t i = 0; i < size_; ++i)
		data_[i] /= t;
	return *this;
}

template<class T>
inline
valarray<T>&
valarray<T>::operator%= (const T& t)
{
	for (size_t i = 0; i < size_; ++i)
		data_[i] %= t;
	return *this;
}

template<class T>
inline
valarray<T>&
valarray<T>::operator+= (const T& t)
{
	for (size_t i = 0; i < size_; ++i)
		data_[i] += t;
	return *this;
}

template<class T>
inline
valarray<T>&
valarray<T>::operator-= (const T& t)
{
	for (size_t i = 0; i < size_; ++i)
		data_[i] -= t;
	return *this;
}

template<class T>
inline
valarray<T>&
valarray<T>::operator^= (const T& t)
{
	for (size_t i = 0; i < size_; ++i)
		data_[i] ^= t;
	return *this;
}

template<class T>
inline
valarray<T>&
valarray<T>::operator&= (const T& t)
{
	for (size_t i = 0; i < size_; ++i)
		data_[i] &= t;
	return *this;
}

template<class T>
inline
valarray<T>&
valarray<T>::operator|= (const T& t)
{
	for (size_t i = 0; i < size_; ++i)
		data_[i] |= t;
	return *this;
}

template<class T>
inline
valarray<T>&
valarray<T>::operator<<= (const T& t)
{
	for (size_t i = 0; i < size_; ++i)
		data_[i] <<= t;
	return *this;
}

template<class T>
inline
valarray<T>&
valarray<T>::operator>>= (const T& t)
{
	for (size_t i = 0; i < size_; ++i)
		data_[i] >>= t;
	return *this;
}

template<class T>
inline
valarray<T>&
valarray<T>::operator*= (const valarray<T>& v)
{
	for (size_t i = 0; i < size_; ++i)
		data_[i] *= v[i];
	return *this;
}

template<class T>
inline
valarray<T>&
valarray<T>::operator/= (const valarray<T>& v)
{
	for (size_t i = 0; i < size_; ++i)
		data_[i] /= v[i];
	return *this;
}

template<class T>
inline
valarray<T>&
valarray<T>::operator%= (const valarray<T>& v)
{
	for (size_t i = 0; i < size_; ++i)
		data_[i] %= v[i];
	return *this;
}

template<class T>
inline
valarray<T>&
valarray<T>::operator+= (const valarray<T>& v)
{
	for (size_t i = 0; i < size_; ++i)
		data_[i] += v[i];
	return *this;
}

template<class T>
inline
valarray<T>&
valarray<T>::operator-= (const valarray<T>& v)
{
	for (size_t i = 0; i < size_; ++i)
		data_[i] -= v[i];
	return *this;
}

template<class T>
inline
valarray<T>&
valarray<T>::operator^= (const valarray<T>& v)
{
	for (size_t i = 0; i < size_; ++i)
		data_[i] ^= v[i];
	return *this;
}

template<class T>
inline
valarray<T>&
valarray<T>::operator|= (const valarray<T>& v)
{
	for (size_t i = 0; i < size_; ++i)
		data_[i] |= v[i];
	return *this;
}

template<class T>
inline
valarray<T>&
valarray<T>::operator&= (const valarray<T>& v)
{
	for (size_t i = 0; i < size_; ++i)
		data_[i] &= v[i];
	return *this;
}

template<class T>
inline
valarray<T>&
valarray<T>::operator<<= (const valarray<T>& v)
{
	for (size_t i = 0; i < size_; ++i)
		data_[i] <<= v[i];
	return *this;
}

template<class T>
inline
valarray<T>&
valarray<T>::operator>>= (const valarray<T>& v)
{
	for (size_t i = 0; i < size_; ++i)
		data_[i] >>= v[i];
	return *this;
}

template<class T>
inline
size_t
valarray<T>::size() const
{
	return size_;
}

template<class T>
T
valarray<T>::sum() const
{
	if (size_ == 0)
		return T();
	T result = data_[0];
	for (size_t i = 1; i < size_; ++i)
		result += data_[i];
	return result;
}

template<class T>
T
valarray<T>::min() const
{
	if (size_ == 0)
		return T();
	T result = data_[0];
	for (size_t i = 1; i < size_; ++i)
		if (data_[i] < result)
			result = data_[i];
	return result;
}

template<class T>
T
valarray<T>::max() const
{
	if (size_ == 0)
		return T();
	T result = data_[0];
	for (size_t i = 1; i < size_; ++i)
		if (result < data_[i])
			result = data_[i];
	return result;
}

template<class T>
valarray<T>
valarray<T>::shift (int n) const
{
	valarray result;
	result.init(size_);
	size_t start;
	size_t end;
	if (n >= 0)
	{
		start = 0;
		if (n <= size_)
			end = size_ - n;
		else
			end = 0;
	}
	else
	{
		start = size_t(-n);
		end = size_;
	}
	{
	for (size_t i = 0; i < start; ++i)
		result[i] = T();
	}
	{
	for (size_t i = start; i < end; ++i)
		result[i] = data_[i+n];
	}
	{
	for (size_t i = end; i < size_; ++i)
		result[i] = T();
	}
	return result;
}

template<class T>
valarray<T>
valarray<T>::cshift(int n) const
{
	valarray result;
	result.init(size_);
	if (size_ > 0)
	{
		while (n < 0)
			n += (int)size_;
		for (size_t i = 0; i < size_; ++i)
			result[i] = data_[(i + n) % size_];
	}
	return result;
}

template<class T>
valarray<T>
valarray<T>::apply(T func(T)) const
{
	valarray result;
	result.init(size_);
	for (size_t i = 0; i < result.size(); ++i)
		result[i] = func(data_[i]);
	return result;
}

template<class T>
valarray<T>
valarray<T>::apply(T func(const T&)) const
{
	valarray result;
	result.init(size_);
	for (size_t i = 0; i < result.size(); ++i)
		result[i] = func(data_[i]);
	return result;
}

template<class T>
void
valarray<T>::resize(size_t sz, T c)
{
	if (size_ != sz)
		change_size(sz);
	_STD::fill_n(data_, size_, c);
}

// slice_array

template <class T>
class slice_array_iterator
{
public:
	T& operator* ();
	slice_array_iterator& operator++ ();
private:
	size_t stride_;
	T* ptr_;

	slice_array_iterator(const slice_array<T>* sa);

	friend class slice_array<T>;
};

template <class T>
inline
T&
slice_array_iterator<T>::operator*()
{
	return *ptr_;
}

template <class T>
inline
slice_array_iterator<T>&
slice_array_iterator<T>::operator++ ()
{
	ptr_ += stride_;
	return *this;
}

template <class T>
inline
slice_array_iterator<T>::slice_array_iterator(const slice_array<T>* sa)
{
	const slice& s = sa->get_slice();
	stride_ = s.stride();
	ptr_ = &const_cast<slice_array<T>*>(sa)->array()[s.start()];
}

template <class T>
class slice_array
{
public:
	typedef T value_type;

	void operator=  (const valarray<T>&) const;
	void operator*= (const valarray<T>&) const;
	void operator/= (const valarray<T>&) const;
	void operator%= (const valarray<T>&) const;
	void operator+= (const valarray<T>&) const;
	void operator-= (const valarray<T>&) const;
	void operator^= (const valarray<T>&) const;
	void operator&= (const valarray<T>&) const;
	void operator|= (const valarray<T>&) const;
	void operator<<=(const valarray<T>&) const;
	void operator>>=(const valarray<T>&) const;

	void operator=(const T&) const;
	// ~slice_array();  // uses compiler generated
private:
	slice_array();                              // Not defined

	typedef slice_array_iterator<T> iterator;

	slice_array(valarray<T>& v, const slice& s);
	const slice& get_slice() const;
	valarray<T>& array();
	const valarray<T>& array() const;
	iterator begin() const;

	valarray<T>* v_;
	slice slice_;

	friend class valarray<T>;
	friend class slice_array_iterator<T>;
};

// slice_array Implementation

template <class T>
void
slice_array<T>::operator= (const valarray<T>& v) const
{
	size_t end = slice_.length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k = v[i];
	}
}

template <class T>
void
slice_array<T>::operator*= (const valarray<T>& v) const
{
	size_t end = slice_.length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k *= v[i];
	}
}

template <class T>
void
slice_array<T>::operator/= (const valarray<T>& v) const
{
	size_t end = slice_.length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k /= v[i];
	}
}

template <class T>
void
slice_array<T>::operator%= (const valarray<T>& v) const
{
	size_t end = slice_.length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k %= v[i];
	}
}

template <class T>
void
slice_array<T>::operator+= (const valarray<T>& v) const
{
	size_t end = slice_.length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k += v[i];
	}
}

template <class T>
void
slice_array<T>::operator-= (const valarray<T>& v) const
{
	size_t end = slice_.length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k -= v[i];
	}
}

template <class T>
void
slice_array<T>::operator^= (const valarray<T>& v) const
{
	size_t end = slice_.length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k ^= v[i];
	}
}

template <class T>
void
slice_array<T>::operator&= (const valarray<T>& v) const
{
	size_t end = slice_.length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k &= v[i];
	}
}

template <class T>
void
slice_array<T>::operator|= (const valarray<T>& v) const
{
	size_t end = slice_.length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k |= v[i];
	}
}

template <class T>
void
slice_array<T>::operator<<= (const valarray<T>& v) const
{
	size_t end = slice_.length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k <<= v[i];
	}
}

template <class T>
void
slice_array<T>::operator>>= (const valarray<T>& v) const
{
	size_t end = slice_.length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k >>= v[i];
	}
}

template <class T>
void
slice_array<T>::operator=(const T& t) const
{
	size_t end = slice_.length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k = t;
	}
}

template <class T>
inline
slice_array<T>::slice_array(valarray<T>& v, const slice& s)
	: v_(&v),
	  slice_(s)
{
}

template <class T>
inline
const slice&
slice_array<T>::get_slice() const
{
	return slice_;
}

template <class T>
inline
valarray<T>&
slice_array<T>::array()
{
	return *v_;
}

template <class T>
inline
const valarray<T>&
slice_array<T>::array() const
{
	return *v_;
}

template <class T>
inline
typename slice_array<T>::iterator
slice_array<T>::begin() const
{
	return iterator(this);
}

// gslice_array

template <class T>
class gslice_array_iterator
{
public:
	T& operator* ();
	gslice_array_iterator& operator++ ();
private:
	size_t stride_;
	T* start_ptr_;
	const valarray<size_t>* sizes_;
	const valarray<size_t>* strides_;
	valarray<size_t> indices_;
	T* ptr_;

	gslice_array_iterator(const gslice_array<T>* gsa);

	friend class gslice_array<T>;
};

template <class T>
inline
T&
gslice_array_iterator<T>::operator*()
{
	return *ptr_;
}

template <class T>
gslice_array_iterator<T>&
gslice_array_iterator<T>::operator++ ()
{
	size_t i = indices_.size() - 1;
	while (true)
	{
		indices_[i] += 1;
		if (indices_[i] < (*sizes_)[i])
		{
			if (i == indices_.size() - 1)
				ptr_ += stride_;
			else
			{
				ptr_ = start_ptr_;
				for (size_t k = 0; k < indices_.size(); ++k)
					ptr_ += indices_[k] * (*strides_)[k];
			}
			break;
		}
		indices_[i] = 0;
		if (i == 0)
		{
			ptr_ = start_ptr_;
			break;
		}
		--i;
	}
	return *this;
}

template <class T>
gslice_array_iterator<T>::gslice_array_iterator(const gslice_array<T>* gsa)
	: indices_(gsa->get_gslice().size().size())
{
	const gslice& gs = gsa->get_gslice();
	sizes_ = &gs.size();
	strides_ = &gs.stride();
	start_ptr_ = &const_cast<gslice_array<T>*>(gsa)->array()[gs.start()];
	stride_ = (*strides_)[indices_.size()-1];
	ptr_ = start_ptr_;
}

template <class T>
class gslice_array
{
public:
	typedef T value_type;

	void operator=  (const valarray<T>&) const;
	void operator*= (const valarray<T>&) const;
	void operator/= (const valarray<T>&) const;
	void operator%= (const valarray<T>&) const;
	void operator+= (const valarray<T>&) const;
	void operator-= (const valarray<T>&) const;
	void operator^= (const valarray<T>&) const;
	void operator&= (const valarray<T>&) const;
	void operator|= (const valarray<T>&) const;
	void operator<<=(const valarray<T>&) const;
	void operator>>=(const valarray<T>&) const;

	void operator=(const T&) const;
	// ~gslice_array();  use compiler generated
private:
	gslice_array();                               // Not defined

	typedef gslice_array_iterator<T> iterator;

	gslice_array(valarray<T>& v, const gslice& gs);
	const gslice& get_gslice() const;
	valarray<T>& array();
	const valarray<T>& array() const;
	iterator begin() const;

	valarray<T>* v_;
	gslice gslice_;

	friend class valarray<T>;
	friend class gslice_array_iterator<T>;
};

// gslice_array Implementation

template <class T>
void
gslice_array<T>::operator= (const valarray<T>& v) const
{
	size_t end = gslice_.length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k = v[i];
	}
}

template <class T>
void
gslice_array<T>::operator*= (const valarray<T>& v) const
{
	size_t end = gslice_.length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k *= v[i];
	}
}

template <class T>
void
gslice_array<T>::operator/= (const valarray<T>& v) const
{
	size_t end = gslice_.length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k /= v[i];
	}
}

template <class T>
void
gslice_array<T>::operator%= (const valarray<T>& v) const
{
	size_t end = gslice_.length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k %= v[i];
	}
}

template <class T>
void
gslice_array<T>::operator+= (const valarray<T>& v) const
{
	size_t end = gslice_.length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k += v[i];
	}
}

template <class T>
void
gslice_array<T>::operator-= (const valarray<T>& v) const
{
	size_t end = gslice_.length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k -= v[i];
	}
}

template <class T>
void
gslice_array<T>::operator^= (const valarray<T>& v) const
{
	size_t end = gslice_.length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k ^= v[i];
	}
}

template <class T>
void
gslice_array<T>::operator&= (const valarray<T>& v) const
{
	size_t end = gslice_.length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k &= v[i];
	}
}

template <class T>
void
gslice_array<T>::operator|= (const valarray<T>& v) const
{
	size_t end = gslice_.length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k |= v[i];
	}
}

template <class T>
void
gslice_array<T>::operator<<= (const valarray<T>& v) const
{
	size_t end = gslice_.length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k <<= v[i];
	}
}

template <class T>
void
gslice_array<T>::operator>>= (const valarray<T>& v) const
{
	size_t end = gslice_.length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k >>= v[i];
	}
}

template <class T>
void
gslice_array<T>::operator=(const T& t) const
{
	size_t end = gslice_.length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k = t;
	}
}

template <class T>
inline
gslice_array<T>::gslice_array(valarray<T>& v, const gslice& gs)
	: v_(&v),
	  gslice_(gs)
{
}

template <class T>
inline
const gslice&
gslice_array<T>::get_gslice() const
{
	return gslice_;
}

template <class T>
inline
valarray<T>&
gslice_array<T>::array()
{
	return *v_;
}

template <class T>
inline
const valarray<T>&
gslice_array<T>::array() const
{
	return *v_;
}

template <class T>
inline
typename gslice_array<T>::iterator
gslice_array<T>::begin() const
{
	return iterator(this);
}

// mask_array

template <class T>
class mask_array_iterator
{
public:
	T& operator* ();
	mask_array_iterator& operator++ ();
private:
	size_t i_;
	const valarray<bool>* mask_;
	T* ptr_;

	mask_array_iterator(const mask_array<T>* ma);

	friend class mask_array<T>;
};

template <class T>
inline
T&
mask_array_iterator<T>::operator*()
{
	return *ptr_;
}

template <class T>
inline
mask_array_iterator<T>&
mask_array_iterator<T>::operator++ ()
{
	++i_;
	++ptr_;
	while (!(*mask_)[i_])
	{
		++i_;
		++ptr_;
	}
	return *this;
}

template <class T>
mask_array_iterator<T>::mask_array_iterator(const mask_array<T>* ma)
	: mask_(&ma->mask()),
	  i_(0),
	  ptr_(&const_cast<mask_array<T>*>(ma)->array()[0])
{
	while (!(*mask_)[i_])
	{
		++i_;
		++ptr_;
	}
}

template <class T>
class mask_array
{
public:
	typedef T value_type;

	void operator=  (const valarray<T>&) const;
	void operator*= (const valarray<T>&) const;
	void operator/= (const valarray<T>&) const;
	void operator%= (const valarray<T>&) const;
	void operator+= (const valarray<T>&) const;
	void operator-= (const valarray<T>&) const;
	void operator^= (const valarray<T>&) const;
	void operator&= (const valarray<T>&) const;
	void operator|= (const valarray<T>&) const;
	void operator<<=(const valarray<T>&) const;
	void operator>>=(const valarray<T>&) const;

	void operator=(const T&) const;
	// ~mask_array();  use compiler generated
private:
	mask_array();                              // Not defined

	typedef mask_array_iterator<T> iterator;

	mask_array(valarray<T>& v, const valarray<bool>& mask);
	const valarray<bool>& mask() const;
	valarray<T>& array();
	const valarray<T>& array() const;
	iterator begin() const;
	size_t length() const;

	valarray<T>* v_;
	valarray<bool> mask_;
	size_t length_;

	friend class valarray<T>;
	friend class mask_array_iterator<T>;
};

template <class T>
void
mask_array<T>::operator= (const valarray<T>& v) const
{
	size_t end = length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k = v[i];
	}
}

template <class T>
void
mask_array<T>::operator*= (const valarray<T>& v) const
{
	size_t end = length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k *= v[i];
	}
}

template <class T>
void
mask_array<T>::operator/= (const valarray<T>& v) const
{
	size_t end = length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k /= v[i];
	}
}

template <class T>
void
mask_array<T>::operator%= (const valarray<T>& v) const
{
	size_t end = length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k %= v[i];
	}
}

template <class T>
void
mask_array<T>::operator+= (const valarray<T>& v) const
{
	size_t end = length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k += v[i];
	}
}

template <class T>
void
mask_array<T>::operator-= (const valarray<T>& v) const
{
	size_t end = length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k -= v[i];
	}
}

template <class T>
void
mask_array<T>::operator^= (const valarray<T>& v) const
{
	size_t end = length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k ^= v[i];
	}
}

template <class T>
void
mask_array<T>::operator&= (const valarray<T>& v) const
{
	size_t end = length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k &= v[i];
	}
}

template <class T>
void
mask_array<T>::operator|= (const valarray<T>& v) const
{
	size_t end = length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k |= v[i];
	}
}

template <class T>
void
mask_array<T>::operator<<= (const valarray<T>& v) const
{
	size_t end = length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k <<= v[i];
	}
}

template <class T>
void
mask_array<T>::operator>>= (const valarray<T>& v) const
{
	size_t end = length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k >>= v[i];
	}
}

template <class T>
void
mask_array<T>::operator=(const T& t) const
{
	size_t end = length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k = t;
	}
}

template <class T>
mask_array<T>::mask_array(valarray<T>& v, const valarray<bool>& mask)
	: v_(&v),
	  mask_(mask),
	  length_(0)
{
	size_t e = v.size();
	if (e > mask.size())
		e = mask.size();
	for (size_t i = 0; i < e; ++i)
		if (mask_[i])
			++length_;
}

template <class T>
inline
const valarray<bool>&
mask_array<T>::mask() const
{
	return mask_;
}

template <class T>
inline
valarray<T>&
mask_array<T>::array()
{
	return *v_;
}

template <class T>
inline
const valarray<T>&
mask_array<T>::array() const
{
	return *v_;
}

template <class T>
inline
typename mask_array<T>::iterator
mask_array<T>::begin() const
{
	return iterator(this);
}

template <class T>
inline
size_t
mask_array<T>::length() const
{
	return length_;
}

// indirect_array

template <class T>
class indirect_array_iterator
{
public:
	T& operator* ();
	indirect_array_iterator& operator++ ();
private:
	size_t i_;
	const indirect_array<T>* ia_;
	T* ptr_;

	indirect_array_iterator(const indirect_array<T>* ia);

	friend class indirect_array<T>;
};

template <class T>
inline
T&
indirect_array_iterator<T>::operator*()
{
	return *ptr_;
}

template <class T>
inline
indirect_array_iterator<T>&
indirect_array_iterator<T>::operator++ ()
{
	ptr_ = &const_cast<indirect_array<T>*>(ia_)->array()[ia_->ia()[++i_]];
	return *this;
}

template <class T>
inline
indirect_array_iterator<T>::indirect_array_iterator(const indirect_array<T>* ia)
	: i_(0),
	  ia_(ia),
	  ptr_(&const_cast<indirect_array<T>*>(ia)->array()[ia->ia()[0]])
{
}

template <class T>
class indirect_array
{
public:
	typedef T value_type;

	void operator=  (const valarray<T>&) const;
	void operator*= (const valarray<T>&) const;
	void operator/= (const valarray<T>&) const;
	void operator%= (const valarray<T>&) const;
	void operator+= (const valarray<T>&) const;
	void operator-= (const valarray<T>&) const;
	void operator^= (const valarray<T>&) const;
	void operator&= (const valarray<T>&) const;
	void operator|= (const valarray<T>&) const;
	void operator<<=(const valarray<T>&) const;
	void operator>>=(const valarray<T>&) const;

	void operator=(const T&) const;
	// ~indirect_array();  use compiler generated
private:
	indirect_array();                                  // Not defined

	typedef indirect_array_iterator<T> iterator;

	indirect_array(valarray<T>& v, const valarray<size_t>& ia);
	const valarray<size_t>& ia() const;
	valarray<T>& array();
	const valarray<T>& array() const;
	iterator begin() const;
	size_t length() const;

	valarray<T>* v_;
	valarray<size_t> ia_;

	friend class valarray<T>;
	friend class indirect_array_iterator<T>;
};

// indirect_array Implementation

template <class T>
void
indirect_array<T>::operator= (const valarray<T>& v) const
{
	size_t end = length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k = v[i];
	}
}

template <class T>
void
indirect_array<T>::operator*= (const valarray<T>& v) const
{
	size_t end = length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k *= v[i];
	}
}

template <class T>
void
indirect_array<T>::operator/= (const valarray<T>& v) const
{
	size_t end = length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k /= v[i];
	}
}

template <class T>
void
indirect_array<T>::operator%= (const valarray<T>& v) const
{
	size_t end = length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k %= v[i];
	}
}

template <class T>
void
indirect_array<T>::operator+= (const valarray<T>& v) const
{
	size_t end = length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k += v[i];
	}
}

template <class T>
void
indirect_array<T>::operator-= (const valarray<T>& v) const
{
	size_t end = length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k -= v[i];
	}
}

template <class T>
void
indirect_array<T>::operator^= (const valarray<T>& v) const
{
	size_t end = length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k ^= v[i];
	}
}

template <class T>
void
indirect_array<T>::operator&= (const valarray<T>& v) const
{
	size_t end = length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k &= v[i];
	}
}

template <class T>
void
indirect_array<T>::operator|= (const valarray<T>& v) const
{
	size_t end = length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k |= v[i];
	}
}

template <class T>
void
indirect_array<T>::operator<<= (const valarray<T>& v) const
{
	size_t end = length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k <<= v[i];
	}
}

template <class T>
void
indirect_array<T>::operator>>= (const valarray<T>& v) const
{
	size_t end = length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k >>= v[i];
	}
}

template <class T>
void
indirect_array<T>::operator=(const T& t) const
{
	size_t end = length();
	if (end > 0)
	{
		iterator k = begin();
		for (size_t i = 0; i < end; ++i, ++k)
			*k = t;
	}
}

template <class T>
inline
indirect_array<T>::indirect_array(valarray<T>& v, const valarray<size_t>& ia)
	: v_(&v),
	  ia_(ia)
{
}

template <class T>
inline
const valarray<size_t>&
indirect_array<T>::ia() const
{
	return ia_;
}

template <class T>
inline
valarray<T>&
indirect_array<T>::array()
{
	return *v_;
}

template <class T>
inline
const valarray<T>&
indirect_array<T>::array() const
{
	return *v_;
}

template <class T>
inline
typename indirect_array<T>::iterator
indirect_array<T>::begin() const
{
	return iterator(this);
}

template <class T>
inline
size_t
indirect_array<T>::length() const
{
	return ia_.size();
}

// valarray binary operators

template<class T>
valarray<T>
operator* (const valarray<T>& x, const valarray<T>& y)
{
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = x[i] * y[i];
	return result;
}

template<class T>
valarray<T>
operator* (const valarray<T>& x, const T& t)
{
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = x[i] * t;
	return result;
}

template<class T>
valarray<T>
operator* (const T& t, const valarray<T>& x)
{
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = t * x[i];
	return result;
}

template<class T>
valarray<T>
operator/ (const valarray<T>& x, const valarray<T>& y)
{
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = x[i] / y[i];
	return result;
}

template<class T>
valarray<T>
operator/ (const valarray<T>& x, const T& t)
{
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = x[i] / t;
	return result;
}

template<class T>
valarray<T>
operator/ (const T& t, const valarray<T>& x)
{
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = t / x[i];
	return result;
}

template<class T>
valarray<T>
operator% (const valarray<T>& x, const valarray<T>& y)
{
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = x[i] % y[i];
	return result;
}

template<class T>
valarray<T>
operator% (const valarray<T>& x, const T& t)
{
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = x[i] % t;
	return result;
}

template<class T>
valarray<T>
operator% (const T& t, const valarray<T>& x)
{
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = t % x[i];
	return result;
}

template<class T>
valarray<T>
operator+ (const valarray<T>& x, const valarray<T>& y)
{
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = x[i] + y[i];
	return result;
}

template<class T>
valarray<T>
operator+ (const valarray<T>& x, const T& t)
{
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = x[i] + t;
	return result;
}

template<class T>
valarray<T>
operator+ (const T& t, const valarray<T>& x)
{
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = t + x[i];
	return result;
}

template<class T>
valarray<T>
operator- (const valarray<T>& x, const valarray<T>& y)
{
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = x[i] - y[i];
	return result;
}

template<class T>
valarray<T>
operator- (const valarray<T>& x, const T& t)
{
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = x[i] - t;
	return result;
}

template<class T>
valarray<T>
operator- (const T& t, const valarray<T>& x)
{
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = t - x[i];
	return result;
}

template<class T>
valarray<T>
operator^ (const valarray<T>& x, const valarray<T>& y)
{
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = x[i] ^ y[i];
	return result;
}

template<class T>
valarray<T>
operator^ (const valarray<T>& x, const T& t)
{
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = x[i] ^ t;
	return result;
}

template<class T>
valarray<T>
operator^ (const T& t, const valarray<T>& x)
{
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = t ^ x[i];
	return result;
}

template<class T>
valarray<T>
operator& (const valarray<T>& x, const valarray<T>& y)
{
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = x[i] & y[i];
	return result;
}

template<class T>
valarray<T>
operator& (const valarray<T>& x, const T& t)
{
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = x[i] & t;
	return result;
}

template<class T>
valarray<T>
operator& (const T& t, const valarray<T>& x)
{
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = t & x[i];
	return result;
}

template<class T>
valarray<T>
operator| (const valarray<T>& x, const valarray<T>& y)
{
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = x[i] | y[i];
	return result;
}

template<class T>
valarray<T>
operator| (const valarray<T>& x, const T& t)
{
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = x[i] | t;
	return result;
}

template<class T>
valarray<T>
operator| (const T& t, const valarray<T>& x)
{
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = t | x[i];
	return result;
}

template<class T>
valarray<T>
operator<< (const valarray<T>& x, const valarray<T>& y)
{
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = x[i] << y[i];
	return result;
}

template<class T>
valarray<T>
operator<< (const valarray<T>& x, const T& t)
{
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = x[i] << t;
	return result;
}

template<class T>
valarray<T>
operator<< (const T& t, const valarray<T>& x)
{
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = t << x[i];
	return result;
}

template<class T>
valarray<T>
operator>> (const valarray<T>& x, const valarray<T>& y)
{
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = x[i] >> y[i];
	return result;
}

template<class T>
valarray<T>
operator>> (const valarray<T>& x, const T& t)
{
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = x[i] >> t;
	return result;
}

template<class T>
valarray<T>
operator>> (const T& t, const valarray<T>& x)
{
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = t >> x[i];
	return result;
}

// valarray logical operators

template<class T>
valarray<bool>
operator&& (const valarray<T>& x, const valarray<T>& y)
{
	const size_t s = x.size();
	valarray<bool> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = x[i] && y[i];
	return result;
}

template<class T>
valarray<bool>
operator&& (const valarray<T>& x, const T& t)
{
	const size_t s = x.size();
	valarray<bool> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = x[i] && t;
	return result;
}

template<class T>
valarray<bool>
operator&& (const T& t, const valarray<T>& x)
{
	const size_t s = x.size();
	valarray<bool> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = t && x[i];
	return result;
}

template<class T>
valarray<bool>
operator|| (const valarray<T>& x, const valarray<T>& y)
{
	const size_t s = x.size();
	valarray<bool> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = x[i] || y[i];
	return result;
}

template<class T>
valarray<bool>
operator|| (const valarray<T>& x, const T& t)
{
	const size_t s = x.size();
	valarray<bool> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = x[i] || t;
	return result;
}

template<class T>
valarray<bool>
operator|| (const T& t, const valarray<T>& x)
{
	const size_t s = x.size();
	valarray<bool> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = t || x[i];
	return result;
}

template<class T>
valarray<bool>
operator== (const valarray<T>& x, const valarray<T>& y)
{
	const size_t s = x.size();
	valarray<bool> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = x[i] == y[i];
	return result;
}

template<class T>
valarray<bool>
operator== (const valarray<T>& x, const T& t)
{
	const size_t s = x.size();
	valarray<bool> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = x[i] == t;
	return result;
}

template<class T>
valarray<bool>
operator== (const T& t, const valarray<T>& x)
{
	const size_t s = x.size();
	valarray<bool> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = t == x[i];
	return result;
}

template<class T>
valarray<bool>
operator!= (const valarray<T>& x, const valarray<T>& y)
{
	const size_t s = x.size();
	valarray<bool> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = x[i] != y[i];
	return result;
}

template<class T>
valarray<bool>
operator!= (const valarray<T>& x, const T& t)
{
	const size_t s = x.size();
	valarray<bool> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = x[i] != t;
	return result;
}

template<class T>
valarray<bool>
operator!= (const T& t, const valarray<T>& x)
{
	const size_t s = x.size();
	valarray<bool> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = t != x[i];
	return result;
}

template<class T>
valarray<bool>
operator<  (const valarray<T>& x, const valarray<T>& y)
{
	const size_t s = x.size();
	valarray<bool> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = x[i] < y[i];
	return result;
}

template<class T>
valarray<bool>
operator<  (const valarray<T>& x, const T& t)
{
	const size_t s = x.size();
	valarray<bool> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = x[i] < t;
	return result;
}

template<class T>
valarray<bool>
operator<  (const T& t, const valarray<T>& x)
{
	const size_t s = x.size();
	valarray<bool> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = t < x[i];
	return result;
}

template<class T>
valarray<bool>
operator>  (const valarray<T>& x, const valarray<T>& y)
{
	const size_t s = x.size();
	valarray<bool> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = x[i] > y[i];
	return result;
}

template<class T>
valarray<bool>
operator>  (const valarray<T>& x, const T& t)
{
	const size_t s = x.size();
	valarray<bool> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = x[i] > t;
	return result;
}

template<class T>
valarray<bool>
operator>  (const T& t, const valarray<T>& x)
{
	const size_t s = x.size();
	valarray<bool> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = t > x[i];
	return result;
}

template<class T>
valarray<bool>
operator<= (const valarray<T>& x, const valarray<T>& y)
{
	const size_t s = x.size();
	valarray<bool> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = x[i] <= y[i];
	return result;
}

template<class T>
valarray<bool>
operator<= (const valarray<T>& x, const T& t)
{
	const size_t s = x.size();
	valarray<bool> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = x[i] <= t;
	return result;
}

template<class T>
valarray<bool>
operator<= (const T& t, const valarray<T>& x)
{
	const size_t s = x.size();
	valarray<bool> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = t <= x[i];
	return result;
}

template<class T>
valarray<bool>
operator>= (const valarray<T>& x, const valarray<T>& y)
{
	const size_t s = x.size();
	valarray<bool> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = x[i] >= y[i];
	return result;
}

template<class T>
valarray<bool>
operator>= (const valarray<T>& x, const T& t)
{
	const size_t s = x.size();
	valarray<bool> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = x[i] >= t;
	return result;
}

template<class T>
valarray<bool>
operator>= (const T& t, const valarray<T>& x)
{
	const size_t s = x.size();
	valarray<bool> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = t >= x[i];
	return result;
}

// valarray transcendentals

template<class T>
valarray<T>
abs(const valarray<T>& x)
{
	using _CSTD::abs;
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = static_cast<T>(abs(x[i]));
	return result;
}

template<class T>
valarray<T>
acos(const valarray<T>& x)
{
	using _CSTD::acos;
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = static_cast<T>(acos(x[i]));
	return result;
}

template<class T>
valarray<T>
asin(const valarray<T>& x)
{
	using _CSTD::asin;
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = static_cast<T>(asin(x[i]));
	return result;
}

template<class T>
valarray<T>
atan(const valarray<T>& x)
{
	using _CSTD::atan;
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = static_cast<T>(atan(x[i]));
	return result;
}

template<class T>
valarray<T>
atan2(const valarray<T>& x, const valarray<T>& y)
{
	using _CSTD::atan2;
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = static_cast<T>(atan2(x[i], y[i]));
	return result;
}

template<class T>
valarray<T>
atan2(const valarray<T>& x, const T& t)
{
	using _CSTD::atan2;
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = static_cast<T>(atan2(x[i], t));
	return result;
}

template<class T>
valarray<T>
atan2(const T& t, const valarray<T>& x)
{
	using _CSTD::atan2;
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = static_cast<T>(atan2(t, x[i]));
	return result;
}

template<class T>
valarray<T>
cos(const valarray<T>& x)
{
	using _CSTD::cos;
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = static_cast<T>(cos(x[i]));
	return result;
}

template<class T>
valarray<T>
cosh(const valarray<T>& x)
{
	using _CSTD::cosh;
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = static_cast<T>(cosh(x[i]));
	return result;
}

template<class T>
valarray<T>
exp(const valarray<T>& x)
{
	using _CSTD::exp;
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = static_cast<T>(exp(x[i]));
	return result;
}

template<class T>
valarray<T>
log(const valarray<T>& x)
{
	using _CSTD::log;
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = static_cast<T>(log(x[i]));
	return result;
}

template<class T>
valarray<T>
log10(const valarray<T>& x)
{
	using _CSTD::log10;
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = static_cast<T>(log10(x[i]));
	return result;
}

template<class T>
valarray<T>
pow(const valarray<T>& x, const valarray<T>& y)
{
	using _CSTD::pow;
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = static_cast<T>(pow(x[i], y[i]));
	return result;
}

template<class T>
valarray<T>
pow(const valarray<T>& x, const T& t)
{
	using _CSTD::pow;
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = static_cast<T>(pow(x[i], t));
	return result;
}

template<class T>
valarray<T>
pow(const T& t, const valarray<T>& x)
{
	using _CSTD::pow;
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = static_cast<T>(pow(t, x[i]));
	return result;
}

template<class T>
valarray<T>
sin(const valarray<T>& x)
{
	using _CSTD::sin;
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = static_cast<T>(sin(x[i]));
	return result;
}

template<class T>
valarray<T>
sinh(const valarray<T>& x)
{
	using _CSTD::sinh;
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = static_cast<T>(sinh(x[i]));
	return result;
}

template<class T>
valarray<T>
sqrt(const valarray<T>& x)
{
	using _CSTD::sqrt;
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = static_cast<T>(sqrt(x[i]));
	return result;
}

template<class T>
valarray<T>
tan(const valarray<T>& x)
{
	using _CSTD::tan;
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = static_cast<T>(tan(x[i]));
	return result;
}

template<class T>
valarray<T>
tanh(const valarray<T>& x)
{
	using _CSTD::tanh;
	const size_t s = x.size();
	valarray<T> result;
	result.init(s);
	for (size_t i = 0; i < s; ++i)
		result[i] = static_cast<T>(tanh(x[i]));
	return result;
}

#ifndef _MSL_NO_CPP_NAMESPACE
	} // namespace std
#endif

#ifdef _MSL_FORCE_ENUMS_ALWAYS_INT
	#pragma enumsalwaysint reset
#endif

#ifdef _MSL_FORCE_ENABLE_BOOL_SUPPORT
	#pragma bool reset
#endif

#ifdef __MWERKS__
#pragma options align=reset
#endif

#endif  // RC_INVOKED // hh 971230

#endif // _VALARRAY

// hh 971220 fixed MOD_INCLUDE
// hh 971226 added alignment wrapper
// hh 971226 Changed filename from valarray.h to valarray
// hh 971226 Made include guards standard
// hh 971226 added MSIPLSTD to min in valarray constructor
// hh 971229 Changed the friend declarations to not require member templates
// hh 971229 removed :: from fill_n in fill
// hh 971229 added val_array prototypes
// hh 971229 gslice_array, indirect_array and mask_array moved up in file to avoid "using
//           incomplete type" errors.
// hh 971230 added RC_INVOKED wrapper
// hh 980408 wrapped in #ifndef _No_Floating_Point
// hh 990113 Rewrote
// hh 001011 Fixed several typename bugs
// hh 001011 Disabled gslice for gcc
// hh 010301 Protected min and max from macro abuse.
// hh 010402 Removed 68K CMF support
// hh 011004 Protected cshift from 0 size
// hh 011004 Optimized valarray constructor for class types
// hh 011004 Protected sum from bizzare default constructor
// hh 011004 changed return type of operator! to valarray<bool>
// hh 021017 Implemented lwg 123
// hh 021017 Implemented lwg 253
// hh 030715 Protected against zero length slices
// hh 030930 Modest optimizations
