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