// The template and inlines for the -*- C++ -*- gslice_array class.

// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2004, 2005, 2009, 2010
// Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.

// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
// <http://www.gnu.org/licenses/>.

/** @file bits/gslice_array.h
 *  This is an internal header file, included by other library headers.
 *  Do not attempt to use it directly. @headername{valarray}
 */

// Written by Gabriel Dos Reis <Gabriel.Dos-Reis@DPTMaths.ENS-Cachan.Fr>

#ifndef _GSLICE_ARRAY_H
#define _GSLICE_ARRAY_H 1

#pragma GCC system_header

namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION

  /**
   * @addtogroup numeric_arrays
   * @{
   */

  /**
   *  @brief  Reference to multi-dimensional subset of an array.
   *
   *  A gslice_array is a reference to the actual elements of an array
   *  specified by a gslice.  The way to get a gslice_array is to call
   *  operator[](gslice) on a valarray.  The returned gslice_array then
   *  permits carrying operations out on the referenced subset of elements in
   *  the original valarray.  For example, operator+=(valarray) will add
   *  values to the subset of elements in the underlying valarray this
   *  gslice_array refers to.
   *
   *  @param  Tp  Element type.
   */
  template<typename _Tp>
    class gslice_array
    {
    public:
      typedef _Tp value_type;

      // _GLIBCXX_RESOLVE_LIB_DEFECTS
      // 253. valarray helper functions are almost entirely useless

      ///  Copy constructor.  Both slices refer to the same underlying array.
      gslice_array(const gslice_array&);

      ///  Assignment operator.  Assigns slice elements to corresponding
      ///  elements of @a a.
      gslice_array& operator=(const gslice_array&);

      ///  Assign slice elements to corresponding elements of @a v.
      void operator=(const valarray<_Tp>&) const;
      ///  Multiply slice elements by corresponding elements of @a v.
      void operator*=(const valarray<_Tp>&) const;
      ///  Divide slice elements by corresponding elements of @a v.
      void operator/=(const valarray<_Tp>&) const;
      ///  Modulo slice elements by corresponding elements of @a v.
      void operator%=(const valarray<_Tp>&) const;
      ///  Add corresponding elements of @a v to slice elements.
      void operator+=(const valarray<_Tp>&) const;
      ///  Subtract corresponding elements of @a v from slice elements.
      void operator-=(const valarray<_Tp>&) const;
      ///  Logical xor slice elements with corresponding elements of @a v.
      void operator^=(const valarray<_Tp>&) const;
      ///  Logical and slice elements with corresponding elements of @a v.
      void operator&=(const valarray<_Tp>&) const;
      ///  Logical or slice elements with corresponding elements of @a v.
      void operator|=(const valarray<_Tp>&) const;
      ///  Left shift slice elements by corresponding elements of @a v.
      void operator<<=(const valarray<_Tp>&) const;
      ///  Right shift slice elements by corresponding elements of @a v.
      void operator>>=(const valarray<_Tp>&) const;
      ///  Assign all slice elements to @a t.
      void operator=(const _Tp&) const;

      template<class _Dom>
        void operator=(const _Expr<_Dom, _Tp>&) const;
      template<class _Dom>
        void operator*=(const _Expr<_Dom, _Tp>&) const;
      template<class _Dom>
        void operator/=(const _Expr<_Dom, _Tp>&) const;
      template<class _Dom>
        void operator%=(const _Expr<_Dom, _Tp>&) const;
      template<class _Dom>
        void operator+=(const _Expr<_Dom, _Tp>&) const;
      template<class _Dom>
        void operator-=(const _Expr<_Dom, _Tp>&) const;
      template<class _Dom>
        void operator^=(const _Expr<_Dom, _Tp>&) const;
      template<class _Dom>
        void operator&=(const _Expr<_Dom, _Tp>&) const;
      template<class _Dom>
        void operator|=(const _Expr<_Dom, _Tp>&) const;
      template<class _Dom>
        void operator<<=(const _Expr<_Dom, _Tp>&) const;
      template<class _Dom>
        void operator>>=(const _Expr<_Dom, _Tp>&) const;

    private:
      _Array<_Tp>    _M_array;
      const valarray<size_t>& _M_index;

      friend class valarray<_Tp>;

      gslice_array(_Array<_Tp>, const valarray<size_t>&);

      // not implemented
      gslice_array();
    };

  template<typename _Tp>
    inline
    gslice_array<_Tp>::gslice_array(_Array<_Tp> __a,
				    const valarray<size_t>& __i)
    : _M_array(__a), _M_index(__i) {}

  template<typename _Tp>
    inline
    gslice_array<_Tp>::gslice_array(const gslice_array<_Tp>& __a)
    : _M_array(__a._M_array), _M_index(__a._M_index) {}

  template<typename _Tp>
    inline gslice_array<_Tp>&
    gslice_array<_Tp>::operator=(const gslice_array<_Tp>& __a)
    {
      std::__valarray_copy(_Array<_Tp>(__a._M_array),
			   _Array<size_t>(__a._M_index), _M_index.size(),
			   _M_array, _Array<size_t>(_M_index));
      return *this;
    }

  template<typename _Tp>
    inline void
    gslice_array<_Tp>::operator=(const _Tp& __t) const
    {
      std::__valarray_fill(_M_array, _Array<size_t>(_M_index),
			   _M_index.size(), __t);
    }

  template<typename _Tp>
    inline void
    gslice_array<_Tp>::operator=(const valarray<_Tp>& __v) const
    {
      std::__valarray_copy(_Array<_Tp>(__v), __v.size(),
			   _M_array, _Array<size_t>(_M_index));
    }

  template<typename _Tp>
    template<class _Dom>
      inline void
      gslice_array<_Tp>::operator=(const _Expr<_Dom, _Tp>& __e) const
      {
	std::__valarray_copy (__e, _M_index.size(), _M_array,
			      _Array<size_t>(_M_index));
      }

