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