Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:28:19

0001 ///////////////////////////////////////////////////////////////////////////////
0002 /// \file valarray.hpp
0003 ///
0004 //  Copyright 2005 Eric Niebler. Distributed under the Boost
0005 //  Software License, Version 1.0. (See accompanying file
0006 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0007 
0008 #ifndef BOOST_NUMERIC_FUNCTIONAL_VALARRAY_HPP_EAN_12_12_2005
0009 #define BOOST_NUMERIC_FUNCTIONAL_VALARRAY_HPP_EAN_12_12_2005
0010 
0011 #ifdef BOOST_NUMERIC_FUNCTIONAL_HPP_INCLUDED
0012 # error Include this file before boost/accumulators/numeric/functional.hpp
0013 #endif
0014 
0015 #include <valarray>
0016 #include <functional>
0017 #include <boost/assert.hpp>
0018 #include <boost/mpl/and.hpp>
0019 #include <boost/mpl/not.hpp>
0020 #include <boost/mpl/assert.hpp>
0021 #include <boost/utility/enable_if.hpp>
0022 #include <boost/type_traits/is_same.hpp>
0023 #include <boost/type_traits/is_scalar.hpp>
0024 #include <boost/type_traits/remove_const.hpp>
0025 #include <boost/typeof/std/valarray.hpp>
0026 #include <boost/accumulators/numeric/functional_fwd.hpp>
0027 
0028 namespace boost { namespace numeric
0029 {
0030     namespace operators
0031     {
0032         namespace acc_detail
0033         {
0034             template<typename Fun>
0035             struct make_valarray
0036             {
0037                 typedef std::valarray<typename Fun::result_type> type;
0038             };
0039         }
0040 
0041         ///////////////////////////////////////////////////////////////////////////////
0042         // Handle valarray<Left> / Right where Right is a scalar and Right != Left.
0043         template<typename Left, typename Right>
0044         typename lazy_enable_if<
0045             mpl::and_<is_scalar<Right>, mpl::not_<is_same<Left, Right> > >
0046           , acc_detail::make_valarray<functional::divides<Left, Right> >
0047         >::type
0048         operator /(std::valarray<Left> const &left, Right const &right)
0049         {
0050             typedef typename functional::divides<Left, Right>::result_type value_type;
0051             std::valarray<value_type> result(left.size());
0052             for(std::size_t i = 0, size = result.size(); i != size; ++i)
0053             {
0054                 result[i] = numeric::divides(left[i], right);
0055             }
0056             return result;
0057         }
0058 
0059         ///////////////////////////////////////////////////////////////////////////////
0060         // Handle valarray<Left> * Right where Right is a scalar and Right != Left.
0061         template<typename Left, typename Right>
0062         typename lazy_enable_if<
0063             mpl::and_<is_scalar<Right>, mpl::not_<is_same<Left, Right> > >
0064           , acc_detail::make_valarray<functional::multiplies<Left, Right> >
0065         >::type
0066         operator *(std::valarray<Left> const &left, Right const &right)
0067         {
0068             typedef typename functional::multiplies<Left, Right>::result_type value_type;
0069             std::valarray<value_type> result(left.size());
0070             for(std::size_t i = 0, size = result.size(); i != size; ++i)
0071             {
0072                 result[i] = numeric::multiplies(left[i], right);
0073             }
0074             return result;
0075         }
0076 
0077         ///////////////////////////////////////////////////////////////////////////////
0078         // Handle valarray<Left> + valarray<Right> where Right != Left.
0079         template<typename Left, typename Right>
0080         typename lazy_disable_if<
0081             is_same<Left, Right>
0082           , acc_detail::make_valarray<functional::plus<Left, Right> >
0083         >::type
0084         operator +(std::valarray<Left> const &left, std::valarray<Right> const &right)
0085         {
0086             typedef typename functional::plus<Left, Right>::result_type value_type;
0087             std::valarray<value_type> result(left.size());
0088             for(std::size_t i = 0, size = result.size(); i != size; ++i)
0089             {
0090                 result[i] = numeric::plus(left[i], right[i]);
0091             }
0092             return result;
0093         }
0094     }
0095 
0096     namespace functional
0097     {
0098         struct std_valarray_tag;
0099 
0100         template<typename T>
0101         struct tag<std::valarray<T> >
0102         {
0103             typedef std_valarray_tag type;
0104         };
0105 
0106     #ifdef __GLIBCXX__
0107         template<typename T, typename U>
0108         struct tag<std::_Expr<T, U> >
0109         {
0110             typedef std_valarray_tag type;
0111         };
0112     #endif
0113 
0114         /// INTERNAL ONLY
0115         ///
0116         // This is necessary because the GCC stdlib uses expression templates, and
0117         // typeof(som-valarray-expression) is not an instance of std::valarray
0118     #define BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP(Name, Op)                   \
0119         template<typename Left, typename Right>                                         \
0120         struct Name<Left, Right, std_valarray_tag, std_valarray_tag>                    \
0121         {                                                                               \
0122             typedef Left first_argument_type;                                           \
0123             typedef Right second_argument_type;                                         \
0124             typedef typename Left::value_type left_value_type;                          \
0125             typedef typename Right::value_type right_value_type;                        \
0126             typedef                                                                     \
0127                 std::valarray<                                                          \
0128                     typename Name<left_value_type, right_value_type>::result_type       \
0129                 >                                                                       \
0130             result_type;                                                                \
0131             result_type                                                                 \
0132             operator ()(Left &left, Right &right) const                                 \
0133             {                                                                           \
0134                 return numeric::promote<std::valarray<left_value_type> >(left)          \
0135                     Op numeric::promote<std::valarray<right_value_type> >(right);       \
0136             }                                                                           \
0137         };                                                                              \
0138         template<typename Left, typename Right>                                         \
0139         struct Name<Left, Right, std_valarray_tag, void>                                \
0140         {                                                                               \
0141             typedef Left first_argument_type;                                           \
0142             typedef Right second_argument_type;                                         \
0143             typedef typename Left::value_type left_value_type;                          \
0144             typedef                                                                     \
0145                 std::valarray<                                                          \
0146                     typename Name<left_value_type, Right>::result_type                  \
0147                 >                                                                       \
0148             result_type;                                                                \
0149             result_type                                                                 \
0150             operator ()(Left &left, Right &right) const                                 \
0151             {                                                                           \
0152                 return numeric::promote<std::valarray<left_value_type> >(left) Op right;\
0153             }                                                                           \
0154         };                                                                              \
0155         template<typename Left, typename Right>                                         \
0156         struct Name<Left, Right, void, std_valarray_tag>                                \
0157         {                                                                               \
0158             typedef Left first_argument_type;                                           \
0159             typedef Right second_argument_type;                                         \
0160             typedef typename Right::value_type right_value_type;                        \
0161             typedef                                                                     \
0162                 std::valarray<                                                          \
0163                     typename Name<Left, right_value_type>::result_type                  \
0164                 >                                                                       \
0165             result_type;                                                                \
0166             result_type                                                                 \
0167             operator ()(Left &left, Right &right) const                                 \
0168             {                                                                           \
0169                 return left Op numeric::promote<std::valarray<right_value_type> >(right);\
0170             }                                                                           \
0171         };
0172 
0173         BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP(plus, +)
0174         BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP(minus, -)
0175         BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP(multiplies, *)
0176         BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP(divides, /)
0177         BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP(modulus, %)
0178 
0179     #undef BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP
0180 
0181         ///////////////////////////////////////////////////////////////////////////////
0182         // element-wise min of std::valarray
0183         template<typename Left, typename Right>
0184         struct min_assign<Left, Right, std_valarray_tag, std_valarray_tag>
0185         {
0186             typedef Left first_argument_type;
0187             typedef Right second_argument_type;
0188             typedef void result_type;
0189 
0190             void operator ()(Left &left, Right &right) const
0191             {
0192                 BOOST_ASSERT(left.size() == right.size());
0193                 for(std::size_t i = 0, size = left.size(); i != size; ++i)
0194                 {
0195                     if(numeric::less(right[i], left[i]))
0196                     {
0197                         left[i] = right[i];
0198                     }
0199                 }
0200             }
0201         };
0202 
0203         ///////////////////////////////////////////////////////////////////////////////
0204         // element-wise max of std::valarray
0205         template<typename Left, typename Right>
0206         struct max_assign<Left, Right, std_valarray_tag, std_valarray_tag>
0207         {
0208             typedef Left first_argument_type;
0209             typedef Right second_argument_type;
0210             typedef void result_type;
0211 
0212             void operator ()(Left &left, Right &right) const
0213             {
0214                 BOOST_ASSERT(left.size() == right.size());
0215                 for(std::size_t i = 0, size = left.size(); i != size; ++i)
0216                 {
0217                     if(numeric::greater(right[i], left[i]))
0218                     {
0219                         left[i] = right[i];
0220                     }
0221                 }
0222             }
0223         };
0224 
0225         // partial specialization of numeric::fdiv<> for std::valarray.
0226         template<typename Left, typename Right, typename RightTag>
0227         struct fdiv<Left, Right, std_valarray_tag, RightTag>
0228           : mpl::if_<
0229                 are_integral<typename Left::value_type, Right>
0230               , divides<Left, double const>
0231               , divides<Left, Right>
0232             >::type
0233         {};
0234 
0235         // promote
0236         template<typename To, typename From>
0237         struct promote<To, From, std_valarray_tag, std_valarray_tag>
0238         {
0239             typedef From argument_type;
0240             typedef To result_type;
0241 
0242             To operator ()(From &arr) const
0243             {
0244                 typename remove_const<To>::type res(arr.size());
0245                 for(std::size_t i = 0, size = arr.size(); i != size; ++i)
0246                 {
0247                     res[i] = numeric::promote<typename To::value_type>(arr[i]);
0248                 }
0249                 return res;
0250             }
0251         };
0252 
0253         template<typename ToFrom>
0254         struct promote<ToFrom, ToFrom, std_valarray_tag, std_valarray_tag>
0255         {
0256             typedef ToFrom argument_type;
0257             typedef ToFrom result_type;
0258 
0259             ToFrom &operator ()(ToFrom &tofrom) const
0260             {
0261                 return tofrom;
0262             }
0263         };
0264 
0265         // for "promoting" a std::valarray<bool> to a bool, useful for
0266         // comparing 2 valarrays for equality:
0267         //   if(numeric::promote<bool>(a == b))
0268         template<typename From>
0269         struct promote<bool, From, void, std_valarray_tag>
0270         {
0271             typedef From argument_type;
0272             typedef bool result_type;
0273 
0274             bool operator ()(From &arr) const
0275             {
0276                 BOOST_MPL_ASSERT((is_same<bool, typename From::value_type>));
0277                 for(std::size_t i = 0, size = arr.size(); i != size; ++i)
0278                 {
0279                     if(!arr[i])
0280                     {
0281                         return false;
0282                     }
0283                 }
0284                 return true;
0285             }
0286         };
0287 
0288         template<typename From>
0289         struct promote<bool const, From, void, std_valarray_tag>
0290           : promote<bool, From, void, std_valarray_tag>
0291         {};
0292 
0293         ///////////////////////////////////////////////////////////////////////////////
0294         // functional::as_min
0295         template<typename T>
0296         struct as_min<T, std_valarray_tag>
0297         {
0298             typedef T argument_type;
0299             typedef typename remove_const<T>::type result_type;
0300 
0301             typename remove_const<T>::type operator ()(T &arr) const
0302             {
0303                 return 0 == arr.size()
0304                   ? T()
0305                   : T(numeric::as_min(arr[0]), arr.size());
0306             }
0307         };
0308 
0309         ///////////////////////////////////////////////////////////////////////////////
0310         // functional::as_max
0311         template<typename T>
0312         struct as_max<T, std_valarray_tag>
0313         {
0314             typedef T argument_type;
0315             typedef typename remove_const<T>::type result_type;
0316 
0317             typename remove_const<T>::type operator ()(T &arr) const
0318             {
0319                 return 0 == arr.size()
0320                   ? T()
0321                   : T(numeric::as_max(arr[0]), arr.size());
0322             }
0323         };
0324 
0325         ///////////////////////////////////////////////////////////////////////////////
0326         // functional::as_zero
0327         template<typename T>
0328         struct as_zero<T, std_valarray_tag>
0329         {
0330             typedef T argument_type;
0331             typedef typename remove_const<T>::type result_type;
0332 
0333             typename remove_const<T>::type operator ()(T &arr) const
0334             {
0335                 return 0 == arr.size()
0336                   ? T()
0337                   : T(numeric::as_zero(arr[0]), arr.size());
0338             }
0339         };
0340 
0341         ///////////////////////////////////////////////////////////////////////////////
0342         // functional::as_one
0343         template<typename T>
0344         struct as_one<T, std_valarray_tag>
0345         {
0346             typedef T argument_type;
0347             typedef typename remove_const<T>::type result_type;
0348 
0349             typename remove_const<T>::type operator ()(T &arr) const
0350             {
0351                 return 0 == arr.size()
0352                   ? T()
0353                   : T(numeric::as_one(arr[0]), arr.size());
0354             }
0355         };
0356 
0357     } // namespace functional
0358 
0359 }} // namespace boost::numeric
0360 
0361 #endif
0362