1 // Copyright John Maddock 2007.
2 // Use, modification and distribution are subject to the
3 // Boost Software License, Version 1.0. (See accompanying file
4 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6 #ifndef BOOST_MATH_POLICY_HPP
7 #define BOOST_MATH_POLICY_HPP
8
9 #include <boost/mpl/list.hpp>
10 #include <boost/mpl/contains.hpp>
11 #include <boost/mpl/if.hpp>
12 #include <boost/mpl/find_if.hpp>
13 #include <boost/mpl/remove_if.hpp>
14 #include <boost/mpl/vector.hpp>
15 #include <boost/mpl/push_back.hpp>
16 #include <boost/mpl/at.hpp>
17 #include <boost/mpl/size.hpp>
18 #include <boost/mpl/comparison.hpp>
19 #include <boost/type_traits/is_same.hpp>
20 #include <boost/static_assert.hpp>
21 #include <boost/assert.hpp>
22 #include <boost/math/tools/config.hpp>
23 #include <limits>
24 // Sadly we do need the .h versions of these to be sure of getting
25 // FLT_MANT_DIG etc.
26 #include <limits.h>
27 #include <stdlib.h>
28 #include <stddef.h>
29 #include <math.h>
30
31 namespace boost{ namespace math{
32
33 namespace tools{
34
35 template <class T>
36 int digits(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T));
37 template <class T>
38 T epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T));
39
40 }
41
42 namespace policies{
43
44 //
45 // Define macros for our default policies, if they're not defined already:
46 //
47 #ifndef BOOST_MATH_DOMAIN_ERROR_POLICY
48 #define BOOST_MATH_DOMAIN_ERROR_POLICY throw_on_error
49 #endif
50 #ifndef BOOST_MATH_POLE_ERROR_POLICY
51 #define BOOST_MATH_POLE_ERROR_POLICY throw_on_error
52 #endif
53 #ifndef BOOST_MATH_OVERFLOW_ERROR_POLICY
54 #define BOOST_MATH_OVERFLOW_ERROR_POLICY throw_on_error
55 #endif
56 #ifndef BOOST_MATH_EVALUATION_ERROR_POLICY
57 #define BOOST_MATH_EVALUATION_ERROR_POLICY throw_on_error
58 #endif
59 #ifndef BOOST_MATH_ROUNDING_ERROR_POLICY
60 #define BOOST_MATH_ROUNDING_ERROR_POLICY throw_on_error
61 #endif
62 #ifndef BOOST_MATH_UNDERFLOW_ERROR_POLICY
63 #define BOOST_MATH_UNDERFLOW_ERROR_POLICY ignore_error
64 #endif
65 #ifndef BOOST_MATH_DENORM_ERROR_POLICY
66 #define BOOST_MATH_DENORM_ERROR_POLICY ignore_error
67 #endif
68 #ifndef BOOST_MATH_INDETERMINATE_RESULT_ERROR_POLICY
69 #define BOOST_MATH_INDETERMINATE_RESULT_ERROR_POLICY ignore_error
70 #endif
71 #ifndef BOOST_MATH_DIGITS10_POLICY
72 #define BOOST_MATH_DIGITS10_POLICY 0
73 #endif
74 #ifndef BOOST_MATH_PROMOTE_FLOAT_POLICY
75 #define BOOST_MATH_PROMOTE_FLOAT_POLICY true
76 #endif
77 #ifndef BOOST_MATH_PROMOTE_DOUBLE_POLICY
78 #ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
79 #define BOOST_MATH_PROMOTE_DOUBLE_POLICY false
80 #else
81 #define BOOST_MATH_PROMOTE_DOUBLE_POLICY true
82 #endif
83 #endif
84 #ifndef BOOST_MATH_DISCRETE_QUANTILE_POLICY
85 #define BOOST_MATH_DISCRETE_QUANTILE_POLICY integer_round_outwards
86 #endif
87 #ifndef BOOST_MATH_ASSERT_UNDEFINED_POLICY
88 #define BOOST_MATH_ASSERT_UNDEFINED_POLICY true
89 #endif
90 #ifndef BOOST_MATH_MAX_SERIES_ITERATION_POLICY
91 #define BOOST_MATH_MAX_SERIES_ITERATION_POLICY 1000000
92 #endif
93 #ifndef BOOST_MATH_MAX_ROOT_ITERATION_POLICY
94 #define BOOST_MATH_MAX_ROOT_ITERATION_POLICY 200
95 #endif
96
97 #if !defined(__BORLANDC__) \
98 && !(defined(__GNUC__) && (__GNUC__ == 3) && (__GNUC_MINOR__ <= 2))
99 #define BOOST_MATH_META_INT(type, name, Default)\
100 template <type N = Default> struct name : public boost::mpl::int_<N>{};\
101 namespace detail{\
102 template <type N>\
103 char test_is_valid_arg(const name<N>*);\
104 char test_is_default_arg(const name<Default>*);\
105 template <class T> struct is_##name##_imp\
106 {\
107 template <type N> static char test(const name<N>*);\
108 static double test(...);\
109 BOOST_STATIC_CONSTANT(bool, value = sizeof(test(static_cast<T*>(0))) == 1);\
110 };\
111 }\
112 template <class T> struct is_##name : public boost::mpl::bool_< ::boost::math::policies::detail::is_##name##_imp<T>::value>{};
113
114 #define BOOST_MATH_META_BOOL(name, Default)\
115 template <bool N = Default> struct name : public boost::mpl::bool_<N>{};\
116 namespace detail{\
117 template <bool N>\
118 char test_is_valid_arg(const name<N>*);\
119 char test_is_default_arg(const name<Default>*);\
120 template <class T> struct is_##name##_imp\
121 {\
122 template <bool N> static char test(const name<N>*);\
123 static double test(...);\
124 BOOST_STATIC_CONSTANT(bool, value = sizeof(test(static_cast<T*>(0))) == 1);\
125 };\
126 }\
127 template <class T> struct is_##name : public boost::mpl::bool_< ::boost::math::policies::detail::is_##name##_imp<T>::value>{};
128 #else
129 #define BOOST_MATH_META_INT(Type, name, Default)\
130 template <Type N = Default> struct name : public boost::mpl::int_<N>{};\
131 namespace detail{\
132 template <Type N>\
133 char test_is_valid_arg(const name<N>*);\
134 char test_is_default_arg(const name<Default>*);\
135 template <class T> struct is_##name##_tester\
136 {\
137 template <Type N> static char test(const name<N>&);\
138 static double test(...);\
139 };\
140 template <class T> struct is_##name##_imp\
141 {\
142 static T inst;\
143 BOOST_STATIC_CONSTANT(bool, value = sizeof( ::boost::math::policies::detail::is_##name##_tester<T>::test(inst)) == 1);\
144 };\
145 }\
146 template <class T> struct is_##name : public boost::mpl::bool_< ::boost::math::policies::detail::is_##name##_imp<T>::value>\
147 {\
148 template <class U> struct apply{ typedef is_##name<U> type; };\
149 };
150
151 #define BOOST_MATH_META_BOOL(name, Default)\
152 template <bool N = Default> struct name : public boost::mpl::bool_<N>{};\
153 namespace detail{\
154 template <bool N>\
155 char test_is_valid_arg(const name<N>*);\
156 char test_is_default_arg(const name<Default>*);\
157 template <class T> struct is_##name##_tester\
158 {\
159 template <bool N> static char test(const name<N>&);\
160 static double test(...);\
161 };\
162 template <class T> struct is_##name##_imp\
163 {\
164 static T inst;\
165 BOOST_STATIC_CONSTANT(bool, value = sizeof( ::boost::math::policies::detail::is_##name##_tester<T>::test(inst)) == 1);\
166 };\
167 }\
168 template <class T> struct is_##name : public boost::mpl::bool_< ::boost::math::policies::detail::is_##name##_imp<T>::value>\
169 {\
170 template <class U> struct apply{ typedef is_##name<U> type; };\
171 };
172 #endif
173 //
174 // Begin by defining policy types for error handling:
175 //
176 enum error_policy_type
177 {
178 throw_on_error = 0,
179 errno_on_error = 1,
180 ignore_error = 2,
181 user_error = 3
182 };
183
184 BOOST_MATH_META_INT(error_policy_type, domain_error, BOOST_MATH_DOMAIN_ERROR_POLICY)
185 BOOST_MATH_META_INT(error_policy_type, pole_error, BOOST_MATH_POLE_ERROR_POLICY)
186 BOOST_MATH_META_INT(error_policy_type, overflow_error, BOOST_MATH_OVERFLOW_ERROR_POLICY)
187 BOOST_MATH_META_INT(error_policy_type, underflow_error, BOOST_MATH_UNDERFLOW_ERROR_POLICY)
188 BOOST_MATH_META_INT(error_policy_type, denorm_error, BOOST_MATH_DENORM_ERROR_POLICY)
189 BOOST_MATH_META_INT(error_policy_type, evaluation_error, BOOST_MATH_EVALUATION_ERROR_POLICY)
190 BOOST_MATH_META_INT(error_policy_type, rounding_error, BOOST_MATH_ROUNDING_ERROR_POLICY)
191 BOOST_MATH_META_INT(error_policy_type, indeterminate_result_error, BOOST_MATH_INDETERMINATE_RESULT_ERROR_POLICY)
192
193 //
194 // Policy types for internal promotion:
195 //
196 BOOST_MATH_META_BOOL(promote_float, BOOST_MATH_PROMOTE_FLOAT_POLICY)
197 BOOST_MATH_META_BOOL(promote_double, BOOST_MATH_PROMOTE_DOUBLE_POLICY)
198 BOOST_MATH_META_BOOL(assert_undefined, BOOST_MATH_ASSERT_UNDEFINED_POLICY)
199 //
200 // Policy types for discrete quantiles:
201 //
202 enum discrete_quantile_policy_type
203 {
204 real,
205 integer_round_outwards,
206 integer_round_inwards,
207 integer_round_down,
208 integer_round_up,
209 integer_round_nearest
210 };
211
212 BOOST_MATH_META_INT(discrete_quantile_policy_type, discrete_quantile, BOOST_MATH_DISCRETE_QUANTILE_POLICY)
213 //
214 // Precision:
215 //
216 BOOST_MATH_META_INT(int, digits10, BOOST_MATH_DIGITS10_POLICY)
217 BOOST_MATH_META_INT(int, digits2, 0)
218 //
219 // Iterations:
220 //
221 BOOST_MATH_META_INT(unsigned long, max_series_iterations, BOOST_MATH_MAX_SERIES_ITERATION_POLICY)
222 BOOST_MATH_META_INT(unsigned long, max_root_iterations, BOOST_MATH_MAX_ROOT_ITERATION_POLICY)
223 //
224 // Define the names for each possible policy:
225 //
226 #define BOOST_MATH_PARAMETER(name)\
227 BOOST_PARAMETER_TEMPLATE_KEYWORD(name##_name)\
228 BOOST_PARAMETER_NAME(name##_name)
229
230 struct default_policy{};
231
232 namespace detail{
233 //
234 // Trait to work out bits precision from digits10 and digits2:
235 //
236 template <class Digits10, class Digits2>
237 struct precision
238 {
239 //
240 // Now work out the precision:
241 //
242 typedef typename mpl::if_c<
243 (Digits10::value == 0),
244 digits2<0>,
245 digits2<((Digits10::value + 1) * 1000L) / 301L>
246 >::type digits2_type;
247 public:
248 #ifdef __BORLANDC__
249 typedef typename mpl::if_c<
250 (Digits2::value > ::boost::math::policies::detail::precision<Digits10,Digits2>::digits2_type::value),
251 Digits2, digits2_type>::type type;
252 #else
253 typedef typename mpl::if_c<
254 (Digits2::value > digits2_type::value),
255 Digits2, digits2_type>::type type;
256 #endif
257 };
258
259 template <class A, class B, bool b>
260 struct select_result
261 {
262 typedef A type;
263 };
264 template <class A, class B>
265 struct select_result<A, B, false>
266 {
267 typedef typename mpl::deref<B>::type type;
268 };
269
270 template <class Seq, class Pred, class DefaultType>
271 struct find_arg
272 {
273 private:
274 typedef typename mpl::find_if<Seq, Pred>::type iter;
275 typedef typename mpl::end<Seq>::type end_type;
276 public:
277 typedef typename select_result<
278 DefaultType, iter,
279 ::boost::is_same<iter, end_type>::value>::type type;
280 };
281
282 double test_is_valid_arg(...);
283 double test_is_default_arg(...);
284 char test_is_valid_arg(const default_policy*);
285 char test_is_default_arg(const default_policy*);
286
287 template <class T>
288 struct is_valid_policy_imp
289 {
290 BOOST_STATIC_CONSTANT(bool, value = sizeof(::boost::math::policies::detail::test_is_valid_arg(static_cast<T*>(0))) == 1);
291 };
292
293 template <class T>
294 struct is_default_policy_imp
295 {
296 BOOST_STATIC_CONSTANT(bool, value = sizeof(::boost::math::policies::detail::test_is_default_arg(static_cast<T*>(0))) == 1);
297 };
298
299 template <class T> struct is_valid_policy
300 : public mpl::bool_<
301 ::boost::math::policies::detail::is_valid_policy_imp<T>::value>
302 {};
303
304 template <class T> struct is_default_policy
305 : public mpl::bool_<
306 ::boost::math::policies::detail::is_default_policy_imp<T>::value>
307 {
308 template <class U>
309 struct apply
310 {
311 typedef is_default_policy<U> type;
312 };
313 };
314
315 template <class Seq, class T, int N>
316 struct append_N
317 {
318 typedef typename mpl::push_back<Seq, T>::type new_seq;
319 typedef typename append_N<new_seq, T, N-1>::type type;
320 };
321
322 template <class Seq, class T>
323 struct append_N<Seq, T, 0>
324 {
325 typedef Seq type;
326 };
327
328 //
329 // Traits class to work out what template parameters our default
330 // policy<> class will have when modified for forwarding:
331 //
332 template <bool f, bool d>
333 struct default_args
334 {
335 typedef promote_float<false> arg1;
336 typedef promote_double<false> arg2;
337 };
338
339 template <>
340 struct default_args<false, false>
341 {
342 typedef default_policy arg1;
343 typedef default_policy arg2;
344 };
345
346 template <>
347 struct default_args<true, false>
348 {
349 typedef promote_float<false> arg1;
350 typedef default_policy arg2;
351 };
352
353 template <>
354 struct default_args<false, true>
355 {
356 typedef promote_double<false> arg1;
357 typedef default_policy arg2;
358 };
359
360 typedef default_args<BOOST_MATH_PROMOTE_FLOAT_POLICY, BOOST_MATH_PROMOTE_DOUBLE_POLICY>::arg1 forwarding_arg1;
361 typedef default_args<BOOST_MATH_PROMOTE_FLOAT_POLICY, BOOST_MATH_PROMOTE_DOUBLE_POLICY>::arg2 forwarding_arg2;
362
363 } // detail
364 //
365 // Now define the policy type with enough arguments to handle all
366 // the policies:
367 //
368 template <class A1 = default_policy,
369 class A2 = default_policy,
370 class A3 = default_policy,
371 class A4 = default_policy,
372 class A5 = default_policy,
373 class A6 = default_policy,
374 class A7 = default_policy,
375 class A8 = default_policy,
376 class A9 = default_policy,
377 class A10 = default_policy,
378 class A11 = default_policy,
379 class A12 = default_policy,
380 class A13 = default_policy>
381 struct policy
382 {
383 private:
384 //
385 // Validate all our arguments:
386 //
387 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A1>::value);
388 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A2>::value);
389 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A3>::value);
390 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A4>::value);
391 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A5>::value);
392 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A6>::value);
393 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A7>::value);
394 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A8>::value);
395 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A9>::value);
396 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A10>::value);
397 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A11>::value);
398 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A12>::value);
399 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A13>::value);
400 //
401 // Typelist of the arguments:
402 //
403 typedef mpl::list<A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13> arg_list;
404
405 public:
406 typedef typename detail::find_arg<arg_list, is_domain_error<mpl::_1>, domain_error<> >::type domain_error_type;
407 typedef typename detail::find_arg<arg_list, is_pole_error<mpl::_1>, pole_error<> >::type pole_error_type;
408 typedef typename detail::find_arg<arg_list, is_overflow_error<mpl::_1>, overflow_error<> >::type overflow_error_type;
409 typedef typename detail::find_arg<arg_list, is_underflow_error<mpl::_1>, underflow_error<> >::type underflow_error_type;
410 typedef typename detail::find_arg<arg_list, is_denorm_error<mpl::_1>, denorm_error<> >::type denorm_error_type;
411 typedef typename detail::find_arg<arg_list, is_evaluation_error<mpl::_1>, evaluation_error<> >::type evaluation_error_type;
412 typedef typename detail::find_arg<arg_list, is_rounding_error<mpl::_1>, rounding_error<> >::type rounding_error_type;
413 typedef typename detail::find_arg<arg_list, is_indeterminate_result_error<mpl::_1>, indeterminate_result_error<> >::type indeterminate_result_error_type;
414 private:
415 //
416 // Now work out the precision:
417 //
418 typedef typename detail::find_arg<arg_list, is_digits10<mpl::_1>, digits10<> >::type digits10_type;
419 typedef typename detail::find_arg<arg_list, is_digits2<mpl::_1>, digits2<> >::type bits_precision_type;
420 public:
421 typedef typename detail::precision<digits10_type, bits_precision_type>::type precision_type;
422 //
423 // Internal promotion:
424 //
425 typedef typename detail::find_arg<arg_list, is_promote_float<mpl::_1>, promote_float<> >::type promote_float_type;
426 typedef typename detail::find_arg<arg_list, is_promote_double<mpl::_1>, promote_double<> >::type promote_double_type;
427 //
428 // Discrete quantiles:
429 //
430 typedef typename detail::find_arg<arg_list, is_discrete_quantile<mpl::_1>, discrete_quantile<> >::type discrete_quantile_type;
431 //
432 // Mathematically undefined properties:
433 //
434 typedef typename detail::find_arg<arg_list, is_assert_undefined<mpl::_1>, assert_undefined<> >::type assert_undefined_type;
435 //
436 // Max iterations:
437 //
438 typedef typename detail::find_arg<arg_list, is_max_series_iterations<mpl::_1>, max_series_iterations<> >::type max_series_iterations_type;
439 typedef typename detail::find_arg<arg_list, is_max_root_iterations<mpl::_1>, max_root_iterations<> >::type max_root_iterations_type;
440 };
441 //
442 // These full specializations are defined to reduce the amount of
443 // template instantiations that have to take place when using the default
444 // policies, they have quite a large impact on compile times:
445 //
446 template <>
447 struct policy<default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy>
448 {
449 public:
450 typedef domain_error<> domain_error_type;
451 typedef pole_error<> pole_error_type;
452 typedef overflow_error<> overflow_error_type;
453 typedef underflow_error<> underflow_error_type;
454 typedef denorm_error<> denorm_error_type;
455 typedef evaluation_error<> evaluation_error_type;
456 typedef rounding_error<> rounding_error_type;
457 typedef indeterminate_result_error<> indeterminate_result_error_type;
458 #if BOOST_MATH_DIGITS10_POLICY == 0
459 typedef digits2<> precision_type;
460 #else
461 typedef detail::precision<digits10<>, digits2<> >::type precision_type;
462 #endif
463 typedef promote_float<> promote_float_type;
464 typedef promote_double<> promote_double_type;
465 typedef discrete_quantile<> discrete_quantile_type;
466 typedef assert_undefined<> assert_undefined_type;
467 typedef max_series_iterations<> max_series_iterations_type;
468 typedef max_root_iterations<> max_root_iterations_type;
469 };
470
471 template <>
472 struct policy<detail::forwarding_arg1, detail::forwarding_arg2, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy>
473 {
474 public:
475 typedef domain_error<> domain_error_type;
476 typedef pole_error<> pole_error_type;
477 typedef overflow_error<> overflow_error_type;
478 typedef underflow_error<> underflow_error_type;
479 typedef denorm_error<> denorm_error_type;
480 typedef evaluation_error<> evaluation_error_type;
481 typedef rounding_error<> rounding_error_type;
482 typedef indeterminate_result_error<> indeterminate_result_error_type;
483 #if BOOST_MATH_DIGITS10_POLICY == 0
484 typedef digits2<> precision_type;
485 #else
486 typedef detail::precision<digits10<>, digits2<> >::type precision_type;
487 #endif
488 typedef promote_float<false> promote_float_type;
489 typedef promote_double<false> promote_double_type;
490 typedef discrete_quantile<> discrete_quantile_type;
491 typedef assert_undefined<> assert_undefined_type;
492 typedef max_series_iterations<> max_series_iterations_type;
493 typedef max_root_iterations<> max_root_iterations_type;
494 };
495
496 template <class Policy,
497 class A1 = default_policy,
498 class A2 = default_policy,
499 class A3 = default_policy,
500 class A4 = default_policy,
501 class A5 = default_policy,
502 class A6 = default_policy,
503 class A7 = default_policy,
504 class A8 = default_policy,
505 class A9 = default_policy,
506 class A10 = default_policy,
507 class A11 = default_policy,
508 class A12 = default_policy,
509 class A13 = default_policy>
510 struct normalise
511 {
512 private:
513 typedef mpl::list<A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13> arg_list;
514 typedef typename detail::find_arg<arg_list, is_domain_error<mpl::_1>, typename Policy::domain_error_type >::type domain_error_type;
515 typedef typename detail::find_arg<arg_list, is_pole_error<mpl::_1>, typename Policy::pole_error_type >::type pole_error_type;
516 typedef typename detail::find_arg<arg_list, is_overflow_error<mpl::_1>, typename Policy::overflow_error_type >::type overflow_error_type;
517 typedef typename detail::find_arg<arg_list, is_underflow_error<mpl::_1>, typename Policy::underflow_error_type >::type underflow_error_type;
518 typedef typename detail::find_arg<arg_list, is_denorm_error<mpl::_1>, typename Policy::denorm_error_type >::type denorm_error_type;
519 typedef typename detail::find_arg<arg_list, is_evaluation_error<mpl::_1>, typename Policy::evaluation_error_type >::type evaluation_error_type;
520 typedef typename detail::find_arg<arg_list, is_rounding_error<mpl::_1>, typename Policy::rounding_error_type >::type rounding_error_type;
521 typedef typename detail::find_arg<arg_list, is_indeterminate_result_error<mpl::_1>, typename Policy::indeterminate_result_error_type >::type indeterminate_result_error_type;
522 //
523 // Now work out the precision:
524 //
525 typedef typename detail::find_arg<arg_list, is_digits10<mpl::_1>, digits10<> >::type digits10_type;
526 typedef typename detail::find_arg<arg_list, is_digits2<mpl::_1>, typename Policy::precision_type >::type bits_precision_type;
527 typedef typename detail::precision<digits10_type, bits_precision_type>::type precision_type;
528 //
529 // Internal promotion:
530 //
531 typedef typename detail::find_arg<arg_list, is_promote_float<mpl::_1>, typename Policy::promote_float_type >::type promote_float_type;
532 typedef typename detail::find_arg<arg_list, is_promote_double<mpl::_1>, typename Policy::promote_double_type >::type promote_double_type;
533 //
534 // Discrete quantiles:
535 //
536 typedef typename detail::find_arg<arg_list, is_discrete_quantile<mpl::_1>, typename Policy::discrete_quantile_type >::type discrete_quantile_type;
537 //
538 // Mathematically undefined properties:
539 //
540 typedef typename detail::find_arg<arg_list, is_assert_undefined<mpl::_1>, typename Policy::assert_undefined_type >::type assert_undefined_type;
541 //
542 // Max iterations:
543 //
544 typedef typename detail::find_arg<arg_list, is_max_series_iterations<mpl::_1>, typename Policy::max_series_iterations_type>::type max_series_iterations_type;
545 typedef typename detail::find_arg<arg_list, is_max_root_iterations<mpl::_1>, typename Policy::max_root_iterations_type>::type max_root_iterations_type;
546 //
547 // Define a typelist of the policies:
548 //
549 typedef mpl::vector<
550 domain_error_type,
551 pole_error_type,
552 overflow_error_type,
553 underflow_error_type,
554 denorm_error_type,
555 evaluation_error_type,
556 rounding_error_type,
557 indeterminate_result_error_type,
558 precision_type,
559 promote_float_type,
560 promote_double_type,
561 discrete_quantile_type,
562 assert_undefined_type,
563 max_series_iterations_type,
564 max_root_iterations_type> result_list;
565 //
566 // Remove all the policies that are the same as the default:
567 //
568 typedef typename mpl::remove_if<result_list, detail::is_default_policy<mpl::_> >::type reduced_list;
569 //
570 // Pad out the list with defaults:
571 //
572 typedef typename detail::append_N<reduced_list, default_policy, (14 - ::boost::mpl::size<reduced_list>::value)>::type result_type;
573 public:
574 typedef policy<
575 typename mpl::at<result_type, mpl::int_<0> >::type,
576 typename mpl::at<result_type, mpl::int_<1> >::type,
577 typename mpl::at<result_type, mpl::int_<2> >::type,
578 typename mpl::at<result_type, mpl::int_<3> >::type,
579 typename mpl::at<result_type, mpl::int_<4> >::type,
580 typename mpl::at<result_type, mpl::int_<5> >::type,
581 typename mpl::at<result_type, mpl::int_<6> >::type,
582 typename mpl::at<result_type, mpl::int_<7> >::type,
583 typename mpl::at<result_type, mpl::int_<8> >::type,
584 typename mpl::at<result_type, mpl::int_<9> >::type,
585 typename mpl::at<result_type, mpl::int_<10> >::type,
586 typename mpl::at<result_type, mpl::int_<11> >::type,
587 typename mpl::at<result_type, mpl::int_<12> >::type > type;
588 };
589 //
590 // Full specialisation to speed up compilation of the common case:
591 //
592 template <>
593 struct normalise<policy<>,
594 promote_float<false>,
595 promote_double<false>,
596 discrete_quantile<>,
597 assert_undefined<>,
598 default_policy,
599 default_policy,
600 default_policy,
601 default_policy,
602 default_policy,
603 default_policy,
604 default_policy>
605 {
606 typedef policy<detail::forwarding_arg1, detail::forwarding_arg2> type;
607 };
608
609 template <>
610 struct normalise<policy<detail::forwarding_arg1, detail::forwarding_arg2>,
611 promote_float<false>,
612 promote_double<false>,
613 discrete_quantile<>,
614 assert_undefined<>,
615 default_policy,
616 default_policy,
617 default_policy,
618 default_policy,
619 default_policy,
620 default_policy,
621 default_policy>
622 {
623 typedef policy<detail::forwarding_arg1, detail::forwarding_arg2> type;
624 };
625
make_policy()626 inline policy<> make_policy()
627 { return policy<>(); }
628
629 template <class A1>
make_policy(const A1 &)630 inline typename normalise<policy<>, A1>::type make_policy(const A1&)
631 {
632 typedef typename normalise<policy<>, A1>::type result_type;
633 return result_type();
634 }
635
636 template <class A1, class A2>
make_policy(const A1 &,const A2 &)637 inline typename normalise<policy<>, A1, A2>::type make_policy(const A1&, const A2&)
638 {
639 typedef typename normalise<policy<>, A1, A2>::type result_type;
640 return result_type();
641 }
642
643 template <class A1, class A2, class A3>
make_policy(const A1 &,const A2 &,const A3 &)644 inline typename normalise<policy<>, A1, A2, A3>::type make_policy(const A1&, const A2&, const A3&)
645 {
646 typedef typename normalise<policy<>, A1, A2, A3>::type result_type;
647 return result_type();
648 }
649
650 template <class A1, class A2, class A3, class A4>
make_policy(const A1 &,const A2 &,const A3 &,const A4 &)651 inline typename normalise<policy<>, A1, A2, A3, A4>::type make_policy(const A1&, const A2&, const A3&, const A4&)
652 {
653 typedef typename normalise<policy<>, A1, A2, A3, A4>::type result_type;
654 return result_type();
655 }
656
657 template <class A1, class A2, class A3, class A4, class A5>
make_policy(const A1 &,const A2 &,const A3 &,const A4 &,const A5 &)658 inline typename normalise<policy<>, A1, A2, A3, A4, A5>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&)
659 {
660 typedef typename normalise<policy<>, A1, A2, A3, A4, A5>::type result_type;
661 return result_type();
662 }
663
664 template <class A1, class A2, class A3, class A4, class A5, class A6>
make_policy(const A1 &,const A2 &,const A3 &,const A4 &,const A5 &,const A6 &)665 inline typename normalise<policy<>, A1, A2, A3, A4, A5, A6>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&)
666 {
667 typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6>::type result_type;
668 return result_type();
669 }
670
671 template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
make_policy(const A1 &,const A2 &,const A3 &,const A4 &,const A5 &,const A6 &,const A7 &)672 inline typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&, const A7&)
673 {
674 typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7>::type result_type;
675 return result_type();
676 }
677
678 template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
make_policy(const A1 &,const A2 &,const A3 &,const A4 &,const A5 &,const A6 &,const A7 &,const A8 &)679 inline typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&, const A7&, const A8&)
680 {
681 typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8>::type result_type;
682 return result_type();
683 }
684
685 template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
make_policy(const A1 &,const A2 &,const A3 &,const A4 &,const A5 &,const A6 &,const A7 &,const A8 &,const A9 &)686 inline typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&, const A7&, const A8&, const A9&)
687 {
688 typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9>::type result_type;
689 return result_type();
690 }
691
692 template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
make_policy(const A1 &,const A2 &,const A3 &,const A4 &,const A5 &,const A6 &,const A7 &,const A8 &,const A9 &,const A10 &)693 inline typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&, const A7&, const A8&, const A9&, const A10&)
694 {
695 typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>::type result_type;
696 return result_type();
697 }
698
699 template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10, class A11>
make_policy(const A1 &,const A2 &,const A3 &,const A4 &,const A5 &,const A6 &,const A7 &,const A8 &,const A9 &,const A10 &,const A11 &)700 inline typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&, const A7&, const A8&, const A9&, const A10&, const A11&)
701 {
702 typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11>::type result_type;
703 return result_type();
704 }
705
706 //
707 // Traits class to handle internal promotion:
708 //
709 template <class Real, class Policy>
710 struct evaluation
711 {
712 typedef Real type;
713 };
714
715 template <class Policy>
716 struct evaluation<float, Policy>
717 {
718 typedef typename mpl::if_<typename Policy::promote_float_type, double, float>::type type;
719 };
720
721 template <class Policy>
722 struct evaluation<double, Policy>
723 {
724 typedef typename mpl::if_<typename Policy::promote_double_type, long double, double>::type type;
725 };
726
727 #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
728
729 template <class Real>
730 struct basic_digits : public mpl::int_<0>{ };
731 template <>
732 struct basic_digits<float> : public mpl::int_<FLT_MANT_DIG>{ };
733 template <>
734 struct basic_digits<double> : public mpl::int_<DBL_MANT_DIG>{ };
735 template <>
736 struct basic_digits<long double> : public mpl::int_<LDBL_MANT_DIG>{ };
737
738 template <class Real, class Policy>
739 struct precision
740 {
741 BOOST_STATIC_ASSERT( ::std::numeric_limits<Real>::radix == 2);
742 typedef typename Policy::precision_type precision_type;
743 typedef basic_digits<Real> digits_t;
744 typedef typename mpl::if_<
745 mpl::equal_to<digits_t, mpl::int_<0> >,
746 // Possibly unknown precision:
747 precision_type,
748 typename mpl::if_<
749 mpl::or_<mpl::less_equal<digits_t, precision_type>, mpl::less_equal<precision_type, mpl::int_<0> > >,
750 // Default case, full precision for RealType:
751 digits2< ::std::numeric_limits<Real>::digits>,
752 // User customised precision:
753 precision_type
754 >::type
755 >::type type;
756 };
757
758 template <class Policy>
759 struct precision<float, Policy>
760 {
761 typedef digits2<FLT_MANT_DIG> type;
762 };
763 template <class Policy>
764 struct precision<double, Policy>
765 {
766 typedef digits2<DBL_MANT_DIG> type;
767 };
768 template <class Policy>
769 struct precision<long double, Policy>
770 {
771 typedef digits2<LDBL_MANT_DIG> type;
772 };
773
774 #else
775
776 template <class Real, class Policy>
777 struct precision
778 {
779 BOOST_STATIC_ASSERT((::std::numeric_limits<Real>::radix == 2) || ((::std::numeric_limits<Real>::is_specialized == 0) || (::std::numeric_limits<Real>::digits == 0)));
780 #ifndef __BORLANDC__
781 typedef typename Policy::precision_type precision_type;
782 typedef typename mpl::if_c<
783 ((::std::numeric_limits<Real>::is_specialized == 0) || (::std::numeric_limits<Real>::digits == 0)),
784 // Possibly unknown precision:
785 precision_type,
786 typename mpl::if_c<
787 ((::std::numeric_limits<Real>::digits <= precision_type::value)
788 || (Policy::precision_type::value <= 0)),
789 // Default case, full precision for RealType:
790 digits2< ::std::numeric_limits<Real>::digits>,
791 // User customised precision:
792 precision_type
793 >::type
794 >::type type;
795 #else
796 typedef typename Policy::precision_type precision_type;
797 typedef mpl::int_< ::std::numeric_limits<Real>::digits> digits_t;
798 typedef mpl::bool_< ::std::numeric_limits<Real>::is_specialized> spec_t;
799 typedef typename mpl::if_<
800 mpl::or_<mpl::equal_to<spec_t, mpl::false_>, mpl::equal_to<digits_t, mpl::int_<0> > >,
801 // Possibly unknown precision:
802 precision_type,
803 typename mpl::if_<
804 mpl::or_<mpl::less_equal<digits_t, precision_type>, mpl::less_equal<precision_type, mpl::int_<0> > >,
805 // Default case, full precision for RealType:
806 digits2< ::std::numeric_limits<Real>::digits>,
807 // User customised precision:
808 precision_type
809 >::type
810 >::type type;
811 #endif
812 };
813
814 #endif
815
816 namespace detail{
817
818 template <class T, class Policy>
digits_imp(mpl::true_ const &)819 inline int digits_imp(mpl::true_ const&)
820 {
821 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
822 BOOST_STATIC_ASSERT( ::std::numeric_limits<T>::is_specialized);
823 #else
824 BOOST_ASSERT(::std::numeric_limits<T>::is_specialized);
825 #endif
826 typedef typename boost::math::policies::precision<T, Policy>::type p_t;
827 return p_t::value;
828 }
829
830 template <class T, class Policy>
digits_imp(mpl::false_ const &)831 inline int digits_imp(mpl::false_ const&)
832 {
833 return tools::digits<T>();
834 }
835
836 } // namespace detail
837
838 template <class T, class Policy>
digits(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE (T))839 inline int digits(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T))
840 {
841 typedef mpl::bool_< std::numeric_limits<T>::is_specialized > tag_type;
842 return detail::digits_imp<T, Policy>(tag_type());
843 }
844
845 template <class Policy>
get_max_series_iterations()846 inline unsigned long get_max_series_iterations()
847 {
848 typedef typename Policy::max_series_iterations_type iter_type;
849 return iter_type::value;
850 }
851
852 template <class Policy>
get_max_root_iterations()853 inline unsigned long get_max_root_iterations()
854 {
855 typedef typename Policy::max_root_iterations_type iter_type;
856 return iter_type::value;
857 }
858
859 namespace detail{
860
861 template <class T, class Digits, class Small, class Default>
862 struct series_factor_calc
863 {
getboost::math::policies::detail::series_factor_calc864 static T get()
865 {
866 return ldexp(T(1.0), 1 - Digits::value);
867 }
868 };
869
870 template <class T, class Digits>
871 struct series_factor_calc<T, Digits, mpl::true_, mpl::true_>
872 {
getboost::math::policies::detail::series_factor_calc873 static T get()
874 {
875 return boost::math::tools::epsilon<T>();
876 }
877 };
878 template <class T, class Digits>
879 struct series_factor_calc<T, Digits, mpl::true_, mpl::false_>
880 {
getboost::math::policies::detail::series_factor_calc881 static T get()
882 {
883 static const boost::uintmax_t v = static_cast<boost::uintmax_t>(1u) << (Digits::value - 1);
884 return 1 / static_cast<T>(v);
885 }
886 };
887 template <class T, class Digits>
888 struct series_factor_calc<T, Digits, mpl::false_, mpl::true_>
889 {
getboost::math::policies::detail::series_factor_calc890 static T get()
891 {
892 return boost::math::tools::epsilon<T>();
893 }
894 };
895
896 template <class T, class Policy>
get_epsilon_imp(mpl::true_ const &)897 inline T get_epsilon_imp(mpl::true_ const&)
898 {
899 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
900 BOOST_STATIC_ASSERT( ::std::numeric_limits<T>::is_specialized);
901 BOOST_STATIC_ASSERT( ::std::numeric_limits<T>::radix == 2);
902 #else
903 BOOST_ASSERT(::std::numeric_limits<T>::is_specialized);
904 BOOST_ASSERT(::std::numeric_limits<T>::radix == 2);
905 #endif
906 typedef typename boost::math::policies::precision<T, Policy>::type p_t;
907 typedef mpl::bool_<p_t::value <= std::numeric_limits<boost::uintmax_t>::digits> is_small_int;
908 typedef mpl::bool_<p_t::value >= std::numeric_limits<T>::digits> is_default_value;
909 return series_factor_calc<T, p_t, is_small_int, is_default_value>::get();
910 }
911
912 template <class T, class Policy>
get_epsilon_imp(mpl::false_ const &)913 inline T get_epsilon_imp(mpl::false_ const&)
914 {
915 return tools::epsilon<T>();
916 }
917
918 } // namespace detail
919
920 template <class T, class Policy>
get_epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE (T))921 inline T get_epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T))
922 {
923 typedef mpl::bool_< (std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::radix == 2)) > tag_type;
924 return detail::get_epsilon_imp<T, Policy>(tag_type());
925 }
926
927 namespace detail{
928
929 template <class A1,
930 class A2,
931 class A3,
932 class A4,
933 class A5,
934 class A6,
935 class A7,
936 class A8,
937 class A9,
938 class A10,
939 class A11>
940 char test_is_policy(const policy<A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11>*);
941 double test_is_policy(...);
942
943 template <class P>
944 struct is_policy_imp
945 {
946 BOOST_STATIC_CONSTANT(bool, value = (sizeof(::boost::math::policies::detail::test_is_policy(static_cast<P*>(0))) == 1));
947 };
948
949 }
950
951 template <class P>
952 struct is_policy : public mpl::bool_< ::boost::math::policies::detail::is_policy_imp<P>::value> {};
953
954 //
955 // Helper traits class for distribution error handling:
956 //
957 template <class Policy>
958 struct constructor_error_check
959 {
960 typedef typename Policy::domain_error_type domain_error_type;
961 typedef typename mpl::if_c<
962 (domain_error_type::value == throw_on_error) || (domain_error_type::value == user_error),
963 mpl::true_,
964 mpl::false_>::type type;
965 };
966
967 template <class Policy>
968 struct method_error_check
969 {
970 typedef typename Policy::domain_error_type domain_error_type;
971 typedef typename mpl::if_c<
972 (domain_error_type::value == throw_on_error) && (domain_error_type::value != user_error),
973 mpl::false_,
974 mpl::true_>::type type;
975 };
976
977 }}} // namespaces
978
979 #endif // BOOST_MATH_POLICY_HPP
980
981
982
983