valarray_before.h

Go to the documentation of this file.
00001 // The template and inlines for the -*- C++ -*- internal _Meta class.
00002 
00003 // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
00004 //
00005 // This file is part of the GNU ISO C++ Library.  This library is free
00006 // software; you can redistribute it and/or modify it under the
00007 // terms of the GNU General Public License as published by the
00008 // Free Software Foundation; either version 2, or (at your option)
00009 // any later version.
00010 
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 
00016 // You should have received a copy of the GNU General Public License along
00017 // with this library; see the file COPYING.  If not, write to the Free
00018 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
00019 // USA.
00020 
00021 // As a special exception, you may use this file as part of a free software
00022 // library without restriction.  Specifically, if other files instantiate
00023 // templates or use macros or inline functions from this file, or you compile
00024 // this file and link it with other files to produce an executable, this
00025 // file does not by itself cause the resulting executable to be covered by
00026 // the GNU General Public License.  This exception does not however
00027 // invalidate any other reasons why the executable file might be covered by
00028 // the GNU General Public License.
00029 
00030 // Written by Gabriel Dos Reis <Gabriel.Dos-Reis@cmla.ens-cachan.fr>
00031 
00037 #ifndef _VALARRAY_BEFORE_H
00038 #define _VALARRAY_BEFORE_H 1
00039 
00040 #pragma GCC system_header
00041 
00042 #include <bits/slice_array.h>
00043 
00044 namespace std
00045 {
00046   //
00047   // Implementing a loosened valarray return value is tricky.
00048   // First we need to meet 26.3.1/3: we should not add more than
00049   // two levels of template nesting. Therefore we resort to template
00050   // template to "flatten" loosened return value types.
00051   // At some point we use partial specialization to remove one level
00052   // template nesting due to _Expr<>
00053   //
00054 
00055   // This class is NOT defined. It doesn't need to.
00056   template<typename _Tp1, typename _Tp2> class _Constant;
00057 
00058   // Implementations of unary functions applied to valarray<>s.
00059   // I use hard-coded object functions here instead of a generic
00060   // approach like pointers to function:
00061   //    1) correctness: some functions take references, others values.
00062   //       we can't deduce the correct type afterwards.
00063   //    2) efficiency -- object functions can be easily inlined
00064   //    3) be Koenig-lookup-friendly
00065 
00066   struct __abs
00067   {
00068     template<typename _Tp>
00069       _Tp operator()(const _Tp& __t) const { return abs(__t); }
00070   };
00071 
00072   struct __cos
00073   {
00074     template<typename _Tp>
00075       _Tp operator()(const _Tp& __t) const { return cos(__t); }
00076   };
00077 
00078   struct __acos
00079   {
00080     template<typename _Tp>
00081       _Tp operator()(const _Tp& __t) const { return acos(__t); }
00082   };
00083 
00084   struct __cosh
00085   {
00086     template<typename _Tp>
00087       _Tp operator()(const _Tp& __t) const { return cosh(__t); }
00088   };
00089 
00090   struct __sin
00091   {
00092     template<typename _Tp>
00093       _Tp operator()(const _Tp& __t) const { return sin(__t); }
00094   };
00095 
00096   struct __asin
00097   {
00098     template<typename _Tp>
00099       _Tp operator()(const _Tp& __t) const { return asin(__t); }
00100   };
00101 
00102   struct __sinh
00103   {
00104     template<typename _Tp>
00105       _Tp operator()(const _Tp& __t) const { return sinh(__t); }
00106   };
00107 
00108   struct __tan
00109   {
00110     template<typename _Tp>
00111       _Tp operator()(const _Tp& __t) const { return tan(__t); }
00112   };
00113 
00114   struct __atan
00115   {
00116     template<typename _Tp>
00117       _Tp operator()(const _Tp& __t) const { return atan(__t); }
00118   };
00119 
00120   struct __tanh
00121   {
00122     template<typename _Tp>
00123       _Tp operator()(const _Tp& __t) const { return tanh(__t); }
00124   };
00125 
00126   struct __exp
00127   {
00128     template<typename _Tp>
00129       _Tp operator()(const _Tp& __t) const { return exp(__t); }
00130   };
00131 
00132   struct __log
00133   {
00134     template<typename _Tp>
00135       _Tp operator()(const _Tp& __t) const { return log(__t); }
00136   };
00137 
00138   struct __log10
00139   {
00140     template<typename _Tp>
00141       _Tp operator()(const _Tp& __t) const { return log10(__t); }
00142   };
00143 
00144   struct __sqrt
00145   {
00146     template<typename _Tp>
00147       _Tp operator()(const _Tp& __t) const { return sqrt(__t); }
00148   };
00149 
00150   // In the past, we used to tailor operator applications semantics
00151   // to the specialization of standard function objects (i.e. plus<>, etc.)
00152   // That is incorrect.  Therefore we provide our own surrogates.
00153 
00154   struct __unary_plus
00155   {
00156     template<typename _Tp>
00157       _Tp operator()(const _Tp& __t) const { return +__t; }
00158   };
00159 
00160   struct __negate
00161   {
00162     template<typename _Tp>
00163       _Tp operator()(const _Tp& __t) const { return -__t; }
00164   };
00165 
00166   struct __bitwise_not
00167   {
00168     template<typename _Tp>
00169       _Tp operator()(const _Tp& __t) const { return ~__t; }
00170   };
00171 
00172   struct __plus
00173   {
00174     template<typename _Tp>
00175       _Tp operator()(const _Tp& __x, const _Tp& __y) const
00176       { return __x + __y; }
00177   };
00178 
00179   struct __minus
00180   {
00181     template<typename _Tp>
00182       _Tp operator()(const _Tp& __x, const _Tp& __y) const
00183       { return __x - __y; }
00184   };
00185 
00186   struct __multiplies
00187   {
00188     template<typename _Tp>
00189       _Tp operator()(const _Tp& __x, const _Tp& __y) const
00190       { return __x * __y; }
00191   };
00192 
00193   struct __divides
00194   {
00195     template<typename _Tp>
00196       _Tp operator()(const _Tp& __x, const _Tp& __y) const
00197       { return __x / __y; }
00198   };
00199 
00200   struct __modulus
00201   {
00202     template<typename _Tp>
00203       _Tp operator()(const _Tp& __x, const _Tp& __y) const
00204       { return __x % __y; }
00205   };
00206 
00207   struct __bitwise_xor
00208   {
00209     template<typename _Tp>
00210       _Tp operator()(const _Tp& __x, const _Tp& __y) const
00211       { return __x ^ __y; }
00212   };
00213 
00214   struct __bitwise_and
00215   {
00216     template<typename _Tp>
00217       _Tp operator()(const _Tp& __x, const _Tp& __y) const
00218       { return __x & __y; }
00219   };
00220 
00221   struct __bitwise_or
00222   {
00223     template<typename _Tp>
00224       _Tp operator()(const _Tp& __x, const _Tp& __y) const
00225       { return __x | __y; }
00226   };
00227 
00228   struct __shift_left
00229   {
00230     template<typename _Tp>
00231       _Tp operator()(const _Tp& __x, const _Tp& __y) const
00232       { return __x << __y; }
00233   };
00234 
00235   struct __shift_right
00236   {
00237     template<typename _Tp>
00238       _Tp operator()(const _Tp& __x, const _Tp& __y) const
00239       { return __x >> __y; }
00240   };
00241 
00242   struct __logical_and
00243   {
00244     template<typename _Tp>
00245       bool operator()(const _Tp& __x, const _Tp& __y) const
00246       { return __x && __y; }
00247   };
00248 
00249   struct __logical_or
00250   {
00251     template<typename _Tp>
00252       bool operator()(const _Tp& __x, const _Tp& __y) const
00253       { return __x || __y; }
00254   };
00255 
00256   struct __logical_not
00257   {
00258     template<typename _Tp>
00259       bool operator()(const _Tp& __x) const { return !__x; }
00260   };
00261 
00262   struct __equal_to
00263   {
00264     template<typename _Tp>
00265       bool operator()(const _Tp& __x, const _Tp& __y) const
00266       { return __x == __y; }
00267   };
00268 
00269   struct __not_equal_to
00270   {
00271     template<typename _Tp>
00272       bool operator()(const _Tp& __x, const _Tp& __y) const
00273       { return __x != __y; }
00274   };
00275 
00276   struct __less
00277   {
00278     template<typename _Tp>
00279       bool operator()(const _Tp& __x, const _Tp& __y) const
00280       { return __x < __y; }
00281   };
00282 
00283   struct __greater
00284   {
00285     template<typename _Tp>
00286       bool operator()(const _Tp& __x, const _Tp& __y) const
00287       { return __x > __y; }
00288   };
00289 
00290   struct __less_equal
00291   {
00292     template<typename _Tp>
00293       bool operator()(const _Tp& __x, const _Tp& __y) const
00294       { return __x <= __y; }
00295   };
00296 
00297   struct __greater_equal
00298   {
00299     template<typename _Tp>
00300       bool operator()(const _Tp& __x, const _Tp& __y) const
00301       { return __x >= __y; }
00302   };
00303 
00304   // The few binary functions we miss.
00305   struct __atan2
00306   {
00307     template<typename _Tp>
00308       _Tp operator()(const _Tp& __x, const _Tp& __y) const
00309       { return atan2(__x, __y); }
00310   };
00311 
00312   struct __pow
00313   {
00314     template<typename _Tp>
00315       _Tp operator()(const _Tp& __x, const _Tp& __y) const
00316       { return pow(__x, __y); }
00317   };
00318 
00319 
00320   // We need these bits in order to recover the return type of
00321   // some functions/operators now that we're no longer using
00322   // function templates.
00323   template<typename, typename _Tp>
00324     struct __fun
00325     {
00326       typedef _Tp result_type;
00327     };
00328 
00329   // several specializations for relational operators.
00330   template<typename _Tp>
00331     struct __fun<__logical_not, _Tp>
00332     {
00333       typedef bool result_type;
00334     };
00335 
00336   template<typename _Tp>
00337     struct __fun<__logical_and, _Tp>
00338     {
00339       typedef bool result_type;
00340     };
00341 
00342   template<typename _Tp>
00343     struct __fun<__logical_or, _Tp>
00344     {
00345       typedef bool result_type;
00346     };
00347 
00348   template<typename _Tp>
00349     struct __fun<__less, _Tp>
00350     {
00351       typedef bool result_type;
00352     };
00353 
00354   template<typename _Tp>
00355     struct __fun<__greater, _Tp>
00356     {
00357       typedef bool result_type;
00358     };
00359 
00360   template<typename _Tp>
00361     struct __fun<__less_equal, _Tp>
00362     {
00363       typedef bool result_type;
00364     };
00365 
00366   template<typename _Tp>
00367     struct __fun<__greater_equal, _Tp>
00368     {
00369       typedef bool result_type;
00370     };
00371 
00372   template<typename _Tp>
00373     struct __fun<__equal_to, _Tp>
00374     {
00375       typedef bool result_type;
00376     };
00377 
00378   template<typename _Tp>
00379     struct __fun<__not_equal_to, _Tp>
00380     {
00381       typedef bool result_type;
00382     };
00383 
00384     //
00385     // Apply function taking a value/const reference closure
00386     //
00387 
00388   template<typename _Dom, typename _Arg>
00389     class _FunBase
00390     {
00391     public:
00392       typedef typename _Dom::value_type value_type;
00393 
00394       _FunBase(const _Dom& __e, value_type __f(_Arg))
00395     : _M_expr(__e), _M_func(__f) {}
00396 
00397       value_type operator[](size_t __i) const
00398       { return _M_func (_M_expr[__i]); }
00399 
00400       size_t size() const { return _M_expr.size ();}
00401 
00402     private:
00403         const _Dom& _M_expr;
00404         value_type (*_M_func)(_Arg);
00405     };
00406 
00407   template<class _Dom>
00408     struct _ValFunClos<_Expr,_Dom> : _FunBase<_Dom, typename _Dom::value_type>
00409     {
00410       typedef _FunBase<_Dom, typename _Dom::value_type> _Base;
00411       typedef typename _Base::value_type value_type;
00412       typedef value_type _Tp;
00413 
00414       _ValFunClos(const _Dom& __e, _Tp __f(_Tp)) : _Base(__e, __f) {}
00415     };
00416 
00417   template<typename _Tp>
00418     struct _ValFunClos<_ValArray,_Tp> : _FunBase<valarray<_Tp>, _Tp>
00419     {
00420       typedef _FunBase<valarray<_Tp>, _Tp> _Base;
00421       typedef _Tp value_type;
00422 
00423       _ValFunClos(const valarray<_Tp>& __v, _Tp __f(_Tp)) : _Base(__v, __f) {}
00424     };
00425 
00426   template<class _Dom>
00427     struct _RefFunClos<_Expr,_Dom> :
00428         _FunBase<_Dom, const typename _Dom::value_type&>
00429     {
00430       typedef _FunBase<_Dom, const typename _Dom::value_type&> _Base;
00431       typedef typename _Base::value_type value_type;
00432       typedef value_type _Tp;
00433 
00434       _RefFunClos(const _Dom& __e, _Tp __f(const _Tp&))
00435     : _Base(__e, __f) {}
00436     };
00437 
00438   template<typename _Tp>
00439     struct _RefFunClos<_ValArray,_Tp> : _FunBase<valarray<_Tp>, const _Tp&>
00440     {
00441       typedef _FunBase<valarray<_Tp>, const _Tp&> _Base;
00442       typedef _Tp value_type;
00443 
00444       _RefFunClos(const valarray<_Tp>& __v, _Tp __f(const _Tp&))
00445     : _Base(__v, __f) {}
00446     };
00447 
00448   //
00449   // Unary expression closure.
00450   //
00451 
00452   template<class _Oper, class _Arg>
00453     class _UnBase
00454     {
00455     public:
00456       typedef typename _Arg::value_type _Vt;
00457       typedef typename __fun<_Oper, _Vt>::result_type value_type;
00458 
00459       _UnBase(const _Arg& __e) : _M_expr(__e) {}
00460 
00461       value_type operator[](size_t __i) const
00462       { return _Oper()(_M_expr[__i]); }
00463 
00464       size_t size() const { return _M_expr.size(); }
00465 
00466     private:
00467       const _Arg& _M_expr;
00468     };
00469 
00470   template<class _Oper, class _Dom>
00471     struct _UnClos<_Oper, _Expr, _Dom> :  _UnBase<_Oper, _Dom>
00472     {
00473       typedef _Dom _Arg;
00474       typedef _UnBase<_Oper, _Dom> _Base;
00475       typedef typename _Base::value_type value_type;
00476 
00477       _UnClos(const _Arg& __e) : _Base(__e) {}
00478     };
00479 
00480   template<class _Oper, typename _Tp>
00481     struct _UnClos<_Oper, _ValArray, _Tp> : _UnBase<_Oper, valarray<_Tp> >
00482     {
00483       typedef valarray<_Tp> _Arg;
00484       typedef _UnBase<_Oper, valarray<_Tp> > _Base;
00485       typedef typename _Base::value_type value_type;
00486 
00487       _UnClos(const _Arg& __e) : _Base(__e) {}
00488     };
00489 
00490 
00491   //
00492   // Binary expression closure.
00493   //
00494 
00495   template<class _Oper, class _FirstArg, class _SecondArg>
00496     class _BinBase
00497     {
00498     public:
00499         typedef typename _FirstArg::value_type _Vt;
00500         typedef typename __fun<_Oper, _Vt>::result_type value_type;
00501 
00502       _BinBase(const _FirstArg& __e1, const _SecondArg& __e2)
00503     : _M_expr1(__e1), _M_expr2(__e2) {}
00504 
00505       value_type operator[](size_t __i) const
00506       { return _Oper()(_M_expr1[__i], _M_expr2[__i]); }
00507 
00508       size_t size() const { return _M_expr1.size(); }
00509 
00510     private:
00511       const _FirstArg& _M_expr1;
00512       const _SecondArg& _M_expr2;
00513     };
00514 
00515 
00516   template<class _Oper, class _Clos>
00517     class _BinBase2
00518     {
00519     public:
00520       typedef typename _Clos::value_type _Vt;
00521       typedef typename __fun<_Oper, _Vt>::result_type value_type;
00522 
00523       _BinBase2(const _Clos& __e, const _Vt& __t)
00524     : _M_expr1(__e), _M_expr2(__t) {}
00525 
00526       value_type operator[](size_t __i) const
00527       { return _Oper()(_M_expr1[__i], _M_expr2); }
00528 
00529       size_t size() const { return _M_expr1.size(); }
00530 
00531     private:
00532       const _Clos& _M_expr1;
00533       const _Vt& _M_expr2;
00534     };
00535 
00536   template<class _Oper, class _Clos>
00537     class _BinBase1
00538     {
00539     public:
00540       typedef typename _Clos::value_type _Vt;
00541       typedef typename __fun<_Oper, _Vt>::result_type value_type;
00542 
00543       _BinBase1(const _Vt& __t, const _Clos& __e)
00544     : _M_expr1(__t), _M_expr2(__e) {}
00545 
00546       value_type operator[](size_t __i) const
00547       { return _Oper()(_M_expr1, _M_expr2[__i]); }
00548 
00549       size_t size() const { return _M_expr2.size(); }
00550 
00551     private:
00552       const _Vt& _M_expr1;
00553       const _Clos& _M_expr2;
00554     };
00555 
00556   template<class _Oper, class _Dom1, class _Dom2>
00557     struct _BinClos<_Oper, _Expr, _Expr, _Dom1, _Dom2>
00558         : _BinBase<_Oper,_Dom1,_Dom2>
00559     {
00560       typedef _BinBase<_Oper,_Dom1,_Dom2> _Base;
00561       typedef typename _Base::value_type value_type;
00562 
00563       _BinClos(const _Dom1& __e1, const _Dom2& __e2) : _Base(__e1, __e2) {}
00564     };
00565 
00566   template<class _Oper, typename _Tp>
00567     struct _BinClos<_Oper,_ValArray,_ValArray,_Tp,_Tp>
00568       : _BinBase<_Oper,valarray<_Tp>,valarray<_Tp> >
00569     {
00570       typedef _BinBase<_Oper,valarray<_Tp>,valarray<_Tp> > _Base;
00571       typedef _Tp value_type;
00572 
00573       _BinClos(const valarray<_Tp>& __v, const valarray<_Tp>& __w)
00574     : _Base(__v, __w) {}
00575     };
00576 
00577   template<class _Oper, class _Dom>
00578     struct _BinClos<_Oper,_Expr,_ValArray,_Dom,typename _Dom::value_type>
00579       : _BinBase<_Oper,_Dom,valarray<typename _Dom::value_type> >
00580     {
00581       typedef typename _Dom::value_type _Tp;
00582       typedef _BinBase<_Oper,_Dom,valarray<_Tp> > _Base;
00583       typedef typename _Base::value_type value_type;
00584 
00585       _BinClos(const _Dom& __e1, const valarray<_Tp>& __e2)
00586     : _Base(__e1, __e2) {}
00587     };
00588 
00589   template<class _Oper, class _Dom>
00590     struct  _BinClos<_Oper,_ValArray,_Expr,typename _Dom::value_type,_Dom>
00591       : _BinBase<_Oper,valarray<typename _Dom::value_type>,_Dom>
00592     {
00593       typedef typename _Dom::value_type _Tp;
00594       typedef _BinBase<_Oper,valarray<_Tp>,_Dom> _Base;
00595       typedef typename _Base::value_type value_type;
00596 
00597       _BinClos(const valarray<_Tp>& __e1, const _Dom& __e2)
00598     : _Base(__e1, __e2) {}
00599     };
00600 
00601   template<class _Oper, class _Dom>
00602     struct _BinClos<_Oper,_Expr,_Constant,_Dom,typename _Dom::value_type>
00603       : _BinBase2<_Oper,_Dom>
00604     {
00605       typedef typename _Dom::value_type _Tp;
00606       typedef _BinBase2<_Oper,_Dom> _Base;
00607       typedef typename _Base::value_type value_type;
00608 
00609       _BinClos(const _Dom& __e1, const _Tp& __e2) : _Base(__e1, __e2) {}
00610     };
00611 
00612   template<class _Oper, class _Dom>
00613     struct _BinClos<_Oper,_Constant,_Expr,typename _Dom::value_type,_Dom>
00614       : _BinBase1<_Oper,_Dom>
00615     {
00616       typedef typename _Dom::value_type _Tp;
00617       typedef _BinBase1<_Oper,_Dom> _Base;
00618       typedef typename _Base::value_type value_type;
00619 
00620       _BinClos(const _Tp& __e1, const _Dom& __e2) : _Base(__e1, __e2) {}
00621     };
00622 
00623   template<class _Oper, typename _Tp>
00624     struct _BinClos<_Oper,_ValArray,_Constant,_Tp,_Tp>
00625       : _BinBase2<_Oper,valarray<_Tp> >
00626     {
00627       typedef _BinBase2<_Oper,valarray<_Tp> > _Base;
00628       typedef typename _Base::value_type value_type;
00629 
00630       _BinClos(const valarray<_Tp>& __v, const _Tp& __t) : _Base(__v, __t) {}
00631     };
00632 
00633   template<class _Oper, typename _Tp>
00634     struct _BinClos<_Oper,_Constant,_ValArray,_Tp,_Tp>
00635       : _BinBase1<_Oper,valarray<_Tp> >
00636     {
00637       typedef _BinBase1<_Oper,valarray<_Tp> > _Base;
00638       typedef typename _Base::value_type value_type;
00639 
00640       _BinClos(const _Tp& __t, const valarray<_Tp>& __v) : _Base(__t, __v) {}
00641     };
00642 
00643 
00644     //
00645     // slice_array closure.
00646     //
00647     template<typename _Dom>  class _SBase {
00648     public:
00649         typedef typename _Dom::value_type value_type;
00650 
00651         _SBase (const _Dom& __e, const slice& __s)
00652                 : _M_expr (__e), _M_slice (__s) {}
00653         value_type operator[] (size_t __i) const
00654         { return _M_expr[_M_slice.start () + __i * _M_slice.stride ()]; }
00655         size_t size() const { return _M_slice.size (); }
00656 
00657     private:
00658         const _Dom& _M_expr;
00659         const slice& _M_slice;
00660     };
00661 
00662     template<typename _Tp> class _SBase<_Array<_Tp> > {
00663     public:
00664         typedef _Tp value_type;
00665 
00666         _SBase (_Array<_Tp> __a, const slice& __s)
00667                 : _M_array (__a._M_data+__s.start()), _M_size (__s.size()),
00668                   _M_stride (__s.stride()) {}
00669         value_type operator[] (size_t __i) const
00670         { return _M_array._M_data[__i * _M_stride]; }
00671         size_t size() const { return _M_size; }
00672 
00673     private:
00674         const _Array<_Tp> _M_array;
00675         const size_t _M_size;
00676         const size_t _M_stride;
00677     };
00678 
00679     template<class _Dom> struct  _SClos<_Expr,_Dom> : _SBase<_Dom> {
00680         typedef _SBase<_Dom> _Base;
00681         typedef typename _Base::value_type value_type;
00682 
00683         _SClos (const _Dom& __e, const slice& __s) : _Base (__e, __s) {}
00684     };
00685 
00686     template<typename _Tp>
00687     struct _SClos<_ValArray,_Tp> : _SBase<_Array<_Tp> > {
00688         typedef  _SBase<_Array<_Tp> > _Base;
00689         typedef _Tp value_type;
00690 
00691         _SClos (_Array<_Tp> __a, const slice& __s) : _Base (__a, __s) {}
00692     };
00693 
00694 } // std::
00695 
00696 
00697 #endif /* _CPP_VALARRAY_BEFORE_H */
00698 
00699 // Local Variables:
00700 // mode:c++
00701 // End:

Generated on Tue Jan 30 17:31:56 2007 for GNU C++ STL by doxygen 1.3.6