/Src/Dependencies/Boost/boost/accumulators/numeric/functional.hpp

http://hadesmem.googlecode.com/ · C++ Header · 490 lines · 394 code · 62 blank · 34 comment · 2 complexity · 9c728dcd0cdf902362cc4a0863d40913 MD5 · raw file

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