Statistics
| Revision:

root / tmp / org.txm.statsengine.r.core.win32 / res / win32 / library / BH / include / boost / accumulators / numeric / functional / valarray.hpp @ 2486

History | View | Annotate | Download (16.4 kB)

1
///////////////////////////////////////////////////////////////////////////////
2
/// \file valarray.hpp
3
///
4
//  Copyright 2005 Eric Niebler. Distributed under the Boost
5
//  Software License, Version 1.0. (See accompanying file
6
//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7

    
8
#ifndef BOOST_NUMERIC_FUNCTIONAL_VALARRAY_HPP_EAN_12_12_2005
9
#define BOOST_NUMERIC_FUNCTIONAL_VALARRAY_HPP_EAN_12_12_2005
10

    
11
#ifdef BOOST_NUMERIC_FUNCTIONAL_HPP_INCLUDED
12
# error Include this file before boost/accumulators/numeric/functional.hpp
13
#endif
14

    
15
#include <valarray>
16
#include <functional>
17
#include <boost/assert.hpp>
18
#include <boost/mpl/and.hpp>
19
#include <boost/mpl/not.hpp>
20
#include <boost/mpl/assert.hpp>
21
#include <boost/utility/enable_if.hpp>
22
#include <boost/type_traits/is_same.hpp>
23
#include <boost/type_traits/is_scalar.hpp>
24
#include <boost/type_traits/remove_const.hpp>
25
#include <boost/typeof/std/valarray.hpp>
26
#include <boost/accumulators/numeric/functional_fwd.hpp>
27

    
28
namespace boost { namespace numeric
29
{
30
    namespace operators
31
    {
32
        namespace acc_detail
33
        {
34
            template<typename Fun>
35
            struct make_valarray
36
            {
37
                typedef std::valarray<typename Fun::result_type> type;
38
            };
39
        }
40

    
41
        ///////////////////////////////////////////////////////////////////////////////
42
        // Handle valarray<Left> / Right where Right is a scalar and Right != Left.
43
        template<typename Left, typename Right>
44
        typename lazy_enable_if<
45
            mpl::and_<is_scalar<Right>, mpl::not_<is_same<Left, Right> > >
46
          , acc_detail::make_valarray<functional::divides<Left, Right> >
47
        >::type
48
        operator /(std::valarray<Left> const &left, Right const &right)
49
        {
50
            typedef typename functional::divides<Left, Right>::result_type value_type;
51
            std::valarray<value_type> result(left.size());
52
            for(std::size_t i = 0, size = result.size(); i != size; ++i)
53
            {
54
                result[i] = numeric::divides(left[i], right);
55
            }
56
            return result;
57
        }
58

    
59
        ///////////////////////////////////////////////////////////////////////////////
60
        // Handle valarray<Left> * Right where Right is a scalar and Right != Left.
61
        template<typename Left, typename Right>
62
        typename lazy_enable_if<
63
            mpl::and_<is_scalar<Right>, mpl::not_<is_same<Left, Right> > >
64
          , acc_detail::make_valarray<functional::multiplies<Left, Right> >
65
        >::type
66
        operator *(std::valarray<Left> const &left, Right const &right)
67
        {
68
            typedef typename functional::multiplies<Left, Right>::result_type value_type;
69
            std::valarray<value_type> result(left.size());
70
            for(std::size_t i = 0, size = result.size(); i != size; ++i)
71
            {
72
                result[i] = numeric::multiplies(left[i], right);
73
            }
74
            return result;
75
        }
76

    
77
        ///////////////////////////////////////////////////////////////////////////////
78
        // Handle valarray<Left> + valarray<Right> where Right != Left.
79
        template<typename Left, typename Right>
80
        typename lazy_disable_if<
81
            is_same<Left, Right>
82
          , acc_detail::make_valarray<functional::plus<Left, Right> >
83
        >::type
84
        operator +(std::valarray<Left> const &left, std::valarray<Right> const &right)
85
        {
86
            typedef typename functional::plus<Left, Right>::result_type value_type;
87
            std::valarray<value_type> result(left.size());
88
            for(std::size_t i = 0, size = result.size(); i != size; ++i)
89
            {
90
                result[i] = numeric::plus(left[i], right[i]);
91
            }
92
            return result;
93
        }
94
    }
95

    
96
    namespace functional
97
    {
98
        struct std_valarray_tag;
99

    
100
        template<typename T>
101
        struct tag<std::valarray<T> >
102
        {
103
            typedef std_valarray_tag type;
104
        };
105

    
106
    #ifdef __GLIBCXX__
107
        template<typename T, typename U>
108
        struct tag<std::_Expr<T, U> >
109
        {
110
            typedef std_valarray_tag type;
111
        };
112
    #endif
113

    
114
        /// INTERNAL ONLY
115
        ///
116
        // This is necessary because the GCC stdlib uses expression templates, and
117
        // typeof(som-valarray-expression) is not an instance of std::valarray
118
    #define BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP(Name, Op)                   \
119
        template<typename Left, typename Right>                                         \
120
        struct Name<Left, Right, std_valarray_tag, std_valarray_tag>                    \
121
          : std::binary_function<                                                       \
122
                Left                                                                    \
123
              , Right                                                                   \
124
              , std::valarray<                                                          \
125
                    typename Name<                                                      \
126
                        typename Left::value_type                                       \
127
                      , typename Right::value_type                                      \
128
                    >::result_type                                                      \
129
                >                                                                       \
130
            >                                                                           \
131
        {                                                                               \
132
            typedef typename Left::value_type left_value_type;                          \
133
            typedef typename Right::value_type right_value_type;                        \
134
            typedef                                                                     \
135
                std::valarray<                                                          \
136
                    typename Name<left_value_type, right_value_type>::result_type       \
137
                >                                                                       \
138
            result_type;                                                                \
139
            result_type                                                                 \
140
            operator ()(Left &left, Right &right) const                                 \
141
            {                                                                           \
142
                return numeric::promote<std::valarray<left_value_type> >(left)          \
143
                    Op numeric::promote<std::valarray<right_value_type> >(right);       \
144
            }                                                                           \
145
        };                                                                              \
146
        template<typename Left, typename Right>                                         \
147
        struct Name<Left, Right, std_valarray_tag, void>                                \
148
          : std::binary_function<                                                       \
149
                Left                                                                    \
150
              , Right                                                                   \
151
              , std::valarray<                                                          \
152
                    typename Name<typename Left::value_type, Right>::result_type        \
153
                >                                                                       \
154
            >                                                                           \
155
        {                                                                               \
156
            typedef typename Left::value_type left_value_type;                          \
157
            typedef                                                                     \
158
                std::valarray<                                                          \
159
                    typename Name<left_value_type, Right>::result_type                  \
160
                >                                                                       \
161
            result_type;                                                                \
162
            result_type                                                                 \
163
            operator ()(Left &left, Right &right) const                                 \
164
            {                                                                           \
165
                return numeric::promote<std::valarray<left_value_type> >(left) Op right;\
166
            }                                                                           \
167
        };                                                                              \
168
        template<typename Left, typename Right>                                         \
169
        struct Name<Left, Right, void, std_valarray_tag>                                \
170
          : std::binary_function<                                                       \
171
                Left                                                                    \
172
              , Right                                                                   \
173
              , std::valarray<                                                          \
174
                    typename Name<Left, typename Right::value_type>::result_type        \
175
                >                                                                       \
176
            >                                                                           \
177
        {                                                                               \
178
            typedef typename Right::value_type right_value_type;                        \
179
            typedef                                                                     \
180
                std::valarray<                                                          \
181
                    typename Name<Left, right_value_type>::result_type                  \
182
                >                                                                       \
183
            result_type;                                                                \
184
            result_type                                                                 \
185
            operator ()(Left &left, Right &right) const                                 \
186
            {                                                                           \
187
                return left Op numeric::promote<std::valarray<right_value_type> >(right);\
188
            }                                                                           \
189
        };
190

    
191
        BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP(plus, +)
192
        BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP(minus, -)
193
        BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP(multiplies, *)
194
        BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP(divides, /)
195
        BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP(modulus, %)
196

    
197
    #undef BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP
198

    
199
        ///////////////////////////////////////////////////////////////////////////////
200
        // element-wise min of std::valarray
201
        template<typename Left, typename Right>
202
        struct min_assign<Left, Right, std_valarray_tag, std_valarray_tag>
203
          : std::binary_function<Left, Right, void>
204
        {
205
            void operator ()(Left &left, Right &right) const
206
            {
207
                BOOST_ASSERT(left.size() == right.size());
208
                for(std::size_t i = 0, size = left.size(); i != size; ++i)
209
                {
210
                    if(numeric::less(right[i], left[i]))
211
                    {
212
                        left[i] = right[i];
213
                    }
214
                }
215
            }
216
        };
217

    
218
        ///////////////////////////////////////////////////////////////////////////////
219
        // element-wise max of std::valarray
220
        template<typename Left, typename Right>
221
        struct max_assign<Left, Right, std_valarray_tag, std_valarray_tag>
222
          : std::binary_function<Left, Right, void>
223
        {
224
            void operator ()(Left &left, Right &right) const
225
            {
226
                BOOST_ASSERT(left.size() == right.size());
227
                for(std::size_t i = 0, size = left.size(); i != size; ++i)
228
                {
229
                    if(numeric::greater(right[i], left[i]))
230
                    {
231
                        left[i] = right[i];
232
                    }
233
                }
234
            }
235
        };
236

    
237
        // partial specialization of numeric::fdiv<> for std::valarray.
238
        template<typename Left, typename Right, typename RightTag>
239
        struct fdiv<Left, Right, std_valarray_tag, RightTag>
240
          : mpl::if_<
241
                are_integral<typename Left::value_type, Right>
242
              , divides<Left, double const>
243
              , divides<Left, Right>
244
            >::type
245
        {};
246

    
247
        // promote
248
        template<typename To, typename From>
249
        struct promote<To, From, std_valarray_tag, std_valarray_tag>
250
          : std::unary_function<From, To>
251
        {
252
            To operator ()(From &arr) const
253
            {
254
                typename remove_const<To>::type res(arr.size());
255
                for(std::size_t i = 0, size = arr.size(); i != size; ++i)
256
                {
257
                    res[i] = numeric::promote<typename To::value_type>(arr[i]);
258
                }
259
                return res;
260
            }
261
        };
262

    
263
        template<typename ToFrom>
264
        struct promote<ToFrom, ToFrom, std_valarray_tag, std_valarray_tag>
265
          : std::unary_function<ToFrom, ToFrom>
266
        {
267
            ToFrom &operator ()(ToFrom &tofrom) const
268
            {
269
                return tofrom;
270
            }
271
        };
272

    
273
        // for "promoting" a std::valarray<bool> to a bool, useful for
274
        // comparing 2 valarrays for equality:
275
        //   if(numeric::promote<bool>(a == b))
276
        template<typename From>
277
        struct promote<bool, From, void, std_valarray_tag>
278
          : std::unary_function<From, bool>
279
        {
280
            bool operator ()(From &arr) const
281
            {
282
                BOOST_MPL_ASSERT((is_same<bool, typename From::value_type>));
283
                for(std::size_t i = 0, size = arr.size(); i != size; ++i)
284
                {
285
                    if(!arr[i])
286
                    {
287
                        return false;
288
                    }
289
                }
290
                return true;
291
            }
292
        };
293

    
294
        template<typename From>
295
        struct promote<bool const, From, void, std_valarray_tag>
296
          : promote<bool, From, void, std_valarray_tag>
297
        {};
298

    
299
        ///////////////////////////////////////////////////////////////////////////////
300
        // functional::as_min
301
        template<typename T>
302
        struct as_min<T, std_valarray_tag>
303
            : std::unary_function<T, typename remove_const<T>::type>
304
        {
305
            typename remove_const<T>::type operator ()(T &arr) const
306
            {
307
                return 0 == arr.size()
308
                  ? T()
309
                  : T(numeric::as_min(arr[0]), arr.size());
310
            }
311
        };
312

    
313
        ///////////////////////////////////////////////////////////////////////////////
314
        // functional::as_max
315
        template<typename T>
316
        struct as_max<T, std_valarray_tag>
317
          : std::unary_function<T, typename remove_const<T>::type>
318
        {
319
            typename remove_const<T>::type operator ()(T &arr) const
320
            {
321
                return 0 == arr.size()
322
                  ? T()
323
                  : T(numeric::as_max(arr[0]), arr.size());
324
            }
325
        };
326

    
327
        ///////////////////////////////////////////////////////////////////////////////
328
        // functional::as_zero
329
        template<typename T>
330
        struct as_zero<T, std_valarray_tag>
331
          : std::unary_function<T, typename remove_const<T>::type>
332
        {
333
            typename remove_const<T>::type operator ()(T &arr) const
334
            {
335
                return 0 == arr.size()
336
                  ? T()
337
                  : T(numeric::as_zero(arr[0]), arr.size());
338
            }
339
        };
340

    
341
        ///////////////////////////////////////////////////////////////////////////////
342
        // functional::as_one
343
        template<typename T>
344
        struct as_one<T, std_valarray_tag>
345
          : std::unary_function<T, typename remove_const<T>::type>
346
        {
347
            typename remove_const<T>::type operator ()(T &arr) const
348
            {
349
                return 0 == arr.size()
350
                  ? T()
351
                  : T(numeric::as_one(arr[0]), arr.size());
352
            }
353
        };
354

    
355
    } // namespace functional
356

    
357
}} // namespace boost::numeric
358

    
359
#endif
360