100db7afdSDavid E. O'Brien // The template and inlines for the -*- C++ -*- internal _Array helper class.
200db7afdSDavid E. O'Brien 
3*ffeaf689SAlexander Kabaev // Copyright (C) 1997, 1998, 1999, 2000, 2003
4*ffeaf689SAlexander Kabaev //  Free Software Foundation, Inc.
500db7afdSDavid E. O'Brien //
600db7afdSDavid E. O'Brien // This file is part of the GNU ISO C++ Library.  This library is free
700db7afdSDavid E. O'Brien // software; you can redistribute it and/or modify it under the
800db7afdSDavid E. O'Brien // terms of the GNU General Public License as published by the
900db7afdSDavid E. O'Brien // Free Software Foundation; either version 2, or (at your option)
1000db7afdSDavid E. O'Brien // any later version.
1100db7afdSDavid E. O'Brien 
1200db7afdSDavid E. O'Brien // This library is distributed in the hope that it will be useful,
1300db7afdSDavid E. O'Brien // but WITHOUT ANY WARRANTY; without even the implied warranty of
1400db7afdSDavid E. O'Brien // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1500db7afdSDavid E. O'Brien // GNU General Public License for more details.
1600db7afdSDavid E. O'Brien 
1700db7afdSDavid E. O'Brien // You should have received a copy of the GNU General Public License along
1800db7afdSDavid E. O'Brien // with this library; see the file COPYING.  If not, write to the Free
1900db7afdSDavid E. O'Brien // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
2000db7afdSDavid E. O'Brien // USA.
2100db7afdSDavid E. O'Brien 
2200db7afdSDavid E. O'Brien // As a special exception, you may use this file as part of a free software
2300db7afdSDavid E. O'Brien // library without restriction.  Specifically, if other files instantiate
2400db7afdSDavid E. O'Brien // templates or use macros or inline functions from this file, or you compile
2500db7afdSDavid E. O'Brien // this file and link it with other files to produce an executable, this
2600db7afdSDavid E. O'Brien // file does not by itself cause the resulting executable to be covered by
2700db7afdSDavid E. O'Brien // the GNU General Public License.  This exception does not however
2800db7afdSDavid E. O'Brien // invalidate any other reasons why the executable file might be covered by
2900db7afdSDavid E. O'Brien // the GNU General Public License.
3000db7afdSDavid E. O'Brien 
3100db7afdSDavid E. O'Brien // Written by Gabriel Dos Reis <[email protected]>
3200db7afdSDavid E. O'Brien 
3300db7afdSDavid E. O'Brien /** @file valarray_array.h
3400db7afdSDavid E. O'Brien  *  This is an internal header file, included by other library headers.
3500db7afdSDavid E. O'Brien  *  You should not attempt to use it directly.
3600db7afdSDavid E. O'Brien  */
3700db7afdSDavid E. O'Brien 
38*ffeaf689SAlexander Kabaev #ifndef _VALARRAY_ARRAY_H
39*ffeaf689SAlexander Kabaev #define _VALARRAY_ARRAY_H 1
4000db7afdSDavid E. O'Brien 
4100db7afdSDavid E. O'Brien #pragma GCC system_header
4200db7afdSDavid E. O'Brien 
4300db7afdSDavid E. O'Brien #include <bits/c++config.h>
4400db7afdSDavid E. O'Brien #include <bits/cpp_type_traits.h>
4500db7afdSDavid E. O'Brien #include <cstdlib>
4600db7afdSDavid E. O'Brien #include <cstring>
4700db7afdSDavid E. O'Brien #include <new>
4800db7afdSDavid E. O'Brien 
4900db7afdSDavid E. O'Brien namespace std
5000db7afdSDavid E. O'Brien {
5100db7afdSDavid E. O'Brien   //
5200db7afdSDavid E. O'Brien   // Helper functions on raw pointers
5300db7afdSDavid E. O'Brien   //
5400db7afdSDavid E. O'Brien 
5500db7afdSDavid E. O'Brien   // We get memory by the old fashion way
5600db7afdSDavid E. O'Brien   inline void*
5700db7afdSDavid E. O'Brien   __valarray_get_memory(size_t __n)
5800db7afdSDavid E. O'Brien   { return operator new(__n); }
5900db7afdSDavid E. O'Brien 
6000db7afdSDavid E. O'Brien   template<typename _Tp>
6100db7afdSDavid E. O'Brien      inline _Tp*__restrict__
6200db7afdSDavid E. O'Brien      __valarray_get_storage(size_t __n)
6300db7afdSDavid E. O'Brien      {
6400db7afdSDavid E. O'Brien        return static_cast<_Tp*__restrict__>
65*ffeaf689SAlexander Kabaev          (std::__valarray_get_memory(__n * sizeof(_Tp)));
6600db7afdSDavid E. O'Brien      }
6700db7afdSDavid E. O'Brien 
6800db7afdSDavid E. O'Brien   // Return memory to the system
6900db7afdSDavid E. O'Brien   inline void
7000db7afdSDavid E. O'Brien   __valarray_release_memory(void* __p)
7100db7afdSDavid E. O'Brien   { operator delete(__p); }
7200db7afdSDavid E. O'Brien 
7300db7afdSDavid E. O'Brien   // Turn a raw-memory into an array of _Tp filled with _Tp()
7400db7afdSDavid E. O'Brien   // This is required in 'valarray<T> v(n);'
7500db7afdSDavid E. O'Brien   template<typename _Tp, bool>
7600db7afdSDavid E. O'Brien      struct _Array_default_ctor
7700db7afdSDavid E. O'Brien      {
7800db7afdSDavid E. O'Brien        // Please note that this isn't exception safe.  But
7900db7afdSDavid E. O'Brien        // valarrays aren't required to be exception safe.
8000db7afdSDavid E. O'Brien        inline static void
8100db7afdSDavid E. O'Brien        _S_do_it(_Tp* __restrict__ __b, _Tp* __restrict__ __e)
8200db7afdSDavid E. O'Brien        { while (__b != __e) new(__b++) _Tp(); }
8300db7afdSDavid E. O'Brien      };
8400db7afdSDavid E. O'Brien 
8500db7afdSDavid E. O'Brien   template<typename _Tp>
8600db7afdSDavid E. O'Brien      struct _Array_default_ctor<_Tp, true>
8700db7afdSDavid E. O'Brien      {
8800db7afdSDavid E. O'Brien        // For fundamental types, it suffices to say 'memset()'
8900db7afdSDavid E. O'Brien        inline static void
9000db7afdSDavid E. O'Brien        _S_do_it(_Tp* __restrict__ __b, _Tp* __restrict__ __e)
91*ffeaf689SAlexander Kabaev        { std::memset(__b, 0, (__e - __b)*sizeof(_Tp)); }
9200db7afdSDavid E. O'Brien      };
9300db7afdSDavid E. O'Brien 
9400db7afdSDavid E. O'Brien   template<typename _Tp>
9500db7afdSDavid E. O'Brien      inline void
9600db7afdSDavid E. O'Brien      __valarray_default_construct(_Tp* __restrict__ __b, _Tp* __restrict__ __e)
9700db7afdSDavid E. O'Brien      {
9800db7afdSDavid E. O'Brien        _Array_default_ctor<_Tp, __is_fundamental<_Tp>::_M_type>::
9900db7afdSDavid E. O'Brien          _S_do_it(__b, __e);
10000db7afdSDavid E. O'Brien      }
10100db7afdSDavid E. O'Brien 
10200db7afdSDavid E. O'Brien   // Turn a raw-memory into an array of _Tp filled with __t
10300db7afdSDavid E. O'Brien   // This is the required in valarray<T> v(n, t).  Also
10400db7afdSDavid E. O'Brien   // used in valarray<>::resize().
10500db7afdSDavid E. O'Brien   template<typename _Tp, bool>
10600db7afdSDavid E. O'Brien      struct _Array_init_ctor
10700db7afdSDavid E. O'Brien      {
10800db7afdSDavid E. O'Brien        // Please note that this isn't exception safe.  But
10900db7afdSDavid E. O'Brien        // valarrays aren't required to be exception safe.
11000db7afdSDavid E. O'Brien        inline static void
11100db7afdSDavid E. O'Brien        _S_do_it(_Tp* __restrict__ __b, _Tp* __restrict__ __e, const _Tp __t)
11200db7afdSDavid E. O'Brien        { while (__b != __e) new(__b++) _Tp(__t); }
11300db7afdSDavid E. O'Brien      };
11400db7afdSDavid E. O'Brien 
11500db7afdSDavid E. O'Brien   template<typename _Tp>
11600db7afdSDavid E. O'Brien      struct _Array_init_ctor<_Tp, true>
11700db7afdSDavid E. O'Brien      {
11800db7afdSDavid E. O'Brien        inline static void
11900db7afdSDavid E. O'Brien        _S_do_it(_Tp* __restrict__ __b, _Tp* __restrict__ __e,  const _Tp __t)
12000db7afdSDavid E. O'Brien        { while (__b != __e) *__b++ = __t; }
12100db7afdSDavid E. O'Brien      };
12200db7afdSDavid E. O'Brien 
12300db7afdSDavid E. O'Brien   template<typename _Tp>
12400db7afdSDavid E. O'Brien      inline void
12500db7afdSDavid E. O'Brien      __valarray_fill_construct(_Tp* __restrict__ __b, _Tp* __restrict__ __e,
12600db7afdSDavid E. O'Brien                                const _Tp __t)
12700db7afdSDavid E. O'Brien      {
12800db7afdSDavid E. O'Brien        _Array_init_ctor<_Tp, __is_fundamental<_Tp>::_M_type>::
12900db7afdSDavid E. O'Brien          _S_do_it(__b, __e, __t);
13000db7afdSDavid E. O'Brien      }
13100db7afdSDavid E. O'Brien 
13200db7afdSDavid E. O'Brien   //
13300db7afdSDavid E. O'Brien   // copy-construct raw array [__o, *) from plain array [__b, __e)
13400db7afdSDavid E. O'Brien   // We can't just say 'memcpy()'
13500db7afdSDavid E. O'Brien   //
13600db7afdSDavid E. O'Brien   template<typename _Tp, bool>
13700db7afdSDavid E. O'Brien      struct _Array_copy_ctor
13800db7afdSDavid E. O'Brien      {
13900db7afdSDavid E. O'Brien        // Please note that this isn't exception safe.  But
14000db7afdSDavid E. O'Brien        // valarrays aren't required to be exception safe.
14100db7afdSDavid E. O'Brien        inline static void
14200db7afdSDavid E. O'Brien        _S_do_it(const _Tp* __restrict__ __b, const _Tp* __restrict__ __e,
14300db7afdSDavid E. O'Brien                 _Tp* __restrict__ __o)
14400db7afdSDavid E. O'Brien        { while (__b != __e) new(__o++) _Tp(*__b++); }
14500db7afdSDavid E. O'Brien      };
14600db7afdSDavid E. O'Brien 
14700db7afdSDavid E. O'Brien   template<typename _Tp>
14800db7afdSDavid E. O'Brien      struct _Array_copy_ctor<_Tp, true>
14900db7afdSDavid E. O'Brien      {
15000db7afdSDavid E. O'Brien        inline static void
15100db7afdSDavid E. O'Brien        _S_do_it(const _Tp* __restrict__ __b, const _Tp* __restrict__ __e,
15200db7afdSDavid E. O'Brien                 _Tp* __restrict__ __o)
153*ffeaf689SAlexander Kabaev        { std::memcpy(__o, __b, (__e - __b)*sizeof(_Tp)); }
15400db7afdSDavid E. O'Brien      };
15500db7afdSDavid E. O'Brien 
15600db7afdSDavid E. O'Brien   template<typename _Tp>
15700db7afdSDavid E. O'Brien      inline void
15800db7afdSDavid E. O'Brien      __valarray_copy_construct(const _Tp* __restrict__ __b,
15900db7afdSDavid E. O'Brien                                const _Tp* __restrict__ __e,
16000db7afdSDavid E. O'Brien                                _Tp* __restrict__ __o)
16100db7afdSDavid E. O'Brien      {
16200db7afdSDavid E. O'Brien        _Array_copy_ctor<_Tp, __is_fundamental<_Tp>::_M_type>::
16300db7afdSDavid E. O'Brien          _S_do_it(__b, __e, __o);
16400db7afdSDavid E. O'Brien      }
16500db7afdSDavid E. O'Brien 
16600db7afdSDavid E. O'Brien   // copy-construct raw array [__o, *) from strided array __a[<__n : __s>]
16700db7afdSDavid E. O'Brien   template<typename _Tp>
16800db7afdSDavid E. O'Brien      inline void
16900db7afdSDavid E. O'Brien      __valarray_copy_construct (const _Tp* __restrict__ __a, size_t __n,
17000db7afdSDavid E. O'Brien                                 size_t __s, _Tp* __restrict__ __o)
17100db7afdSDavid E. O'Brien      {
17200db7afdSDavid E. O'Brien        if (__is_fundamental<_Tp>::_M_type)
17300db7afdSDavid E. O'Brien          while (__n--) { *__o++ = *__a; __a += __s; }
17400db7afdSDavid E. O'Brien        else
17500db7afdSDavid E. O'Brien          while (__n--) { new(__o++) _Tp(*__a);  __a += __s; }
17600db7afdSDavid E. O'Brien      }
17700db7afdSDavid E. O'Brien 
17800db7afdSDavid E. O'Brien   // copy-construct raw array [__o, *) from indexed array __a[__i[<__n>]]
17900db7afdSDavid E. O'Brien   template<typename _Tp>
18000db7afdSDavid E. O'Brien      inline void
18100db7afdSDavid E. O'Brien      __valarray_copy_construct (const _Tp* __restrict__ __a,
18200db7afdSDavid E. O'Brien                                 const size_t* __restrict__ __i,
18300db7afdSDavid E. O'Brien                                 _Tp* __restrict__ __o, size_t __n)
18400db7afdSDavid E. O'Brien      {
18500db7afdSDavid E. O'Brien        if (__is_fundamental<_Tp>::_M_type)
18600db7afdSDavid E. O'Brien          while (__n--) *__o++ = __a[*__i++];
18700db7afdSDavid E. O'Brien        else
18800db7afdSDavid E. O'Brien          while (__n--) new (__o++) _Tp(__a[*__i++]);
18900db7afdSDavid E. O'Brien      }
19000db7afdSDavid E. O'Brien 
19100db7afdSDavid E. O'Brien   // Do the necessary cleanup when we're done with arrays.
19200db7afdSDavid E. O'Brien   template<typename _Tp>
19300db7afdSDavid E. O'Brien      inline void
19400db7afdSDavid E. O'Brien      __valarray_destroy_elements(_Tp* __restrict__ __b, _Tp* __restrict__ __e)
19500db7afdSDavid E. O'Brien      {
19600db7afdSDavid E. O'Brien        if (!__is_fundamental<_Tp>::_M_type)
19700db7afdSDavid E. O'Brien          while (__b != __e) { __b->~_Tp(); ++__b; }
19800db7afdSDavid E. O'Brien      }
19900db7afdSDavid E. O'Brien 
20000db7afdSDavid E. O'Brien   // Fill a plain array __a[<__n>] with __t
20100db7afdSDavid E. O'Brien   template<typename _Tp>
20200db7afdSDavid E. O'Brien      inline void
20300db7afdSDavid E. O'Brien      __valarray_fill (_Tp* __restrict__ __a, size_t __n, const _Tp& __t)
20400db7afdSDavid E. O'Brien      { while (__n--) *__a++ = __t; }
20500db7afdSDavid E. O'Brien 
20600db7afdSDavid E. O'Brien   // fill strided array __a[<__n-1 : __s>] with __t
20700db7afdSDavid E. O'Brien   template<typename _Tp>
20800db7afdSDavid E. O'Brien      inline void
20900db7afdSDavid E. O'Brien      __valarray_fill (_Tp* __restrict__ __a, size_t __n,
21000db7afdSDavid E. O'Brien                       size_t __s, const _Tp& __t)
21100db7afdSDavid E. O'Brien      { for (size_t __i=0; __i<__n; ++__i, __a+=__s) *__a = __t; }
21200db7afdSDavid E. O'Brien 
21300db7afdSDavid E. O'Brien   // fill indir   ect array __a[__i[<__n>]] with __i
21400db7afdSDavid E. O'Brien   template<typename _Tp>
21500db7afdSDavid E. O'Brien      inline void
21600db7afdSDavid E. O'Brien      __valarray_fill(_Tp* __restrict__ __a, const size_t* __restrict__ __i,
21700db7afdSDavid E. O'Brien                      size_t __n, const _Tp& __t)
21800db7afdSDavid E. O'Brien      { for (size_t __j=0; __j<__n; ++__j, ++__i) __a[*__i] = __t; }
21900db7afdSDavid E. O'Brien 
22000db7afdSDavid E. O'Brien   // copy plain array __a[<__n>] in __b[<__n>]
22100db7afdSDavid E. O'Brien   // For non-fundamental types, it is wrong to say 'memcpy()'
22200db7afdSDavid E. O'Brien   template<typename _Tp, bool>
22300db7afdSDavid E. O'Brien      struct _Array_copier
22400db7afdSDavid E. O'Brien      {
22500db7afdSDavid E. O'Brien        inline static void
22600db7afdSDavid E. O'Brien        _S_do_it(const _Tp* __restrict__ __a, size_t __n, _Tp* __restrict__ __b)
22700db7afdSDavid E. O'Brien        { while (__n--) *__b++ = *__a++; }
22800db7afdSDavid E. O'Brien      };
22900db7afdSDavid E. O'Brien 
23000db7afdSDavid E. O'Brien   template<typename _Tp>
23100db7afdSDavid E. O'Brien      struct _Array_copier<_Tp, true>
23200db7afdSDavid E. O'Brien      {
23300db7afdSDavid E. O'Brien        inline static void
23400db7afdSDavid E. O'Brien        _S_do_it(const _Tp* __restrict__ __a, size_t __n, _Tp* __restrict__ __b)
235*ffeaf689SAlexander Kabaev        { std::memcpy (__b, __a, __n * sizeof (_Tp)); }
23600db7afdSDavid E. O'Brien      };
23700db7afdSDavid E. O'Brien 
23800db7afdSDavid E. O'Brien   // Copy a plain array __a[<__n>] into a play array __b[<>]
23900db7afdSDavid E. O'Brien   template<typename _Tp>
24000db7afdSDavid E. O'Brien      inline void
24100db7afdSDavid E. O'Brien      __valarray_copy(const _Tp* __restrict__ __a, size_t __n,
24200db7afdSDavid E. O'Brien                       _Tp* __restrict__ __b)
24300db7afdSDavid E. O'Brien      {
24400db7afdSDavid E. O'Brien        _Array_copier<_Tp, __is_fundamental<_Tp>::_M_type>::
24500db7afdSDavid E. O'Brien          _S_do_it(__a, __n, __b);
24600db7afdSDavid E. O'Brien      }
24700db7afdSDavid E. O'Brien 
24800db7afdSDavid E. O'Brien   // Copy strided array __a[<__n : __s>] in plain __b[<__n>]
24900db7afdSDavid E. O'Brien   template<typename _Tp>
25000db7afdSDavid E. O'Brien      inline void
25100db7afdSDavid E. O'Brien      __valarray_copy(const _Tp* __restrict__ __a, size_t __n, size_t __s,
25200db7afdSDavid E. O'Brien                       _Tp* __restrict__ __b)
25300db7afdSDavid E. O'Brien      { for (size_t __i=0; __i<__n; ++__i, ++__b, __a += __s) *__b = *__a; }
25400db7afdSDavid E. O'Brien 
25500db7afdSDavid E. O'Brien   // Copy a plain array  __a[<__n>] into a strided array __b[<__n : __s>]
25600db7afdSDavid E. O'Brien   template<typename _Tp>
25700db7afdSDavid E. O'Brien      inline void
25800db7afdSDavid E. O'Brien      __valarray_copy(const _Tp* __restrict__ __a, _Tp* __restrict__ __b,
25900db7afdSDavid E. O'Brien                       size_t __n, size_t __s)
26000db7afdSDavid E. O'Brien      { for (size_t __i=0; __i<__n; ++__i, ++__a, __b+=__s) *__b = *__a; }
26100db7afdSDavid E. O'Brien 
26200db7afdSDavid E. O'Brien   // Copy strided array __src[<__n : __s1>] into another
26300db7afdSDavid E. O'Brien   // strided array __dst[< : __s2>].  Their sizes must match.
26400db7afdSDavid E. O'Brien   template<typename _Tp>
26500db7afdSDavid E. O'Brien      inline void
26600db7afdSDavid E. O'Brien      __valarray_copy(const _Tp* __restrict__ __src, size_t __n, size_t __s1,
26700db7afdSDavid E. O'Brien                      _Tp* __restrict__ __dst, size_t __s2)
26800db7afdSDavid E. O'Brien      {
26900db7afdSDavid E. O'Brien        for (size_t __i = 0; __i < __n; ++__i)
27000db7afdSDavid E. O'Brien          __dst[__i * __s2] = __src [ __i * __s1];
27100db7afdSDavid E. O'Brien      }
27200db7afdSDavid E. O'Brien 
27300db7afdSDavid E. O'Brien 
27400db7afdSDavid E. O'Brien   // Copy an indexed array __a[__i[<__n>]] in plain array __b[<__n>]
27500db7afdSDavid E. O'Brien   template<typename _Tp>
27600db7afdSDavid E. O'Brien      inline void
27700db7afdSDavid E. O'Brien      __valarray_copy (const _Tp* __restrict__ __a,
27800db7afdSDavid E. O'Brien                       const size_t* __restrict__ __i,
27900db7afdSDavid E. O'Brien                       _Tp* __restrict__ __b, size_t __n)
28000db7afdSDavid E. O'Brien      { for (size_t __j=0; __j<__n; ++__j, ++__b, ++__i) *__b = __a[*__i]; }
28100db7afdSDavid E. O'Brien 
28200db7afdSDavid E. O'Brien   // Copy a plain array __a[<__n>] in an indexed array __b[__i[<__n>]]
28300db7afdSDavid E. O'Brien   template<typename _Tp>
28400db7afdSDavid E. O'Brien      inline void
28500db7afdSDavid E. O'Brien      __valarray_copy (const _Tp* __restrict__ __a, size_t __n,
28600db7afdSDavid E. O'Brien                       _Tp* __restrict__ __b, const size_t* __restrict__ __i)
28700db7afdSDavid E. O'Brien      { for (size_t __j=0; __j<__n; ++__j, ++__a, ++__i) __b[*__i] = *__a; }
28800db7afdSDavid E. O'Brien 
28900db7afdSDavid E. O'Brien   // Copy the __n first elements of an indexed array __src[<__i>] into
29000db7afdSDavid E. O'Brien   // another indexed array __dst[<__j>].
29100db7afdSDavid E. O'Brien   template<typename _Tp>
29200db7afdSDavid E. O'Brien      inline void
29300db7afdSDavid E. O'Brien      __valarray_copy(const _Tp* __restrict__ __src, size_t __n,
29400db7afdSDavid E. O'Brien                      const size_t* __restrict__ __i,
29500db7afdSDavid E. O'Brien                      _Tp* __restrict__ __dst, const size_t* __restrict__ __j)
29600db7afdSDavid E. O'Brien      {
29700db7afdSDavid E. O'Brien        for (size_t __k = 0; __k < __n; ++__k)
29800db7afdSDavid E. O'Brien          __dst[*__j++] = __src[*__i++];
29900db7afdSDavid E. O'Brien      }
30000db7afdSDavid E. O'Brien 
30100db7afdSDavid E. O'Brien   //
30200db7afdSDavid E. O'Brien   // Compute the sum of elements in range [__f, __l)
30300db7afdSDavid E. O'Brien   // This is a naive algorithm.  It suffers from cancelling.
30400db7afdSDavid E. O'Brien   // In the future try to specialize
30500db7afdSDavid E. O'Brien   // for _Tp = float, double, long double using a more accurate
30600db7afdSDavid E. O'Brien   // algorithm.
30700db7afdSDavid E. O'Brien   //
30800db7afdSDavid E. O'Brien   template<typename _Tp>
30900db7afdSDavid E. O'Brien      inline _Tp
31000db7afdSDavid E. O'Brien      __valarray_sum(const _Tp* __restrict__ __f, const _Tp* __restrict__ __l)
31100db7afdSDavid E. O'Brien      {
31200db7afdSDavid E. O'Brien        _Tp __r = _Tp();
31300db7afdSDavid E. O'Brien        while (__f != __l) __r += *__f++;
31400db7afdSDavid E. O'Brien        return __r;
31500db7afdSDavid E. O'Brien      }
31600db7afdSDavid E. O'Brien 
31700db7afdSDavid E. O'Brien   // Compute the product of all elements in range [__f, __l)
31800db7afdSDavid E. O'Brien   template<typename _Tp>
31900db7afdSDavid E. O'Brien      inline _Tp
32000db7afdSDavid E. O'Brien      __valarray_product(const _Tp* __restrict__ __f,
32100db7afdSDavid E. O'Brien                         const _Tp* __restrict__ __l)
32200db7afdSDavid E. O'Brien      {
32300db7afdSDavid E. O'Brien        _Tp __r = _Tp(1);
32400db7afdSDavid E. O'Brien        while (__f != __l) __r = __r * *__f++;
32500db7afdSDavid E. O'Brien        return __r;
32600db7afdSDavid E. O'Brien      }
32700db7afdSDavid E. O'Brien 
32800db7afdSDavid E. O'Brien   // Compute the min/max of an array-expression
32900db7afdSDavid E. O'Brien   template<typename _Ta>
33000db7afdSDavid E. O'Brien      inline typename _Ta::value_type
33100db7afdSDavid E. O'Brien      __valarray_min(const _Ta& __a)
33200db7afdSDavid E. O'Brien      {
33300db7afdSDavid E. O'Brien        size_t __s = __a.size();
33400db7afdSDavid E. O'Brien        typedef typename _Ta::value_type _Value_type;
33500db7afdSDavid E. O'Brien        _Value_type __r = __s == 0 ? _Value_type() : __a[0];
33600db7afdSDavid E. O'Brien        for (size_t __i = 1; __i < __s; ++__i)
33700db7afdSDavid E. O'Brien          {
33800db7afdSDavid E. O'Brien            _Value_type __t = __a[__i];
33900db7afdSDavid E. O'Brien            if (__t < __r)
34000db7afdSDavid E. O'Brien              __r = __t;
34100db7afdSDavid E. O'Brien          }
34200db7afdSDavid E. O'Brien        return __r;
34300db7afdSDavid E. O'Brien      }
34400db7afdSDavid E. O'Brien 
34500db7afdSDavid E. O'Brien   template<typename _Ta>
34600db7afdSDavid E. O'Brien      inline typename _Ta::value_type
34700db7afdSDavid E. O'Brien      __valarray_max(const _Ta& __a)
34800db7afdSDavid E. O'Brien      {
34900db7afdSDavid E. O'Brien        size_t __s = __a.size();
35000db7afdSDavid E. O'Brien        typedef typename _Ta::value_type _Value_type;
35100db7afdSDavid E. O'Brien        _Value_type __r = __s == 0 ? _Value_type() : __a[0];
35200db7afdSDavid E. O'Brien        for (size_t __i = 1; __i < __s; ++__i)
35300db7afdSDavid E. O'Brien          {
35400db7afdSDavid E. O'Brien            _Value_type __t = __a[__i];
35500db7afdSDavid E. O'Brien            if (__t > __r)
35600db7afdSDavid E. O'Brien              __r = __t;
35700db7afdSDavid E. O'Brien          }
35800db7afdSDavid E. O'Brien        return __r;
35900db7afdSDavid E. O'Brien      }
36000db7afdSDavid E. O'Brien 
36100db7afdSDavid E. O'Brien   //
36200db7afdSDavid E. O'Brien   // Helper class _Array, first layer of valarray abstraction.
36300db7afdSDavid E. O'Brien   // All operations on valarray should be forwarded to this class
36400db7afdSDavid E. O'Brien   // whenever possible. -- gdr
36500db7afdSDavid E. O'Brien   //
36600db7afdSDavid E. O'Brien 
36700db7afdSDavid E. O'Brien   template<typename _Tp>
36800db7afdSDavid E. O'Brien      struct _Array
36900db7afdSDavid E. O'Brien      {
37000db7afdSDavid E. O'Brien        explicit _Array (size_t);
37100db7afdSDavid E. O'Brien        explicit _Array (_Tp* const __restrict__);
37200db7afdSDavid E. O'Brien        explicit _Array (const valarray<_Tp>&);
37300db7afdSDavid E. O'Brien        _Array (const _Tp* __restrict__, size_t);
37400db7afdSDavid E. O'Brien 
37500db7afdSDavid E. O'Brien        _Tp* begin () const;
37600db7afdSDavid E. O'Brien 
37700db7afdSDavid E. O'Brien        _Tp* const __restrict__ _M_data;
37800db7afdSDavid E. O'Brien      };
37900db7afdSDavid E. O'Brien 
38000db7afdSDavid E. O'Brien   template<typename _Tp>
38100db7afdSDavid E. O'Brien      inline void
38200db7afdSDavid E. O'Brien      __valarray_fill (_Array<_Tp> __a, size_t __n, const _Tp& __t)
383*ffeaf689SAlexander Kabaev      { std::__valarray_fill (__a._M_data, __n, __t); }
38400db7afdSDavid E. O'Brien 
38500db7afdSDavid E. O'Brien   template<typename _Tp>
38600db7afdSDavid E. O'Brien      inline void
38700db7afdSDavid E. O'Brien      __valarray_fill (_Array<_Tp> __a, size_t __n, size_t __s, const _Tp& __t)
388*ffeaf689SAlexander Kabaev      { std::__valarray_fill (__a._M_data, __n, __s, __t); }
38900db7afdSDavid E. O'Brien 
39000db7afdSDavid E. O'Brien   template<typename _Tp>
39100db7afdSDavid E. O'Brien      inline void
39200db7afdSDavid E. O'Brien      __valarray_fill (_Array<_Tp> __a, _Array<size_t> __i,
39300db7afdSDavid E. O'Brien                       size_t __n, const _Tp& __t)
394*ffeaf689SAlexander Kabaev      { std::__valarray_fill (__a._M_data, __i._M_data, __n, __t); }
39500db7afdSDavid E. O'Brien 
39600db7afdSDavid E. O'Brien   // Copy a plain array __a[<__n>] into a play array __b[<>]
39700db7afdSDavid E. O'Brien   template<typename _Tp>
39800db7afdSDavid E. O'Brien      inline void
39900db7afdSDavid E. O'Brien      __valarray_copy(_Array<_Tp> __a, size_t __n, _Array<_Tp> __b)
400*ffeaf689SAlexander Kabaev      { std::__valarray_copy(__a._M_data, __n, __b._M_data); }
40100db7afdSDavid E. O'Brien 
40200db7afdSDavid E. O'Brien   // Copy strided array __a[<__n : __s>] in plain __b[<__n>]
40300db7afdSDavid E. O'Brien   template<typename _Tp>
40400db7afdSDavid E. O'Brien      inline void
40500db7afdSDavid E. O'Brien      __valarray_copy(_Array<_Tp> __a, size_t __n, size_t __s, _Array<_Tp> __b)
406*ffeaf689SAlexander Kabaev      { std::__valarray_copy(__a._M_data, __n, __s, __b._M_data); }
40700db7afdSDavid E. O'Brien 
40800db7afdSDavid E. O'Brien   // Copy a plain array  __a[<__n>] into a strided array __b[<__n : __s>]
40900db7afdSDavid E. O'Brien   template<typename _Tp>
41000db7afdSDavid E. O'Brien      inline void
41100db7afdSDavid E. O'Brien      __valarray_copy(_Array<_Tp> __a, _Array<_Tp> __b, size_t __n, size_t __s)
41200db7afdSDavid E. O'Brien      { __valarray_copy(__a._M_data, __b._M_data, __n, __s); }
41300db7afdSDavid E. O'Brien 
41400db7afdSDavid E. O'Brien   // Copy strided array __src[<__n : __s1>] into another
41500db7afdSDavid E. O'Brien   // strided array __dst[< : __s2>].  Their sizes must match.
41600db7afdSDavid E. O'Brien   template<typename _Tp>
41700db7afdSDavid E. O'Brien      inline void
41800db7afdSDavid E. O'Brien      __valarray_copy(_Array<_Tp> __a, size_t __n, size_t __s1,
41900db7afdSDavid E. O'Brien                      _Array<_Tp> __b, size_t __s2)
420*ffeaf689SAlexander Kabaev      { std::__valarray_copy(__a._M_data, __n, __s1, __b._M_data, __s2); }
42100db7afdSDavid E. O'Brien 
42200db7afdSDavid E. O'Brien 
42300db7afdSDavid E. O'Brien   // Copy an indexed array __a[__i[<__n>]] in plain array __b[<__n>]
42400db7afdSDavid E. O'Brien   template<typename _Tp>
42500db7afdSDavid E. O'Brien      inline void
42600db7afdSDavid E. O'Brien      __valarray_copy(_Array<_Tp> __a, _Array<size_t> __i,
42700db7afdSDavid E. O'Brien                       _Array<_Tp> __b, size_t __n)
428*ffeaf689SAlexander Kabaev      { std::__valarray_copy(__a._M_data, __i._M_data, __b._M_data, __n); }
42900db7afdSDavid E. O'Brien 
43000db7afdSDavid E. O'Brien   // Copy a plain array __a[<__n>] in an indexed array __b[__i[<__n>]]
43100db7afdSDavid E. O'Brien   template<typename _Tp>
43200db7afdSDavid E. O'Brien      inline void
43300db7afdSDavid E. O'Brien      __valarray_copy(_Array<_Tp> __a, size_t __n, _Array<_Tp> __b,
43400db7afdSDavid E. O'Brien                       _Array<size_t> __i)
435*ffeaf689SAlexander Kabaev      { std::__valarray_copy(__a._M_data, __n, __b._M_data, __i._M_data); }
43600db7afdSDavid E. O'Brien 
43700db7afdSDavid E. O'Brien   // Copy the __n first elements of an indexed array __src[<__i>] into
43800db7afdSDavid E. O'Brien   // another indexed array __dst[<__j>].
43900db7afdSDavid E. O'Brien   template<typename _Tp>
44000db7afdSDavid E. O'Brien      inline void
44100db7afdSDavid E. O'Brien      __valarray_copy(_Array<_Tp> __src, size_t __n, _Array<size_t> __i,
44200db7afdSDavid E. O'Brien                      _Array<_Tp> __dst, _Array<size_t> __j)
44300db7afdSDavid E. O'Brien      {
444*ffeaf689SAlexander Kabaev        std::__valarray_copy(__src._M_data, __n, __i._M_data,
44500db7afdSDavid E. O'Brien 			    __dst._M_data, __j._M_data);
44600db7afdSDavid E. O'Brien      }
44700db7afdSDavid E. O'Brien 
44800db7afdSDavid E. O'Brien   template<typename _Tp>
44900db7afdSDavid E. O'Brien      inline
45000db7afdSDavid E. O'Brien      _Array<_Tp>::_Array (size_t __n)
45100db7afdSDavid E. O'Brien        : _M_data(__valarray_get_storage<_Tp>(__n))
452*ffeaf689SAlexander Kabaev      { std::__valarray_default_construct(_M_data, _M_data + __n); }
45300db7afdSDavid E. O'Brien 
45400db7afdSDavid E. O'Brien   template<typename _Tp>
45500db7afdSDavid E. O'Brien      inline
45600db7afdSDavid E. O'Brien      _Array<_Tp>::_Array (_Tp* const __restrict__ __p) : _M_data (__p) {}
45700db7afdSDavid E. O'Brien 
45800db7afdSDavid E. O'Brien   template<typename _Tp>
45900db7afdSDavid E. O'Brien      inline _Array<_Tp>::_Array (const valarray<_Tp>& __v)
46000db7afdSDavid E. O'Brien          : _M_data (__v._M_data) {}
46100db7afdSDavid E. O'Brien 
46200db7afdSDavid E. O'Brien   template<typename _Tp>
46300db7afdSDavid E. O'Brien      inline
46400db7afdSDavid E. O'Brien      _Array<_Tp>::_Array (const _Tp* __restrict__ __b, size_t __s)
46500db7afdSDavid E. O'Brien        : _M_data(__valarray_get_storage<_Tp>(__s))
466*ffeaf689SAlexander Kabaev      { std::__valarray_copy_construct(__b, __s, _M_data); }
46700db7afdSDavid E. O'Brien 
46800db7afdSDavid E. O'Brien   template<typename _Tp>
46900db7afdSDavid E. O'Brien      inline _Tp*
47000db7afdSDavid E. O'Brien      _Array<_Tp>::begin () const
47100db7afdSDavid E. O'Brien      { return _M_data; }
47200db7afdSDavid E. O'Brien 
47300db7afdSDavid E. O'Brien #define _DEFINE_ARRAY_FUNCTION(_Op, _Name)				\
47400db7afdSDavid E. O'Brien template<typename _Tp>							\
47500db7afdSDavid E. O'Brien inline void								\
47600db7afdSDavid E. O'Brien _Array_augmented_##_Name (_Array<_Tp> __a, size_t __n, const _Tp& __t)	\
47700db7afdSDavid E. O'Brien {									\
47800db7afdSDavid E. O'Brien   for (_Tp* __p=__a._M_data; __p<__a._M_data+__n; ++__p)		\
47900db7afdSDavid E. O'Brien     *__p _Op##= __t;							\
48000db7afdSDavid E. O'Brien }									\
48100db7afdSDavid E. O'Brien 									\
48200db7afdSDavid E. O'Brien template<typename _Tp>							\
48300db7afdSDavid E. O'Brien inline void								\
48400db7afdSDavid E. O'Brien _Array_augmented_##_Name (_Array<_Tp> __a, size_t __n, _Array<_Tp> __b)	\
48500db7afdSDavid E. O'Brien {									\
48600db7afdSDavid E. O'Brien   _Tp* __p = __a._M_data;						\
48700db7afdSDavid E. O'Brien   for (_Tp* __q=__b._M_data; __q<__b._M_data+__n; ++__p, ++__q)		\
48800db7afdSDavid E. O'Brien     *__p _Op##= *__q;							\
48900db7afdSDavid E. O'Brien }									\
49000db7afdSDavid E. O'Brien 									\
49100db7afdSDavid E. O'Brien template<typename _Tp, class _Dom>					\
49200db7afdSDavid E. O'Brien void									\
49300db7afdSDavid E. O'Brien _Array_augmented_##_Name (_Array<_Tp> __a,				\
49400db7afdSDavid E. O'Brien                          const _Expr<_Dom,_Tp>& __e, size_t __n)	\
49500db7afdSDavid E. O'Brien {									\
49600db7afdSDavid E. O'Brien     _Tp* __p (__a._M_data);						\
49700db7afdSDavid E. O'Brien     for (size_t __i=0; __i<__n; ++__i, ++__p) *__p _Op##= __e[__i];	\
49800db7afdSDavid E. O'Brien }									\
49900db7afdSDavid E. O'Brien 									\
50000db7afdSDavid E. O'Brien template<typename _Tp>							\
50100db7afdSDavid E. O'Brien inline void								\
50200db7afdSDavid E. O'Brien _Array_augmented_##_Name (_Array<_Tp> __a, size_t __n, size_t __s,	\
50300db7afdSDavid E. O'Brien 			 _Array<_Tp> __b)				\
50400db7afdSDavid E. O'Brien {									\
50500db7afdSDavid E. O'Brien     _Tp* __q (__b._M_data);						\
50600db7afdSDavid E. O'Brien     for (_Tp* __p=__a._M_data; __p<__a._M_data+__s*__n; __p+=__s, ++__q) \
50700db7afdSDavid E. O'Brien       *__p _Op##= *__q;							\
50800db7afdSDavid E. O'Brien }									\
50900db7afdSDavid E. O'Brien 									\
51000db7afdSDavid E. O'Brien template<typename _Tp>							\
51100db7afdSDavid E. O'Brien inline void								\
51200db7afdSDavid E. O'Brien _Array_augmented_##_Name (_Array<_Tp> __a, _Array<_Tp> __b,		\
51300db7afdSDavid E. O'Brien 			 size_t __n, size_t __s)			\
51400db7afdSDavid E. O'Brien {									\
51500db7afdSDavid E. O'Brien     _Tp* __q (__b._M_data);						\
51600db7afdSDavid E. O'Brien     for (_Tp* __p=__a._M_data; __p<__a._M_data+__n; ++__p, __q+=__s)	\
51700db7afdSDavid E. O'Brien       *__p _Op##= *__q;							\
51800db7afdSDavid E. O'Brien }									\
51900db7afdSDavid E. O'Brien 									\
52000db7afdSDavid E. O'Brien template<typename _Tp, class _Dom>					\
52100db7afdSDavid E. O'Brien void									\
52200db7afdSDavid E. O'Brien _Array_augmented_##_Name (_Array<_Tp> __a, size_t __s,			\
52300db7afdSDavid E. O'Brien                           const _Expr<_Dom,_Tp>& __e, size_t __n)	\
52400db7afdSDavid E. O'Brien {									\
52500db7afdSDavid E. O'Brien     _Tp* __p (__a._M_data);						\
52600db7afdSDavid E. O'Brien     for (size_t __i=0; __i<__n; ++__i, __p+=__s) *__p _Op##= __e[__i];	\
52700db7afdSDavid E. O'Brien }									\
52800db7afdSDavid E. O'Brien 									\
52900db7afdSDavid E. O'Brien template<typename _Tp>							\
53000db7afdSDavid E. O'Brien inline void								\
53100db7afdSDavid E. O'Brien _Array_augmented_##_Name (_Array<_Tp> __a, _Array<size_t> __i,		\
53200db7afdSDavid E. O'Brien                           _Array<_Tp> __b, size_t __n)			\
53300db7afdSDavid E. O'Brien {									\
53400db7afdSDavid E. O'Brien     _Tp* __q (__b._M_data);						\
53500db7afdSDavid E. O'Brien     for (size_t* __j=__i._M_data; __j<__i._M_data+__n; ++__j, ++__q)	\
53600db7afdSDavid E. O'Brien         __a._M_data[*__j] _Op##= *__q;					\
53700db7afdSDavid E. O'Brien }									\
53800db7afdSDavid E. O'Brien 									\
53900db7afdSDavid E. O'Brien template<typename _Tp>							\
54000db7afdSDavid E. O'Brien inline void								\
54100db7afdSDavid E. O'Brien _Array_augmented_##_Name (_Array<_Tp> __a, size_t __n,			\
54200db7afdSDavid E. O'Brien                           _Array<_Tp> __b, _Array<size_t> __i)		\
54300db7afdSDavid E. O'Brien {									\
54400db7afdSDavid E. O'Brien     _Tp* __p (__a._M_data);						\
54500db7afdSDavid E. O'Brien     for (size_t* __j=__i._M_data; __j<__i._M_data+__n; ++__j, ++__p)	\
54600db7afdSDavid E. O'Brien         *__p _Op##= __b._M_data[*__j];					\
54700db7afdSDavid E. O'Brien }									\
54800db7afdSDavid E. O'Brien 									\
54900db7afdSDavid E. O'Brien template<typename _Tp, class _Dom>					\
55000db7afdSDavid E. O'Brien void									\
55100db7afdSDavid E. O'Brien _Array_augmented_##_Name (_Array<_Tp> __a, _Array<size_t> __i,		\
55200db7afdSDavid E. O'Brien                           const _Expr<_Dom, _Tp>& __e, size_t __n)	\
55300db7afdSDavid E. O'Brien {									\
55400db7afdSDavid E. O'Brien     size_t* __j (__i._M_data);						\
55500db7afdSDavid E. O'Brien     for (size_t __k=0; __k<__n; ++__k, ++__j)				\
55600db7afdSDavid E. O'Brien       __a._M_data[*__j] _Op##= __e[__k];				\
55700db7afdSDavid E. O'Brien }									\
55800db7afdSDavid E. O'Brien 									\
55900db7afdSDavid E. O'Brien template<typename _Tp>							\
56000db7afdSDavid E. O'Brien void									\
56100db7afdSDavid E. O'Brien _Array_augmented_##_Name (_Array<_Tp> __a, _Array<bool> __m,		\
56200db7afdSDavid E. O'Brien                           _Array<_Tp> __b, size_t __n)			\
56300db7afdSDavid E. O'Brien {									\
56400db7afdSDavid E. O'Brien     bool* ok (__m._M_data);						\
56500db7afdSDavid E. O'Brien     _Tp* __p (__a._M_data);						\
56600db7afdSDavid E. O'Brien     for (_Tp* __q=__b._M_data; __q<__b._M_data+__n; ++__q, ++ok, ++__p) { \
56700db7afdSDavid E. O'Brien         while (! *ok) {							\
56800db7afdSDavid E. O'Brien             ++ok;							\
56900db7afdSDavid E. O'Brien             ++__p;							\
57000db7afdSDavid E. O'Brien         }								\
57100db7afdSDavid E. O'Brien         *__p _Op##= *__q;						\
57200db7afdSDavid E. O'Brien     }									\
57300db7afdSDavid E. O'Brien }									\
57400db7afdSDavid E. O'Brien 									\
57500db7afdSDavid E. O'Brien template<typename _Tp>							\
57600db7afdSDavid E. O'Brien void									\
57700db7afdSDavid E. O'Brien _Array_augmented_##_Name (_Array<_Tp> __a, size_t __n,			\
57800db7afdSDavid E. O'Brien                          _Array<_Tp> __b, _Array<bool> __m)		\
57900db7afdSDavid E. O'Brien {									\
58000db7afdSDavid E. O'Brien     bool* ok (__m._M_data);						\
58100db7afdSDavid E. O'Brien     _Tp* __q (__b._M_data);						\
58200db7afdSDavid E. O'Brien     for (_Tp* __p=__a._M_data; __p<__a._M_data+__n; ++__p, ++ok, ++__q) { \
58300db7afdSDavid E. O'Brien         while (! *ok) {							\
58400db7afdSDavid E. O'Brien             ++ok;							\
58500db7afdSDavid E. O'Brien             ++__q;							\
58600db7afdSDavid E. O'Brien         }								\
58700db7afdSDavid E. O'Brien         *__p _Op##= *__q;						\
58800db7afdSDavid E. O'Brien     }									\
58900db7afdSDavid E. O'Brien }									\
59000db7afdSDavid E. O'Brien 									\
59100db7afdSDavid E. O'Brien template<typename _Tp, class _Dom>					\
59200db7afdSDavid E. O'Brien void									\
59300db7afdSDavid E. O'Brien _Array_augmented_##_Name (_Array<_Tp> __a, _Array<bool> __m,		\
59400db7afdSDavid E. O'Brien                           const _Expr<_Dom, _Tp>& __e, size_t __n)	\
59500db7afdSDavid E. O'Brien {									\
59600db7afdSDavid E. O'Brien     bool* ok(__m._M_data);						\
59700db7afdSDavid E. O'Brien     _Tp* __p (__a._M_data);						\
59800db7afdSDavid E. O'Brien     for (size_t __i=0; __i<__n; ++__i, ++ok, ++__p) {			\
59900db7afdSDavid E. O'Brien         while (! *ok) {							\
60000db7afdSDavid E. O'Brien             ++ok;							\
60100db7afdSDavid E. O'Brien             ++__p;							\
60200db7afdSDavid E. O'Brien         }								\
60300db7afdSDavid E. O'Brien         *__p _Op##= __e[__i];						\
60400db7afdSDavid E. O'Brien     }									\
60500db7afdSDavid E. O'Brien }
60600db7afdSDavid E. O'Brien 
6071b86b14eSAlexander Kabaev    _DEFINE_ARRAY_FUNCTION(+, __plus)
6081b86b14eSAlexander Kabaev    _DEFINE_ARRAY_FUNCTION(-, __minus)
6091b86b14eSAlexander Kabaev    _DEFINE_ARRAY_FUNCTION(*, __multiplies)
6101b86b14eSAlexander Kabaev    _DEFINE_ARRAY_FUNCTION(/, __divides)
6111b86b14eSAlexander Kabaev    _DEFINE_ARRAY_FUNCTION(%, __modulus)
6121b86b14eSAlexander Kabaev    _DEFINE_ARRAY_FUNCTION(^, __bitwise_xor)
6131b86b14eSAlexander Kabaev    _DEFINE_ARRAY_FUNCTION(|, __bitwise_or)
6141b86b14eSAlexander Kabaev    _DEFINE_ARRAY_FUNCTION(&, __bitwise_and)
6151b86b14eSAlexander Kabaev    _DEFINE_ARRAY_FUNCTION(<<, __shift_left)
6161b86b14eSAlexander Kabaev    _DEFINE_ARRAY_FUNCTION(>>, __shift_right)
61700db7afdSDavid E. O'Brien 
61800db7afdSDavid E. O'Brien #undef _DEFINE_VALARRAY_FUNCTION
619*ffeaf689SAlexander Kabaev } // namespace std
62000db7afdSDavid E. O'Brien 
621*ffeaf689SAlexander Kabaev #ifndef _GLIBCXX_EXPORT_TEMPLATE
62200db7afdSDavid E. O'Brien # include <bits/valarray_array.tcc>
62300db7afdSDavid E. O'Brien #endif
62400db7afdSDavid E. O'Brien 
625*ffeaf689SAlexander Kabaev #endif /* _ARRAY_H */
626