______________________________________________________________________

  26   Numerics library                                   [lib.numerics]

  ______________________________________________________________________

1 This clause describes components that C++ programs may use to  perform
  seminumerical operations.

2 The following subclauses describe components for complex number types,
  numeric ( n-at-a-time) arrays,  generalized  numeric  algorithms,  and
  facilities included from the ISO C library, as summarized in Table 1:

                    Table 1--Numerics library summary

  +----------------------------------------------------------------------+
  |                    Subclause       Header(s)                         |
  +----------------------------------------------------------------------+
  |_lib.numeric.requirements_ Requirements                               |
  +----------------------------------------------------------------------+
  |_lib.complex.numbers_ Complex numbers   <complex>                     |
  +----------------------------------------------------------------------+
  |_lib.numarray_ Numeric arrays   <valarray>                            |
  +----------------------------------------------------------------------+
  |_lib.numeric.ops_ Generalized numeric operations        <numeric>     |
  +----------------------------------------------------------------------+
  |_lib.c.math_ C library  <cmath>                                       |
  |      <cstdlib>                                                       |
  +----------------------------------------------------------------------+

  26.1  Numeric type requirements             [lib.numeric.requirements]

1 The  complex  and valarray components are parameterized by the type of
  information they contain and manipulate.  A C++ program shall  instan­
  tiate   these   components  with  types  that  satisfy  the  following
  requirements:1)

  --T is not an abstract class (it has  no  pure  virtual  member  func­
    tions);

  --T is not a reference type;

  _________________________
  1) In other words, value types.   These  include  built-in  arithmetic
  types,  pointers,  the  library  class  complex, and instantiations of
  valarray for value types.

  --T is not cv-qualified;

  --If T is a class, it has a public default constructor;

  --If T is a class, it has a public copy constructor with the signature
    T::T(const T&)

  --If T is a class, it has a public destructor;

  --If T is a class, it has a public assignment operator whose signature
    is either
    T& T::operator=(const T&) or T& T::operator=(T)

  --If T is a class, its assignment operator, copy and default construc­
    tors, and destructor must correspond to each other in the  following
    sense:  Initialization of raw storage using the default constructor,
    followed by assignment, is semantically equivalent to initialization
    of  raw  storage  using  the  copy  constructor.   Destruction of an
    object, followed by initialization of its raw storage using the copy
    constructor,  is semantically equivalent to assignment to the origi­
    nal object.
    [Note: This rule states that there must not be  any  subtle  differ­
    ences  in  the  semantics of initialization versus assignment.  This
    gives an implementation considerable flexibility in how  arrays  are
    initialized.
    [Example:  An  implementation is allowed to initialize a valarray by
    allocating storage using the new operator (which implies a  call  to
    the  default  constructor  for each element) and then assigning each
    element its value.  Or the implementation can allocate  raw  storage
    and  use  the  copy  constructor to initialize each element.   --end
    example]
    If the distinction between initialization and assignment  is  impor­
    tant  for a class, or if it fails to satisfy any of the other condi­
    tions listed above, the programmer should use vector  (_lib.vector_)
    instead of valarray for that class;  --end note]

  --If T is a class, it does not overload unary operator&.

2 In  addition,  many member and related functions of valarray<T> can be
  successfully instantiated and will exhibit  well-defined  behavior  if
  and  only  if  T  satisfies additional requirements specified for each
  such member or related function.

3 [Example: It is valid to  instantiate  valarray<complex>,  but  opera­
  tor>()  will  not  be  successfully instantiated for valarray<complex>
  operands, since complex does not have any ordering operators.    --end
  example]

  26.2  Complex numbers                            [lib.complex.numbers]

1 The  header <complex> defines a template class, and numerous functions
  for representing and manipulating complex numbers.

2 The  effect  of  instantiating the template complex for any type other
  than float, double or long double is unspecified.

