1// The template and inlines for the -*- C++ -*- internal _Array helper class.
2
3// Copyright (C) 1997, 1998, 1999, 2000, 2003, 2004, 2005
4//  Free Software Foundation, Inc.
5//
6// This file is part of the GNU ISO C++ Library.  This library is free
7// software; you can redistribute it and/or modify it under the
8// terms of the GNU General Public License as published by the
9// Free Software Foundation; either version 2, or (at your option)
10// any later version.
11
12// This library is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15// GNU General Public License for more details.
16
17// You should have received a copy of the GNU General Public License along
18// with this library; see the file COPYING.  If not, write to the Free
19// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20// USA.
21
22// As a special exception, you may use this file as part of a free software
23// library without restriction.  Specifically, if other files instantiate
24// templates or use macros or inline functions from this file, or you compile
25// this file and link it with other files to produce an executable, this
26// file does not by itself cause the resulting executable to be covered by
27// the GNU General Public License.  This exception does not however
28// invalidate any other reasons why the executable file might be covered by
29// the GNU General Public License.
30
31// Written by Gabriel Dos Reis <Gabriel.Dos-Reis@DPTMaths.ENS-Cachan.Fr>
32
33/** @file valarray_array.h
34 *  This is an internal header file, included by other library headers.
35 *  You should not attempt to use it directly.
36 */
37
38#ifndef _VALARRAY_ARRAY_H
39#define _VALARRAY_ARRAY_H 1
40
41#pragma GCC system_header
42
43#include <bits/c++config.h>
44#include <bits/cpp_type_traits.h>
45#include <cstdlib>
46#include <cstring>
47#include <new>
48
49namespace std
50{
51  //
52  // Helper functions on raw pointers
53  //
54
55  // We get memory by the old fashion way
56  inline void*
57  __valarray_get_memory(size_t __n)
58  { return operator new(__n); }
59
60  template<typename _Tp>
61    inline _Tp*__restrict__
62    __valarray_get_storage(size_t __n)
63    {
64      return static_cast<_Tp*__restrict__>
65	(std::__valarray_get_memory(__n * sizeof(_Tp)));
66    }
67
68  // Return memory to the system
69  inline void
70  __valarray_release_memory(void* __p)
71  { operator delete(__p); }
72
73  // Turn a raw-memory into an array of _Tp filled with _Tp()
74  // This is required in 'valarray<T> v(n);'
75  template<typename _Tp, bool>
76    struct _Array_default_ctor
77    {
78      // Please note that this isn't exception safe.  But
79      // valarrays aren't required to be exception safe.
80      inline static void
81      _S_do_it(_Tp* __restrict__ __b, _Tp* __restrict__ __e)
82      {
83	while (__b != __e)
84	  new(__b++) _Tp();
85      }
86    };
87
88  template<typename _Tp>
89    struct _Array_default_ctor<_Tp, true>
90    {
91      // For fundamental types, it suffices to say 'memset()'
92      inline static void
93      _S_do_it(_Tp* __restrict__ __b, _Tp* __restrict__ __e)
94      { std::memset(__b, 0, (__e - __b) * sizeof(_Tp)); }
95    };
96
97  template<typename _Tp>
98    inline void
99    __valarray_default_construct(_Tp* __restrict__ __b, _Tp* __restrict__ __e)
100    {
101      _Array_default_ctor<_Tp, __is_fundamental<_Tp>::__value>::
102	_S_do_it(__b, __e);
103    }
104
105  // Turn a raw-memory into an array of _Tp filled with __t
106  // This is the required in valarray<T> v(n, t).  Also
107  // used in valarray<>::resize().
108  template<typename _Tp, bool>
109    struct _Array_init_ctor
110    {
111      // Please note that this isn't exception safe.  But
112      // valarrays aren't required to be exception safe.
113      inline static void
114      _S_do_it(_Tp* __restrict__ __b, _Tp* __restrict__ __e, const _Tp __t)
115      {
116	while (__b != __e)
117	  new(__b++) _Tp(__t);
118      }
119    };
120
121  template<typename _Tp>
122    struct _Array_init_ctor<_Tp, true>
123    {
124      inline static void
125      _S_do_it(_Tp* __restrict__ __b, _Tp* __restrict__ __e,  const _Tp __t)
126      {
127	while (__b != __e)
128	  *__b++ = __t;
129      }
130    };
131
132  template<typename _Tp>
133    inline void
134    __valarray_fill_construct(_Tp* __restrict__ __b, _Tp* __restrict__ __e,
135			      const _Tp __t)
136    {
137      _Array_init_ctor<_Tp, __is_fundamental<_Tp>::__value>::
138	_S_do_it(__b, __e, __t);
139    }
140
141  //
142  // copy-construct raw array [__o, *) from plain array [__b, __e)
143  // We can't just say 'memcpy()'
144  //
145  template<typename _Tp, bool>
146    struct _Array_copy_ctor
147    {
148      // Please note that this isn't exception safe.  But
149      // valarrays aren't required to be exception safe.
150      inline static void
151      _S_do_it(const _Tp* __restrict__ __b, const _Tp* __restrict__ __e,
152	       _Tp* __restrict__ __o)
153      {
154	while (__b != __e)
155	  new(__o++) _Tp(*__b++);
156      }
157    };
158
159  template<typename _Tp>
160    struct _Array_copy_ctor<_Tp, true>
161    {
162      inline static void
163      _S_do_it(const _Tp* __restrict__ __b, const _Tp* __restrict__ __e,
164	       _Tp* __restrict__ __o)
165      { std::memcpy(__o, __b, (__e - __b)*sizeof(_Tp)); }
166    };
167
168  template<typename _Tp>
169    inline void
170    __valarray_copy_construct(const _Tp* __restrict__ __b,
171			      const _Tp* __restrict__ __e,
172			      _Tp* __restrict__ __o)
173    {
174      _Array_copy_ctor<_Tp, __is_fundamental<_Tp>::__value>::
175	_S_do_it(__b, __e, __o);
176    }
177
178  // copy-construct raw array [__o, *) from strided array __a[<__n : __s>]
179  template<typename _Tp>
180    inline void
181    __valarray_copy_construct (const _Tp* __restrict__ __a, size_t __n,
182			       size_t __s, _Tp* __restrict__ __o)
183    {
184      if (__is_fundamental<_Tp>::__value)
185	while (__n--)
186	  {
187	    *__o++ = *__a;
188	    __a += __s;
189	  }
190      else
191	while (__n--)
192	  {
193	    new(__o++) _Tp(*__a);
194	    __a += __s;
195	  }
196    }
197
198  // copy-construct raw array [__o, *) from indexed array __a[__i[<__n>]]
199  template<typename _Tp>
200    inline void
201    __valarray_copy_construct (const _Tp* __restrict__ __a,
202			       const size_t* __restrict__ __i,
203			       _Tp* __restrict__ __o, size_t __n)
204    {
205      if (__is_fundamental<_Tp>::__value)
206	while (__n--)
207	  *__o++ = __a[*__i++];
208      else
209	while (__n--)
210	  new (__o++) _Tp(__a[*__i++]);
211    }
212
213  // Do the necessary cleanup when we're done with arrays.
214  template<typename _Tp>
215    inline void
216    __valarray_destroy_elements(_Tp* __restrict__ __b, _Tp* __restrict__ __e)
217    {
218      if (!__is_fundamental<_Tp>::__value)
219	while (__b != __e)
220	  {
221	    __b->~_Tp();
222	    ++__b;
223	  }
224    }
225
226  // Fill a plain array __a[<__n>] with __t
227  template<typename _Tp>
228    inline void
229    __valarray_fill(_Tp* __restrict__ __a, size_t __n, const _Tp& __t)
230    {
231      while (__n--)
232	*__a++ = __t;
233    }
234
235  // fill strided array __a[<__n-1 : __s>] with __t
236  template<typename _Tp>
237    inline void
238    __valarray_fill(_Tp* __restrict__ __a, size_t __n,
239		    size_t __s, const _Tp& __t)
240    {
241      for (size_t __i = 0; __i < __n; ++__i, __a += __s)
242	*__a = __t;
243    }
244
245  // fill indir   ect array __a[__i[<__n>]] with __i
246  template<typename _Tp>
247    inline void
248    __valarray_fill(_Tp* __restrict__ __a, const size_t* __restrict__ __i,
249		    size_t __n, const _Tp& __t)
250    {
251      for (size_t __j = 0; __j < __n; ++__j, ++__i)
252	__a[*__i] = __t;
253    }
254
255  // copy plain array __a[<__n>] in __b[<__n>]
256  // For non-fundamental types, it is wrong to say 'memcpy()'
257  template<typename _Tp, bool>
258    struct _Array_copier
259    {
260      inline static void
261      _S_do_it(const _Tp* __restrict__ __a, size_t __n, _Tp* __restrict__ __b)
262      {
263	while(__n--)
264	  *__b++ = *__a++;
265      }
266    };
267
268  template<typename _Tp>
269    struct _Array_copier<_Tp, true>
270    {
271      inline static void
272      _S_do_it(const _Tp* __restrict__ __a, size_t __n, _Tp* __restrict__ __b)
273      { std::memcpy (__b, __a, __n * sizeof (_Tp)); }
274    };
275
276  // Copy a plain array __a[<__n>] into a play array __b[<>]
277  template<typename _Tp>
278    inline void
279    __valarray_copy(const _Tp* __restrict__ __a, size_t __n,
280		    _Tp* __restrict__ __b)
281    {
282      _Array_copier<_Tp, __is_fundamental<_Tp>::__value>::
283	_S_do_it(__a, __n, __b);
284    }
285
286  // Copy strided array __a[<__n : __s>] in plain __b[<__n>]
287  template<typename _Tp>
288    inline void
289    __valarray_copy(const _Tp* __restrict__ __a, size_t __n, size_t __s,
290		    _Tp* __restrict__ __b)
291    {
292      for (size_t __i = 0; __i < __n; ++__i, ++__b, __a += __s)
293	*__b = *__a;
294    }
295
296  // Copy a plain array  __a[<__n>] into a strided array __b[<__n : __s>]
297  template<typename _Tp>
298    inline void
299    __valarray_copy(const _Tp* __restrict__ __a, _Tp* __restrict__ __b,
300		    size_t __n, size_t __s)
301    {
302      for (size_t __i = 0; __i < __n; ++__i, ++__a, __b += __s)
303	*__b = *__a;
304    }
305
306  // Copy strided array __src[<__n : __s1>] into another
307  // strided array __dst[< : __s2>].  Their sizes must match.
308  template<typename _Tp>
309    inline void
310    __valarray_copy(const _Tp* __restrict__ __src, size_t __n, size_t __s1,
311		    _Tp* __restrict__ __dst, size_t __s2)
312    {
313      for (size_t __i = 0; __i < __n; ++__i)
314	__dst[__i * __s2] = __src[__i * __s1];
315    }
316
317  // Copy an indexed array __a[__i[<__n>]] in plain array __b[<__n>]
318  template<typename _Tp>
319    inline void
320    __valarray_copy(const _Tp* __restrict__ __a,
321		    const size_t* __restrict__ __i,
322		    _Tp* __restrict__ __b, size_t __n)
323    {
324      for (size_t __j = 0; __j < __n; ++__j, ++__b, ++__i)
325	*__b = __a[*__i];
326    }
327
328  // Copy a plain array __a[<__n>] in an indexed array __b[__i[<__n>]]
329  template<typename _Tp>
330    inline void
331    __valarray_copy(const _Tp* __restrict__ __a, size_t __n,
332		    _Tp* __restrict__ __b, const size_t* __restrict__ __i)
333    {
334      for (size_t __j = 0; __j < __n; ++__j, ++__a, ++__i)
335	__b[*__i] = *__a;
336    }
337
338  // Copy the __n first elements of an indexed array __src[<__i>] into
339  // another indexed array __dst[<__j>].
340  template<typename _Tp>
341    inline void
342    __valarray_copy(const _Tp* __restrict__ __src, size_t __n,
343		    const size_t* __restrict__ __i,
344		    _Tp* __restrict__ __dst, const size_t* __restrict__ __j)
345    {
346      for (size_t __k = 0; __k < __n; ++__k)
347	__dst[*__j++] = __src[*__i++];
348    }
349
350  //
351  // Compute the sum of elements in range [__f, __l)
352  // This is a naive algorithm.  It suffers from cancelling.
353  // In the future try to specialize
354  // for _Tp = float, double, long double using a more accurate
355  // algorithm.
356  //
357  template<typename _Tp>
358    inline _Tp
359    __valarray_sum(const _Tp* __restrict__ __f, const _Tp* __restrict__ __l)
360    {
361      _Tp __r = _Tp();
362      while (__f != __l)
363	__r += *__f++;
364      return __r;
365    }
366
367  // Compute the product of all elements in range [__f, __l)
368  template<typename _Tp>
369    inline _Tp
370    __valarray_product(const _Tp* __restrict__ __f,
371		       const _Tp* __restrict__ __l)
372    {
373      _Tp __r = _Tp(1);
374      while (__f != __l)
375	__r = __r * *__f++;
376      return __r;
377    }
378
379  // Compute the min/max of an array-expression
380  template<typename _Ta>
381    inline typename _Ta::value_type
382    __valarray_min(const _Ta& __a)
383    {
384      size_t __s = __a.size();
385      typedef typename _Ta::value_type _Value_type;
386      _Value_type __r = __s == 0 ? _Value_type() : __a[0];
387      for (size_t __i = 1; __i < __s; ++__i)
388	{
389	  _Value_type __t = __a[__i];
390	  if (__t < __r)
391	    __r = __t;
392	}
393      return __r;
394    }
395
396  template<typename _Ta>
397    inline typename _Ta::value_type
398    __valarray_max(const _Ta& __a)
399    {
400      size_t __s = __a.size();
401      typedef typename _Ta::value_type _Value_type;
402      _Value_type __r = __s == 0 ? _Value_type() : __a[0];
403      for (size_t __i = 1; __i < __s; ++__i)
404	{
405	  _Value_type __t = __a[__i];
406	  if (__t > __r)
407	    __r = __t;
408	}
409      return __r;
410    }
411
412  //
413  // Helper class _Array, first layer of valarray abstraction.
414  // All operations on valarray should be forwarded to this class
415  // whenever possible. -- gdr
416  //
417
418  template<typename _Tp>
419    struct _Array
420    {
421      explicit _Array(size_t);
422      explicit _Array(_Tp* const __restrict__);
423      explicit _Array(const valarray<_Tp>&);
424      _Array(const _Tp* __restrict__, size_t);
425
426      _Tp* begin() const;
427
428      _Tp* const __restrict__ _M_data;
429    };
430
431  template<typename _Tp>
432    inline void
433    __valarray_fill (_Array<_Tp> __a, size_t __n, const _Tp& __t)
434    { std::__valarray_fill(__a._M_data, __n, __t); }
435
436  template<typename _Tp>
437    inline void
438    __valarray_fill(_Array<_Tp> __a, size_t __n, size_t __s, const _Tp& __t)
439    { std::__valarray_fill(__a._M_data, __n, __s, __t); }
440
441  template<typename _Tp>
442    inline void
443    __valarray_fill(_Array<_Tp> __a, _Array<size_t> __i,
444		    size_t __n, const _Tp& __t)
445    { std::__valarray_fill(__a._M_data, __i._M_data, __n, __t); }
446
447  // Copy a plain array __a[<__n>] into a play array __b[<>]
448  template<typename _Tp>
449    inline void
450    __valarray_copy(_Array<_Tp> __a, size_t __n, _Array<_Tp> __b)
451    { std::__valarray_copy(__a._M_data, __n, __b._M_data); }
452
453  // Copy strided array __a[<__n : __s>] in plain __b[<__n>]
454  template<typename _Tp>
455    inline void
456    __valarray_copy(_Array<_Tp> __a, size_t __n, size_t __s, _Array<_Tp> __b)
457    { std::__valarray_copy(__a._M_data, __n, __s, __b._M_data); }
458
459  // Copy a plain array  __a[<__n>] into a strided array __b[<__n : __s>]
460  template<typename _Tp>
461    inline void
462    __valarray_copy(_Array<_Tp> __a, _Array<_Tp> __b, size_t __n, size_t __s)
463    { __valarray_copy(__a._M_data, __b._M_data, __n, __s); }
464
465  // Copy strided array __src[<__n : __s1>] into another
466  // strided array __dst[< : __s2>].  Their sizes must match.
467  template<typename _Tp>
468    inline void
469    __valarray_copy(_Array<_Tp> __a, size_t __n, size_t __s1,
470                    _Array<_Tp> __b, size_t __s2)
471    { std::__valarray_copy(__a._M_data, __n, __s1, __b._M_data, __s2); }
472
473  // Copy an indexed array __a[__i[<__n>]] in plain array __b[<__n>]
474  template<typename _Tp>
475    inline void
476    __valarray_copy(_Array<_Tp> __a, _Array<size_t> __i,
477		    _Array<_Tp> __b, size_t __n)
478    { std::__valarray_copy(__a._M_data, __i._M_data, __b._M_data, __n); }
479
480  // Copy a plain array __a[<__n>] in an indexed array __b[__i[<__n>]]
481  template<typename _Tp>
482    inline void
483    __valarray_copy(_Array<_Tp> __a, size_t __n, _Array<_Tp> __b,
484		    _Array<size_t> __i)
485    { std::__valarray_copy(__a._M_data, __n, __b._M_data, __i._M_data); }
486
487  // Copy the __n first elements of an indexed array __src[<__i>] into
488  // another indexed array __dst[<__j>].
489  template<typename _Tp>
490    inline void
491    __valarray_copy(_Array<_Tp> __src, size_t __n, _Array<size_t> __i,
492                    _Array<_Tp> __dst, _Array<size_t> __j)
493    {
494      std::__valarray_copy(__src._M_data, __n, __i._M_data,
495		    __dst._M_data, __j._M_data);
496    }
497
498  template<typename _Tp>
499    inline
500    _Array<_Tp>::_Array(size_t __n)
501    : _M_data(__valarray_get_storage<_Tp>(__n))
502    { std::__valarray_default_construct(_M_data, _M_data + __n); }
503
504  template<typename _Tp>
505    inline
506    _Array<_Tp>::_Array(_Tp* const __restrict__ __p)
507    : _M_data (__p) {}
508
509  template<typename _Tp>
510    inline
511    _Array<_Tp>::_Array(const valarray<_Tp>& __v)
512    : _M_data (__v._M_data) {}
513
514  template<typename _Tp>
515    inline
516    _Array<_Tp>::_Array(const _Tp* __restrict__ __b, size_t __s)
517    : _M_data(__valarray_get_storage<_Tp>(__s))
518    { std::__valarray_copy_construct(__b, __s, _M_data); }
519
520  template<typename _Tp>
521    inline _Tp*
522    _Array<_Tp>::begin () const
523    { return _M_data; }
524
525#define _DEFINE_ARRAY_FUNCTION(_Op, _Name)				\
526  template<typename _Tp>		        			\
527    inline void								\
528    _Array_augmented_##_Name(_Array<_Tp> __a, size_t __n, const _Tp& __t) \
529    {									\
530      for (_Tp* __p = __a._M_data; __p < __a._M_data + __n; ++__p)	\
531        *__p _Op##= __t;						\
532    }									\
533									\
534  template<typename _Tp>						\
535    inline void								\
536    _Array_augmented_##_Name(_Array<_Tp> __a, size_t __n, _Array<_Tp> __b) \
537    {									\
538      _Tp* __p = __a._M_data;						\
539      for (_Tp* __q = __b._M_data; __q < __b._M_data + __n; ++__p, ++__q) \
540        *__p _Op##= *__q;						\
541    }									\
542									\
543  template<typename _Tp, class _Dom>					\
544    void								\
545    _Array_augmented_##_Name(_Array<_Tp> __a,	        		\
546                             const _Expr<_Dom, _Tp>& __e, size_t __n)	\
547    {									\
548      _Tp* __p(__a._M_data);						\
549      for (size_t __i = 0; __i < __n; ++__i, ++__p)                     \
550        *__p _Op##= __e[__i];                                          	\
551    }									\
552									\
553  template<typename _Tp>						\
554    inline void								\
555    _Array_augmented_##_Name(_Array<_Tp> __a, size_t __n, size_t __s,	\
556	                     _Array<_Tp> __b)				\
557    {									\
558      _Tp* __q(__b._M_data);						\
559      for (_Tp* __p = __a._M_data; __p < __a._M_data + __s * __n;       \
560	   __p += __s, ++__q)                                           \
561        *__p _Op##= *__q;						\
562    }									\
563									\
564  template<typename _Tp>						\
565    inline void								\
566    _Array_augmented_##_Name(_Array<_Tp> __a, _Array<_Tp> __b,		\
567		             size_t __n, size_t __s)			\
568    {									\
569      _Tp* __q(__b._M_data);						\
570      for (_Tp* __p = __a._M_data; __p < __a._M_data + __n;             \
571	   ++__p, __q += __s)                                           \
572        *__p _Op##= *__q;						\
573    }									\
574									\
575  template<typename _Tp, class _Dom>					\
576    void								\
577    _Array_augmented_##_Name(_Array<_Tp> __a, size_t __s,		\
578                             const _Expr<_Dom, _Tp>& __e, size_t __n)	\
579    {									\
580      _Tp* __p(__a._M_data);						\
581      for (size_t __i = 0; __i < __n; ++__i, __p += __s)                \
582        *__p _Op##= __e[__i];                                          	\
583    }									\
584									\
585  template<typename _Tp>						\
586    inline void								\
587    _Array_augmented_##_Name(_Array<_Tp> __a, _Array<size_t> __i,	\
588                             _Array<_Tp> __b, size_t __n)		\
589    {									\
590      _Tp* __q(__b._M_data);						\
591      for (size_t* __j = __i._M_data; __j < __i._M_data + __n;          \
592           ++__j, ++__q)                                                \
593        __a._M_data[*__j] _Op##= *__q;					\
594    }									\
595									\
596  template<typename _Tp>						\
597    inline void					        		\
598    _Array_augmented_##_Name(_Array<_Tp> __a, size_t __n,		\
599                             _Array<_Tp> __b, _Array<size_t> __i)	\
600    {									\
601      _Tp* __p(__a._M_data);						\
602      for (size_t* __j = __i._M_data; __j<__i._M_data + __n;            \
603	   ++__j, ++__p)                                                \
604        *__p _Op##= __b._M_data[*__j];					\
605    }									\
606									\
607  template<typename _Tp, class _Dom>					\
608    void								\
609    _Array_augmented_##_Name(_Array<_Tp> __a, _Array<size_t> __i,	\
610                             const _Expr<_Dom, _Tp>& __e, size_t __n)	\
611    {									\
612      size_t* __j(__i._M_data);	        				\
613      for (size_t __k = 0; __k<__n; ++__k, ++__j)			\
614        __a._M_data[*__j] _Op##= __e[__k];				\
615    }									\
616									\
617  template<typename _Tp>						\
618    void								\
619    _Array_augmented_##_Name(_Array<_Tp> __a, _Array<bool> __m,         \
620                             _Array<_Tp> __b, size_t __n)		\
621    {									\
622      bool* __ok(__m._M_data);						\
623      _Tp* __p(__a._M_data);						\
624      for (_Tp* __q = __b._M_data; __q < __b._M_data + __n;             \
625	   ++__q, ++__ok, ++__p)                                        \
626        {                                                               \
627          while (! *__ok)                                               \
628            {						        	\
629              ++__ok;							\
630              ++__p;							\
631            }								\
632          *__p _Op##= *__q;						\
633        }								\
634    }									\
635									\
636  template<typename _Tp>						\
637    void								\
638    _Array_augmented_##_Name(_Array<_Tp> __a, size_t __n,		\
639                             _Array<_Tp> __b, _Array<bool> __m)   	\
640    {									\
641      bool* __ok(__m._M_data);						\
642      _Tp* __q(__b._M_data);						\
643      for (_Tp* __p = __a._M_data; __p < __a._M_data + __n;             \
644	   ++__p, ++__ok, ++__q)                                        \
645        {                                                               \
646          while (! *__ok)                                               \
647            {					        		\
648              ++__ok;							\
649              ++__q;							\
650            }								\
651          *__p _Op##= *__q;						\
652        }								\
653    }									\
654									\
655  template<typename _Tp, class _Dom>					\
656    void								\
657    _Array_augmented_##_Name(_Array<_Tp> __a, _Array<bool> __m,  	\
658                             const _Expr<_Dom, _Tp>& __e, size_t __n)	\
659    {									\
660      bool* __ok(__m._M_data);						\
661      _Tp* __p(__a._M_data);						\
662      for (size_t __i = 0; __i < __n; ++__i, ++__ok, ++__p)             \
663        {	                                           		\
664          while (! *__ok)                                               \
665            {		         					\
666	      ++__ok;							\
667              ++__p;							\
668            }								\
669          *__p _Op##= __e[__i];						\
670        }								\
671    }
672
673   _DEFINE_ARRAY_FUNCTION(+, __plus)
674   _DEFINE_ARRAY_FUNCTION(-, __minus)
675   _DEFINE_ARRAY_FUNCTION(*, __multiplies)
676   _DEFINE_ARRAY_FUNCTION(/, __divides)
677   _DEFINE_ARRAY_FUNCTION(%, __modulus)
678   _DEFINE_ARRAY_FUNCTION(^, __bitwise_xor)
679   _DEFINE_ARRAY_FUNCTION(|, __bitwise_or)
680   _DEFINE_ARRAY_FUNCTION(&, __bitwise_and)
681   _DEFINE_ARRAY_FUNCTION(<<, __shift_left)
682   _DEFINE_ARRAY_FUNCTION(>>, __shift_right)
683
684#undef _DEFINE_VALARRAY_FUNCTION
685} // namespace std
686
687#ifndef _GLIBCXX_EXPORT_TEMPLATE
688# include <bits/valarray_array.tcc>
689#endif
690
691#endif /* _ARRAY_H */
692