#undef _DEFINE_VALARRAY_OPERATOR
#define _DEFINE_VALARRAY_OPERATOR(_Op, _Name)				\
  template<typename _Tp>						\
    inline void								\
    gslice_array<_Tp>::operator _Op##=(const valarray<_Tp>& __v) const	\
    {									\
      _Array_augmented_##_Name(_M_array, _Array<size_t>(_M_index),	\
			       _Array<_Tp>(__v), __v.size());		\
    }									\
									\
  template<typename _Tp>                                                \
    template<class _Dom>				                \
      inline void							\
      gslice_array<_Tp>::operator _Op##= (const _Expr<_Dom, _Tp>& __e) const\
      {									\
	_Array_augmented_##_Name(_M_array, _Array<size_t>(_M_index), __e,\
				 _M_index.size());			\
      }

_DEFINE_VALARRAY_OPERATOR(*, __multiplies)
_DEFINE_VALARRAY_OPERATOR(/, __divides)
_DEFINE_VALARRAY_OPERATOR(%, __modulus)
_DEFINE_VALARRAY_OPERATOR(+, __plus)
_DEFINE_VALARRAY_OPERATOR(-, __minus)
_DEFINE_VALARRAY_OPERATOR(^, __bitwise_xor)
_DEFINE_VALARRAY_OPERATOR(&, __bitwise_and)
_DEFINE_VALARRAY_OPERATOR(|, __bitwise_or)
_DEFINE_VALARRAY_OPERATOR(<<, __shift_left)
_DEFINE_VALARRAY_OPERATOR(>>, __shift_right)

#undef _DEFINE_VALARRAY_OPERATOR

  // @} group numeric_arrays

_GLIBCXX_END_NAMESPACE_VERSION
} // namespace

#endif /* _GSLICE_ARRAY_H */