3 If the result of a function is not mathematically defined  or  not  in
  the  range of representable values for its type, the behavior is unde­
  fined.

  26.2.1  Header <complex> synopsis               [lib.complex.synopsis]
  namespace std {
    template<class T> class complex;
    class complex<float>;
    class complex<double>;
    class complex<long double>;
    // _lib.complex.ops_ operators:
    template<class T>
      complex<T> operator+(const complex<T>&, const complex<T>&);
    template<class T> complex<T> operator+(const complex<T>&, const T&);
    template<class T> complex<T> operator+(const T&, const complex<T>&);
    template<class T> complex<T> operator-(const complex<T>&, const complex<T>&);
    template<class T> complex<T> operator-(const complex<T>&, const T&);
    template<class T> complex<T> operator-(const T&, const complex<T>&);
    template<class T> complex<T> operator*(const complex<T>&, const complex<T>&);
    template<class T> complex<T> operator*(const complex<T>&, const T&);
    template<class T> complex<T> operator*(const T&, const complex<T>&);
    template<class T> complex<T> operator/(const complex<T>&, const complex<T>&);
    template<class T> complex<T> operator/(const complex<T>&, const T&);
    template<class T> complex<T> operator/(const T&, const complex<T>&);
    template<class T> complex<T> operator+(const complex<T>&);
    template<class T> complex<T> operator-(const complex<T>&);
    template<class T> bool operator==(const complex<T>&, const complex<T>&);
    template<class T> bool operator==(const complex<T>&, const T&);
    template<class T> bool operator==(const T&, const complex<T>&);
    template<class T> bool operator!=(const complex<T>&, const complex<T>&);
    template<class T> bool operator!=(const complex<T>&, const T&);
    template<class T> bool operator!=(const T&, const complex<T>&);
    template<class T, class charT, class traits>
    basic_istream<charT, traits>&
    operator>>(basic_istream<charT, traits>&, complex<T>&);

    template<class T, class charT, class traits>
    basic_ostream<charT, traits>&
    operator<<(basic_ostream<charT, traits>&, const complex<T>&);
    // _lib.complex.value.ops_ values:
    template<class T> T real(const complex<T>&);
    template<class T> T imag(const complex<T>&);
    template<class T> T abs(const complex<T>&);
    template<class T> T arg(const complex<T>&);
    template<class T> T norm(const complex<T>&);
    template<class T> complex<T> conj(const complex<T>&);
    template<class T> complex<T> polar(const T&, const T&);

    // _lib.complex.transcendentals_ transcendentals:
    template<class T> complex<T> cos  (const complex<T>&);
    template<class T> complex<T> cosh (const complex<T>&);
    template<class T> complex<T> exp  (const complex<T>&);
    template<class T> complex<T> log  (const complex<T>&);
    template<class T> complex<T> log10(const complex<T>&);
    template<class T> complex<T> pow(const complex<T>&, int);
    template<class T> complex<T> pow(const complex<T>&, const T&);
    template<class T> complex<T> pow(const complex<T>&, const complex<T>&);
    template<class T> complex<T> pow(const T&, const complex<T>&);
    template<class T> complex<T> sin  (const complex<T>&);
    template<class T> complex<T> sinh (const complex<T>&);
    template<class T> complex<T> sqrt (const complex<T>&);
    template<class T> complex<T> tan  (const complex<T>&);
    template<class T> complex<T> tanh (const complex<T>&);
  }

  26.2.2  Template class complex                           [lib.complex]
  namespace std {
    template<class T>
    class complex {
    public:
      typedef T value_type;

      complex(const T& re = T(), const T& im = T());
      template<class X> complex(const complex<X>&);
      T real() const;
      T imag() const;

      complex<T>& operator= (const T&);
      complex<T>& operator+=(const T&);
      complex<T>& operator-=(const T&);
      complex<T>& operator*=(const T&);
      complex<T>& operator/=(const T&);

      template<class X> complex<T>& operator= (const complex<X>&);
      template<class X> complex<T>& operator+=(const complex<X>&);
      template<class X> complex<T>& operator-=(const complex<X>&);
      template<class X> complex<T>& operator*=(const complex<X>&);
      template<class X> complex<T>& operator/=(const complex<X>&);
    };

  template<class T> complex<T> operator+(const complex<T>&, const T&);
  template<class T> complex<T> operator+(const T&, const complex<T>&);
  template<class T> complex<T> operator-(const complex<T>&, const T&);
  template<class T> complex<T> operator-(const T&, const complex<T>&);
  template<class T> complex<T> operator*(const complex<T>&, const T&);
  template<class T> complex<T> operator*(const T&, const complex<T>&);
  template<class T> complex<T> operator/(const complex<T>&, const T&);
  template<class T> complex<T> operator/(const T&, const complex<T>&);
  template<class T> complex<T> operator==(const complex<T>&, const T&);
  template<class T> complex<T> operator==(const T&, const complex<T>&);
  template<class T> complex<T> operator!=(const complex<T>&, const T&);
  template<class T> complex<T> operator!=(const T&, const complex<T>&);

1 The class complex describes an object that  can  store  the  Cartesian
  components, real() and imag(), of a complex number.

  26.2.3  complex specializations                  [lib.complex.special]
    class complex<float> {
    public:
      typedef float value_type;

      complex(float re = 0.0f, float im = 0.0f);
      explicit complex(const complex<double>&);
      explicit complex(const complex<long double>&);
      float real() const;
      float imag() const;

      complex<float>& operator= (float);
      complex<float>& operator+=(float);
      complex<float>& operator-=(float);
      complex<float>& operator*=(float);
      complex<float>& operator/=(float);

      template<class X> complex<float>& operator= (const complex<X>&);
      template<class X> complex<float>& operator+=(const complex<X>&);
      template<class X> complex<float>& operator-=(const complex<X>&);
      template<class X> complex<float>& operator*=(const complex<X>&);
      template<class X> complex<float>& operator/=(const complex<X>&);
    };
    class complex<double> {
    public:
      typedef double value_type;

      complex(double re = 0.0, double im = 0.0);
      complex(const complex<float>&);
      explicit complex(const complex<long double>&);
      double real() const;
      double imag() const;

      complex<double>& operator= (double);
      complex<double>& operator+=(double);
      complex<double>& operator-=(double);
      complex<double>& operator*=(double);
      complex<double>& operator/=(double);

      template<class X> complex<double>& operator= (const complex<X>&);
      template<class X> complex<double>& operator+=(const complex<X>&);
      template<class X> complex<double>& operator-=(const complex<X>&);
      template<class X> complex<double>& operator*=(const complex<X>&);
      template<class X> complex<double>& operator/=(const complex<X>&);
    };

    class complex<long double> {
    public:
      typedef long double value_type;

      complex(long double re = 0.0L, long double im = 0.0L);
      complex(const complex<float>&);
      complex(const complex<double>&);
      long double real() const;
      long double imag() const;

      complex<long double>& operator= (long double&);
      complex<long double>& operator+=(long double&);
      complex<long double>& operator-=(long double&);
      complex<long double>& operator*=(long double&);
      complex<long double>& operator/=(long double&);

      template<class X> complex<long double>& operator= (const complex<X>&);
      template<class X> complex<long double>& operator+=(const complex<X>&);
      template<class X> complex<long double>& operator-=(const complex<X>&);
      template<class X> complex<long double>& operator*=(const complex<X>&);
      template<class X> complex<long double>& operator/=(const complex<X>&);
    };

  26.2.4  complex member functions                 [lib.complex.members]

  template<class T> complex(const T& re = T(), const T& im = T());

  Effects:
    Constructs an object of class complex.

1 Postcondition: real() == re  && imag() == im.

  26.2.5  complex member operators              [lib.complex.member.ops]

  complex<T>& operator+=(const T& rhs);

  Effects:
    Adds the scalar value rhs to the real  part  of  the  complex  value
    *this  and  stores the result in the real part of *this, leaving the
    imaginary part unchanged.
  Returns:
    *this.

  complex<T>& operator-=(const T& rhs);

  Effects:
    Subtracts the scalar value rhs from the real  part  of  the  complex
    value *this and stores the result in the real part of *this, leaving
    the imaginary part unchanged.

  Returns:
    *this.

  complex<T>& operator*=(const T& rhs);

  Effects:
    Multiplies the scalar value rhs  by  the  complex  value  *this  and
    stores the result in *this.
  Returns:
    *this.

  complex<T>& operator/=(const T& rhs);

  Effects:
    Divides the scalar value rhs into the complex value *this and stores
    the result in *this.
  Returns:
    *this.

  template<class T> complex<T>& operator+=(const complex<T>& rhs);

  Effects:
    Adds the complex value rhs to the complex value *this and stores the
    sum in *this.
  Returns:
    *this.

  template<class T> complex<T>& operator-=(const complex<T>& rhs);

  Effects:
    Subtracts  the  complex  value  rhs from the complex value *this and
    stores the difference in *this.
  Returns:
    *this.

  template<class T> complex<T>& operator*=(const complex<T>& rhs);

  Effects:
    Multiplies the complex value rhs by  the  complex  value  *this  and
    stores the product in *this.
  Returns:
    *this.

  template<class T> complex<T>& operator/=(const complex<T>& rhs);

  Effects:
    Divides  the  complex  value  rhs  into  the complex value *this and

    stores the quotient in *this.
  Returns:
    *this.

  26.2.6  complex non-member operations                [lib.complex.ops]

  template<class T> complex<T> operator+(const complex<T>& lhs);

  Notes:
    unary operator.
  Returns:
    complex<T>(lhs).

  template<class T>
    complex<T> operator+(const complex<T>& lhs, const complex<T>& rhs);
  template<class T> complex<T> operator+(const complex<T>& lhs, const T& rhs);
  template<class T> complex<T> operator+(const T& lhs, const complex<T>& rhs);

  Returns:
    complex<T>(lhs) += rhs.

  template<class T> complex<T> operator-(const complex<T>& lhs);

  Notes:
    unary operator.
  Returns:
    complex<T>(-lhs.real(),-lhs.imag()).

  template<class T>
    complex<T> operator-(const complex<T>& lhs, const complex<T>& rhs);
  template<class T> complex<T> operator-(const complex<T>& lhs, const T& rhs);
  template<class T> complex<T> operator-(const T& lhs, const complex<T>& rhs);

  Returns:
    complex<T>(lhs) -= rhs.

  template<class T>
    complex<T> operator*(const complex<T>& lhs, const complex<T>& rhs);
  template<class T> complex<T> operator*(const complex<T>& lhs, const T& rhs);
  template<class T> complex<T> operator*(const T& lhs, const complex<T>& rhs);

  Returns:
    complex<T>(lhs) *= rhs.

  template<class T>
    complex<T> operator/(const complex<T>& lhs, const complex<T>& rhs);
  template<class T> complex<T> operator/(const complex<T>& lhs, const T& rhs);
  template<class T> complex<T> operator/(const T& lhs, const complex<T>& rhs);

  Returns:
    complex<T>(lhs) /= rhs.

  template<class T>
    bool operator==(const complex<T>& lhs, const complex<T>& >rhs);
  template<class T> bool operator==(const complex<T>& lhs, const T& rhs);
  template<class T> bool operator==(const T& lhs, const complex<T>& rhs);

  Returns:
    lhs.real() == rhs.real() && lhs.imag() == rhs.imag().
  Notes:
    The imaginary part is assumed to be T(), or 0.0,  for  the  T  argu­
    ments.

  template<class T>
    bool operator!=(complex<T>& lhs, complex<T>& rhs);
  template<class T> bool operator!=(complex<T>& lhs, const T& rhs);
  template<class T> bool operator!=(const T& lhs, complex<T>& rhs);

  Returns:
    rhs.real() != lhs.real() || rhs.imag() != lhs.imag().

  template<class T, class charT, class traits>
  basic_istream<charT, traits>&
  operator>>(basic_istream<charT, traits>& is, complex<T>& x);

  Effects:
    Extracts  a  complex number x of the form: u, (u), or (u,v), where u
    is the real part and v is the imaginary  part  (_lib.istream.format­
    ted_).
  Requires:
    The input values be convertible to T.
    If  bad input is encountered, calls is.setstate(ios::failbit) (which
    may throw ios::failure (_lib.iostate.flags_).
  Returns:
    is.

  template<class T, class charT, class traits>
  basic_ostream<charT, traits>&
  operator<<(basic_ostream<charT, traits>& o, const complex<T>& x);

  Effects:
    inserts the complex number x onto the stream o as if it were  imple­
    mented as follows:

      template<class T, class charT, class traits>
      basic_ostream<charT, traits>&
      operator<<(basic_ostream<charT, traits>& o, const complex<T>& x)
      {
              basic_ostringstream<charT, traits> s;
              s.flags(o.flags());
              s.imbue(o.getloc());
              s.precision(o.precision());
              s << '(' << x.real() << "," << x.imag() << ')' << ends;
              return o << s.str();
      }

  26.2.7  complex value operations               [lib.complex.value.ops]

  template<class T> T real(const complex<T>& x);

  Returns:
    x.real().

  template<class T> T imag(const complex<T>& x);

  Returns:
    x.imag().

  template<class T> T abs(const complex<T>& x);

  Returns:
    the magnitude of x.

  template<class T> T arg(const complex<T>& x);

  Returns:
    the phase angle of x, or atan2(imag(x), real(x)).

  template<class T> T norm(const complex<T>& x);

  Returns:
    the squared magnitude of x.

  template<class T> complex<T> conj(const complex<T>& x);

  Returns:
    the complex conjugate of x.

  template<class T> complex<T> polar(const T& rho, const T& theta = 0);

  Returns:
    the  complex value corresponding to a complex number whose magnitude
    is rho and whose phase angle is theta.

  26.2.8  complex transcendentals          [lib.complex.transcendentals]

  template<class T> complex<T> cos(const complex<T>& x);

  Returns:
    the complex cosine of x.

  template<class T> complex<T> cosh(const complex<T>& x);

  Returns:
    the complex hyperbolic cosine of x.

  template<class T> complex<T> exp(const complex<T>& x);

  Returns:
    the complex base e exponential of x.

  template<class T> complex<T> log(const complex<T>& x);

  Notes:
    the branch cuts are along the negative real axis.
  Returns:
    the complex natural (base e) logarithm of x, in the range of a strip
    mathematically unbounded along the real axis and in the interval [-i
    times pi, i times pi ] along the imaginary axis. When x is  a  nega­
    tive real number, imag(log(x)) is pi.

  template<class T> complex<T> log10(const complex<T>& x);

  Notes:
    the branch cuts are along the negative real axis.
  Returns:
    the   complex   common   (base   10)logarithm   of   x,  defined  as
    log(x)/log(10).

  template<class T> complex<T> pow(const complex<T>& x, int y);
  template<class T>
    complex<T> pow(const complex<T>& x, const complex<T>& y);
  template<class T> complex<T> pow  (const complex<T>& x, const T& y);
  template<class T> complex<T> pow  (const T& x, const complex<T>& y);

  Notes:
    the branch cuts are along the negative real axis.

  Returns:
    the complex power of base x raised to the  y-th  power,  defined  as
    exp(y*log(x)).   The  value returned for pow(0,0) is implementation-
    defined.

  template<class T> complex<T> sin  (const complex<T>& x);

  Returns:
    the complex sine of x.

  template<class T> complex<T> sinh (const complex<T>& x);

  Returns:
    the complex hyperbolic sine of x.

  template<class T> complex<T> sqrt (const complex<T>& x);

  Notes:
    the branch cuts are along the negative real axis.
  Returns:
    the complex square root of x, in the range of the right  half-plane.
    If  the  argument is a negative real number, the value returned lies
    on the positive imaginary axis.

  template<class T> complex<T> tan  (const complex<T>& x);

  Returns:
    the complex tangent of x.

  template<class T> complex<T> tanh (const complex<T>& x);

  Returns:
    the complex hyperbolic tangent of x.

  26.3  Numeric arrays                                    [lib.numarray]

  26.4  Header <valarray> synopsis               [lib.valarray.synopsis]
  namespace std {
    template<class T> class valarray;       // An array of type T
    class slice;                            // a BLAS-like slice out of an array
    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> T min(const valarray<T>&);
    template<class T> T max(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>&);
  }

1 The header  <valarray>  defines  five  template  classes  (  valarray,
  slice_array,   gslice_array,   mask_array,  and  indirect_array),  two
  classes ( slice and gslice), and a series of related  function  signa­
  tures for representing and manipulating arrays of values.

2 The  valarray array classes are defined to be free of certain forms of
  aliasing, thus allowing operations on these classes to be optimized.

3 Any function returning a valarray<T> is permitted to return an  object
  of  another  type,  provided  all the const member functions of valar­
  ray<T> are also applicable to this type. This return  type  shall  not
  add  more  than  two  levels  of template nesting over the most deeply
  nested argument type.2)

4 Implementations introducing such replacement types shall provide addi­
  tional functions and operators as follows:

  --for  every  functions taking a constvalarray<T>& identical functions
    taking the replacement types must be added;

  --for every function taking two constvalarray<T>& arguments, identical
    functions taking every combination of constvalarray<T>& and replace­
    ment types must be added.

5 In particular, an implementation must allow a valarray<T> to  be  con­
  structed  from  such  replacement types and must allow assignments and
  computed assignments of such  types  to  valarray<T>,  slice_array<T>,
  gslice_array<T>, mask_array<T> and indirect_array<T> objects.

6 These   library   functions   are   permitted  to  throw  a  bad_alloc
  (_lib.bad.alloc_) exception if  there  are  not  sufficient  resources
  available  to carry out the operation.  Note that the exception is not
  mandated.

  26.4.1  Template class valarray                [lib.template.valarray]
  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();

  _________________________
  2) _limits_ recommends a minimum number of recursively nested template
  instantiations.  This  requirement  thus indirectly suggests a minimum
  allowable complexity for valarray expressions.

    // _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.subset_ 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;

      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 free();
      void resize(size_t sz, const T& c = T());
    };
  }

