197403Sobrien// The template and inlines for the -*- C++ -*- internal _Array helper class.
297403Sobrien
3169691Skan// Copyright (C) 1997, 1998, 1999, 2000, 2003, 2004, 2005, 2006
4132720Skan//  Free Software Foundation, Inc.
597403Sobrien//
697403Sobrien// This file is part of the GNU ISO C++ Library.  This library is free
797403Sobrien// software; you can redistribute it and/or modify it under the
897403Sobrien// terms of the GNU General Public License as published by the
997403Sobrien// Free Software Foundation; either version 2, or (at your option)
1097403Sobrien// any later version.
1197403Sobrien
1297403Sobrien// This library is distributed in the hope that it will be useful,
1397403Sobrien// but WITHOUT ANY WARRANTY; without even the implied warranty of
1497403Sobrien// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1597403Sobrien// GNU General Public License for more details.
1697403Sobrien
1797403Sobrien// You should have received a copy of the GNU General Public License along
1897403Sobrien// with this library; see the file COPYING.  If not, write to the Free
19169691Skan// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
2097403Sobrien// USA.
2197403Sobrien
2297403Sobrien// As a special exception, you may use this file as part of a free software
2397403Sobrien// library without restriction.  Specifically, if other files instantiate
2497403Sobrien// templates or use macros or inline functions from this file, or you compile
2597403Sobrien// this file and link it with other files to produce an executable, this
2697403Sobrien// file does not by itself cause the resulting executable to be covered by
2797403Sobrien// the GNU General Public License.  This exception does not however
2897403Sobrien// invalidate any other reasons why the executable file might be covered by
2997403Sobrien// the GNU General Public License.
3097403Sobrien
3197403Sobrien/** @file valarray_array.h
3297403Sobrien *  This is an internal header file, included by other library headers.
3397403Sobrien *  You should not attempt to use it directly.
3497403Sobrien */
3597403Sobrien
36169691Skan// Written by Gabriel Dos Reis <Gabriel.Dos-Reis@DPTMaths.ENS-Cachan.Fr>
37169691Skan
38132720Skan#ifndef _VALARRAY_ARRAY_H
39132720Skan#define _VALARRAY_ARRAY_H 1
4097403Sobrien
4197403Sobrien#pragma GCC system_header
4297403Sobrien
4397403Sobrien#include <bits/c++config.h>
4497403Sobrien#include <bits/cpp_type_traits.h>
4597403Sobrien#include <cstdlib>
4697403Sobrien#include <cstring>
4797403Sobrien#include <new>
4897403Sobrien
49169691Skan_GLIBCXX_BEGIN_NAMESPACE(std)
50169691Skan
5197403Sobrien  //
5297403Sobrien  // Helper functions on raw pointers
5397403Sobrien  //
54132720Skan
5597403Sobrien  // We get memory by the old fashion way
5697403Sobrien  inline void*
5797403Sobrien  __valarray_get_memory(size_t __n)
5897403Sobrien  { return operator new(__n); }
59132720Skan
6097403Sobrien  template<typename _Tp>
61169691Skan    inline _Tp*__restrict__
62169691Skan    __valarray_get_storage(size_t __n)
63169691Skan    {
64169691Skan      return static_cast<_Tp*__restrict__>
65169691Skan	(std::__valarray_get_memory(__n * sizeof(_Tp)));
66169691Skan    }
6797403Sobrien
6897403Sobrien  // Return memory to the system
6997403Sobrien  inline void
7097403Sobrien  __valarray_release_memory(void* __p)
7197403Sobrien  { operator delete(__p); }
7297403Sobrien
7397403Sobrien  // Turn a raw-memory into an array of _Tp filled with _Tp()
7497403Sobrien  // This is required in 'valarray<T> v(n);'
7597403Sobrien  template<typename _Tp, bool>
76169691Skan    struct _Array_default_ctor
77169691Skan    {
78169691Skan      // Please note that this isn't exception safe.  But
79169691Skan      // valarrays aren't required to be exception safe.
80169691Skan      inline static void
81169691Skan      _S_do_it(_Tp* __restrict__ __b, _Tp* __restrict__ __e)
82169691Skan      {
83169691Skan	while (__b != __e)
84169691Skan	  new(__b++) _Tp();
85169691Skan      }
86169691Skan    };
8797403Sobrien
8897403Sobrien  template<typename _Tp>
89169691Skan    struct _Array_default_ctor<_Tp, true>
90169691Skan    {
91169691Skan      // For fundamental types, it suffices to say 'memset()'
92169691Skan      inline static void
93169691Skan      _S_do_it(_Tp* __restrict__ __b, _Tp* __restrict__ __e)
94169691Skan      { std::memset(__b, 0, (__e - __b) * sizeof(_Tp)); }
95169691Skan    };
9697403Sobrien
9797403Sobrien  template<typename _Tp>
98169691Skan    inline void
99169691Skan    __valarray_default_construct(_Tp* __restrict__ __b, _Tp* __restrict__ __e)
100169691Skan    {
101169691Skan      _Array_default_ctor<_Tp, __is_pod<_Tp>::__value>::_S_do_it(__b, __e);
102169691Skan    }
103132720Skan
10497403Sobrien  // Turn a raw-memory into an array of _Tp filled with __t
10597403Sobrien  // This is the required in valarray<T> v(n, t).  Also
10697403Sobrien  // used in valarray<>::resize().
10797403Sobrien  template<typename _Tp, bool>
108169691Skan    struct _Array_init_ctor
109169691Skan    {
110169691Skan      // Please note that this isn't exception safe.  But
111169691Skan      // valarrays aren't required to be exception safe.
112169691Skan      inline static void
113169691Skan      _S_do_it(_Tp* __restrict__ __b, _Tp* __restrict__ __e, const _Tp __t)
114169691Skan      {
115169691Skan	while (__b != __e)
116169691Skan	  new(__b++) _Tp(__t);
117169691Skan      }
118169691Skan    };
11997403Sobrien
12097403Sobrien  template<typename _Tp>
121169691Skan    struct _Array_init_ctor<_Tp, true>
122169691Skan    {
123169691Skan      inline static void
124169691Skan      _S_do_it(_Tp* __restrict__ __b, _Tp* __restrict__ __e,  const _Tp __t)
125169691Skan      {
126169691Skan	while (__b != __e)
127169691Skan	  *__b++ = __t;
128169691Skan      }
129169691Skan    };
13097403Sobrien
13197403Sobrien  template<typename _Tp>
132169691Skan    inline void
133169691Skan    __valarray_fill_construct(_Tp* __restrict__ __b, _Tp* __restrict__ __e,
134169691Skan			      const _Tp __t)
135169691Skan    {
136169691Skan      _Array_init_ctor<_Tp, __is_pod<_Tp>::__value>::_S_do_it(__b, __e, __t);
137169691Skan    }
13897403Sobrien
13997403Sobrien  //
14097403Sobrien  // copy-construct raw array [__o, *) from plain array [__b, __e)
14197403Sobrien  // We can't just say 'memcpy()'
14297403Sobrien  //
14397403Sobrien  template<typename _Tp, bool>
144169691Skan    struct _Array_copy_ctor
145169691Skan    {
146169691Skan      // Please note that this isn't exception safe.  But
147169691Skan      // valarrays aren't required to be exception safe.
148169691Skan      inline static void
149169691Skan      _S_do_it(const _Tp* __restrict__ __b, const _Tp* __restrict__ __e,
150169691Skan	       _Tp* __restrict__ __o)
151169691Skan      {
152169691Skan	while (__b != __e)
153169691Skan	  new(__o++) _Tp(*__b++);
154169691Skan      }
155169691Skan    };
15697403Sobrien
15797403Sobrien  template<typename _Tp>
158169691Skan    struct _Array_copy_ctor<_Tp, true>
159169691Skan    {
160169691Skan      inline static void
161169691Skan      _S_do_it(const _Tp* __restrict__ __b, const _Tp* __restrict__ __e,
162169691Skan	       _Tp* __restrict__ __o)
163169691Skan      { std::memcpy(__o, __b, (__e - __b)*sizeof(_Tp)); }
164169691Skan    };
16597403Sobrien
16697403Sobrien  template<typename _Tp>
167169691Skan    inline void
168169691Skan    __valarray_copy_construct(const _Tp* __restrict__ __b,
169169691Skan			      const _Tp* __restrict__ __e,
170169691Skan			      _Tp* __restrict__ __o)
171169691Skan    {
172169691Skan      _Array_copy_ctor<_Tp, __is_pod<_Tp>::__value>::_S_do_it(__b, __e, __o);
173169691Skan    }
17497403Sobrien
17597403Sobrien  // copy-construct raw array [__o, *) from strided array __a[<__n : __s>]
17697403Sobrien  template<typename _Tp>
177169691Skan    inline void
178169691Skan    __valarray_copy_construct (const _Tp* __restrict__ __a, size_t __n,
179169691Skan			       size_t __s, _Tp* __restrict__ __o)
180169691Skan    {
181169691Skan      if (__is_pod<_Tp>::__value)
182169691Skan	while (__n--)
183169691Skan	  {
184169691Skan	    *__o++ = *__a;
185169691Skan	    __a += __s;
186169691Skan	  }
187169691Skan      else
188169691Skan	while (__n--)
189169691Skan	  {
190169691Skan	    new(__o++) _Tp(*__a);
191169691Skan	    __a += __s;
192169691Skan	  }
193169691Skan    }
19497403Sobrien
19597403Sobrien  // copy-construct raw array [__o, *) from indexed array __a[__i[<__n>]]
19697403Sobrien  template<typename _Tp>
197169691Skan    inline void
198169691Skan    __valarray_copy_construct (const _Tp* __restrict__ __a,
199169691Skan			       const size_t* __restrict__ __i,
200169691Skan			       _Tp* __restrict__ __o, size_t __n)
201169691Skan    {
202169691Skan      if (__is_pod<_Tp>::__value)
203169691Skan	while (__n--)
204169691Skan	  *__o++ = __a[*__i++];
205169691Skan      else
206169691Skan	while (__n--)
207169691Skan	  new (__o++) _Tp(__a[*__i++]);
208169691Skan    }
20997403Sobrien
21097403Sobrien  // Do the necessary cleanup when we're done with arrays.
21197403Sobrien  template<typename _Tp>
212169691Skan    inline void
213169691Skan    __valarray_destroy_elements(_Tp* __restrict__ __b, _Tp* __restrict__ __e)
214169691Skan    {
215169691Skan      if (!__is_pod<_Tp>::__value)
216169691Skan	while (__b != __e)
217169691Skan	  {
218169691Skan	    __b->~_Tp();
219169691Skan	    ++__b;
220169691Skan	  }
221169691Skan    }
222132720Skan
22397403Sobrien  // Fill a plain array __a[<__n>] with __t
22497403Sobrien  template<typename _Tp>
225169691Skan    inline void
226169691Skan    __valarray_fill(_Tp* __restrict__ __a, size_t __n, const _Tp& __t)
227169691Skan    {
228169691Skan      while (__n--)
229169691Skan	*__a++ = __t;
230169691Skan    }
231169691Skan
23297403Sobrien  // fill strided array __a[<__n-1 : __s>] with __t
23397403Sobrien  template<typename _Tp>
234169691Skan    inline void
235169691Skan    __valarray_fill(_Tp* __restrict__ __a, size_t __n,
236169691Skan		    size_t __s, const _Tp& __t)
237169691Skan    {
238169691Skan      for (size_t __i = 0; __i < __n; ++__i, __a += __s)
239169691Skan	*__a = __t;
240169691Skan    }
24197403Sobrien
24297403Sobrien  // fill indir   ect array __a[__i[<__n>]] with __i
24397403Sobrien  template<typename _Tp>
244169691Skan    inline void
245169691Skan    __valarray_fill(_Tp* __restrict__ __a, const size_t* __restrict__ __i,
246169691Skan		    size_t __n, const _Tp& __t)
247169691Skan    {
248169691Skan      for (size_t __j = 0; __j < __n; ++__j, ++__i)
249169691Skan	__a[*__i] = __t;
250169691Skan    }
251169691Skan
25297403Sobrien  // copy plain array __a[<__n>] in __b[<__n>]
25397403Sobrien  // For non-fundamental types, it is wrong to say 'memcpy()'
25497403Sobrien  template<typename _Tp, bool>
255169691Skan    struct _Array_copier
256169691Skan    {
257169691Skan      inline static void
258169691Skan      _S_do_it(const _Tp* __restrict__ __a, size_t __n, _Tp* __restrict__ __b)
259169691Skan      {
260169691Skan	while(__n--)
261169691Skan	  *__b++ = *__a++;
262169691Skan      }
263169691Skan    };
26497403Sobrien
26597403Sobrien  template<typename _Tp>
266169691Skan    struct _Array_copier<_Tp, true>
267169691Skan    {
268169691Skan      inline static void
269169691Skan      _S_do_it(const _Tp* __restrict__ __a, size_t __n, _Tp* __restrict__ __b)
270169691Skan      { std::memcpy (__b, __a, __n * sizeof (_Tp)); }
271169691Skan    };
27297403Sobrien
27397403Sobrien  // Copy a plain array __a[<__n>] into a play array __b[<>]
27497403Sobrien  template<typename _Tp>
275169691Skan    inline void
276169691Skan    __valarray_copy(const _Tp* __restrict__ __a, size_t __n,
277169691Skan		    _Tp* __restrict__ __b)
278169691Skan    {
279169691Skan      _Array_copier<_Tp, __is_pod<_Tp>::__value>::_S_do_it(__a, __n, __b);
280169691Skan    }
28197403Sobrien
28297403Sobrien  // Copy strided array __a[<__n : __s>] in plain __b[<__n>]
28397403Sobrien  template<typename _Tp>
284169691Skan    inline void
285169691Skan    __valarray_copy(const _Tp* __restrict__ __a, size_t __n, size_t __s,
286169691Skan		    _Tp* __restrict__ __b)
287169691Skan    {
288169691Skan      for (size_t __i = 0; __i < __n; ++__i, ++__b, __a += __s)
289169691Skan	*__b = *__a;
290169691Skan    }
29197403Sobrien
29297403Sobrien  // Copy a plain array  __a[<__n>] into a strided array __b[<__n : __s>]
29397403Sobrien  template<typename _Tp>
294169691Skan    inline void
295169691Skan    __valarray_copy(const _Tp* __restrict__ __a, _Tp* __restrict__ __b,
296169691Skan		    size_t __n, size_t __s)
297169691Skan    {
298169691Skan      for (size_t __i = 0; __i < __n; ++__i, ++__a, __b += __s)
299169691Skan	*__b = *__a;
300169691Skan    }
30197403Sobrien
30297403Sobrien  // Copy strided array __src[<__n : __s1>] into another
30397403Sobrien  // strided array __dst[< : __s2>].  Their sizes must match.
30497403Sobrien  template<typename _Tp>
305169691Skan    inline void
306169691Skan    __valarray_copy(const _Tp* __restrict__ __src, size_t __n, size_t __s1,
307169691Skan		    _Tp* __restrict__ __dst, size_t __s2)
308169691Skan    {
309169691Skan      for (size_t __i = 0; __i < __n; ++__i)
310169691Skan	__dst[__i * __s2] = __src[__i * __s1];
311169691Skan    }
31297403Sobrien
31397403Sobrien  // Copy an indexed array __a[__i[<__n>]] in plain array __b[<__n>]
31497403Sobrien  template<typename _Tp>
315169691Skan    inline void
316169691Skan    __valarray_copy(const _Tp* __restrict__ __a,
317169691Skan		    const size_t* __restrict__ __i,
318169691Skan		    _Tp* __restrict__ __b, size_t __n)
319169691Skan    {
320169691Skan      for (size_t __j = 0; __j < __n; ++__j, ++__b, ++__i)
321169691Skan	*__b = __a[*__i];
322169691Skan    }
32397403Sobrien
32497403Sobrien  // Copy a plain array __a[<__n>] in an indexed array __b[__i[<__n>]]
32597403Sobrien  template<typename _Tp>
326169691Skan    inline void
327169691Skan    __valarray_copy(const _Tp* __restrict__ __a, size_t __n,
328169691Skan		    _Tp* __restrict__ __b, const size_t* __restrict__ __i)
329169691Skan    {
330169691Skan      for (size_t __j = 0; __j < __n; ++__j, ++__a, ++__i)
331169691Skan	__b[*__i] = *__a;
332169691Skan    }
33397403Sobrien
33497403Sobrien  // Copy the __n first elements of an indexed array __src[<__i>] into
33597403Sobrien  // another indexed array __dst[<__j>].
33697403Sobrien  template<typename _Tp>
337169691Skan    inline void
338169691Skan    __valarray_copy(const _Tp* __restrict__ __src, size_t __n,
339169691Skan		    const size_t* __restrict__ __i,
340169691Skan		    _Tp* __restrict__ __dst, const size_t* __restrict__ __j)
341169691Skan    {
342169691Skan      for (size_t __k = 0; __k < __n; ++__k)
343169691Skan	__dst[*__j++] = __src[*__i++];
344169691Skan    }
34597403Sobrien
34697403Sobrien  //
34797403Sobrien  // Compute the sum of elements in range [__f, __l)
34897403Sobrien  // This is a naive algorithm.  It suffers from cancelling.
34997403Sobrien  // In the future try to specialize
35097403Sobrien  // for _Tp = float, double, long double using a more accurate
35197403Sobrien  // algorithm.
35297403Sobrien  //
35397403Sobrien  template<typename _Tp>
354169691Skan    inline _Tp
355169691Skan    __valarray_sum(const _Tp* __restrict__ __f, const _Tp* __restrict__ __l)
356169691Skan    {
357169691Skan      _Tp __r = _Tp();
358169691Skan      while (__f != __l)
359169691Skan	__r += *__f++;
360169691Skan      return __r;
361169691Skan    }
36297403Sobrien
36397403Sobrien  // Compute the product of all elements in range [__f, __l)
36497403Sobrien  template<typename _Tp>
365169691Skan    inline _Tp
366169691Skan    __valarray_product(const _Tp* __restrict__ __f,
367169691Skan		       const _Tp* __restrict__ __l)
368169691Skan    {
369169691Skan      _Tp __r = _Tp(1);
370169691Skan      while (__f != __l)
371169691Skan	__r = __r * *__f++;
372169691Skan      return __r;
373169691Skan    }
37497403Sobrien
37597403Sobrien  // Compute the min/max of an array-expression
37697403Sobrien  template<typename _Ta>
377169691Skan    inline typename _Ta::value_type
378169691Skan    __valarray_min(const _Ta& __a)
379169691Skan    {
380169691Skan      size_t __s = __a.size();
381169691Skan      typedef typename _Ta::value_type _Value_type;
382169691Skan      _Value_type __r = __s == 0 ? _Value_type() : __a[0];
383169691Skan      for (size_t __i = 1; __i < __s; ++__i)
384169691Skan	{
385169691Skan	  _Value_type __t = __a[__i];
386169691Skan	  if (__t < __r)
387169691Skan	    __r = __t;
388169691Skan	}
389169691Skan      return __r;
390169691Skan    }
391132720Skan
39297403Sobrien  template<typename _Ta>
393169691Skan    inline typename _Ta::value_type
394169691Skan    __valarray_max(const _Ta& __a)
395169691Skan    {
396169691Skan      size_t __s = __a.size();
397169691Skan      typedef typename _Ta::value_type _Value_type;
398169691Skan      _Value_type __r = __s == 0 ? _Value_type() : __a[0];
399169691Skan      for (size_t __i = 1; __i < __s; ++__i)
400169691Skan	{
401169691Skan	  _Value_type __t = __a[__i];
402169691Skan	  if (__t > __r)
403169691Skan	    __r = __t;
404169691Skan	}
405169691Skan      return __r;
406169691Skan    }
407132720Skan
40897403Sobrien  //
40997403Sobrien  // Helper class _Array, first layer of valarray abstraction.
41097403Sobrien  // All operations on valarray should be forwarded to this class
41197403Sobrien  // whenever possible. -- gdr
41297403Sobrien  //
413132720Skan
41497403Sobrien  template<typename _Tp>
415169691Skan    struct _Array
416169691Skan    {
417169691Skan      explicit _Array(size_t);
418169691Skan      explicit _Array(_Tp* const __restrict__);
419169691Skan      explicit _Array(const valarray<_Tp>&);
420169691Skan      _Array(const _Tp* __restrict__, size_t);
421169691Skan
422169691Skan      _Tp* begin() const;
423169691Skan
424169691Skan      _Tp* const __restrict__ _M_data;
425169691Skan    };
42697403Sobrien
42797403Sobrien
428169691Skan  // Copy-construct plain array __b[<__n>] from indexed array __a[__i[<__n>]]
429169691Skan  template<typename _Tp>
430169691Skan    inline void
431169691Skan    __valarray_copy_construct(_Array<_Tp> __a, _Array<size_t> __i,
432169691Skan			      _Array<_Tp> __b, size_t __n)
433169691Skan    { std::__valarray_copy_construct(__a._M_data, __i._M_data,
434169691Skan				     __b._M_data, __n); }
435132720Skan
436169691Skan  // Copy-construct plain array __b[<__n>] from strided array __a[<__n : __s>]
43797403Sobrien  template<typename _Tp>
438169691Skan    inline void
439169691Skan    __valarray_copy_construct(_Array<_Tp> __a, size_t __n, size_t __s,
440169691Skan			      _Array<_Tp> __b)
441169691Skan    { std::__valarray_copy_construct(__a._M_data, __n, __s, __b._M_data); }
442132720Skan
44397403Sobrien  template<typename _Tp>
444169691Skan    inline void
445169691Skan    __valarray_fill (_Array<_Tp> __a, size_t __n, const _Tp& __t)
446169691Skan    { std::__valarray_fill(__a._M_data, __n, __t); }
447132720Skan
44897403Sobrien  template<typename _Tp>
449169691Skan    inline void
450169691Skan    __valarray_fill(_Array<_Tp> __a, size_t __n, size_t __s, const _Tp& __t)
451169691Skan    { std::__valarray_fill(__a._M_data, __n, __s, __t); }
45297403Sobrien
453169691Skan  template<typename _Tp>
454169691Skan    inline void
455169691Skan    __valarray_fill(_Array<_Tp> __a, _Array<size_t> __i,
456169691Skan		    size_t __n, const _Tp& __t)
457169691Skan    { std::__valarray_fill(__a._M_data, __i._M_data, __n, __t); }
458169691Skan
45997403Sobrien  // Copy a plain array __a[<__n>] into a play array __b[<>]
46097403Sobrien  template<typename _Tp>
461169691Skan    inline void
462169691Skan    __valarray_copy(_Array<_Tp> __a, size_t __n, _Array<_Tp> __b)
463169691Skan    { std::__valarray_copy(__a._M_data, __n, __b._M_data); }
464132720Skan
46597403Sobrien  // Copy strided array __a[<__n : __s>] in plain __b[<__n>]
46697403Sobrien  template<typename _Tp>
467169691Skan    inline void
468169691Skan    __valarray_copy(_Array<_Tp> __a, size_t __n, size_t __s, _Array<_Tp> __b)
469169691Skan    { std::__valarray_copy(__a._M_data, __n, __s, __b._M_data); }
47097403Sobrien
47197403Sobrien  // Copy a plain array  __a[<__n>] into a strided array __b[<__n : __s>]
47297403Sobrien  template<typename _Tp>
473169691Skan    inline void
474169691Skan    __valarray_copy(_Array<_Tp> __a, _Array<_Tp> __b, size_t __n, size_t __s)
475169691Skan    { __valarray_copy(__a._M_data, __b._M_data, __n, __s); }
47697403Sobrien
47797403Sobrien  // Copy strided array __src[<__n : __s1>] into another
47897403Sobrien  // strided array __dst[< : __s2>].  Their sizes must match.
47997403Sobrien  template<typename _Tp>
480169691Skan    inline void
481169691Skan    __valarray_copy(_Array<_Tp> __a, size_t __n, size_t __s1,
482169691Skan                    _Array<_Tp> __b, size_t __s2)
483169691Skan    { std::__valarray_copy(__a._M_data, __n, __s1, __b._M_data, __s2); }
48497403Sobrien
48597403Sobrien  // Copy an indexed array __a[__i[<__n>]] in plain array __b[<__n>]
48697403Sobrien  template<typename _Tp>
487169691Skan    inline void
488169691Skan    __valarray_copy(_Array<_Tp> __a, _Array<size_t> __i,
489169691Skan		    _Array<_Tp> __b, size_t __n)
490169691Skan    { std::__valarray_copy(__a._M_data, __i._M_data, __b._M_data, __n); }
491132720Skan
49297403Sobrien  // Copy a plain array __a[<__n>] in an indexed array __b[__i[<__n>]]
49397403Sobrien  template<typename _Tp>
494169691Skan    inline void
495169691Skan    __valarray_copy(_Array<_Tp> __a, size_t __n, _Array<_Tp> __b,
496169691Skan		    _Array<size_t> __i)
497169691Skan    { std::__valarray_copy(__a._M_data, __n, __b._M_data, __i._M_data); }
49897403Sobrien
49997403Sobrien  // Copy the __n first elements of an indexed array __src[<__i>] into
50097403Sobrien  // another indexed array __dst[<__j>].
50197403Sobrien  template<typename _Tp>
502169691Skan    inline void
503169691Skan    __valarray_copy(_Array<_Tp> __src, size_t __n, _Array<size_t> __i,
504169691Skan                    _Array<_Tp> __dst, _Array<size_t> __j)
505169691Skan    {
506169691Skan      std::__valarray_copy(__src._M_data, __n, __i._M_data,
507169691Skan		    __dst._M_data, __j._M_data);
508169691Skan    }
50997403Sobrien
51097403Sobrien  template<typename _Tp>
511169691Skan    inline
512169691Skan    _Array<_Tp>::_Array(size_t __n)
513169691Skan    : _M_data(__valarray_get_storage<_Tp>(__n))
514169691Skan    { std::__valarray_default_construct(_M_data, _M_data + __n); }
51597403Sobrien
51697403Sobrien  template<typename _Tp>
517169691Skan    inline
518169691Skan    _Array<_Tp>::_Array(_Tp* const __restrict__ __p)
519169691Skan    : _M_data (__p) {}
520132720Skan
52197403Sobrien  template<typename _Tp>
522169691Skan    inline
523169691Skan    _Array<_Tp>::_Array(const valarray<_Tp>& __v)
524169691Skan    : _M_data (__v._M_data) {}
525132720Skan
52697403Sobrien  template<typename _Tp>
527169691Skan    inline
528169691Skan    _Array<_Tp>::_Array(const _Tp* __restrict__ __b, size_t __s)
529169691Skan    : _M_data(__valarray_get_storage<_Tp>(__s))
530169691Skan    { std::__valarray_copy_construct(__b, __s, _M_data); }
53197403Sobrien
53297403Sobrien  template<typename _Tp>
533169691Skan    inline _Tp*
534169691Skan    _Array<_Tp>::begin () const
535169691Skan    { return _M_data; }
53697403Sobrien
53797403Sobrien#define _DEFINE_ARRAY_FUNCTION(_Op, _Name)				\
538169691Skan  template<typename _Tp>		        			\
539169691Skan    inline void								\
540169691Skan    _Array_augmented_##_Name(_Array<_Tp> __a, size_t __n, const _Tp& __t) \
541169691Skan    {									\
542169691Skan      for (_Tp* __p = __a._M_data; __p < __a._M_data + __n; ++__p)	\
543169691Skan        *__p _Op##= __t;						\
544169691Skan    }									\
54597403Sobrien									\
546169691Skan  template<typename _Tp>						\
547169691Skan    inline void								\
548169691Skan    _Array_augmented_##_Name(_Array<_Tp> __a, size_t __n, _Array<_Tp> __b) \
549169691Skan    {									\
550169691Skan      _Tp* __p = __a._M_data;						\
551169691Skan      for (_Tp* __q = __b._M_data; __q < __b._M_data + __n; ++__p, ++__q) \
552169691Skan        *__p _Op##= *__q;						\
553169691Skan    }									\
55497403Sobrien									\
555169691Skan  template<typename _Tp, class _Dom>					\
556169691Skan    void								\
557169691Skan    _Array_augmented_##_Name(_Array<_Tp> __a,	        		\
558169691Skan                             const _Expr<_Dom, _Tp>& __e, size_t __n)	\
559169691Skan    {									\
560169691Skan      _Tp* __p(__a._M_data);						\
561169691Skan      for (size_t __i = 0; __i < __n; ++__i, ++__p)                     \
562169691Skan        *__p _Op##= __e[__i];                                          	\
563169691Skan    }									\
56497403Sobrien									\
565169691Skan  template<typename _Tp>						\
566169691Skan    inline void								\
567169691Skan    _Array_augmented_##_Name(_Array<_Tp> __a, size_t __n, size_t __s,	\
568169691Skan	                     _Array<_Tp> __b)				\
569169691Skan    {									\
570169691Skan      _Tp* __q(__b._M_data);						\
571169691Skan      for (_Tp* __p = __a._M_data; __p < __a._M_data + __s * __n;       \
572169691Skan	   __p += __s, ++__q)                                           \
573169691Skan        *__p _Op##= *__q;						\
574169691Skan    }									\
57597403Sobrien									\
576169691Skan  template<typename _Tp>						\
577169691Skan    inline void								\
578169691Skan    _Array_augmented_##_Name(_Array<_Tp> __a, _Array<_Tp> __b,		\
579169691Skan		             size_t __n, size_t __s)			\
580169691Skan    {									\
581169691Skan      _Tp* __q(__b._M_data);						\
582169691Skan      for (_Tp* __p = __a._M_data; __p < __a._M_data + __n;             \
583169691Skan	   ++__p, __q += __s)                                           \
584169691Skan        *__p _Op##= *__q;						\
585169691Skan    }									\
58697403Sobrien									\
587169691Skan  template<typename _Tp, class _Dom>					\
588169691Skan    void								\
589169691Skan    _Array_augmented_##_Name(_Array<_Tp> __a, size_t __s,		\
590169691Skan                             const _Expr<_Dom, _Tp>& __e, size_t __n)	\
591169691Skan    {									\
592169691Skan      _Tp* __p(__a._M_data);						\
593169691Skan      for (size_t __i = 0; __i < __n; ++__i, __p += __s)                \
594169691Skan        *__p _Op##= __e[__i];                                          	\
595169691Skan    }									\
59697403Sobrien									\
597169691Skan  template<typename _Tp>						\
598169691Skan    inline void								\
599169691Skan    _Array_augmented_##_Name(_Array<_Tp> __a, _Array<size_t> __i,	\
600169691Skan                             _Array<_Tp> __b, size_t __n)		\
601169691Skan    {									\
602169691Skan      _Tp* __q(__b._M_data);						\
603169691Skan      for (size_t* __j = __i._M_data; __j < __i._M_data + __n;          \
604169691Skan           ++__j, ++__q)                                                \
60597403Sobrien        __a._M_data[*__j] _Op##= *__q;					\
606169691Skan    }									\
60797403Sobrien									\
608169691Skan  template<typename _Tp>						\
609169691Skan    inline void					        		\
610169691Skan    _Array_augmented_##_Name(_Array<_Tp> __a, size_t __n,		\
611169691Skan                             _Array<_Tp> __b, _Array<size_t> __i)	\
612169691Skan    {									\
613169691Skan      _Tp* __p(__a._M_data);						\
614169691Skan      for (size_t* __j = __i._M_data; __j<__i._M_data + __n;            \
615169691Skan	   ++__j, ++__p)                                                \
61697403Sobrien        *__p _Op##= __b._M_data[*__j];					\
617169691Skan    }									\
61897403Sobrien									\
619169691Skan  template<typename _Tp, class _Dom>					\
620169691Skan    void								\
621169691Skan    _Array_augmented_##_Name(_Array<_Tp> __a, _Array<size_t> __i,	\
622169691Skan                             const _Expr<_Dom, _Tp>& __e, size_t __n)	\
623169691Skan    {									\
624169691Skan      size_t* __j(__i._M_data);	        				\
625169691Skan      for (size_t __k = 0; __k<__n; ++__k, ++__j)			\
626169691Skan        __a._M_data[*__j] _Op##= __e[__k];				\
627169691Skan    }									\
62897403Sobrien									\
629169691Skan  template<typename _Tp>						\
630169691Skan    void								\
631169691Skan    _Array_augmented_##_Name(_Array<_Tp> __a, _Array<bool> __m,         \
632169691Skan                             _Array<_Tp> __b, size_t __n)		\
633169691Skan    {									\
634169691Skan      bool* __ok(__m._M_data);						\
635169691Skan      _Tp* __p(__a._M_data);						\
636169691Skan      for (_Tp* __q = __b._M_data; __q < __b._M_data + __n;             \
637169691Skan	   ++__q, ++__ok, ++__p)                                        \
638169691Skan        {                                                               \
639169691Skan          while (! *__ok)                                               \
640169691Skan            {						        	\
641169691Skan              ++__ok;							\
642169691Skan              ++__p;							\
643169691Skan            }								\
644169691Skan          *__p _Op##= *__q;						\
64597403Sobrien        }								\
64697403Sobrien    }									\
64797403Sobrien									\
648169691Skan  template<typename _Tp>						\
649169691Skan    void								\
650169691Skan    _Array_augmented_##_Name(_Array<_Tp> __a, size_t __n,		\
651169691Skan                             _Array<_Tp> __b, _Array<bool> __m)   	\
652169691Skan    {									\
653169691Skan      bool* __ok(__m._M_data);						\
654169691Skan      _Tp* __q(__b._M_data);						\
655169691Skan      for (_Tp* __p = __a._M_data; __p < __a._M_data + __n;             \
656169691Skan	   ++__p, ++__ok, ++__q)                                        \
657169691Skan        {                                                               \
658169691Skan          while (! *__ok)                                               \
659169691Skan            {					        		\
660169691Skan              ++__ok;							\
661169691Skan              ++__q;							\
662169691Skan            }								\
663169691Skan          *__p _Op##= *__q;						\
66497403Sobrien        }								\
66597403Sobrien    }									\
66697403Sobrien									\
667169691Skan  template<typename _Tp, class _Dom>					\
668169691Skan    void								\
669169691Skan    _Array_augmented_##_Name(_Array<_Tp> __a, _Array<bool> __m,  	\
670169691Skan                             const _Expr<_Dom, _Tp>& __e, size_t __n)	\
671169691Skan    {									\
672169691Skan      bool* __ok(__m._M_data);						\
673169691Skan      _Tp* __p(__a._M_data);						\
674169691Skan      for (size_t __i = 0; __i < __n; ++__i, ++__ok, ++__p)             \
675169691Skan        {	                                           		\
676169691Skan          while (! *__ok)                                               \
677169691Skan            {		         					\
678169691Skan	      ++__ok;							\
679169691Skan              ++__p;							\
680169691Skan            }								\
681169691Skan          *__p _Op##= __e[__i];						\
68297403Sobrien        }								\
683169691Skan    }
68497403Sobrien
685117397Skan   _DEFINE_ARRAY_FUNCTION(+, __plus)
686117397Skan   _DEFINE_ARRAY_FUNCTION(-, __minus)
687117397Skan   _DEFINE_ARRAY_FUNCTION(*, __multiplies)
688117397Skan   _DEFINE_ARRAY_FUNCTION(/, __divides)
689117397Skan   _DEFINE_ARRAY_FUNCTION(%, __modulus)
690117397Skan   _DEFINE_ARRAY_FUNCTION(^, __bitwise_xor)
691117397Skan   _DEFINE_ARRAY_FUNCTION(|, __bitwise_or)
692132720Skan   _DEFINE_ARRAY_FUNCTION(&, __bitwise_and)
693117397Skan   _DEFINE_ARRAY_FUNCTION(<<, __shift_left)
694117397Skan   _DEFINE_ARRAY_FUNCTION(>>, __shift_right)
69597403Sobrien
696169691Skan#undef _DEFINE_ARRAY_FUNCTION
69797403Sobrien
698169691Skan_GLIBCXX_END_NAMESPACE
699169691Skan
700132720Skan#ifndef _GLIBCXX_EXPORT_TEMPLATE
701132720Skan# include <bits/valarray_array.tcc>
70297403Sobrien#endif
70397403Sobrien
704132720Skan#endif /* _ARRAY_H */
705