1 // The template and inlines for the -*- C++ -*- internal _Meta class. 2 3 // Copyright (C) 1997-2018 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_before.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@cmla.ens-cachan.fr> 31 32 #ifndef _VALARRAY_BEFORE_H 33 #define _VALARRAY_BEFORE_H 1 34 35 #pragma GCC system_header 36 37 #include <bits/slice_array.h> 38 39 namespace std _GLIBCXX_VISIBILITY(default) 40 { 41 _GLIBCXX_BEGIN_NAMESPACE_VERSION 42 43 // 44 // Implementing a loosened valarray return value is tricky. 45 // First we need to meet 26.3.1/3: we should not add more than 46 // two levels of template nesting. Therefore we resort to template 47 // template to "flatten" loosened return value types. 48 // At some point we use partial specialization to remove one level 49 // template nesting due to _Expr<> 50 // 51 52 // This class is NOT defined. It doesn't need to. 53 template<typename _Tp1, typename _Tp2> class _Constant; 54 55 // Implementations of unary functions applied to valarray<>s. 56 // I use hard-coded object functions here instead of a generic 57 // approach like pointers to function: 58 // 1) correctness: some functions take references, others values. 59 // we can't deduce the correct type afterwards. 60 // 2) efficiency -- object functions can be easily inlined 61 // 3) be Koenig-lookup-friendly 62 63 struct _Abs 64 { 65 template<typename _Tp> 66 _Tp operator()(const _Tp& __t) const 67 { return abs(__t); } 68 }; 69 70 struct _Cos 71 { 72 template<typename _Tp> 73 _Tp operator()(const _Tp& __t) const 74 { return cos(__t); } 75 }; 76 77 struct _Acos 78 { 79 template<typename _Tp> 80 _Tp operator()(const _Tp& __t) const 81 { return acos(__t); } 82 }; 83 84 struct _Cosh 85 { 86 template<typename _Tp> 87 _Tp operator()(const _Tp& __t) const 88 { return cosh(__t); } 89 }; 90 91 struct _Sin 92 { 93 template<typename _Tp> 94 _Tp operator()(const _Tp& __t) const 95 { return sin(__t); } 96 }; 97 98 struct _Asin 99 { 100 template<typename _Tp> 101 _Tp operator()(const _Tp& __t) const 102 { return asin(__t); } 103 }; 104 105 struct _Sinh 106 { 107 template<typename _Tp> 108 _Tp operator()(const _Tp& __t) const 109 { return sinh(__t); } 110 }; 111 112 struct _Tan 113 { 114 template<typename _Tp> 115 _Tp operator()(const _Tp& __t) const 116 { return tan(__t); } 117 }; 118 119 struct _Atan 120 { 121 template<typename _Tp> 122 _Tp operator()(const _Tp& __t) const 123 { return atan(__t); } 124 }; 125 126 struct _Tanh 127 { 128 template<typename _Tp> 129 _Tp operator()(const _Tp& __t) const 130 { return tanh(__t); } 131 }; 132 133 struct _Exp 134 { 135 template<typename _Tp> 136 _Tp operator()(const _Tp& __t) const 137 { return exp(__t); } 138 }; 139 140 struct _Log 141 { 142 template<typename _Tp> 143 _Tp operator()(const _Tp& __t) const 144 { return log(__t); } 145 }; 146 147 struct _Log10 148 { 149 template<typename _Tp> 150 _Tp operator()(const _Tp& __t) const 151 { return log10(__t); } 152 }; 153 154 struct _Sqrt 155 { 156 template<typename _Tp> 157 _Tp operator()(const _Tp& __t) const 158 { return sqrt(__t); } 159 }; 160 161 // In the past, we used to tailor operator applications semantics 162 // to the specialization of standard function objects (i.e. plus<>, etc.) 163 // That is incorrect. Therefore we provide our own surrogates. 164 165 struct __unary_plus 166 { 167 template<typename _Tp> 168 _Tp operator()(const _Tp& __t) const 169 { return +__t; } 170 }; 171 172 struct __negate 173 { 174 template<typename _Tp> 175 _Tp operator()(const _Tp& __t) const 176 { return -__t; } 177 }; 178 179 struct __bitwise_not 180 { 181 template<typename _Tp> 182 _Tp operator()(const _Tp& __t) const 183 { return ~__t; } 184 }; 185 186 struct __plus 187 { 188 template<typename _Tp> 189 _Tp operator()(const _Tp& __x, const _Tp& __y) const 190 { return __x + __y; } 191 }; 192 193 struct __minus 194 { 195 template<typename _Tp> 196 _Tp operator()(const _Tp& __x, const _Tp& __y) const 197 { return __x - __y; } 198 }; 199 200 struct __multiplies 201 { 202 template<typename _Tp> 203 _Tp operator()(const _Tp& __x, const _Tp& __y) const 204 { return __x * __y; } 205 }; 206 207 struct __divides 208 { 209 template<typename _Tp> 210 _Tp operator()(const _Tp& __x, const _Tp& __y) const 211 { return __x / __y; } 212 }; 213 214 struct __modulus 215 { 216 template<typename _Tp> 217 _Tp operator()(const _Tp& __x, const _Tp& __y) const 218 { return __x % __y; } 219 }; 220 221 struct __bitwise_xor 222 { 223 template<typename _Tp> 224 _Tp operator()(const _Tp& __x, const _Tp& __y) const 225 { return __x ^ __y; } 226 }; 227 228 struct __bitwise_and 229 { 230 template<typename _Tp> 231 _Tp operator()(const _Tp& __x, const _Tp& __y) const 232 { return __x & __y; } 233 }; 234 235 struct __bitwise_or 236 { 237 template<typename _Tp> 238 _Tp operator()(const _Tp& __x, const _Tp& __y) const 239 { return __x | __y; } 240 }; 241 242 struct __shift_left 243 { 244 template<typename _Tp> 245 _Tp operator()(const _Tp& __x, const _Tp& __y) const 246 { return __x << __y; } 247 }; 248 249 struct __shift_right 250 { 251 template<typename _Tp> 252 _Tp operator()(const _Tp& __x, const _Tp& __y) const 253 { return __x >> __y; } 254 }; 255 256 struct __logical_and 257 { 258 template<typename _Tp> 259 bool operator()(const _Tp& __x, const _Tp& __y) const 260 { return __x && __y; } 261 }; 262 263 struct __logical_or 264 { 265 template<typename _Tp> 266 bool operator()(const _Tp& __x, const _Tp& __y) const 267 { return __x || __y; } 268 }; 269 270 struct __logical_not 271 { 272 template<typename _Tp> 273 bool operator()(const _Tp& __x) const 274 { return !__x; } 275 }; 276 277 struct __equal_to 278 { 279 template<typename _Tp> 280 bool operator()(const _Tp& __x, const _Tp& __y) const 281 { return __x == __y; } 282 }; 283 284 struct __not_equal_to 285 { 286 template<typename _Tp> 287 bool operator()(const _Tp& __x, const _Tp& __y) const 288 { return __x != __y; } 289 }; 290 291 struct __less 292 { 293 template<typename _Tp> 294 bool operator()(const _Tp& __x, const _Tp& __y) const 295 { return __x < __y; } 296 }; 297 298 struct __greater 299 { 300 template<typename _Tp> 301 bool operator()(const _Tp& __x, const _Tp& __y) const 302 { return __x > __y; } 303 }; 304 305 struct __less_equal 306 { 307 template<typename _Tp> 308 bool operator()(const _Tp& __x, const _Tp& __y) const 309 { return __x <= __y; } 310 }; 311 312 struct __greater_equal 313 { 314 template<typename _Tp> 315 bool operator()(const _Tp& __x, const _Tp& __y) const 316 { return __x >= __y; } 317 }; 318 319 // The few binary functions we miss. 320 struct _Atan2 321 { 322 template<typename _Tp> 323 _Tp operator()(const _Tp& __x, const _Tp& __y) const 324 { return atan2(__x, __y); } 325 }; 326 327 struct _Pow 328 { 329 template<typename _Tp> 330 _Tp operator()(const _Tp& __x, const _Tp& __y) const 331 { return pow(__x, __y); } 332 }; 333 334 template<typename _Tp, bool _IsValidValarrayValue = !__is_abstract(_Tp)> 335 struct __fun_with_valarray 336 { 337 typedef _Tp result_type; 338 }; 339 340 template<typename _Tp> 341 struct __fun_with_valarray<_Tp, false> 342 { 343 // No result type defined for invalid value types. 344 }; 345 346 // We need these bits in order to recover the return type of 347 // some functions/operators now that we're no longer using 348 // function templates. 349 template<typename, typename _Tp> 350 struct __fun : __fun_with_valarray<_Tp> 351 { 352 }; 353 354 // several specializations for relational operators. 355 template<typename _Tp> 356 struct __fun<__logical_not, _Tp> 357 { 358 typedef bool result_type; 359 }; 360 361 template<typename _Tp> 362 struct __fun<__logical_and, _Tp> 363 { 364 typedef bool result_type; 365 }; 366 367 template<typename _Tp> 368 struct __fun<__logical_or, _Tp> 369 { 370 typedef bool result_type; 371 }; 372 373 template<typename _Tp> 374 struct __fun<__less, _Tp> 375 { 376 typedef bool result_type; 377 }; 378 379 template<typename _Tp> 380 struct __fun<__greater, _Tp> 381 { 382 typedef bool result_type; 383 }; 384 385 template<typename _Tp> 386 struct __fun<__less_equal, _Tp> 387 { 388 typedef bool result_type; 389 }; 390 391 template<typename _Tp> 392 struct __fun<__greater_equal, _Tp> 393 { 394 typedef bool result_type; 395 }; 396 397 template<typename _Tp> 398 struct __fun<__equal_to, _Tp> 399 { 400 typedef bool result_type; 401 }; 402 403 template<typename _Tp> 404 struct __fun<__not_equal_to, _Tp> 405 { 406 typedef bool result_type; 407 }; 408 409 // 410 // Apply function taking a value/const reference closure 411 // 412 413 template<typename _Dom, typename _Arg> 414 class _FunBase 415 { 416 public: 417 typedef typename _Dom::value_type value_type; 418 419 _FunBase(const _Dom& __e, value_type __f(_Arg)) 420 : _M_expr(__e), _M_func(__f) {} 421 422 value_type operator[](size_t __i) const 423 { return _M_func (_M_expr[__i]); } 424 425 size_t size() const { return _M_expr.size ();} 426 427 private: 428 const _Dom& _M_expr; 429 value_type (*_M_func)(_Arg); 430 }; 431 432 template<class _Dom> 433 struct _ValFunClos<_Expr,_Dom> : _FunBase<_Dom, typename _Dom::value_type> 434 { 435 typedef _FunBase<_Dom, typename _Dom::value_type> _Base; 436 typedef typename _Base::value_type value_type; 437 typedef value_type _Tp; 438 439 _ValFunClos(const _Dom& __e, _Tp __f(_Tp)) : _Base(__e, __f) {} 440 }; 441 442 template<typename _Tp> 443 struct _ValFunClos<_ValArray,_Tp> : _FunBase<valarray<_Tp>, _Tp> 444 { 445 typedef _FunBase<valarray<_Tp>, _Tp> _Base; 446 typedef _Tp value_type; 447 448 _ValFunClos(const valarray<_Tp>& __v, _Tp __f(_Tp)) : _Base(__v, __f) {} 449 }; 450 451 template<class _Dom> 452 struct _RefFunClos<_Expr, _Dom> 453 : _FunBase<_Dom, const typename _Dom::value_type&> 454 { 455 typedef _FunBase<_Dom, const typename _Dom::value_type&> _Base; 456 typedef typename _Base::value_type value_type; 457 typedef value_type _Tp; 458 459 _RefFunClos(const _Dom& __e, _Tp __f(const _Tp&)) 460 : _Base(__e, __f) {} 461 }; 462 463 template<typename _Tp> 464 struct _RefFunClos<_ValArray, _Tp> 465 : _FunBase<valarray<_Tp>, const _Tp&> 466 { 467 typedef _FunBase<valarray<_Tp>, const _Tp&> _Base; 468 typedef _Tp value_type; 469 470 _RefFunClos(const valarray<_Tp>& __v, _Tp __f(const _Tp&)) 471 : _Base(__v, __f) {} 472 }; 473 474 // 475 // Unary expression closure. 476 // 477 478 template<class _Oper, class _Arg> 479 class _UnBase 480 { 481 public: 482 typedef typename _Arg::value_type _Vt; 483 typedef typename __fun<_Oper, _Vt>::result_type value_type; 484 485 _UnBase(const _Arg& __e) : _M_expr(__e) {} 486 487 value_type operator[](size_t __i) const 488 { return _Oper()(_M_expr[__i]); } 489 490 size_t size() const { return _M_expr.size(); } 491 492 private: 493 const _Arg& _M_expr; 494 }; 495 496 template<class _Oper, class _Dom> 497 struct _UnClos<_Oper, _Expr, _Dom> 498 : _UnBase<_Oper, _Dom> 499 { 500 typedef _Dom _Arg; 501 typedef _UnBase<_Oper, _Dom> _Base; 502 typedef typename _Base::value_type value_type; 503 504 _UnClos(const _Arg& __e) : _Base(__e) {} 505 }; 506 507 template<class _Oper, typename _Tp> 508 struct _UnClos<_Oper, _ValArray, _Tp> 509 : _UnBase<_Oper, valarray<_Tp> > 510 { 511 typedef valarray<_Tp> _Arg; 512 typedef _UnBase<_Oper, valarray<_Tp> > _Base; 513 typedef typename _Base::value_type value_type; 514 515 _UnClos(const _Arg& __e) : _Base(__e) {} 516 }; 517 518 519 // 520 // Binary expression closure. 521 // 522 523 template<class _Oper, class _FirstArg, class _SecondArg> 524 class _BinBase 525 { 526 public: 527 typedef typename _FirstArg::value_type _Vt; 528 typedef typename __fun<_Oper, _Vt>::result_type value_type; 529 530 _BinBase(const _FirstArg& __e1, const _SecondArg& __e2) 531 : _M_expr1(__e1), _M_expr2(__e2) {} 532 533 value_type operator[](size_t __i) const 534 { return _Oper()(_M_expr1[__i], _M_expr2[__i]); } 535 536 size_t size() const { return _M_expr1.size(); } 537 538 private: 539 const _FirstArg& _M_expr1; 540 const _SecondArg& _M_expr2; 541 }; 542 543 544 template<class _Oper, class _Clos> 545 class _BinBase2 546 { 547 public: 548 typedef typename _Clos::value_type _Vt; 549 typedef typename __fun<_Oper, _Vt>::result_type value_type; 550 551 _BinBase2(const _Clos& __e, const _Vt& __t) 552 : _M_expr1(__e), _M_expr2(__t) {} 553 554 value_type operator[](size_t __i) const 555 { return _Oper()(_M_expr1[__i], _M_expr2); } 556 557 size_t size() const { return _M_expr1.size(); } 558 559 private: 560 const _Clos& _M_expr1; 561 const _Vt& _M_expr2; 562 }; 563 564 template<class _Oper, class _Clos> 565 class _BinBase1 566 { 567 public: 568 typedef typename _Clos::value_type _Vt; 569 typedef typename __fun<_Oper, _Vt>::result_type value_type; 570 571 _BinBase1(const _Vt& __t, const _Clos& __e) 572 : _M_expr1(__t), _M_expr2(__e) {} 573 574 value_type operator[](size_t __i) const 575 { return _Oper()(_M_expr1, _M_expr2[__i]); } 576 577 size_t size() const { return _M_expr2.size(); } 578 579 private: 580 const _Vt& _M_expr1; 581 const _Clos& _M_expr2; 582 }; 583 584 template<class _Oper, class _Dom1, class _Dom2> 585 struct _BinClos<_Oper, _Expr, _Expr, _Dom1, _Dom2> 586 : _BinBase<_Oper, _Dom1, _Dom2> 587 { 588 typedef _BinBase<_Oper, _Dom1, _Dom2> _Base; 589 typedef typename _Base::value_type value_type; 590 591 _BinClos(const _Dom1& __e1, const _Dom2& __e2) : _Base(__e1, __e2) {} 592 }; 593 594 template<class _Oper, typename _Tp> 595 struct _BinClos<_Oper,_ValArray, _ValArray, _Tp, _Tp> 596 : _BinBase<_Oper, valarray<_Tp>, valarray<_Tp> > 597 { 598 typedef _BinBase<_Oper, valarray<_Tp>, valarray<_Tp> > _Base; 599 typedef typename _Base::value_type value_type; 600 601 _BinClos(const valarray<_Tp>& __v, const valarray<_Tp>& __w) 602 : _Base(__v, __w) {} 603 }; 604 605 template<class _Oper, class _Dom> 606 struct _BinClos<_Oper, _Expr, _ValArray, _Dom, typename _Dom::value_type> 607 : _BinBase<_Oper, _Dom, valarray<typename _Dom::value_type> > 608 { 609 typedef typename _Dom::value_type _Tp; 610 typedef _BinBase<_Oper,_Dom,valarray<_Tp> > _Base; 611 typedef typename _Base::value_type value_type; 612 613 _BinClos(const _Dom& __e1, const valarray<_Tp>& __e2) 614 : _Base(__e1, __e2) {} 615 }; 616 617 template<class _Oper, class _Dom> 618 struct _BinClos<_Oper, _ValArray, _Expr, typename _Dom::value_type, _Dom> 619 : _BinBase<_Oper, valarray<typename _Dom::value_type>,_Dom> 620 { 621 typedef typename _Dom::value_type _Tp; 622 typedef _BinBase<_Oper, valarray<_Tp>, _Dom> _Base; 623 typedef typename _Base::value_type value_type; 624 625 _BinClos(const valarray<_Tp>& __e1, const _Dom& __e2) 626 : _Base(__e1, __e2) {} 627 }; 628 629 template<class _Oper, class _Dom> 630 struct _BinClos<_Oper, _Expr, _Constant, _Dom, typename _Dom::value_type> 631 : _BinBase2<_Oper, _Dom> 632 { 633 typedef typename _Dom::value_type _Tp; 634 typedef _BinBase2<_Oper,_Dom> _Base; 635 typedef typename _Base::value_type value_type; 636 637 _BinClos(const _Dom& __e1, const _Tp& __e2) : _Base(__e1, __e2) {} 638 }; 639 640 template<class _Oper, class _Dom> 641 struct _BinClos<_Oper, _Constant, _Expr, typename _Dom::value_type, _Dom> 642 : _BinBase1<_Oper, _Dom> 643 { 644 typedef typename _Dom::value_type _Tp; 645 typedef _BinBase1<_Oper, _Dom> _Base; 646 typedef typename _Base::value_type value_type; 647 648 _BinClos(const _Tp& __e1, const _Dom& __e2) : _Base(__e1, __e2) {} 649 }; 650 651 template<class _Oper, typename _Tp> 652 struct _BinClos<_Oper, _ValArray, _Constant, _Tp, _Tp> 653 : _BinBase2<_Oper, valarray<_Tp> > 654 { 655 typedef _BinBase2<_Oper,valarray<_Tp> > _Base; 656 typedef typename _Base::value_type value_type; 657 658 _BinClos(const valarray<_Tp>& __v, const _Tp& __t) : _Base(__v, __t) {} 659 }; 660 661 template<class _Oper, typename _Tp> 662 struct _BinClos<_Oper, _Constant, _ValArray, _Tp, _Tp> 663 : _BinBase1<_Oper, valarray<_Tp> > 664 { 665 typedef _BinBase1<_Oper, valarray<_Tp> > _Base; 666 typedef typename _Base::value_type value_type; 667 668 _BinClos(const _Tp& __t, const valarray<_Tp>& __v) : _Base(__t, __v) {} 669 }; 670 671 // 672 // slice_array closure. 673 // 674 template<typename _Dom> 675 class _SBase 676 { 677 public: 678 typedef typename _Dom::value_type value_type; 679 680 _SBase (const _Dom& __e, const slice& __s) 681 : _M_expr (__e), _M_slice (__s) {} 682 683 value_type 684 operator[] (size_t __i) const 685 { return _M_expr[_M_slice.start () + __i * _M_slice.stride ()]; } 686 687 size_t 688 size() const 689 { return _M_slice.size (); } 690 691 private: 692 const _Dom& _M_expr; 693 const slice& _M_slice; 694 }; 695 696 template<typename _Tp> 697 class _SBase<_Array<_Tp> > 698 { 699 public: 700 typedef _Tp value_type; 701 702 _SBase (_Array<_Tp> __a, const slice& __s) 703 : _M_array (__a._M_data+__s.start()), _M_size (__s.size()), 704 _M_stride (__s.stride()) {} 705 706 value_type 707 operator[] (size_t __i) const 708 { return _M_array._M_data[__i * _M_stride]; } 709 710 size_t 711 size() const 712 { return _M_size; } 713 714 private: 715 const _Array<_Tp> _M_array; 716 const size_t _M_size; 717 const size_t _M_stride; 718 }; 719 720 template<class _Dom> 721 struct _SClos<_Expr, _Dom> 722 : _SBase<_Dom> 723 { 724 typedef _SBase<_Dom> _Base; 725 typedef typename _Base::value_type value_type; 726 727 _SClos (const _Dom& __e, const slice& __s) : _Base (__e, __s) {} 728 }; 729 730 template<typename _Tp> 731 struct _SClos<_ValArray, _Tp> 732 : _SBase<_Array<_Tp> > 733 { 734 typedef _SBase<_Array<_Tp> > _Base; 735 typedef _Tp value_type; 736 737 _SClos (_Array<_Tp> __a, const slice& __s) : _Base (__a, __s) {} 738 }; 739 740 _GLIBCXX_END_NAMESPACE_VERSION 741 } // namespace 742 743 #endif /* _CPP_VALARRAY_BEFORE_H */ 744