1 The template class valarray<T> is a one-dimensional smart array,  with
  elements  numbered  sequentially from zero.  It is a representation of
  the mathematical concept of an ordered set of values.  The illusion of
  higher  dimensionality  may  be produced by the familiar idiom of com­
  puted indices, together with the powerful subsetting capabilities pro­
  vided by the generalized subscript operators.3)

2 An  implementation  is  permitted  to  qualify  any  of  the functions
  declared in <valarray> as inline.

  26.4.1.1  valarray constructors                    [lib.valarray.cons]

  valarray();

  Effects:
    Constructs an object of class valarray<T>,4) which has  zero  length
    until it is passed into a library function as a modifiable lvalue or
    through a non-constant this pointer.4)

  explicit valarray(size_t);

1 The array created by this constructor has a length equal to the  value
  of  the argument.  The elements of the array are constructed using the
  default constructor for the instantiating type T.

  valarray(const T&, size_t);

  _________________________
  3)  The  intent  is  to specify an array template that has the minimum
  functionality necessary to address aliasing ambiguities and  the  pro­
  liferation  of  temporaries.  Thus, the valarray template is neither a
  matrix class nor a field class.  However, it is a very useful building
  block for designing such classes.
  4) For  convenience,  such  objects  are  referred  to  as  ``arrays''
  throughout the remainder of subclause _lib.numarray_.
  5) This default constructor is essential, since arrays of valarray are
  likely to prove useful.  There must also be a way to change  the  size
  of an array after initialization; this is supplied by the semantics of
  the resize member function.

