| 1 | /////////////////////////////////////////////////////////////////////////////// |
| 2 | /// \file functional.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_HPP_EAN_08_12_2005 |
| 9 | #define BOOST_NUMERIC_FUNCTIONAL_HPP_EAN_08_12_2005 |
| 10 | |
| 11 | #include <limits> |
| 12 | #include <functional> |
| 13 | #include <boost/static_assert.hpp> |
| 14 | #include <boost/mpl/if.hpp> |
| 15 | #include <boost/mpl/and.hpp> |
| 16 | #include <boost/type_traits/remove_const.hpp> |
| 17 | #include <boost/type_traits/add_reference.hpp> |
| 18 | #include <boost/type_traits/is_empty.hpp> |
| 19 | #include <boost/type_traits/is_integral.hpp> |
| 20 | #include <boost/type_traits/is_floating_point.hpp> |
| 21 | #include <boost/utility/enable_if.hpp> |
| 22 | #include <boost/typeof/typeof.hpp> |
| 23 | #include <boost/accumulators/accumulators_fwd.hpp> |
| 24 | #include <boost/accumulators/numeric/functional_fwd.hpp> |
| 25 | #include <boost/accumulators/numeric/detail/function1.hpp> |
| 26 | #include <boost/accumulators/numeric/detail/function2.hpp> |
| 27 | #include <boost/accumulators/numeric/detail/pod_singleton.hpp> |
| 28 | |
| 29 | #ifdef BOOST_NUMERIC_FUNCTIONAL_STD_VECTOR_SUPPORT |
| 30 | # include <boost/accumulators/numeric/functional/vector.hpp> |
| 31 | #endif |
| 32 | |
| 33 | #ifdef BOOST_NUMERIC_FUNCTIONAL_STD_VALARRAY_SUPPORT |
| 34 | # include <boost/accumulators/numeric/functional/valarray.hpp> |
| 35 | #endif |
| 36 | |
| 37 | #ifdef BOOST_NUMERIC_FUNCTIONAL_STD_COMPLEX_SUPPORT |
| 38 | # include <boost/accumulators/numeric/functional/complex.hpp> |
| 39 | #endif |
| 40 | |
| 41 | /// INTERNAL ONLY |
| 42 | /// |
| 43 | #define BOOST_NUMERIC_FUNCTIONAL_HPP_INCLUDED |
| 44 | |
| 45 | #ifdef BOOST_NUMERIC_FUNCTIONAL_DOXYGEN_INVOKED |
| 46 | // Hack to make Doxygen show the inheritance relationships |
| 47 | /// INTERNAL ONLY |
| 48 | /// |
| 49 | namespace std |
| 50 | { |
| 51 | /// INTERNAL ONLY |
| 52 | /// |
| 53 | template<class Arg, class Ret> struct unary_function {}; |
| 54 | /// INTERNAL ONLY |
| 55 | /// |
| 56 | template<class Left, class Right, class Ret> struct binary_function {}; |
| 57 | } |
| 58 | #endif |
| 59 | |
| 60 | namespace boost { namespace numeric |
| 61 | { |
| 62 | namespace functional |
| 63 | { |
| 64 | /// INTERNAL ONLY |
| 65 | /// |
| 66 | template<typename A0, typename A1> |
| 67 | struct are_integral |
| 68 | : mpl::and_<is_integral<A0>, is_integral<A1> > |
| 69 | {}; |
| 70 | |
| 71 | template<typename Left, typename Right> |
| 72 | struct left_ref |
| 73 | { |
| 74 | typedef Left &type; |
| 75 | }; |
| 76 | |
| 77 | namespace detail |
| 78 | { |
| 79 | template<typename T> |
| 80 | T &lvalue_of(); |
| 81 | } |
| 82 | } |
| 83 | |
| 84 | // TODO: handle complex weight, valarray, MTL vectors |
| 85 | |
| 86 | /// INTERNAL ONLY |
| 87 | /// |
| 88 | #define BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP(Name, Op) \ |
| 89 | namespace functional \ |
| 90 | { \ |
| 91 | template<typename Arg> \ |
| 92 | struct result_of_ ## Name \ |
| 93 | { \ |
| 94 | BOOST_TYPEOF_NESTED_TYPEDEF_TPL( \ |
| 95 | nested \ |
| 96 | , Op boost::numeric::functional::detail::lvalue_of<Arg>() \ |
| 97 | ) \ |
| 98 | typedef typename nested::type type; \ |
| 99 | }; \ |
| 100 | template<typename Arg, typename EnableIf> \ |
| 101 | struct Name ## _base \ |
| 102 | { \ |
| 103 | typedef typename remove_const<Arg>::type argument_type; \ |
| 104 | typedef typename result_of_ ## Name<Arg>::type result_type; \ |
| 105 | typename result_of_ ## Name<Arg>::type operator ()(Arg &arg) const \ |
| 106 | { \ |
| 107 | return Op arg; \ |
| 108 | } \ |
| 109 | }; \ |
| 110 | template<typename Arg, typename ArgTag> \ |
| 111 | struct Name \ |
| 112 | : Name ## _base<Arg, void> \ |
| 113 | {}; \ |
| 114 | } \ |
| 115 | namespace op \ |
| 116 | { \ |
| 117 | struct Name \ |
| 118 | : boost::detail::function1<functional::Name<_, functional::tag<_> > > \ |
| 119 | {}; \ |
| 120 | } \ |
| 121 | namespace \ |
| 122 | { \ |
| 123 | op::Name const &Name = boost::detail::pod_singleton<op::Name>::instance; \ |
| 124 | } \ |
| 125 | /**/ |
| 126 | |
| 127 | /// INTERNAL ONLY |
| 128 | /// |
| 129 | #define BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(Name, Op, RetType) \ |
| 130 | namespace functional \ |
| 131 | { \ |
| 132 | template<typename Left, typename Right, typename EnableIf> \ |
| 133 | struct result_of_ ## Name \ |
| 134 | { \ |
| 135 | RetType(Left, Op, Right) \ |
| 136 | }; \ |
| 137 | template<typename Left, typename Right, typename EnableIf> \ |
| 138 | struct Name ## _base \ |
| 139 | { \ |
| 140 | typedef typename remove_const<Left>::type first_argument_type; \ |
| 141 | typedef typename remove_const<Right>::type second_argument_type; \ |
| 142 | typedef typename result_of_ ## Name<Left, Right>::type result_type; \ |
| 143 | typename result_of_ ## Name<Left, Right>::type \ |
| 144 | operator ()(Left &left, Right &right) const \ |
| 145 | { \ |
| 146 | return left Op right; \ |
| 147 | } \ |
| 148 | }; \ |
| 149 | template<typename Left, typename Right, typename LeftTag, typename RightTag> \ |
| 150 | struct Name \ |
| 151 | : Name ## _base<Left, Right, void> \ |
| 152 | {}; \ |
| 153 | } \ |
| 154 | namespace op \ |
| 155 | { \ |
| 156 | struct Name \ |
| 157 | : boost::detail::function2< \ |
| 158 | functional::Name<_1, _2, functional::tag<_1>, functional::tag<_2> > \ |
| 159 | > \ |
| 160 | {}; \ |
| 161 | } \ |
| 162 | namespace \ |
| 163 | { \ |
| 164 | op::Name const &Name = boost::detail::pod_singleton<op::Name>::instance; \ |
| 165 | } \ |
| 166 | BOOST_ACCUMULATORS_IGNORE_GLOBAL(Name) \ |
| 167 | /**/ |
| 168 | |
| 169 | /// INTERNAL ONLY |
| 170 | /// |
| 171 | #define BOOST_NUMERIC_FUNCTIONAL_DEDUCED(Left, Op, Right) \ |
| 172 | BOOST_TYPEOF_NESTED_TYPEDEF_TPL( \ |
| 173 | nested \ |
| 174 | , boost::numeric::functional::detail::lvalue_of<Left>() Op \ |
| 175 | boost::numeric::functional::detail::lvalue_of<Right>() \ |
| 176 | ) \ |
| 177 | typedef typename nested::type type; \ |
| 178 | /**/ |
| 179 | |
| 180 | /// INTERNAL ONLY |
| 181 | /// |
| 182 | #define BOOST_NUMERIC_FUNCTIONAL_LEFT(Left, Op, Right) \ |
| 183 | typedef Left &type; \ |
| 184 | /**/ |
| 185 | |
| 186 | BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(plus, +, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) |
| 187 | BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(minus, -, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) |
| 188 | BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(multiplies, *, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) |
| 189 | BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(divides, /, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) |
| 190 | BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(modulus, %, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) |
| 191 | BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(greater, >, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) |
| 192 | BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(greater_equal, >=, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) |
| 193 | BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(less, <, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) |
| 194 | BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(less_equal, <=, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) |
| 195 | BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(equal_to, ==, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) |
| 196 | BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(not_equal_to, !=, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) |
| 197 | |
| 198 | BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(assign, =, BOOST_NUMERIC_FUNCTIONAL_LEFT) |
| 199 | BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(plus_assign, +=, BOOST_NUMERIC_FUNCTIONAL_LEFT) |
| 200 | BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(minus_assign, -=, BOOST_NUMERIC_FUNCTIONAL_LEFT) |
| 201 | BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(multiplies_assign, *=, BOOST_NUMERIC_FUNCTIONAL_LEFT) |
| 202 | BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(divides_assign, /=, BOOST_NUMERIC_FUNCTIONAL_LEFT) |
| 203 | BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(modulus_assign, %=, BOOST_NUMERIC_FUNCTIONAL_LEFT) |
| 204 | |
| 205 | BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP(unary_plus, +) |
| 206 | BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP(unary_minus, -) |
| 207 | BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP(complement, ~) |
| 208 | BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP(logical_not, !) |
| 209 | |
| 210 | #undef BOOST_NUMERIC_FUNCTIONAL_LEFT |
| 211 | #undef BOOST_NUMERIC_FUNCTIONAL_DEDUCED |
| 212 | #undef BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP |
| 213 | #undef BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP |
| 214 | |
| 215 | namespace functional |
| 216 | { |
| 217 | template<typename Left, typename Right, typename EnableIf> |
| 218 | struct min_assign_base |
| 219 | { |
| 220 | typedef Left first_argument_type; |
| 221 | typedef Right second_argument_type; |
| 222 | typedef void result_type; |
| 223 | |
| 224 | void operator ()(Left &left, Right &right) const |
| 225 | { |
| 226 | if(numeric::less(right, left)) |
| 227 | { |
| 228 | left = right; |
| 229 | } |
| 230 | } |
| 231 | }; |
| 232 | |
| 233 | template<typename Left, typename Right, typename EnableIf> |
| 234 | struct max_assign_base |
| 235 | { |
| 236 | typedef Left first_argument_type; |
| 237 | typedef Right second_argument_type; |
| 238 | typedef void result_type; |
| 239 | |
| 240 | void operator ()(Left &left, Right &right) const |
| 241 | { |
| 242 | if(numeric::greater(right, left)) |
| 243 | { |
| 244 | left = right; |
| 245 | } |
| 246 | } |
| 247 | }; |
| 248 | |
| 249 | template<typename Left, typename Right, typename EnableIf> |
| 250 | struct fdiv_base |
| 251 | : functional::divides<Left, Right> |
| 252 | {}; |
| 253 | |
| 254 | // partial specialization that promotes the arguments to double for |
| 255 | // integral division. |
| 256 | template<typename Left, typename Right> |
| 257 | struct fdiv_base<Left, Right, typename enable_if<are_integral<Left, Right> >::type> |
| 258 | : functional::divides<double const, double const> |
| 259 | {}; |
| 260 | |
| 261 | template<typename To, typename From, typename EnableIf> |
| 262 | struct promote_base |
| 263 | { |
| 264 | typedef From argument_type; |
| 265 | typedef To result_type; |
| 266 | |
| 267 | To operator ()(From &from) const |
| 268 | { |
| 269 | return from; |
| 270 | } |
| 271 | }; |
| 272 | |
| 273 | template<typename ToFrom> |
| 274 | struct promote_base<ToFrom, ToFrom, void> |
| 275 | { |
| 276 | typedef ToFrom argument_type; |
| 277 | typedef ToFrom result_type; |
| 278 | |
| 279 | ToFrom &operator ()(ToFrom &tofrom) |
| 280 | { |
| 281 | return tofrom; |
| 282 | } |
| 283 | }; |
| 284 | |
| 285 | template<typename Arg, typename EnableIf> |
| 286 | struct as_min_base |
| 287 | { |
| 288 | BOOST_STATIC_ASSERT(std::numeric_limits<typename remove_const<Arg>::type>::is_specialized); |
| 289 | |
| 290 | typedef Arg argument_type; |
| 291 | typedef typename remove_const<Arg>::type result_type; |
| 292 | |
| 293 | typename remove_const<Arg>::type operator ()(Arg &) const |
| 294 | { |
| 295 | return (std::numeric_limits<typename remove_const<Arg>::type>::min)(); |
| 296 | } |
| 297 | }; |
| 298 | |
| 299 | template<typename Arg> |
| 300 | struct as_min_base<Arg, typename enable_if<is_floating_point<Arg> >::type> |
| 301 | { |
| 302 | BOOST_STATIC_ASSERT(std::numeric_limits<typename remove_const<Arg>::type>::is_specialized); |
| 303 | |
| 304 | typedef Arg argument_type; |
| 305 | typedef typename remove_const<Arg>::type result_type; |
| 306 | |
| 307 | typename remove_const<Arg>::type operator ()(Arg &) const |
| 308 | { |
| 309 | return -(std::numeric_limits<typename remove_const<Arg>::type>::max)(); |
| 310 | } |
| 311 | }; |
| 312 | |
| 313 | template<typename Arg, typename EnableIf> |
| 314 | struct as_max_base |
| 315 | { |
| 316 | BOOST_STATIC_ASSERT(std::numeric_limits<typename remove_const<Arg>::type>::is_specialized); |
| 317 | |
| 318 | typedef Arg argument_type; |
| 319 | typedef typename remove_const<Arg>::type result_type; |
| 320 | |
| 321 | typename remove_const<Arg>::type operator ()(Arg &) const |
| 322 | { |
| 323 | return (std::numeric_limits<typename remove_const<Arg>::type>::max)(); |
| 324 | } |
| 325 | }; |
| 326 | |
| 327 | template<typename Arg, typename EnableIf> |
| 328 | struct as_zero_base |
| 329 | { |
| 330 | typedef Arg argument_type; |
| 331 | typedef typename remove_const<Arg>::type result_type; |
| 332 | |
| 333 | typename remove_const<Arg>::type operator ()(Arg &) const |
| 334 | { |
| 335 | return numeric::zero<typename remove_const<Arg>::type>::value; |
| 336 | } |
| 337 | }; |
| 338 | |
| 339 | template<typename Arg, typename EnableIf> |
| 340 | struct as_one_base |
| 341 | { |
| 342 | typedef Arg argument_type; |
| 343 | typedef typename remove_const<Arg>::type result_type; |
| 344 | |
| 345 | typename remove_const<Arg>::type operator ()(Arg &) const |
| 346 | { |
| 347 | return numeric::one<typename remove_const<Arg>::type>::value; |
| 348 | } |
| 349 | }; |
| 350 | |
| 351 | template<typename To, typename From, typename ToTag, typename FromTag> |
| 352 | struct promote |
| 353 | : promote_base<To, From, void> |
| 354 | {}; |
| 355 | |
| 356 | template<typename Left, typename Right, typename LeftTag, typename RightTag> |
| 357 | struct min_assign |
| 358 | : min_assign_base<Left, Right, void> |
| 359 | {}; |
| 360 | |
| 361 | template<typename Left, typename Right, typename LeftTag, typename RightTag> |
| 362 | struct max_assign |
| 363 | : max_assign_base<Left, Right, void> |
| 364 | {}; |
| 365 | |
| 366 | template<typename Left, typename Right, typename LeftTag, typename RightTag> |
| 367 | struct fdiv |
| 368 | : fdiv_base<Left, Right, void> |
| 369 | {}; |
| 370 | |
| 371 | /// INTERNAL ONLY |
| 372 | /// For back-compat only. Use fdiv. |
| 373 | template<typename Left, typename Right, typename LeftTag, typename RightTag> |
| 374 | struct average |
| 375 | : fdiv<Left, Right, LeftTag, RightTag> |
| 376 | {}; |
| 377 | |
| 378 | template<typename Arg, typename Tag> |
| 379 | struct as_min |
| 380 | : as_min_base<Arg, void> |
| 381 | {}; |
| 382 | |
| 383 | template<typename Arg, typename Tag> |
| 384 | struct as_max |
| 385 | : as_max_base<Arg, void> |
| 386 | {}; |
| 387 | |
| 388 | template<typename Arg, typename Tag> |
| 389 | struct as_zero |
| 390 | : as_zero_base<Arg, void> |
| 391 | {}; |
| 392 | |
| 393 | template<typename Arg, typename Tag> |
| 394 | struct as_one |
| 395 | : as_one_base<Arg, void> |
| 396 | {}; |
| 397 | } |
| 398 | |
| 399 | namespace op |
| 400 | { |
| 401 | template<typename To> |
| 402 | struct promote |
| 403 | : boost::detail::function1<functional::promote<To, _, typename functional::tag<To>::type, functional::tag<_> > > |
| 404 | {}; |
| 405 | |
| 406 | struct min_assign |
| 407 | : boost::detail::function2<functional::min_assign<_1, _2, functional::tag<_1>, functional::tag<_2> > > |
| 408 | {}; |
| 409 | |
| 410 | struct max_assign |
| 411 | : boost::detail::function2<functional::max_assign<_1, _2, functional::tag<_1>, functional::tag<_2> > > |
| 412 | {}; |
| 413 | |
| 414 | struct fdiv |
| 415 | : boost::detail::function2<functional::fdiv<_1, _2, functional::tag<_1>, functional::tag<_2> > > |
| 416 | {}; |
| 417 | |
| 418 | /// INTERNAL ONLY |
| 419 | struct average |
| 420 | : boost::detail::function2<functional::fdiv<_1, _2, functional::tag<_1>, functional::tag<_2> > > |
| 421 | {}; |
| 422 | |
| 423 | struct as_min |
| 424 | : boost::detail::function1<functional::as_min<_, functional::tag<_> > > |
| 425 | {}; |
| 426 | |
| 427 | struct as_max |
| 428 | : boost::detail::function1<functional::as_max<_, functional::tag<_> > > |
| 429 | {}; |
| 430 | |
| 431 | struct as_zero |
| 432 | : boost::detail::function1<functional::as_zero<_, functional::tag<_> > > |
| 433 | {}; |
| 434 | |
| 435 | struct as_one |
| 436 | : boost::detail::function1<functional::as_one<_, functional::tag<_> > > |
| 437 | {}; |
| 438 | } |
| 439 | |
| 440 | namespace |
| 441 | { |
| 442 | op::min_assign const &min_assign = boost::detail::pod_singleton<op::min_assign>::instance; |
| 443 | op::max_assign const &max_assign = boost::detail::pod_singleton<op::max_assign>::instance; |
| 444 | op::fdiv const &fdiv = boost::detail::pod_singleton<op::fdiv>::instance; |
| 445 | op::fdiv const &average = boost::detail::pod_singleton<op::fdiv>::instance; ///< INTERNAL ONLY |
| 446 | op::as_min const &as_min = boost::detail::pod_singleton<op::as_min>::instance; |
| 447 | op::as_max const &as_max = boost::detail::pod_singleton<op::as_max>::instance; |
| 448 | op::as_zero const &as_zero = boost::detail::pod_singleton<op::as_zero>::instance; |
| 449 | op::as_one const &as_one = boost::detail::pod_singleton<op::as_one>::instance; |
| 450 | |
| 451 | BOOST_ACCUMULATORS_IGNORE_GLOBAL(min_assign) |
| 452 | BOOST_ACCUMULATORS_IGNORE_GLOBAL(max_assign) |
| 453 | BOOST_ACCUMULATORS_IGNORE_GLOBAL(fdiv) |
| 454 | BOOST_ACCUMULATORS_IGNORE_GLOBAL(average) |
| 455 | BOOST_ACCUMULATORS_IGNORE_GLOBAL(as_min) |
| 456 | BOOST_ACCUMULATORS_IGNORE_GLOBAL(as_max) |
| 457 | BOOST_ACCUMULATORS_IGNORE_GLOBAL(as_zero) |
| 458 | BOOST_ACCUMULATORS_IGNORE_GLOBAL(as_one) |
| 459 | } |
| 460 | |
| 461 | /////////////////////////////////////////////////////////////////////////////// |
| 462 | // promote |
| 463 | template<typename To, typename From> |
| 464 | typename lazy_disable_if<is_const<From>, mpl::if_<is_same<To, From>, To &, To> >::type |
| 465 | promote(From &from) |
| 466 | { |
| 467 | return functional::promote<To, From>()(from); |
| 468 | } |
| 469 | |
| 470 | template<typename To, typename From> |
| 471 | typename mpl::if_<is_same<To const, From const>, To const &, To const>::type |
| 472 | promote(From const &from) |
| 473 | { |
| 474 | return functional::promote<To const, From const>()(from); |
| 475 | } |
| 476 | |
| 477 | template<typename T> |
| 478 | struct default_ |
| 479 | { |
| 480 | typedef default_ type; |
| 481 | typedef T value_type; |
| 482 | static T const value; |
| 483 | |
| 484 | operator T const & () const |
| 485 | { |
| 486 | return default_::value; |
| 487 | } |
| 488 | }; |
| 489 | |
| 490 | template<typename T> |
| 491 | T const default_<T>::value = T(); |
| 492 | |
| 493 | template<typename T> |
| 494 | struct one |
| 495 | { |
| 496 | typedef one type; |
| 497 | typedef T value_type; |
| 498 | static T const value; |
| 499 | |
| 500 | operator T const & () const |
| 501 | { |
| 502 | return one::value; |
| 503 | } |
| 504 | }; |
| 505 | |
| 506 | template<typename T> |
| 507 | T const one<T>::value = T(1); |
| 508 | |
| 509 | template<typename T> |
| 510 | struct zero |
| 511 | { |
| 512 | typedef zero type; |
| 513 | typedef T value_type; |
| 514 | static T const value; |
| 515 | |
| 516 | operator T const & () const |
| 517 | { |
| 518 | return zero::value; |
| 519 | } |
| 520 | }; |
| 521 | |
| 522 | template<typename T> |
| 523 | T const zero<T>::value = T(); |
| 524 | |
| 525 | template<typename T> |
| 526 | struct one_or_default |
| 527 | : mpl::if_<is_empty<T>, default_<T>, one<T> >::type |
| 528 | {}; |
| 529 | |
| 530 | template<typename T> |
| 531 | struct zero_or_default |
| 532 | : mpl::if_<is_empty<T>, default_<T>, zero<T> >::type |
| 533 | {}; |
| 534 | |
| 535 | }} // namespace boost::numeric |
| 536 | |
| 537 | #endif |
| 538 | |