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