2 The array created by this constructor has a length equal to the second
  argument.  The elements of the array are initialized with the value of
  the first argument.

  valarray(const T*, size_t);

3 The array created by this constructor has a length equal to the second
  argument  n.   The values of the elements of the array are initialized
  with the first n values pointed to by the  first  argument.6)  If  the
  value  of  the  second  argument  is greater than the number of values
  pointed to by the first argument, the behavior is undefined.

  valarray(const valarray<T>&);

4 The array created by this constructor has the same length as the argu­
  ment array. The elements are initialized with the values of the corre­
  sponding elements of the argument array.7)

  valarray(const slice_array<T>&);
  valarray(const gslice_array<T>&);
  valarray(const mask_array<T>&);
  valarray(const indirect_array<T>&);

5 These conversion constructors convert one of the four  reference  tem­
  plates to a valarray.

  ~valarray();

6 The  destructor  is  applied  to every element of *this; all allocated
  memory is returned.

  +-------                      BEGIN BOX 1                     -------+
  (Daveed Vandevoorde) This last phrase should probably read 'an  imple­
  mentation  may  return  all  allocated memory', since delete/free have
  similarly weak requirements.
  +-------                       END BOX 1                      -------+

  _________________________
  6) This constructor is the preferred method for converting a  C  array
  to a valarray object.
  7)  This  copy  constructor  creates  a  distinct array rather than an
  alias.  Implementations in which arrays share storage  are  permitted,
  but  they  must implement a copy-on-reference mechanism to ensure that
  arrays are conceptually distinct.

  26.4.1.2  valarray assignment                    [lib.valarray.assign]

  valarray<T>& operator=(const valarray<T>&);

1 Each element of the *this array is assigned the value  of  the  corre­
  sponding  element  of  the  argument array.  The resulting behavior is
  undefined if the length of the argument array  is  not  equal  to  the
  length of the *this array.

  valarray<T>& operator=(const T&);

2 The  scalar assignment operator causes each element of the *this array
  to be assigned the value of the argument.

  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>&);

3 These operators allow the results of a generalized subscripting opera­
  tion to be assigned directly to a valarray.

4 If the value of an element in the left hand side of a valarray assign­
  ment operator depends on the value of another  element  in  that  left
  hand side, the resulting behavior is undefined.

  26.4.1.3  valarray element access                [lib.valarray.access]

  T  operator[](size_t) const;
  T& operator[](size_t);

1 When  applied  to a constant array, the subscript operator returns the
  value of the corresponding element of the array.  When  applied  to  a
  non-constant  array, the subscript operator returns a reference to the
  corresponding element of the array.

2 Thus, the expression (a[i] = q, a[i]) == q evaluates as true  for  any
  non-constant  valarray<T>  a,  any T q, and for any size_t i such that
  the value of i is less than the length of a.

3 The expression &a[i+j] == &a[i] + j evaluates as true for all size_t i
  and size_t j such that i+j is less than the length of the non-constant
  array a.

4 Likewise, the expression &a[i] != &b[j] evaluates as true for any  two
  non-constant  arrays  a  and  b and for any size_t i and size_t j such
  that i is less than the length of a and j is less than the  length  of
  b.   This property indicates an absence of aliasing and may be used to
  advantage by optimizing compilers.8)

5 The reference returned by the subscript operator  for  a  non-constant
  array   is   guaranteed   to   be  valid  until  the  member  function
  resize(size_t, const T&) (_lib.valarray.members_) is called  for  that
  array  or  until  the  lifetime  of that array ends, whichever happens
  first.

6 If the subscript operator is invoked  with  a  size_t  argument  whose
  value  is not less than the length of the array, the behavior is unde­
  fined.

  26.4.1.4  valarray subset operations                [lib.valarray.sub]

  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>&);

1 Each of these operations returns a subset of the  array.   The  const-
  qualified  versions  return  this  subset as a new valarray.  The non-
  const versions return a class  template  object  which  has  reference
  semantics to the original array.

  26.4.1.5  valarray unary operators                [lib.valarray.unary]

  valarray<T> operator+() const;
  valarray<T> operator-() const;
  valarray<T> operator~() const;
  valarray<bool> operator!() const;

1 Each of these operators may only be instantiated for a type T to which
  the indicated operator can be applied  and  for  which  the  indicated
  operator returns a value which is of type &T (&bool for &operator!) or
  which may be unambiguously converted to type T (&bool for &operator!).

  _________________________
  8) Compilers may take advantage  of  inlining,  constant  propagation,
  loop fusion, tracking of pointers obtained from operator new, and oth­
  er techniques to generate efficient valarrays.

2 Each  of these operators returns an array whose length is equal to the
  length of the array.  Each element of the returned array  is  initial­
  ized  with the result of applying the indicated operator to the corre­
  sponding element of the array.

  26.4.1.6  valarray computed assignment          [lib.valarray.cassign]

  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>&);

1 Each of these operators may only be instantiated for a type T to which
  the  indicated  operator can be applied.  Each of these operators per­
  forms the indicated operation on each of its elements and  the  corre­
  sponding element of the argument array.

2 The array is then returned by reference.

