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