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