3 If  the  array and the argument array do not have the same length, the
  behavior is undefined.  The appearance of an array on  the  left  hand
  side of a computed assignment does not invalidate references or point­
  ers.

4 If the value of an element in the left hand side of  a  valarray  com­
  puted  assignment  operator depends on the value of another element in
  that left hand side, the resulting behavior is undefined.

  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&);

5 Each of these operators may only be instantiated for a type T to which
  the indicated operator can be applied.

6 Each  of  these operators applies the indicated operation to each ele­
  ment of the array and the non-array argument.

7 The array is then returned by reference.

8 The appearance of an array on the left hand side of a computed assign­
  ment does not invalidate references or pointers to the elements of the
  array.

  26.4.1.7  valarray member functions             [lib.valarray.members]

  size_t size() const;

1 This function returns the number of elements in the array.

  T sum() const;

  This function may only be instantiated for a type T  to  which  opera­
  tor+=  can  be applied.  This function returns the sum of all the ele­
  ments of the array.

2 If the array has length 0, the behavior is undefined.   If  the  array
  has  length  1,  sum() returns the value of element 0.  Otherwise, the
  returned value is calculated by applying operator+= to a  copy  of  an
  element of the array and all other elements of the array in an unspec­
  ified order.

  T min() const;

3 This function returns the minimum value contained in *this.  The value
  returned for an array of length 0 is undefined. For an array of length
  1, the value of element 0 is returned. For all  other  array  lengths,
  the determination is made using operator<.

  T max() const;

4 This function returns the maximum value contained in *this.  The value
  returned for an array of length 0 is undefined. For an array of length
  1,  the  value  of element 0 is returned. For all other array lengths,
  the determination is made using operator<.

  valarray<T> shift(int) const;

5 This function returns an array whose length is identical to the array,
  but whose element values are shifted the number of places indicated by
  the argument.

6 A positive argument value results in a left shift, a negative value in
  a right shift, and a zero value in no shift.

7 [Example:  If the argument has the value -2, the first two elements of
  the result will be constructed  using  the  default  constructor;  the
  third  element  of  the result will be assigned the value of the first
  element of the argument; etc.   --end example]

  valarray<T> cshift(int) const;

8 This function returns an array whose length is identical to the array,
  but  whose element values are shifted in a circular fashion the number
  of places indicated by the argument.

9 A positive argument value results in a left shift, a negative value in
  a right shift, and a zero value in no shift.

  valarray<T> apply(T func(T)) const;
  valarray<T> apply(T func(const T&)) const;

10These  functions  return  an array whose length is equal to the array.
  Each element of the returned array is assigned the value  returned  by
  applying  the  argument  function  to the corresponding element of the
  array.

  void free();

11This function sets the length of an array to zero.9)

  void resize(size_t sz, const T& c = T());

12This  member  function changes the length of the *this array to sz and
  then assigns to each element the value of the second argument.  Resiz­
  ing  invalidates all pointers and references to elements in the array.

  _________________________
  9) An implementation may reclaim the storage used by  the  array  when
  this function is called.

  26.4.2  valarray non-member operations       [lib.valarray.nonmembers]

  26.4.2.1  valarray binary operators              [lib.valarray.binary]

  template<class T> valarray<T> operator*
      (const valarray<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 valarray<T>&);
  template<class T> valarray<T> operator+
      (const valarray<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 valarray<T>&);
  template<class T> valarray<T> operator&
      (const valarray<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 valarray<T>&);
  template<class T> valarray<T> operator>>
      (const valarray<T>&, const valarray<T>&);

1 Each of these operators may only be instantiated for a type T to which
  the  indicated  operator  can  be  applied and for which the indicated
  operator returns a value which is of type T or which can be  unambigu­
  ously converted to type T.

2 Each  of these operators returns an array whose length is equal to the
  lengths of the argument arrays.  Each element of the returned array is
  initialized  with the result of applying the indicated operator to the
  corresponding elements of the argument arrays.

3 If the argument arrays do not have the same length,  the  behavior  is
  undefined.

  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 T&);
  template<class T> valarray<T> operator/ (const 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 T&);
  template<class T> valarray<T> operator+ (const 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 T&);
  template<class T> valarray<T> operator^ (const 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 T&);
  template<class T> valarray<T> operator| (const 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 T&);
  template<class T> valarray<T> operator>>(const T&, const valarray<T>&);

4 Each of these operators may only be instantiated for a type T to which
  the indicated operator can be applied  and  for  which  the  indicated
  operator  returns a value which is of type T or which can be unambigu­
  ously converted to type T.

5 Each of these operators returns an array whose length is equal to  the
  length  of  the array argument.  Each element of the returned array is
  initialized with the result of applying the indicated operator to  the
  corresponding  element  of  the array argument and the non-array argu­
  ment.

  26.4.2.2  valarray logical operators         [lib.valarray.comparison]

  template<class T> valarray<bool> operator==
      (const valarray<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 valarray<T>&);
  template<class T> valarray<bool> operator>
      (const valarray<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 valarray<T>&);
  template<class T> valarray<bool> operator&&
      (const valarray<T>&, const valarray<T>&);
  template<class T> valarray<bool> operator||
      (const valarray<T>&, const valarray<T>&);

1 Each of these operators may only be instantiated for a type T to which
  the  indicated  operator  can  be  applied and for which the indicated
  operator returns a value which is of type bool or which can  be  unam­
  biguously converted to type bool.

2 Each  of these operators returns a bool array whose length is equal to
  the length of the array arguments.  Each element of the returned array
  is  initialized  with the result of applying the indicated operator to
  the corresponding elements of the argument arrays.

3 If the two array arguments do not have the same length,  the  behavior
  is undefined.

  template<class T> valarray<bool> operator==(const valarray&, const T&);
  template<class T> valarray<bool> operator==(const T&, const valarray&);
  template<class T> valarray<bool> operator!=(const valarray&, const T&);
  template<class T> valarray<bool> operator!=(const T&, const valarray&);
  template<class T> valarray<bool> operator< (const valarray&, const T&);
  template<class T> valarray<bool> operator< (const T&, const valarray&);
  template<class T> valarray<bool> operator> (const valarray&, const T&);
  template<class T> valarray<bool> operator> (const T&, const valarray&);
  template<class T> valarray<bool> operator<=(const valarray&, const T&);
  template<class T> valarray<bool> operator<=(const T&, const valarray&);
  template<class T> valarray<bool> operator>=(const valarray&, const T&);
  template<class T> valarray<bool> operator>=(const T&, const valarray&);
  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 T&);
  template<class T> valarray<bool> operator||(const T&, const valarray<T>&);

4 Each of these operators may only be instantiated for a type T to which
  the indicated operator can be applied  and  for  which  the  indicated
  operator  returns  a value which is of type bool or which can be unam­
  biguously converted to type bool.

5 Each of these operators returns a bool array whose length is equal  to
  the  length of the array argument.  Each element of the returned array
  is initialized with the result of applying the indicated  operator  to
  the corresponding element of the array and the non-array argument.

  26.4.2.3  valarray transcendentals            [lib.valarray.transcend]

  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>&);

