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