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