1 Each of these functions may only be instantiated for a type T to which
  a unique function with the indicated name can be applied.  This  func­
  tion  must return a value which is of type T or which can be unambigu­
  ously converted to type T.

  26.4.3  Class slice                                  [lib.class.slice]
  namespace std {
    class slice {
    public:
      slice();
      slice(size_t, size_t, size_t);

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

1 The slice class represents a BLAS-like slice from an  array.   Such  a
  slice is specified by a starting index, a length, and a stride.10)

  _________________________
  10)  BLAS  stands  for Basic Linear Algebra Subprograms.  C++ programs
  may instantiate this class.  See,  for  example,  Dongarra,  Du  Croz,
  Duff,  and  Hammerling:  A set of Level 3 Basic Linear Algebra Subpro­
  grams;  Technical  Report  MCS-P1-0888,  Argonne  National  Laboratory
  (USA), Mathematics and Computer Science Division, August, 1988.

  26.4.3.1  slice constructors                          [lib.cons.slice]

  slice();
  slice(size_t start, size_t length, size_t stride);
  slice(const slice&);

1 The  default  constructor for slice creates a slice which specifies no
  elements.  A default constructor is provided only to permit the decla­
  ration  of  arrays  of  slices.   The constructor with arguments for a
  slice takes a start, length, and stride parameter.

2 [Example: slice(3, 8, 2) constructs a slice which selects elements  3,
  5, 7, ... 17 from an array.   --end example]

  26.4.3.2  slice access functions                    [lib.slice.access]

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

1 These  functions  return  the  start, length, or stride specified by a
  slice object.

  26.4.4  Template class slice_array          [lib.template.slice.array]
  namespace std {
    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 fill(const T&);
     ~slice_array();
    private:
      slice_array();
      slice_array(const slice_array&);
      slice_array& operator=(const slice_array&);
      //   remainder implementation defined
    };
  }

1 The slice_array template is a helper template used by the  slice  sub­
  script operator
  slice_array<T> valarray<T>::operator[](slice);
  It  has  reference  semantics  to  a subset of an array specified by a
  slice object.

2 [Example: The expression a[slice(1, 5, 3)] =  b;  has  the  effect  of
  assigning  the elements of b to a slice of the elements in a.  For the
  slice shown, the elements selected from a are 1, 4, ..., 13.     --end
  example]

3 [Note:  C++  programs  may  not instantiate slice_array, since all its
  constructors are private.  It is intended purely as a helper class and
  should be transparent to the user.   --end note]

  26.4.4.1  slice_array constructors                [lib.cons.slice.arr]

  slice_array();
  slice_array(const slice_array&);

1 The  slice_array template has no public constructors.  These construc­
  tors are declared to be  private.   These  constructors  need  not  be
  defined.

  26.4.4.2  slice_array assignment                [lib.slice.arr.assign]

  void         operator=(const valarray<T>&) const;
  slice_array& operator=(const slice_array&);

1 The  second  of these two assignment operators is declared private and
  need not be defined.  The first has reference semantics, assigning the
  values  of  the  argument  array  elements to selected elements of the
  valarray<T> object to which the slice_array object refers.

  26.4.4.3  slice_array computed             [lib.slice.arr.comp.assign]
       assignment

  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;

1 These  computed  assignments  have  reference  semantics, applying the
  indicated operation to the elements of the argument array and selected
  elements  of  the  valarray<T>  object to which the slice_array object
  refers.

  26.4.4.4  slice_array fill function               [lib.slice.arr.fill]

  void fill(const T&);

1 This function has reference semantics,  assigning  the  value  of  its
  argument  to  the  elements  of  the  valarray<T>  object to which the
  slice_array object refers.

  26.4.5  The gslice class                            [lib.class.gslice]
  namespace std {
    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;
    };
  }

1 This class represents a generalized slice out of an array.   A  gslice
  is  defined by a starting offset (s), a set of lengths (lj), and a set
  of strides (dj).  The number of  lengths  must  equal  the  number  of
  strides.

2 A  gslice  represents  a  mapping from a set of indices (ij), equal in
  number to the number of strides, to a single index k.   It  is  useful
  for  building  multidimensional  array classes using the valarray tem­
  plate, which is one-dimensional.  The  set  of  one-dimensional  index
  values  specified by a gslice are k=s+ ijdj where the multidimensional
  indices ij range in value from 0 to lij-1.

3 [Example: The gslice specification
  start  = 3
  length = {2, 4, 3}
  stride = {19, 4, 1}
  yields the sequence of one-dimensional indices

                    k=3+(0,1)×19+(0,1,2,3)×4+(0,1,2)×1
  which are ordered as shown in the following table:

      (i0, i1, i2, k) =
              (0, 0, 0, 3),
              (0, 0, 1, 4),
              (0, 0, 2, 5),
              (0, 1, 0, 7),
              (0, 1, 1, 8),
              (0, 1, 2, 9),
              (0, 2, 0, 11),
              (0, 2, 1, 12),
              (0, 2, 2, 13),
              (0, 3, 0, 15),
              (0, 3, 1, 16),
              (0, 3, 2, 17),
              (1, 0, 0, 22),
              (1, 0, 1, 23),
              ...
              (1, 3, 2, 36)
  That is, the highest-ordered index turns fastest.   --end example]

4 It is possible to have  degenerate  generalized  slices  in  which  an
  address is repeated.

5 [Example: If the stride parameters in the previous example are changed
  to {1, 1, 1}, the first few elements  of  the  resulting  sequence  of
  indices will be
              (0, 0, 0, 3),
              (0, 0, 1, 4),
              (0, 0, 2, 5),
              (0, 1, 0, 4),
              (0, 1, 1, 5),
              (0, 1, 2, 6),
              ...
   --end example]

6 If a degenerate slice is used as the argument to the non-const version
  of operator[](const gslice&), the resulting behavior is undefined.

  26.4.5.1  gslice constructors                        [lib.gslice.cons]

  gslice();
  gslice(size_t start, const valarray<size_t>& lengths,
                             const valarray<size_t>& strides);
  gslice(const gslice&);

1 The default constructor creates a gslice which specifies no  elements.
  The  constructor  with arguments builds a gslice based on a specifica­
  tion of start, lengths, and strides, as explained in the previous sec­
  tion.

  26.4.5.2  gslice access functions                  [lib.gslice.access]

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

  These  access  functions  return  the  representation  of  the  start,
  lengths, or strides specified for the gslice.

  26.4.6  Template class gslice_array        [lib.template.gslice.array]
  namespace std {
    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 fill(const T&);
     ~gslice_array();
    private:
      gslice_array();
      gslice_array(const gslice_array&);
      gslice_array& operator=(const gslice_array&);
      //  remainder implementation defined
    };
  }

1 This template is a helper template used by the slice subscript  opera­
  tor
  gslice_array<T> valarray<T>::operator[](const gslice&);
  It  has  reference  semantics  to  a subset of an array specified by a
  gslice object.

2 Thus, the expression a[gslice(1, length, stride)] = b has  the  effect
  of  assigning the elements of b to a generalized slice of the elements
  in a.

