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