1// The template and inlines for the -*- C++ -*- valarray class.
2
3// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
4// 2006, 2007, 2008, 2009
5// Free Software Foundation, Inc.
6//
7// This file is part of the GNU ISO C++ Library.  This library is free
8// software; you can redistribute it and/or modify it under the
9// terms of the GNU General Public License as published by the
10// Free Software Foundation; either version 3, or (at your option)
11// any later version.
12
13// This library is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16// GNU General Public License for more details.
17
18// Under Section 7 of GPL version 3, you are granted additional
19// permissions described in the GCC Runtime Library Exception, version
20// 3.1, as published by the Free Software Foundation.
21
22// You should have received a copy of the GNU General Public License and
23// a copy of the GCC Runtime Library Exception along with this program;
24// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
25// <http://www.gnu.org/licenses/>.
26
27/** @file valarray
28 *  This is a Standard C++ Library header. 
29 */
30
31// Written by Gabriel Dos Reis <Gabriel.Dos-Reis@DPTMaths.ENS-Cachan.Fr>
32
33#ifndef _GLIBCXX_VALARRAY
34#define _GLIBCXX_VALARRAY 1
35
36#pragma GCC system_header
37
38#include <bits/c++config.h>
39#include <cstddef>
40#include <cmath>
41#include <algorithm>
42#include <debug/debug.h>
43#include <initializer_list>
44
45_GLIBCXX_BEGIN_NAMESPACE(std)
46
47  template<class _Clos, typename _Tp> 
48    class _Expr;
49
50  template<typename _Tp1, typename _Tp2> 
51    class _ValArray;    
52
53  template<class _Oper, template<class, class> class _Meta, class _Dom>
54    struct _UnClos;
55
56  template<class _Oper,
57        template<class, class> class _Meta1,
58        template<class, class> class _Meta2,
59        class _Dom1, class _Dom2> 
60    class _BinClos;
61
62  template<template<class, class> class _Meta, class _Dom> 
63    class _SClos;
64
65  template<template<class, class> class _Meta, class _Dom> 
66    class _GClos;
67    
68  template<template<class, class> class _Meta, class _Dom> 
69    class _IClos;
70    
71  template<template<class, class> class _Meta, class _Dom> 
72    class _ValFunClos;
73  
74  template<template<class, class> class _Meta, class _Dom> 
75    class _RefFunClos;
76
77  template<class _Tp> class valarray;   // An array of type _Tp
78  class slice;                          // BLAS-like slice out of an array
79  template<class _Tp> class slice_array;
80  class gslice;                         // generalized slice out of an array
81  template<class _Tp> class gslice_array;
82  template<class _Tp> class mask_array;     // masked array
83  template<class _Tp> class indirect_array; // indirected array
84
85_GLIBCXX_END_NAMESPACE
86
87#include <bits/valarray_array.h>
88#include <bits/valarray_before.h>
89  
90_GLIBCXX_BEGIN_NAMESPACE(std)
91
92  /**
93   * @defgroup numeric_arrays Numeric Arrays
94   * @ingroup numerics
95   *
96   * Classes and functions for representing and manipulating arrays of elements.
97   * @{
98   */
99
100  /**
101   *  @brief  Smart array designed to support numeric processing.
102   *
103   *  A valarray is an array that provides constraints intended to allow for
104   *  effective optimization of numeric array processing by reducing the
105   *  aliasing that can result from pointer representations.  It represents a
106   *  one-dimensional array from which different multidimensional subsets can
107   *  be accessed and modified.
108   *  
109   *  @param  Tp  Type of object in the array.
110   */
111  template<class _Tp> 
112    class valarray
113    {
114      template<class _Op>
115	struct _UnaryOp 
116	{
117	  typedef typename __fun<_Op, _Tp>::result_type __rt;
118	  typedef _Expr<_UnClos<_Op, _ValArray, _Tp>, __rt> _Rt;
119	};
120    public:
121      typedef _Tp value_type;
122      
123	// _lib.valarray.cons_ construct/destroy:
124      ///  Construct an empty array.
125      valarray();
126
127      ///  Construct an array with @a n elements.
128      explicit valarray(size_t);
129
130      ///  Construct an array with @a n elements initialized to @a t.
131      valarray(const _Tp&, size_t);
132
133      ///  Construct an array initialized to the first @a n elements of @a t.
134      valarray(const _Tp* __restrict__, size_t);
135
136      ///  Copy constructor.
137      valarray(const valarray&);
138
139      ///  Construct an array with the same size and values in @a sa.
140      valarray(const slice_array<_Tp>&);
141
142      ///  Construct an array with the same size and values in @a ga.
143      valarray(const gslice_array<_Tp>&);
144
145      ///  Construct an array with the same size and values in @a ma.
146      valarray(const mask_array<_Tp>&);
147
148      ///  Construct an array with the same size and values in @a ia.
149      valarray(const indirect_array<_Tp>&);
150
151#ifdef __GXX_EXPERIMENTAL_CXX0X__
152      ///  Construct an array with an initializer_list of values.
153      valarray(initializer_list<_Tp>);
154#endif
155
156      template<class _Dom>
157	valarray(const _Expr<_Dom, _Tp>& __e);
158
159      ~valarray();
160
161      // _lib.valarray.assign_ assignment:
162      /**
163       *  @brief  Assign elements to an array.
164       *
165       *  Assign elements of array to values in @a v.  Results are undefined
166       *  if @a v does not have the same size as this array.
167       *
168       *  @param  v  Valarray to get values from.
169       */
170      valarray<_Tp>& operator=(const valarray<_Tp>&);
171
172      /**
173       *  @brief  Assign elements to a value.
174       *
175       *  Assign all elements of array to @a t.
176       *
177       *  @param  t  Value for elements.
178       */
179      valarray<_Tp>& operator=(const _Tp&);
180
181      /**
182       *  @brief  Assign elements to an array subset.
183       *
184       *  Assign elements of array to values in @a sa.  Results are undefined
185       *  if @a sa does not have the same size as this array.
186       *
187       *  @param  sa  Array slice to get values from.
188       */
189      valarray<_Tp>& operator=(const slice_array<_Tp>&);
190
191      /**
192       *  @brief  Assign elements to an array subset.
193       *
194       *  Assign elements of array to values in @a ga.  Results are undefined
195       *  if @a ga does not have the same size as this array.
196       *
197       *  @param  ga  Array slice to get values from.
198       */
199      valarray<_Tp>& operator=(const gslice_array<_Tp>&);
200
201      /**
202       *  @brief  Assign elements to an array subset.
203       *
204       *  Assign elements of array to values in @a ma.  Results are undefined
205       *  if @a ma does not have the same size as this array.
206       *
207       *  @param  ma  Array slice to get values from.
208       */
209      valarray<_Tp>& operator=(const mask_array<_Tp>&);
210
211      /**
212       *  @brief  Assign elements to an array subset.
213       *
214       *  Assign elements of array to values in @a ia.  Results are undefined
215       *  if @a ia does not have the same size as this array.
216       *
217       *  @param  ia  Array slice to get values from.
218       */
219      valarray<_Tp>& operator=(const indirect_array<_Tp>&);
220
221#ifdef __GXX_EXPERIMENTAL_CXX0X__
222      /**
223       *  @brief  Assign elements to an initializer_list.
224       *
225       *  Assign elements of array to values in @a l.  Results are undefined
226       *  if @a l does not have the same size as this array.
227       *
228       *  @param  l  initializer_list to get values from.
229       */
230      valarray& operator=(initializer_list<_Tp>);
231#endif
232
233      template<class _Dom> valarray<_Tp>&
234	operator= (const _Expr<_Dom, _Tp>&);
235
236      // _lib.valarray.access_ element access:
237      /**
238       *  Return a reference to the i'th array element.  
239       *
240       *  @param  i  Index of element to return.
241       *  @return  Reference to the i'th element.
242       */
243      _Tp&                operator[](size_t);
244
245      // _GLIBCXX_RESOLVE_LIB_DEFECTS
246      // 389. Const overload of valarray::operator[] returns by value.
247      const _Tp&          operator[](size_t) const;
248
249      // _lib.valarray.sub_ subset operations:
250      /**
251       *  @brief  Return an array subset.
252       *
253       *  Returns a new valarray containing the elements of the array
254       *  indicated by the slice argument.  The new valarray has the same size
255       *  as the input slice.  @see slice.
256       *
257       *  @param  s  The source slice.
258       *  @return  New valarray containing elements in @a s.
259       */
260      _Expr<_SClos<_ValArray, _Tp>, _Tp> operator[](slice) const;
261
262      /**
263       *  @brief  Return a reference to an array subset.
264       *
265       *  Returns a new valarray containing the elements of the array
266       *  indicated by the slice argument.  The new valarray has the same size
267       *  as the input slice.  @see slice.
268       *
269       *  @param  s  The source slice.
270       *  @return  New valarray containing elements in @a s.
271       */
272      slice_array<_Tp>    operator[](slice);
273
274      /**
275       *  @brief  Return an array subset.
276       *
277       *  Returns a slice_array referencing the elements of the array
278       *  indicated by the slice argument.  @see gslice.
279       *
280       *  @param  s  The source slice.
281       *  @return  Slice_array referencing elements indicated by @a s.
282       */
283      _Expr<_GClos<_ValArray, _Tp>, _Tp> operator[](const gslice&) const;
284
285      /**
286       *  @brief  Return a reference to an array subset.
287       *
288       *  Returns a new valarray containing the elements of the array
289       *  indicated by the gslice argument.  The new valarray has
290       *  the same size as the input gslice.  @see gslice.
291       *
292       *  @param  s  The source gslice.
293       *  @return  New valarray containing elements in @a s.
294       */
295      gslice_array<_Tp>   operator[](const gslice&);
296
297      /**
298       *  @brief  Return an array subset.
299       *
300       *  Returns a new valarray containing the elements of the array
301       *  indicated by the argument.  The input is a valarray of bool which
302       *  represents a bitmask indicating which elements should be copied into
303       *  the new valarray.  Each element of the array is added to the return
304       *  valarray if the corresponding element of the argument is true.
305       *
306       *  @param  m  The valarray bitmask.
307       *  @return  New valarray containing elements indicated by @a m.
308       */
309      valarray<_Tp>       operator[](const valarray<bool>&) const;
310
311      /**
312       *  @brief  Return a reference to an array subset.
313       *
314       *  Returns a new mask_array referencing the elements of the array
315       *  indicated by the argument.  The input is a valarray of bool which
316       *  represents a bitmask indicating which elements are part of the
317       *  subset.  Elements of the array are part of the subset if the
318       *  corresponding element of the argument is true.
319       *
320       *  @param  m  The valarray bitmask.
321       *  @return  New valarray containing elements indicated by @a m.
322       */
323      mask_array<_Tp>     operator[](const valarray<bool>&);
324
325      /**
326       *  @brief  Return an array subset.
327       *
328       *  Returns a new valarray containing the elements of the array
329       *  indicated by the argument.  The elements in the argument are
330       *  interpreted as the indices of elements of this valarray to copy to
331       *  the return valarray.
332       *
333       *  @param  i  The valarray element index list.
334       *  @return  New valarray containing elements in @a s.
335       */
336      _Expr<_IClos<_ValArray, _Tp>, _Tp>
337        operator[](const valarray<size_t>&) const;
338
339      /**
340       *  @brief  Return a reference to an array subset.
341       *
342       *  Returns an indirect_array referencing the elements of the array
343       *  indicated by the argument.  The elements in the argument are
344       *  interpreted as the indices of elements of this valarray to include
345       *  in the subset.  The returned indirect_array refers to these
346       *  elements.
347       *
348       *  @param  i  The valarray element index list.
349       *  @return  Indirect_array referencing elements in @a i.
350       */
351      indirect_array<_Tp> operator[](const valarray<size_t>&);
352
353      // _lib.valarray.unary_ unary operators:
354      ///  Return a new valarray by applying unary + to each element.
355      typename _UnaryOp<__unary_plus>::_Rt  operator+() const;
356
357      ///  Return a new valarray by applying unary - to each element.
358      typename _UnaryOp<__negate>::_Rt      operator-() const;
359
360      ///  Return a new valarray by applying unary ~ to each element.
361      typename _UnaryOp<__bitwise_not>::_Rt operator~() const;
362
363      ///  Return a new valarray by applying unary ! to each element.
364      typename _UnaryOp<__logical_not>::_Rt operator!() const;
365
366      // _lib.valarray.cassign_ computed assignment:
367      ///  Multiply each element of array by @a t.
368      valarray<_Tp>& operator*=(const _Tp&);
369
370      ///  Divide each element of array by @a t.
371      valarray<_Tp>& operator/=(const _Tp&);
372
373      ///  Set each element e of array to e % @a t.
374      valarray<_Tp>& operator%=(const _Tp&);
375
376      ///  Add @a t to each element of array.
377      valarray<_Tp>& operator+=(const _Tp&);
378
379      ///  Subtract @a t to each element of array.
380      valarray<_Tp>& operator-=(const _Tp&);
381
382      ///  Set each element e of array to e ^ @a t.
383      valarray<_Tp>& operator^=(const _Tp&);
384
385      ///  Set each element e of array to e & @a t.
386      valarray<_Tp>& operator&=(const _Tp&);
387
388      ///  Set each element e of array to e | @a t.
389      valarray<_Tp>& operator|=(const _Tp&);
390
391      ///  Left shift each element e of array by @a t bits.
392      valarray<_Tp>& operator<<=(const _Tp&);
393
394      ///  Right shift each element e of array by @a t bits.
395      valarray<_Tp>& operator>>=(const _Tp&);
396
397      ///  Multiply elements of array by corresponding elements of @a v.
398      valarray<_Tp>& operator*=(const valarray<_Tp>&);
399
400      ///  Divide elements of array by corresponding elements of @a v.
401      valarray<_Tp>& operator/=(const valarray<_Tp>&);
402
403      ///  Modulo elements of array by corresponding elements of @a v.
404      valarray<_Tp>& operator%=(const valarray<_Tp>&);
405
406      ///  Add corresponding elements of @a v to elements of array.
407      valarray<_Tp>& operator+=(const valarray<_Tp>&);
408
409      ///  Subtract corresponding elements of @a v from elements of array.
410      valarray<_Tp>& operator-=(const valarray<_Tp>&);
411
412      ///  Logical xor corresponding elements of @a v with elements of array.
413      valarray<_Tp>& operator^=(const valarray<_Tp>&);
414
415      ///  Logical or corresponding elements of @a v with elements of array.
416      valarray<_Tp>& operator|=(const valarray<_Tp>&);
417
418      ///  Logical and corresponding elements of @a v with elements of array.
419      valarray<_Tp>& operator&=(const valarray<_Tp>&);
420
421      ///  Left shift elements of array by corresponding elements of @a v.
422      valarray<_Tp>& operator<<=(const valarray<_Tp>&);
423
424      ///  Right shift elements of array by corresponding elements of @a v.
425      valarray<_Tp>& operator>>=(const valarray<_Tp>&);
426
427      template<class _Dom>
428	valarray<_Tp>& operator*=(const _Expr<_Dom, _Tp>&);
429      template<class _Dom>
430	valarray<_Tp>& operator/=(const _Expr<_Dom, _Tp>&);
431      template<class _Dom>
432	valarray<_Tp>& operator%=(const _Expr<_Dom, _Tp>&);
433      template<class _Dom>
434	valarray<_Tp>& operator+=(const _Expr<_Dom, _Tp>&);
435      template<class _Dom>
436	valarray<_Tp>& operator-=(const _Expr<_Dom, _Tp>&);
437      template<class _Dom>
438	valarray<_Tp>& operator^=(const _Expr<_Dom, _Tp>&);
439      template<class _Dom>
440	valarray<_Tp>& operator|=(const _Expr<_Dom, _Tp>&);
441      template<class _Dom>
442	valarray<_Tp>& operator&=(const _Expr<_Dom, _Tp>&);
443      template<class _Dom>
444        valarray<_Tp>& operator<<=(const _Expr<_Dom, _Tp>&);
445      template<class _Dom>
446	valarray<_Tp>& operator>>=(const _Expr<_Dom, _Tp>&);
447
448      // _lib.valarray.members_ member functions:
449      ///  Return the number of elements in array.
450      size_t size() const;
451
452      /**
453       *  @brief  Return the sum of all elements in the array.
454       *
455       *  Accumulates the sum of all elements into a Tp using +=.  The order
456       *  of adding the elements is unspecified.
457       */
458      _Tp    sum() const;
459
460      ///  Return the minimum element using operator<().
461      _Tp    min() const;	
462
463      ///  Return the maximum element using operator<().
464      _Tp    max() const;	
465
466      /**
467       *  @brief  Return a shifted array.
468       *
469       *  A new valarray is constructed as a copy of this array with elements
470       *  in shifted positions.  For an element with index i, the new position
471       *  is i - n.  The new valarray has the same size as the current one.
472       *  New elements without a value are set to 0.  Elements whose new
473       *  position is outside the bounds of the array are discarded.
474       *
475       *  Positive arguments shift toward index 0, discarding elements [0, n).
476       *  Negative arguments discard elements from the top of the array.
477       *
478       *  @param  n  Number of element positions to shift.
479       *  @return  New valarray with elements in shifted positions.
480       */
481      valarray<_Tp> shift (int) const;
482
483      /**
484       *  @brief  Return a rotated array.
485       *
486       *  A new valarray is constructed as a copy of this array with elements
487       *  in shifted positions.  For an element with index i, the new position
488       *  is (i - n) % size().  The new valarray has the same size as the
489       *  current one.  Elements that are shifted beyond the array bounds are
490       *  shifted into the other end of the array.  No elements are lost.
491       *
492       *  Positive arguments shift toward index 0, wrapping around the top.
493       *  Negative arguments shift towards the top, wrapping around to 0.
494       *
495       *  @param  n  Number of element positions to rotate.
496       *  @return  New valarray with elements in shifted positions.
497       */
498      valarray<_Tp> cshift(int) const;
499
500      /**
501       *  @brief  Apply a function to the array.
502       *
503       *  Returns a new valarray with elements assigned to the result of
504       *  applying func to the corresponding element of this array.  The new
505       *  array has the same size as this one.
506       *
507       *  @param  func  Function of Tp returning Tp to apply.
508       *  @return  New valarray with transformed elements.
509       */
510      _Expr<_ValFunClos<_ValArray, _Tp>, _Tp> apply(_Tp func(_Tp)) const;
511
512      /**
513       *  @brief  Apply a function to the array.
514       *
515       *  Returns a new valarray with elements assigned to the result of
516       *  applying func to the corresponding element of this array.  The new
517       *  array has the same size as this one.
518       *
519       *  @param  func  Function of const Tp& returning Tp to apply.
520       *  @return  New valarray with transformed elements.
521       */
522      _Expr<_RefFunClos<_ValArray, _Tp>, _Tp> apply(_Tp func(const _Tp&)) const;
523
524      /**
525       *  @brief  Resize array.
526       *
527       *  Resize this array to @a size and set all elements to @a c.  All
528       *  references and iterators are invalidated.
529       *
530       *  @param  size  New array size.
531       *  @param  c  New value for all elements.
532       */
533      void resize(size_t __size, _Tp __c = _Tp());
534
535    private:
536      size_t _M_size;
537      _Tp* __restrict__ _M_data;
538      
539      friend class _Array<_Tp>;
540    };
541  
542  template<typename _Tp>
543    inline const _Tp&
544    valarray<_Tp>::operator[](size_t __i) const
545    { 
546      __glibcxx_requires_subscript(__i);
547      return _M_data[__i];
548    }
549
550  template<typename _Tp>
551    inline _Tp&
552    valarray<_Tp>::operator[](size_t __i)
553    { 
554      __glibcxx_requires_subscript(__i);
555      return _M_data[__i];
556    }
557
558  // @} group numeric_arrays
559
560_GLIBCXX_END_NAMESPACE
561
562#include <bits/valarray_after.h>
563#include <bits/slice_array.h>
564#include <bits/gslice.h>
565#include <bits/gslice_array.h>
566#include <bits/mask_array.h>
567#include <bits/indirect_array.h>
568
569_GLIBCXX_BEGIN_NAMESPACE(std)
570
571  /**
572   * @addtogroup numeric_arrays
573   * @{
574   */
575
576  template<typename _Tp>
577    inline
578    valarray<_Tp>::valarray() : _M_size(0), _M_data(0) {}
579
580  template<typename _Tp>
581    inline 
582    valarray<_Tp>::valarray(size_t __n) 
583    : _M_size(__n), _M_data(__valarray_get_storage<_Tp>(__n))
584    { std::__valarray_default_construct(_M_data, _M_data + __n); }
585
586  template<typename _Tp>
587    inline
588    valarray<_Tp>::valarray(const _Tp& __t, size_t __n)
589    : _M_size(__n), _M_data(__valarray_get_storage<_Tp>(__n))
590    { std::__valarray_fill_construct(_M_data, _M_data + __n, __t); }
591
592  template<typename _Tp>
593    inline
594    valarray<_Tp>::valarray(const _Tp* __restrict__ __p, size_t __n)
595    : _M_size(__n), _M_data(__valarray_get_storage<_Tp>(__n))
596    { 
597      _GLIBCXX_DEBUG_ASSERT(__p != 0 || __n == 0);
598      std::__valarray_copy_construct(__p, __p + __n, _M_data); 
599    }
600
601  template<typename _Tp>
602    inline
603    valarray<_Tp>::valarray(const valarray<_Tp>& __v)
604    : _M_size(__v._M_size), _M_data(__valarray_get_storage<_Tp>(__v._M_size))
605    { std::__valarray_copy_construct(__v._M_data, __v._M_data + _M_size,
606				     _M_data); }
607
608  template<typename _Tp>
609    inline
610    valarray<_Tp>::valarray(const slice_array<_Tp>& __sa)
611    : _M_size(__sa._M_sz), _M_data(__valarray_get_storage<_Tp>(__sa._M_sz))
612    {
613      std::__valarray_copy_construct
614	(__sa._M_array, __sa._M_sz, __sa._M_stride, _Array<_Tp>(_M_data));
615    }
616
617  template<typename _Tp>
618    inline
619    valarray<_Tp>::valarray(const gslice_array<_Tp>& __ga)
620    : _M_size(__ga._M_index.size()),
621      _M_data(__valarray_get_storage<_Tp>(_M_size))
622    {
623      std::__valarray_copy_construct
624	(__ga._M_array, _Array<size_t>(__ga._M_index),
625	 _Array<_Tp>(_M_data), _M_size);
626    }
627
628  template<typename _Tp>
629    inline
630    valarray<_Tp>::valarray(const mask_array<_Tp>& __ma)
631    : _M_size(__ma._M_sz), _M_data(__valarray_get_storage<_Tp>(__ma._M_sz))
632    {
633      std::__valarray_copy_construct
634	(__ma._M_array, __ma._M_mask, _Array<_Tp>(_M_data), _M_size);
635    }
636
637  template<typename _Tp>
638    inline
639    valarray<_Tp>::valarray(const indirect_array<_Tp>& __ia)
640    : _M_size(__ia._M_sz), _M_data(__valarray_get_storage<_Tp>(__ia._M_sz))
641    {
642      std::__valarray_copy_construct
643	(__ia._M_array, __ia._M_index, _Array<_Tp>(_M_data), _M_size);
644    }
645
646#ifdef __GXX_EXPERIMENTAL_CXX0X__
647  template<typename _Tp>
648    inline
649    valarray<_Tp>::valarray(initializer_list<_Tp> __l)
650    : _M_size(__l.size()), _M_data(__valarray_get_storage<_Tp>(__l.size()))
651    { std::__valarray_copy_construct (__l.begin(), __l.end(), _M_data); }
652#endif
653
654  template<typename _Tp> template<class _Dom>
655    inline
656    valarray<_Tp>::valarray(const _Expr<_Dom, _Tp>& __e)
657    : _M_size(__e.size()), _M_data(__valarray_get_storage<_Tp>(_M_size))
658    { std::__valarray_copy_construct(__e, _M_size, _Array<_Tp>(_M_data)); }
659
660  template<typename _Tp>
661    inline
662    valarray<_Tp>::~valarray()
663    {
664      std::__valarray_destroy_elements(_M_data, _M_data + _M_size);
665      std::__valarray_release_memory(_M_data);
666    }
667
668  template<typename _Tp>
669    inline valarray<_Tp>&
670    valarray<_Tp>::operator=(const valarray<_Tp>& __v)
671    {
672      // _GLIBCXX_RESOLVE_LIB_DEFECTS
673      // 630. arrays of valarray.
674      if (_M_size == __v._M_size)
675	std::__valarray_copy(__v._M_data, _M_size, _M_data);
676      else
677	{
678	  if (_M_data)
679	    {
680	      std::__valarray_destroy_elements(_M_data, _M_data + _M_size);
681	      std::__valarray_release_memory(_M_data);
682	    }
683	  _M_size = __v._M_size;
684	  _M_data = __valarray_get_storage<_Tp>(_M_size);
685	  std::__valarray_copy_construct(__v._M_data, __v._M_data + _M_size,
686					 _M_data);
687	}
688      return *this;
689    }
690
691#ifdef __GXX_EXPERIMENTAL_CXX0X__
692  template<typename _Tp>
693    inline valarray<_Tp>&
694    valarray<_Tp>::operator=(initializer_list<_Tp> __l)
695    {
696      // _GLIBCXX_RESOLVE_LIB_DEFECTS
697      // 630. arrays of valarray.
698      if (_M_size == __l.size())
699	std::__valarray_copy(__l.begin(), __l.size(), _M_data);
700      else
701	{
702	  if (_M_data)
703	    {
704	      std::__valarray_destroy_elements(_M_data, _M_data + _M_size);
705	      std::__valarray_release_memory(_M_data);
706	    }
707	  _M_size = __l.size();
708	  _M_data = __valarray_get_storage<_Tp>(_M_size);
709	  std::__valarray_copy_construct(__l.begin(), __l.begin() + _M_size,
710					 _M_data);
711	}
712      return *this;
713    }
714#endif
715
716  template<typename _Tp>
717    inline valarray<_Tp>&
718    valarray<_Tp>::operator=(const _Tp& __t)
719    {
720      std::__valarray_fill(_M_data, _M_size, __t);
721      return *this;
722    }
723
724  template<typename _Tp>
725    inline valarray<_Tp>&
726    valarray<_Tp>::operator=(const slice_array<_Tp>& __sa)
727    {
728      _GLIBCXX_DEBUG_ASSERT(_M_size == __sa._M_sz);
729      std::__valarray_copy(__sa._M_array, __sa._M_sz,
730			   __sa._M_stride, _Array<_Tp>(_M_data));
731      return *this;
732    }
733
734  template<typename _Tp>
735    inline valarray<_Tp>&
736    valarray<_Tp>::operator=(const gslice_array<_Tp>& __ga)
737    {
738      _GLIBCXX_DEBUG_ASSERT(_M_size == __ga._M_index.size());
739      std::__valarray_copy(__ga._M_array, _Array<size_t>(__ga._M_index),
740			   _Array<_Tp>(_M_data), _M_size);
741      return *this;
742    }
743
744  template<typename _Tp>
745    inline valarray<_Tp>&
746    valarray<_Tp>::operator=(const mask_array<_Tp>& __ma)
747    {
748      _GLIBCXX_DEBUG_ASSERT(_M_size == __ma._M_sz);
749      std::__valarray_copy(__ma._M_array, __ma._M_mask,
750			   _Array<_Tp>(_M_data), _M_size);
751      return *this;
752    }
753
754  template<typename _Tp>
755    inline valarray<_Tp>&
756    valarray<_Tp>::operator=(const indirect_array<_Tp>& __ia)
757    {
758      _GLIBCXX_DEBUG_ASSERT(_M_size == __ia._M_sz);
759      std::__valarray_copy(__ia._M_array, __ia._M_index,
760			   _Array<_Tp>(_M_data), _M_size);
761      return *this;
762    }
763
764  template<typename _Tp> template<class _Dom>
765    inline valarray<_Tp>&
766    valarray<_Tp>::operator=(const _Expr<_Dom, _Tp>& __e)
767    {
768      _GLIBCXX_DEBUG_ASSERT(_M_size == __e.size());
769      std::__valarray_copy(__e, _M_size, _Array<_Tp>(_M_data));
770      return *this;
771    }
772
773  template<typename _Tp>
774    inline _Expr<_SClos<_ValArray,_Tp>, _Tp>
775    valarray<_Tp>::operator[](slice __s) const
776    {
777      typedef _SClos<_ValArray,_Tp> _Closure;
778      return _Expr<_Closure, _Tp>(_Closure (_Array<_Tp>(_M_data), __s));
779    }
780
781  template<typename _Tp>
782    inline slice_array<_Tp>
783    valarray<_Tp>::operator[](slice __s)
784    { return slice_array<_Tp>(_Array<_Tp>(_M_data), __s); }
785
786  template<typename _Tp>
787    inline _Expr<_GClos<_ValArray,_Tp>, _Tp>
788    valarray<_Tp>::operator[](const gslice& __gs) const
789    {
790      typedef _GClos<_ValArray,_Tp> _Closure;
791      return _Expr<_Closure, _Tp>
792	(_Closure(_Array<_Tp>(_M_data), __gs._M_index->_M_index));
793    }
794
795  template<typename _Tp>
796    inline gslice_array<_Tp>
797    valarray<_Tp>::operator[](const gslice& __gs)
798    {
799      return gslice_array<_Tp>
800	(_Array<_Tp>(_M_data), __gs._M_index->_M_index);
801    }
802
803  template<typename _Tp>
804    inline valarray<_Tp>
805    valarray<_Tp>::operator[](const valarray<bool>& __m) const
806    {
807      size_t __s = 0;
808      size_t __e = __m.size();
809      for (size_t __i=0; __i<__e; ++__i)
810	if (__m[__i]) ++__s;
811      return valarray<_Tp>(mask_array<_Tp>(_Array<_Tp>(_M_data), __s,
812					   _Array<bool> (__m)));
813    }
814
815  template<typename _Tp>
816    inline mask_array<_Tp>
817    valarray<_Tp>::operator[](const valarray<bool>& __m)
818    {
819      size_t __s = 0;
820      size_t __e = __m.size();
821      for (size_t __i=0; __i<__e; ++__i)
822	if (__m[__i]) ++__s;
823      return mask_array<_Tp>(_Array<_Tp>(_M_data), __s, _Array<bool>(__m));
824    }
825
826  template<typename _Tp>
827    inline _Expr<_IClos<_ValArray,_Tp>, _Tp>
828    valarray<_Tp>::operator[](const valarray<size_t>& __i) const
829    {
830      typedef _IClos<_ValArray,_Tp> _Closure;
831      return _Expr<_Closure, _Tp>(_Closure(*this, __i));
832    }
833
834  template<typename _Tp>
835    inline indirect_array<_Tp>
836    valarray<_Tp>::operator[](const valarray<size_t>& __i)
837    {
838      return indirect_array<_Tp>(_Array<_Tp>(_M_data), __i.size(),
839				 _Array<size_t>(__i));
840    }
841
842  template<class _Tp>
843    inline size_t 
844    valarray<_Tp>::size() const
845    { return _M_size; }
846
847  template<class _Tp>
848    inline _Tp
849    valarray<_Tp>::sum() const
850    {
851      _GLIBCXX_DEBUG_ASSERT(_M_size > 0);
852      return std::__valarray_sum(_M_data, _M_data + _M_size);
853    }
854
855  template<class _Tp>
856     inline valarray<_Tp>
857     valarray<_Tp>::shift(int __n) const
858     {
859       valarray<_Tp> __ret;
860
861       if (_M_size == 0)
862	 return __ret;
863
864       _Tp* __restrict__ __tmp_M_data =
865	 std::__valarray_get_storage<_Tp>(_M_size);
866
867       if (__n == 0)
868	 std::__valarray_copy_construct(_M_data,
869					_M_data + _M_size, __tmp_M_data);
870       else if (__n > 0)      // shift left
871	 {
872	   if (size_t(__n) > _M_size)
873	     __n = int(_M_size);
874
875	   std::__valarray_copy_construct(_M_data + __n,
876					  _M_data + _M_size, __tmp_M_data);
877	   std::__valarray_default_construct(__tmp_M_data + _M_size - __n,
878					     __tmp_M_data + _M_size);
879	 }
880       else                   // shift right
881	 {
882	   if (-size_t(__n) > _M_size)
883	     __n = -int(_M_size);
884
885	   std::__valarray_copy_construct(_M_data, _M_data + _M_size + __n,
886					  __tmp_M_data - __n);
887	   std::__valarray_default_construct(__tmp_M_data,
888					     __tmp_M_data - __n);
889	 }
890
891       __ret._M_size = _M_size;
892       __ret._M_data = __tmp_M_data;
893       return __ret;
894     }
895
896  template<class _Tp>
897     inline valarray<_Tp>
898     valarray<_Tp>::cshift(int __n) const
899     {
900       valarray<_Tp> __ret;
901
902       if (_M_size == 0)
903	 return __ret;
904
905       _Tp* __restrict__ __tmp_M_data =
906	 std::__valarray_get_storage<_Tp>(_M_size);
907
908       if (__n == 0)
909	 std::__valarray_copy_construct(_M_data,
910					_M_data + _M_size, __tmp_M_data);
911       else if (__n > 0)      // cshift left
912	 {
913	   if (size_t(__n) > _M_size)
914	     __n = int(__n % _M_size);
915
916	   std::__valarray_copy_construct(_M_data, _M_data + __n,
917					  __tmp_M_data + _M_size - __n);
918	   std::__valarray_copy_construct(_M_data + __n, _M_data + _M_size,
919					  __tmp_M_data);
920	 }
921       else                   // cshift right
922	 {
923	   if (-size_t(__n) > _M_size)
924	     __n = -int(-size_t(__n) % _M_size);
925
926	   std::__valarray_copy_construct(_M_data + _M_size + __n,
927					  _M_data + _M_size, __tmp_M_data);
928	   std::__valarray_copy_construct(_M_data, _M_data + _M_size + __n,
929					  __tmp_M_data - __n);
930	 }
931
932       __ret._M_size = _M_size;
933       __ret._M_data = __tmp_M_data;
934       return __ret;
935     }
936
937  template<class _Tp>
938    inline void
939    valarray<_Tp>::resize(size_t __n, _Tp __c)
940    {
941      // This complication is so to make valarray<valarray<T> > work
942      // even though it is not required by the standard.  Nobody should
943      // be saying valarray<valarray<T> > anyway.  See the specs.
944      std::__valarray_destroy_elements(_M_data, _M_data + _M_size);
945      if (_M_size != __n)
946	{
947	  std::__valarray_release_memory(_M_data);
948	  _M_size = __n;
949	  _M_data = __valarray_get_storage<_Tp>(__n);
950	}
951      std::__valarray_fill_construct(_M_data, _M_data + __n, __c);
952    }
953    
954  template<typename _Tp>
955    inline _Tp
956    valarray<_Tp>::min() const
957    {
958      _GLIBCXX_DEBUG_ASSERT(_M_size > 0);
959      return *std::min_element(_M_data, _M_data + _M_size);
960    }
961
962  template<typename _Tp>
963    inline _Tp
964    valarray<_Tp>::max() const
965    {
966      _GLIBCXX_DEBUG_ASSERT(_M_size > 0);
967      return *std::max_element(_M_data, _M_data + _M_size);
968    }
969  
970  template<class _Tp>
971    inline _Expr<_ValFunClos<_ValArray, _Tp>, _Tp>
972    valarray<_Tp>::apply(_Tp func(_Tp)) const
973    {
974      typedef _ValFunClos<_ValArray, _Tp> _Closure;
975      return _Expr<_Closure, _Tp>(_Closure(*this, func));
976    }
977
978  template<class _Tp>
979    inline _Expr<_RefFunClos<_ValArray, _Tp>, _Tp>
980    valarray<_Tp>::apply(_Tp func(const _Tp &)) const
981    {
982      typedef _RefFunClos<_ValArray, _Tp> _Closure;
983      return _Expr<_Closure, _Tp>(_Closure(*this, func));
984    }
985
986#define _DEFINE_VALARRAY_UNARY_OPERATOR(_Op, _Name)                     \
987  template<typename _Tp>						\
988    inline typename valarray<_Tp>::template _UnaryOp<_Name>::_Rt      	\
989    valarray<_Tp>::operator _Op() const					\
990    {									\
991      typedef _UnClos<_Name, _ValArray, _Tp> _Closure;	                \
992      typedef typename __fun<_Name, _Tp>::result_type _Rt;              \
993      return _Expr<_Closure, _Rt>(_Closure(*this));			\
994    }
995
996    _DEFINE_VALARRAY_UNARY_OPERATOR(+, __unary_plus)
997    _DEFINE_VALARRAY_UNARY_OPERATOR(-, __negate)
998    _DEFINE_VALARRAY_UNARY_OPERATOR(~, __bitwise_not)
999    _DEFINE_VALARRAY_UNARY_OPERATOR (!, __logical_not)
1000
1001#undef _DEFINE_VALARRAY_UNARY_OPERATOR
1002
1003#define _DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(_Op, _Name)               \
1004  template<class _Tp>							\
1005    inline valarray<_Tp>&						\
1006    valarray<_Tp>::operator _Op##=(const _Tp &__t)			\
1007    {									\
1008      _Array_augmented_##_Name(_Array<_Tp>(_M_data), _M_size, __t);	\
1009      return *this;							\
1010    }									\
1011									\
1012  template<class _Tp>							\
1013    inline valarray<_Tp>&						\
1014    valarray<_Tp>::operator _Op##=(const valarray<_Tp> &__v)		\
1015    {									\
1016      _GLIBCXX_DEBUG_ASSERT(_M_size == __v._M_size);                    \
1017      _Array_augmented_##_Name(_Array<_Tp>(_M_data), _M_size, 		\
1018			       _Array<_Tp>(__v._M_data));		\
1019      return *this;							\
1020    }
1021
1022_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(+, __plus)
1023_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(-, __minus)
1024_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(*, __multiplies)
1025_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(/, __divides)
1026_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(%, __modulus)
1027_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(^, __bitwise_xor)
1028_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(&, __bitwise_and)
1029_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(|, __bitwise_or)
1030_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(<<, __shift_left)
1031_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(>>, __shift_right)
1032
1033#undef _DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT
1034
1035#define _DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(_Op, _Name)          \
1036  template<class _Tp> template<class _Dom>				\
1037    inline valarray<_Tp>&						\
1038    valarray<_Tp>::operator _Op##=(const _Expr<_Dom, _Tp>& __e)		\
1039    {									\
1040      _Array_augmented_##_Name(_Array<_Tp>(_M_data), __e, _M_size);	\
1041      return *this;							\
1042    }
1043
1044_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(+, __plus)
1045_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(-, __minus)
1046_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(*, __multiplies)
1047_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(/, __divides)
1048_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(%, __modulus)
1049_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(^, __bitwise_xor)
1050_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(&, __bitwise_and)
1051_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(|, __bitwise_or)
1052_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(<<, __shift_left)
1053_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(>>, __shift_right)
1054
1055#undef _DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT
1056    
1057
1058#define _DEFINE_BINARY_OPERATOR(_Op, _Name)				\
1059  template<typename _Tp>						\
1060    inline _Expr<_BinClos<_Name, _ValArray, _ValArray, _Tp, _Tp>,       \
1061                 typename __fun<_Name, _Tp>::result_type>               \
1062    operator _Op(const valarray<_Tp>& __v, const valarray<_Tp>& __w)	\
1063    {									\
1064      _GLIBCXX_DEBUG_ASSERT(__v.size() == __w.size());                  \
1065      typedef _BinClos<_Name, _ValArray, _ValArray, _Tp, _Tp> _Closure; \
1066      typedef typename __fun<_Name, _Tp>::result_type _Rt;              \
1067      return _Expr<_Closure, _Rt>(_Closure(__v, __w));                  \
1068    }									\
1069									\
1070  template<typename _Tp>						\
1071    inline _Expr<_BinClos<_Name, _ValArray,_Constant, _Tp, _Tp>,        \
1072                 typename __fun<_Name, _Tp>::result_type>               \
1073    operator _Op(const valarray<_Tp>& __v, const _Tp& __t)		\
1074    {									\
1075      typedef _BinClos<_Name, _ValArray, _Constant, _Tp, _Tp> _Closure;	\
1076      typedef typename __fun<_Name, _Tp>::result_type _Rt;              \
1077      return _Expr<_Closure, _Rt>(_Closure(__v, __t));	                \
1078    }									\
1079									\
1080  template<typename _Tp>						\
1081    inline _Expr<_BinClos<_Name, _Constant, _ValArray, _Tp, _Tp>,       \
1082                 typename __fun<_Name, _Tp>::result_type>               \
1083    operator _Op(const _Tp& __t, const valarray<_Tp>& __v)		\
1084    {									\
1085      typedef _BinClos<_Name, _Constant, _ValArray, _Tp, _Tp> _Closure; \
1086      typedef typename __fun<_Name, _Tp>::result_type _Rt;              \
1087      return _Expr<_Closure, _Rt>(_Closure(__t, __v));        	        \
1088    }
1089
1090_DEFINE_BINARY_OPERATOR(+, __plus)
1091_DEFINE_BINARY_OPERATOR(-, __minus)
1092_DEFINE_BINARY_OPERATOR(*, __multiplies)
1093_DEFINE_BINARY_OPERATOR(/, __divides)
1094_DEFINE_BINARY_OPERATOR(%, __modulus)
1095_DEFINE_BINARY_OPERATOR(^, __bitwise_xor)
1096_DEFINE_BINARY_OPERATOR(&, __bitwise_and)
1097_DEFINE_BINARY_OPERATOR(|, __bitwise_or)
1098_DEFINE_BINARY_OPERATOR(<<, __shift_left)
1099_DEFINE_BINARY_OPERATOR(>>, __shift_right)
1100_DEFINE_BINARY_OPERATOR(&&, __logical_and)
1101_DEFINE_BINARY_OPERATOR(||, __logical_or)
1102_DEFINE_BINARY_OPERATOR(==, __equal_to)
1103_DEFINE_BINARY_OPERATOR(!=, __not_equal_to)
1104_DEFINE_BINARY_OPERATOR(<, __less)
1105_DEFINE_BINARY_OPERATOR(>, __greater)
1106_DEFINE_BINARY_OPERATOR(<=, __less_equal)
1107_DEFINE_BINARY_OPERATOR(>=, __greater_equal)
1108
1109#undef _DEFINE_BINARY_OPERATOR
1110
1111  // @} group numeric_arrays
1112
1113_GLIBCXX_END_NAMESPACE
1114
1115#endif /* _GLIBCXX_VALARRAY */
1116