3 [Note: C++ programs may not instantiate gslice_array,  since  all  its
  constructors are private.  It is intended purely as a helper class and
  should be transparent to the user.   --end note]

  26.4.6.1  gslice_array constructors            [lib.gslice.array.cons]

  gslice_array();
  gslice_array(const gslice_array&);

1 The gslice_array template has no public constructors.  It declares the
  above  constructors  to  be  private.   These constructors need not be
  defined.

  26.4.6.2  gslice_array assignment            [lib.gslice.array.assign]

  void operator=(const valarray<T>&) const;
  gslice_array& operator=(const gslice_array&);

1 The second of these two assignment operators is declared  private  and
  need not be defined.  The first has reference semantics, assigning the
  values of the argument array elements  to  selected  elements  of  the
  valarray<T> object to which the gslice_array refers.

  26.4.6.3  gslice_array computed         [lib.gslice.array.comp.assign]
       assignment

  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;

1 These computed assignments  have  reference  semantics,  applying  the
  indicated operation to the elements of the argument array and selected
  elements of the valarray<T> object to which  the  gslice_array  object
  refers.

  26.4.6.4  gslice_array fill function           [lib.gslice.array.fill]

  void fill(const T&);

1 This  function  has  reference  semantics,  assigning the value of its
  argument to the elements  of  the  valarray<T>  object  to  which  the
  gslice_array object refers.

  26.4.7  Template class mask_array            [lib.template.mask.array]
  namespace std {
    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 fill(const T&);
     ~mask_array();
    private:
      mask_array();
      mask_array(const mask_array&);
      mask_array& operator=(const mask_array&);
      //  remainder implementation defined
    };
  }

1 This  template  is a helper template used by the mask subscript opera­
  tor:
    mask_array<T> valarray<T>::operator[](const valarray<bool>&).
  It has reference semantics to a subset of  an  array  specified  by  a
  boolean  mask.   Thus,  the  expression a[mask] = b; has the effect of
  assigning the elements of b to the masked elements  in  a  (those  for
  which the corresponding element in mask is true.

2 [Note: C++ programs may not declare instances of mask_array, since all
  its constructors are private.  It  is  intended  purely  as  a  helper
  class, and should be transparent to the user.   --end note]

  26.4.7.1  mask_array constructors                [lib.mask.array.cons]

  mask_array();
  mask_array(const mask_array&);

1 The  mask_array  template has no public constructors.  It declares the
  above constructors to be private.   These  constructors  need  not  be
  defined.

  26.4.7.2  mask_array assignment                [lib.mask.array.assign]

  void operator=(const valarray<T>&) const;
  mask_array& operator=(const mask_array&);

1 The  second  of these two assignment operators is declared private and
  need not be defined.  The first has reference semantics, assigning the
  values  of  the  argument  array  elements to selected elements of the
  valarray<T> object to which it refers.

  26.4.7.3  mask_array computed             [lib.mask.array.comp.assign]
       assignment

  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;

1 These  computed  assignments  have  reference  semantics, applying the
  indicated operation to the elements of the argument array and selected
  elements of the valarray<T> object to which the mask object refers.

  26.4.7.4  mask_array fill function               [lib.mask.array.fill]

  void fill(const T&);

  This  function  has  reference  semantics,  assigning the value of its
  argument to the elements  of  the  valarray<T>  object  to  which  the
  mask_array object refers.

  26.4.8  Template class                   [lib.template.indirect.array]
       indirect_array

  namespace std {
    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 fill(const T&);
     ~indirect_array();
    private:
      indirect_array();
      indirect_array(const indirect_array&);
      indirect_array& operator=(const indirect_array&);
      //  remainder implementation defined
    };
  }

1 This template is a helper template  used  by  the  indirect  subscript
  operator
     indirect_array<T> valarray<T>::operator[](const valarray<size_t>&).
  It has reference semantics to a subset of an  array  specified  by  an
  indirect_array.   Thus  the expression a[indirect] = b; has the effect
  of assigning the elements of b to the  elements  in  a  whose  indices
  appear in indirect.

2 [Note: C++ programs may not declare instances of indirect_array, since
  all its constructors are private.  It is intended purely as  a  helper
  class, and should be transparent to the user.   --end note]

  26.4.8.1  indirect_array constructors        [lib.indirect.array.cons]

  indirect_array();
  indirect_array(const indirect_array&);

  The indirect_array template has no public constructors.  The construc­
  tors listed  above  are  private.   These  constructors  need  not  be
  defined.

  26.4.8.2  indirect_array assignment        [lib.indirect.array.assign]

  void operator=(const valarray<T>&) const;
  indirect_array& operator=(const indirect_array&);

1 The  second  of these two assignment operators is declared private and
  need not be defined.  The first has reference semantics, assigning the
  values  of  the  argument  array  elements to selected elements of the
  valarray<T> object to which it refers.

2 If the indirect_array specifies an element in the  valarray<T>  object
  to which it refers more than once, the behavior is undefined.

3 [Example:
  int addr[] = {2, 3, 1, 4, 4};
  valarray<size_t> indirect(addr, 5);
  valarray<double> a(0., 10), b(1., 5);
  array[indirect] = b;
  results  in  undefined  behavior since element 4 is specified twice in
  the indirection.   --end example]

  26.4.8.3  indirect_array              [lib.indirect.array.comp.assign]
       computed assignment

  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;

1 These  computed  assignments  have  reference  semantics, applying the
  indicated operation to the elements of the argument array and selected
  elements  of the valarray<T> object to which the indirect_array object
  refers.

2 If the indirect_array specifies an element in the  valarray<T>  object
  to which it refers more than once, the behavior is undefined.

  26.4.8.4  indirect_array fill function       [lib.indirect.array.fill]

  void fill(const T&);

1 This  function  has  reference  semantics,  assigning the value of its
  argument to the elements of the valarray<T> object to which the  indi­
  rect_array object refers.

  26.5  Generalized numeric operations                 [lib.numeric.ops]

  Header <numeric> synopsis

  namespace std {
    template <class InputIterator, class T>
      T accumulate(InputIterator first, InputIterator last, T init);
    template <class InputIterator, class T, class BinaryOperation>
      T accumulate(InputIterator first, InputIterator last, T init,
                   BinaryOperation binary_op);
    template <class InputIterator1, class InputIterator2, class T>
      T inner_product(InputIterator1 first1, InputIterator1 last1,
                      InputIterator2 first2, T init);
    template <class InputIterator1, class InputIterator2, class T,
              class BinaryOperation1, class BinaryOperation2>
      T inner_product(InputIterator1 first1, InputIterator1 last1,
                      InputIterator2 first2, T init,
                      BinaryOperation1 binary_op1, BinaryOperation2 binary_op2);
    template <class InputIterator, class OutputIterator>
      OutputIterator partial_sum(InputIterator first, InputIterator last,
                                 OutputIterator result);
    template <class InputIterator, class OutputIterator, class BinaryOperation>
      OutputIterator partial_sum(InputIterator first, InputIterator last,
                                 OutputIterator result, BinaryOperation binary_op);
    template <class InputIterator, class OutputIterator>
      OutputIterator adjacent_difference(InputIterator first, InputIterator last,
                                         OutputIterator result);
    template <class InputIterator, class OutputIterator, class BinaryOperation>
      OutputIterator adjacent_difference(InputIterator first, InputIterator last,
                                         OutputIterator result,
                                         BinaryOperation binary_op);
  }

1 The  requirements  on  the  types  of  algorithms'  arguments that are
  described in the introduction to clause _lib.algorithms_ also apply to
  the following algorithms.

  26.5.1  Accumulate                                    [lib.accumulate]

  template <class InputIterator, class T>
    T accumulate(InputIterator first, InputIterator last, T init);
  template <class InputIterator, class T, class BinaryOperation>
    T accumulate(InputIterator first, InputIterator last, T init,
                 BinaryOperation binary_op);

  Effects:
    Initializes the accumulator acc with the initial value init and then
    modifies it with acc = acc + *i or  acc  =  binary_op(acc,  *i)  for
    every iterator i in the range [first, last) in order.11)
  _________________________
  11)  accumulate  is  similar  to the APL reduction operator and Common
  Lisp reduce function, but it avoids the difficulty of defining the re­

  Requires:
    binary_op shall not cause side effects.

  26.5.2  Inner product                              [lib.inner.product]

  template <class InputIterator1, class InputIterator2, class T>
    T inner_product(InputIterator1 first1, InputIterator1 last1,
                    InputIterator2 first2, T init);
  template <class InputIterator1, class InputIterator2, class T,
            class BinaryOperation1, class BinaryOperation2>
    T inner_product(InputIterator1 first1, InputIterator1 last1,
                    InputIterator2 first2, T init,
                    BinaryOperation1 binary_op1,
                    BinaryOperation2 binary_op2);

  Effects:
    Computes its result by initializing the  accumulator  acc  with  the
    initial  value  init  and then modifying it with acc = acc + (*i1) *
    (*i2) or acc = binary_op1(acc, binary_op2(*i1, *i2)) for every iter­
    ator  i1  in  the  range  [first, last) and iterator i2 in the range
    [first2, first2 + (last - first)) in order.
  Requires:
    binary_op1 and binary_op2 shall not cause side effects.

  26.5.3  Partial sum                                  [lib.partial.sum]

  template <class InputIterator, class OutputIterator>
    OutputIterator
      partial_sum(InputIterator first, InputIterator last,
                  OutputIterator result);
  template
    <class InputIterator, class OutputIterator, class BinaryOperation>
      OutputIterator
        partial_sum(InputIterator first, InputIterator last,
                    OutputIterator result, BinaryOperation binary_op);

  Effects:
    Assigns to every element referred to by  iterator  i  in  the  range
    [result, result + (last - first)) a value correspondingly equal to
    ((...(*first + *(first + 1)) + ...) + *(first + (i - result)))
    or
    binary_op(binary_op(...,   binary_op(*first,   *(first  +  1)),...),
    *(first + (i - result)))
  Returns:
    result + (last - first).
  Complexity:
    Exactly (last - first) - 1 applications of binary_op.

  _________________________
  sult  of reduction on an empty sequence by always requiring an initial
  value.

  Requires:
    binary_op is expected not to have any side effects.
  Notes:
    result may be equal to first.

  26.5.4  Adjacent difference                  [lib.adjacent.difference]

  template <class InputIterator, class OutputIterator>
    OutputIterator
      adjacent_difference(InputIterator first, InputIterator last,
                          OutputIterator result);
  template
    <class InputIterator, class OutputIterator, class BinaryOperation>
      OutputIterator
        adjacent_difference(InputIterator first, InputIterator last,
                            OutputIterator result,
                            BinaryOperation binary_op);

  Effects:
    Assigns to every element referred to by  iterator  i  in  the  range
    [result  + 1, result + (last - first)) a value correspondingly equal
    to
    *(first + (i - result)) - *(first + (i - result) - 1)
    or
    binary_op(*(first + (i - result)), *(first + (i - result) - 1)).
    result gets the value of *first.
  Requires:
    binary_op shall not have any side effects.
  Notes:
    result may be equal to first.
  Returns:
    result + (last - first).
  Complexity:
    Exactly (last - first) - 1 applications of binary_op.

  26.6  C Library                                           [lib.c.math]

1 Tables 2 and 3 describe headers <cmath> and <cstdlib> ( abs(),  div(),
  rand(), srand()), respectively.

                     Table 2--Header <cmath> synopsis

          +-----------------------------------------------------+
          |          Type    Name(s)                            |
          +-----------------------------------------------------+
          |Macro:  HUGE_VAL                                     |
          +-----------------------------------------------------+
          |Functions:                                           |
          |acos    cos     fmod    modf    tan                  |
          |asin    cosh    frexp   pow     tanh                 |
          |atan    exp     ldexp   sin                          |
          |atan2   fabs    log     sinh                         |
          |ceil    floor   log10   sqrt                         |
          +-----------------------------------------------------+

                    Table 2--Header <cstdlib> synopsis

                     +-------------------------------+
                     |   Type    Name(s)             |
                     +-------------------------------+
                     |Macros: RAND_MAX               |
                     +-------------------------------+
                     |Types:  div_t   ldiv_t         |
                     +-------------------------------+
                     |Functions:                     |
                     |abs     labs    srand          |
                     |div     ldiv    rand           |
                     +-------------------------------+

2 The  contents  of these headers are the same as the Standard C library
  headers <math.h> and <stdlib.h> respectively, with the following addi­
  tions:

3 In  addition  to  the  int versions of certain math functions in <cst­
  dlib>, C++ adds long overloaded versions of these functions, with  the
  same semantics.

4 The added signatures are:

  long   abs(long);        // labs()
  ldiv_t div(long, long);  // ldiv()

5 In  addition  to the double versions of the math functions in <cmath>,
  C++ adds float and long double overloaded versions of these functions,
  with the same semantics.

6 The added signatures are:

  float abs  (float);
  float acos (float);
  float asin (float);
  float atan (float);
  float atan2(float, float);
  float ceil (float);
  float cos  (float);
  float cosh (float);
  float exp  (float);
  float fabs (float);
  float floor(float);
  float fmod (float, float);
  float frexp(float, int*);
  float ldexp(float, int);
  float log  (float);
  float log10(float);
  float modf (float, float*);
  float pow  (float, float);
  float pow  (float, int);
  float sin  (float);
  float sinh (float);
  float sqrt (float);
  float tan  (float);
  float tanh (float);

  double abs(double);         // fabs()
  double pow(double, int);

  long double abs  (long double);
  long double acos (long double);
  long double asin (long double);
  long double atan (long double);
  long double atan2(long double, long double);
  long double ceil (long double);
  long double cos  (long double);
  long double cosh (long double);
  long double exp  (long double);
  long double fabs (long double);
  long double floor(long double);
  long double frexp(long double, int*);
  long double fmod (long double, long double);
  long double frexp(long double, int*);
  long double ldexp(long double, int);
  long double log  (long double);
  long double log10(long double);
  long double modf (long double, long double*);
  long double pow  (long double, long double);
  long double pow  (long double, int);
  long double sin  (long double);
  long double sinh (long double);
  long double sqrt (long double);
  long double tan  (long double);
  long double tanh (long double);

  SEE ALSO: ISO C subclauses 7.5, 7.10.2, 7.10.6.