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::integral_constant<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::integral_constant<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::integral_constant<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::integral_constant<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::integral_constant<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::integral_constant<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::integral_constant<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::integral_constant<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 boost::integral_constant<bool, ::boost::math::policies::detail::is_valid_policy_imp<T>::value>
322 {};
323
324 template <class T> struct is_default_policy
325 : public boost::integral_constant<bool, ::boost::math::policies::detail::is_default_policy_imp<T>::value>
326 {
327 template <class U>
328 struct apply
329 {
330 typedef is_default_policy<U> type;
331 };
332 };
333
334 template <class Seq, class T, int N>
335 struct append_N
336 {
337 typedef typename mpl::push_back<Seq, T>::type new_seq;
338 typedef typename append_N<new_seq, T, N-1>::type type;
339 };
340
341 template <class Seq, class T>
342 struct append_N<Seq, T, 0>
343 {
344 typedef Seq type;
345 };
346
347 //
348 // Traits class to work out what template parameters our default
349 // policy<> class will have when modified for forwarding:
350 //
351 template <bool f, bool d>
352 struct default_args
353 {
354 typedef promote_float<false> arg1;
355 typedef promote_double<false> arg2;
356 };
357
358 template <>
359 struct default_args<false, false>
360 {
361 typedef default_policy arg1;
362 typedef default_policy arg2;
363 };
364
365 template <>
366 struct default_args<true, false>
367 {
368 typedef promote_float<false> arg1;
369 typedef default_policy arg2;
370 };
371
372 template <>
373 struct default_args<false, true>
374 {
375 typedef promote_double<false> arg1;
376 typedef default_policy arg2;
377 };
378
379 typedef default_args<BOOST_MATH_PROMOTE_FLOAT_POLICY, BOOST_MATH_PROMOTE_DOUBLE_POLICY>::arg1 forwarding_arg1;
380 typedef default_args<BOOST_MATH_PROMOTE_FLOAT_POLICY, BOOST_MATH_PROMOTE_DOUBLE_POLICY>::arg2 forwarding_arg2;
381
382 } // detail
383 //
384 // Now define the policy type with enough arguments to handle all
385 // the policies:
386 //
387 template <class A1 = default_policy,
388 class A2 = default_policy,
389 class A3 = default_policy,
390 class A4 = default_policy,
391 class A5 = default_policy,
392 class A6 = default_policy,
393 class A7 = default_policy,
394 class A8 = default_policy,
395 class A9 = default_policy,
396 class A10 = default_policy,
397 class A11 = default_policy,
398 class A12 = default_policy,
399 class A13 = default_policy>
400 struct policy
401 {
402 private:
403 //
404 // Validate all our arguments:
405 //
406 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A1>::value);
407 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A2>::value);
408 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A3>::value);
409 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A4>::value);
410 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A5>::value);
411 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A6>::value);
412 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A7>::value);
413 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A8>::value);
414 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A9>::value);
415 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A10>::value);
416 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A11>::value);
417 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A12>::value);
418 BOOST_STATIC_ASSERT(::boost::math::policies::detail::is_valid_policy<A13>::value);
419 //
420 // Typelist of the arguments:
421 //
422 typedef mpl::list<A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13> arg_list;
423
424 public:
425 typedef typename detail::find_arg<arg_list, is_domain_error<mpl::_1>, domain_error<> >::type domain_error_type;
426 typedef typename detail::find_arg<arg_list, is_pole_error<mpl::_1>, pole_error<> >::type pole_error_type;
427 typedef typename detail::find_arg<arg_list, is_overflow_error<mpl::_1>, overflow_error<> >::type overflow_error_type;
428 typedef typename detail::find_arg<arg_list, is_underflow_error<mpl::_1>, underflow_error<> >::type underflow_error_type;
429 typedef typename detail::find_arg<arg_list, is_denorm_error<mpl::_1>, denorm_error<> >::type denorm_error_type;
430 typedef typename detail::find_arg<arg_list, is_evaluation_error<mpl::_1>, evaluation_error<> >::type evaluation_error_type;
431 typedef typename detail::find_arg<arg_list, is_rounding_error<mpl::_1>, rounding_error<> >::type rounding_error_type;
432 typedef typename detail::find_arg<arg_list, is_indeterminate_result_error<mpl::_1>, indeterminate_result_error<> >::type indeterminate_result_error_type;
433 private:
434 //
435 // Now work out the precision:
436 //
437 typedef typename detail::find_arg<arg_list, is_digits10<mpl::_1>, digits10<> >::type digits10_type;
438 typedef typename detail::find_arg<arg_list, is_digits2<mpl::_1>, digits2<> >::type bits_precision_type;
439 public:
440 typedef typename detail::precision<digits10_type, bits_precision_type>::type precision_type;
441 //
442 // Internal promotion:
443 //
444 typedef typename detail::find_arg<arg_list, is_promote_float<mpl::_1>, promote_float<> >::type promote_float_type;
445 typedef typename detail::find_arg<arg_list, is_promote_double<mpl::_1>, promote_double<> >::type promote_double_type;
446 //
447 // Discrete quantiles:
448 //
449 typedef typename detail::find_arg<arg_list, is_discrete_quantile<mpl::_1>, discrete_quantile<> >::type discrete_quantile_type;
450 //
451 // Mathematically undefined properties:
452 //
453 typedef typename detail::find_arg<arg_list, is_assert_undefined<mpl::_1>, assert_undefined<> >::type assert_undefined_type;
454 //
455 // Max iterations:
456 //
457 typedef typename detail::find_arg<arg_list, is_max_series_iterations<mpl::_1>, max_series_iterations<> >::type max_series_iterations_type;
458 typedef typename detail::find_arg<arg_list, is_max_root_iterations<mpl::_1>, max_root_iterations<> >::type max_root_iterations_type;
459 };
460 //
461 // These full specializations are defined to reduce the amount of
462 // template instantiations that have to take place when using the default
463 // policies, they have quite a large impact on compile times:
464 //
465 template <>
466 struct policy<default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy, default_policy>
467 {
468 public:
469 typedef domain_error<> domain_error_type;
470 typedef pole_error<> pole_error_type;
471 typedef overflow_error<> overflow_error_type;
472 typedef underflow_error<> underflow_error_type;
473 typedef denorm_error<> denorm_error_type;
474 typedef evaluation_error<> evaluation_error_type;
475 typedef rounding_error<> rounding_error_type;
476 typedef indeterminate_result_error<> indeterminate_result_error_type;
477 #if BOOST_MATH_DIGITS10_POLICY == 0
478 typedef digits2<> precision_type;
479 #else
480 typedef detail::precision<digits10<>, digits2<> >::type precision_type;
481 #endif
482 typedef promote_float<> promote_float_type;
483 typedef promote_double<> promote_double_type;
484 typedef discrete_quantile<> discrete_quantile_type;
485 typedef assert_undefined<> assert_undefined_type;
486 typedef max_series_iterations<> max_series_iterations_type;
487 typedef max_root_iterations<> max_root_iterations_type;
488 };
489
490 template <>
491 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>
492 {
493 public:
494 typedef domain_error<> domain_error_type;
495 typedef pole_error<> pole_error_type;
496 typedef overflow_error<> overflow_error_type;
497 typedef underflow_error<> underflow_error_type;
498 typedef denorm_error<> denorm_error_type;
499 typedef evaluation_error<> evaluation_error_type;
500 typedef rounding_error<> rounding_error_type;
501 typedef indeterminate_result_error<> indeterminate_result_error_type;
502 #if BOOST_MATH_DIGITS10_POLICY == 0
503 typedef digits2<> precision_type;
504 #else
505 typedef detail::precision<digits10<>, digits2<> >::type precision_type;
506 #endif
507 typedef promote_float<false> promote_float_type;
508 typedef promote_double<false> promote_double_type;
509 typedef discrete_quantile<> discrete_quantile_type;
510 typedef assert_undefined<> assert_undefined_type;
511 typedef max_series_iterations<> max_series_iterations_type;
512 typedef max_root_iterations<> max_root_iterations_type;
513 };
514
515 template <class Policy,
516 class A1 = default_policy,
517 class A2 = default_policy,
518 class A3 = default_policy,
519 class A4 = default_policy,
520 class A5 = default_policy,
521 class A6 = default_policy,
522 class A7 = default_policy,
523 class A8 = default_policy,
524 class A9 = default_policy,
525 class A10 = default_policy,
526 class A11 = default_policy,
527 class A12 = default_policy,
528 class A13 = default_policy>
529 struct normalise
530 {
531 private:
532 typedef mpl::list<A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13> arg_list;
533 typedef typename detail::find_arg<arg_list, is_domain_error<mpl::_1>, typename Policy::domain_error_type >::type domain_error_type;
534 typedef typename detail::find_arg<arg_list, is_pole_error<mpl::_1>, typename Policy::pole_error_type >::type pole_error_type;
535 typedef typename detail::find_arg<arg_list, is_overflow_error<mpl::_1>, typename Policy::overflow_error_type >::type overflow_error_type;
536 typedef typename detail::find_arg<arg_list, is_underflow_error<mpl::_1>, typename Policy::underflow_error_type >::type underflow_error_type;
537 typedef typename detail::find_arg<arg_list, is_denorm_error<mpl::_1>, typename Policy::denorm_error_type >::type denorm_error_type;
538 typedef typename detail::find_arg<arg_list, is_evaluation_error<mpl::_1>, typename Policy::evaluation_error_type >::type evaluation_error_type;
539 typedef typename detail::find_arg<arg_list, is_rounding_error<mpl::_1>, typename Policy::rounding_error_type >::type rounding_error_type;
540 typedef typename detail::find_arg<arg_list, is_indeterminate_result_error<mpl::_1>, typename Policy::indeterminate_result_error_type >::type indeterminate_result_error_type;
541 //
542 // Now work out the precision:
543 //
544 typedef typename detail::find_arg<arg_list, is_digits10<mpl::_1>, digits10<> >::type digits10_type;
545 typedef typename detail::find_arg<arg_list, is_digits2<mpl::_1>, typename Policy::precision_type >::type bits_precision_type;
546 typedef typename detail::precision<digits10_type, bits_precision_type>::type precision_type;
547 //
548 // Internal promotion:
549 //
550 typedef typename detail::find_arg<arg_list, is_promote_float<mpl::_1>, typename Policy::promote_float_type >::type promote_float_type;
551 typedef typename detail::find_arg<arg_list, is_promote_double<mpl::_1>, typename Policy::promote_double_type >::type promote_double_type;
552 //
553 // Discrete quantiles:
554 //
555 typedef typename detail::find_arg<arg_list, is_discrete_quantile<mpl::_1>, typename Policy::discrete_quantile_type >::type discrete_quantile_type;
556 //
557 // Mathematically undefined properties:
558 //
559 typedef typename detail::find_arg<arg_list, is_assert_undefined<mpl::_1>, typename Policy::assert_undefined_type >::type assert_undefined_type;
560 //
561 // Max iterations:
562 //
563 typedef typename detail::find_arg<arg_list, is_max_series_iterations<mpl::_1>, typename Policy::max_series_iterations_type>::type max_series_iterations_type;
564 typedef typename detail::find_arg<arg_list, is_max_root_iterations<mpl::_1>, typename Policy::max_root_iterations_type>::type max_root_iterations_type;
565 //
566 // Define a typelist of the policies:
567 //
568 typedef mpl::vector<
569 domain_error_type,
570 pole_error_type,
571 overflow_error_type,
572 underflow_error_type,
573 denorm_error_type,
574 evaluation_error_type,
575 rounding_error_type,
576 indeterminate_result_error_type,
577 precision_type,
578 promote_float_type,
579 promote_double_type,
580 discrete_quantile_type,
581 assert_undefined_type,
582 max_series_iterations_type,
583 max_root_iterations_type> result_list;
584 //
585 // Remove all the policies that are the same as the default:
586 //
587 typedef typename mpl::remove_if<result_list, detail::is_default_policy<mpl::_> >::type reduced_list;
588 //
589 // Pad out the list with defaults:
590 //
591 typedef typename detail::append_N<reduced_list, default_policy, (14 - ::boost::mpl::size<reduced_list>::value)>::type result_type;
592 public:
593 typedef policy<
594 typename mpl::at<result_type, boost::integral_constant<int, 0> >::type,
595 typename mpl::at<result_type, boost::integral_constant<int, 1> >::type,
596 typename mpl::at<result_type, boost::integral_constant<int, 2> >::type,
597 typename mpl::at<result_type, boost::integral_constant<int, 3> >::type,
598 typename mpl::at<result_type, boost::integral_constant<int, 4> >::type,
599 typename mpl::at<result_type, boost::integral_constant<int, 5> >::type,
600 typename mpl::at<result_type, boost::integral_constant<int, 6> >::type,
601 typename mpl::at<result_type, boost::integral_constant<int, 7> >::type,
602 typename mpl::at<result_type, boost::integral_constant<int, 8> >::type,
603 typename mpl::at<result_type, boost::integral_constant<int, 9> >::type,
604 typename mpl::at<result_type, boost::integral_constant<int, 10> >::type,
605 typename mpl::at<result_type, boost::integral_constant<int, 11> >::type,
606 typename mpl::at<result_type, boost::integral_constant<int, 12> >::type > type;
607 };
608 //
609 // Full specialisation to speed up compilation of the common case:
610 //
611 template <>
612 struct normalise<policy<>,
613 promote_float<false>,
614 promote_double<false>,
615 discrete_quantile<>,
616 assert_undefined<>,
617 default_policy,
618 default_policy,
619 default_policy,
620 default_policy,
621 default_policy,
622 default_policy,
623 default_policy>
624 {
625 typedef policy<detail::forwarding_arg1, detail::forwarding_arg2> type;
626 };
627
628 template <>
629 struct normalise<policy<detail::forwarding_arg1, detail::forwarding_arg2>,
630 promote_float<false>,
631 promote_double<false>,
632 discrete_quantile<>,
633 assert_undefined<>,
634 default_policy,
635 default_policy,
636 default_policy,
637 default_policy,
638 default_policy,
639 default_policy,
640 default_policy>
641 {
642 typedef policy<detail::forwarding_arg1, detail::forwarding_arg2> type;
643 };
644
make_policy()645 inline BOOST_MATH_CONSTEXPR policy<> make_policy() BOOST_NOEXCEPT
646 { return policy<>(); }
647
648 template <class A1>
make_policy(const A1 &)649 inline BOOST_MATH_CONSTEXPR typename normalise<policy<>, A1>::type make_policy(const A1&) BOOST_NOEXCEPT
650 {
651 typedef typename normalise<policy<>, A1>::type result_type;
652 return result_type();
653 }
654
655 template <class A1, class A2>
make_policy(const A1 &,const A2 &)656 inline BOOST_MATH_CONSTEXPR typename normalise<policy<>, A1, A2>::type make_policy(const A1&, const A2&) BOOST_NOEXCEPT
657 {
658 typedef typename normalise<policy<>, A1, A2>::type result_type;
659 return result_type();
660 }
661
662 template <class A1, class A2, class A3>
make_policy(const A1 &,const A2 &,const A3 &)663 inline BOOST_MATH_CONSTEXPR typename normalise<policy<>, A1, A2, A3>::type make_policy(const A1&, const A2&, const A3&) BOOST_NOEXCEPT
664 {
665 typedef typename normalise<policy<>, A1, A2, A3>::type result_type;
666 return result_type();
667 }
668
669 template <class A1, class A2, class A3, class A4>
make_policy(const A1 &,const A2 &,const A3 &,const A4 &)670 inline BOOST_MATH_CONSTEXPR typename normalise<policy<>, A1, A2, A3, A4>::type make_policy(const A1&, const A2&, const A3&, const A4&) BOOST_NOEXCEPT
671 {
672 typedef typename normalise<policy<>, A1, A2, A3, A4>::type result_type;
673 return result_type();
674 }
675
676 template <class A1, class A2, class A3, class A4, class A5>
make_policy(const A1 &,const A2 &,const A3 &,const A4 &,const A5 &)677 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
678 {
679 typedef typename normalise<policy<>, A1, A2, A3, A4, A5>::type result_type;
680 return result_type();
681 }
682
683 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 &)684 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
685 {
686 typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6>::type result_type;
687 return result_type();
688 }
689
690 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 &)691 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
692 {
693 typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7>::type result_type;
694 return result_type();
695 }
696
697 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 &)698 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
699 {
700 typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8>::type result_type;
701 return result_type();
702 }
703
704 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 &)705 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
706 {
707 typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9>::type result_type;
708 return result_type();
709 }
710
711 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 &)712 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
713 {
714 typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>::type result_type;
715 return result_type();
716 }
717
718 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 &)719 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
720 {
721 typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11>::type result_type;
722 return result_type();
723 }
724
725 //
726 // Traits class to handle internal promotion:
727 //
728 template <class Real, class Policy>
729 struct evaluation
730 {
731 typedef Real type;
732 };
733
734 template <class Policy>
735 struct evaluation<float, Policy>
736 {
737 typedef typename mpl::if_<typename Policy::promote_float_type, double, float>::type type;
738 };
739
740 template <class Policy>
741 struct evaluation<double, Policy>
742 {
743 typedef typename mpl::if_<typename Policy::promote_double_type, long double, double>::type type;
744 };
745
746 #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
747
748 template <class Real>
749 struct basic_digits : public boost::integral_constant<int, 0>{ };
750 template <>
751 struct basic_digits<float> : public boost::integral_constant<int, FLT_MANT_DIG>{ };
752 template <>
753 struct basic_digits<double> : public boost::integral_constant<int, DBL_MANT_DIG>{ };
754 template <>
755 struct basic_digits<long double> : public boost::integral_constant<int, LDBL_MANT_DIG>{ };
756
757 template <class Real, class Policy>
758 struct precision
759 {
760 BOOST_STATIC_ASSERT( ::std::numeric_limits<Real>::radix == 2);
761 typedef typename Policy::precision_type precision_type;
762 typedef basic_digits<Real> digits_t;
763 typedef typename mpl::if_<
764 mpl::equal_to<digits_t, boost::integral_constant<int, 0> >,
765 // Possibly unknown precision:
766 precision_type,
767 typename mpl::if_<
768 mpl::or_<mpl::less_equal<digits_t, precision_type>, mpl::less_equal<precision_type, boost::integral_constant<int, 0> > >,
769 // Default case, full precision for RealType:
770 digits2< ::std::numeric_limits<Real>::digits>,
771 // User customised precision:
772 precision_type
773 >::type
774 >::type type;
775 };
776
777 template <class Policy>
778 struct precision<float, Policy>
779 {
780 typedef digits2<FLT_MANT_DIG> type;
781 };
782 template <class Policy>
783 struct precision<double, Policy>
784 {
785 typedef digits2<DBL_MANT_DIG> type;
786 };
787 template <class Policy>
788 struct precision<long double, Policy>
789 {
790 typedef digits2<LDBL_MANT_DIG> type;
791 };
792
793 #else
794
795 template <class Real, class Policy>
796 struct precision
797 {
798 BOOST_STATIC_ASSERT((::std::numeric_limits<Real>::radix == 2) || ((::std::numeric_limits<Real>::is_specialized == 0) || (::std::numeric_limits<Real>::digits == 0)));
799 #ifndef __BORLANDC__
800 typedef typename Policy::precision_type precision_type;
801 typedef typename mpl::if_c<
802 ((::std::numeric_limits<Real>::is_specialized == 0) || (::std::numeric_limits<Real>::digits == 0)),
803 // Possibly unknown precision:
804 precision_type,
805 typename mpl::if_c<
806 ((::std::numeric_limits<Real>::digits <= precision_type::value)
807 || (Policy::precision_type::value <= 0)),
808 // Default case, full precision for RealType:
809 digits2< ::std::numeric_limits<Real>::digits>,
810 // User customised precision:
811 precision_type
812 >::type
813 >::type type;
814 #else
815 typedef typename Policy::precision_type precision_type;
816 typedef boost::integral_constant<int, ::std::numeric_limits<Real>::digits> digits_t;
817 typedef boost::integral_constant<bool, ::std::numeric_limits<Real>::is_specialized> spec_t;
818 typedef typename mpl::if_<
819 mpl::or_<mpl::equal_to<spec_t, boost::true_type>, mpl::equal_to<digits_t, boost::integral_constant<int, 0> > >,
820 // Possibly unknown precision:
821 precision_type,
822 typename mpl::if_<
823 mpl::or_<mpl::less_equal<digits_t, precision_type>, mpl::less_equal<precision_type, boost::integral_constant<int, 0> > >,
824 // Default case, full precision for RealType:
825 digits2< ::std::numeric_limits<Real>::digits>,
826 // User customised precision:
827 precision_type
828 >::type
829 >::type type;
830 #endif
831 };
832
833 #endif
834
835 #ifdef BOOST_MATH_USE_FLOAT128
836
837 template <class Policy>
838 struct precision<BOOST_MATH_FLOAT128_TYPE, Policy>
839 {
840 typedef boost::integral_constant<int, 113> type;
841 };
842
843 #endif
844
845 namespace detail{
846
847 template <class T, class Policy>
digits_imp(boost::true_type const &)848 inline BOOST_MATH_CONSTEXPR int digits_imp(boost::true_type const&) BOOST_NOEXCEPT
849 {
850 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
851 BOOST_STATIC_ASSERT( ::std::numeric_limits<T>::is_specialized);
852 #else
853 BOOST_ASSERT(::std::numeric_limits<T>::is_specialized);
854 #endif
855 typedef typename boost::math::policies::precision<T, Policy>::type p_t;
856 return p_t::value;
857 }
858
859 template <class T, class Policy>
digits_imp(boost::false_type const &)860 inline BOOST_MATH_CONSTEXPR int digits_imp(boost::false_type const&) BOOST_NOEXCEPT
861 {
862 return tools::digits<T>();
863 }
864
865 } // namespace detail
866
867 template <class T, class Policy>
digits(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE (T))868 inline BOOST_MATH_CONSTEXPR int digits(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) BOOST_NOEXCEPT
869 {
870 typedef boost::integral_constant<bool, std::numeric_limits<T>::is_specialized > tag_type;
871 return detail::digits_imp<T, Policy>(tag_type());
872 }
873 template <class T, class Policy>
digits_base10(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE (T))874 inline BOOST_MATH_CONSTEXPR int digits_base10(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) BOOST_NOEXCEPT
875 {
876 return boost::math::policies::digits<T, Policy>() * 301 / 1000L;
877 }
878
879 template <class Policy>
get_max_series_iterations()880 inline BOOST_MATH_CONSTEXPR unsigned long get_max_series_iterations() BOOST_NOEXCEPT
881 {
882 typedef typename Policy::max_series_iterations_type iter_type;
883 return iter_type::value;
884 }
885
886 template <class Policy>
get_max_root_iterations()887 inline BOOST_MATH_CONSTEXPR unsigned long get_max_root_iterations() BOOST_NOEXCEPT
888 {
889 typedef typename Policy::max_root_iterations_type iter_type;
890 return iter_type::value;
891 }
892
893 namespace detail{
894
895 template <class T, class Digits, class Small, class Default>
896 struct series_factor_calc
897 {
getboost::math::policies::detail::series_factor_calc898 static T get() BOOST_MATH_NOEXCEPT(T)
899 {
900 return ldexp(T(1.0), 1 - Digits::value);
901 }
902 };
903
904 template <class T, class Digits>
905 struct series_factor_calc<T, Digits, boost::true_type, boost::true_type>
906 {
getboost::math::policies::detail::series_factor_calc907 static BOOST_MATH_CONSTEXPR T get() BOOST_MATH_NOEXCEPT(T)
908 {
909 return boost::math::tools::epsilon<T>();
910 }
911 };
912 template <class T, class Digits>
913 struct series_factor_calc<T, Digits, boost::true_type, boost::false_type>
914 {
getboost::math::policies::detail::series_factor_calc915 static BOOST_MATH_CONSTEXPR T get() BOOST_MATH_NOEXCEPT(T)
916 {
917 return 1 / static_cast<T>(static_cast<boost::uintmax_t>(1u) << (Digits::value - 1));
918 }
919 };
920 template <class T, class Digits>
921 struct series_factor_calc<T, Digits, boost::false_type, boost::true_type>
922 {
getboost::math::policies::detail::series_factor_calc923 static BOOST_MATH_CONSTEXPR T get() BOOST_MATH_NOEXCEPT(T)
924 {
925 return boost::math::tools::epsilon<T>();
926 }
927 };
928
929 template <class T, class Policy>
get_epsilon_imp(boost::true_type const &)930 inline BOOST_MATH_CONSTEXPR T get_epsilon_imp(boost::true_type const&) BOOST_MATH_NOEXCEPT(T)
931 {
932 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
933 BOOST_STATIC_ASSERT( ::std::numeric_limits<T>::is_specialized);
934 BOOST_STATIC_ASSERT( ::std::numeric_limits<T>::radix == 2);
935 #else
936 BOOST_ASSERT(::std::numeric_limits<T>::is_specialized);
937 BOOST_ASSERT(::std::numeric_limits<T>::radix == 2);
938 #endif
939 typedef typename boost::math::policies::precision<T, Policy>::type p_t;
940 typedef boost::integral_constant<bool, p_t::value <= std::numeric_limits<boost::uintmax_t>::digits> is_small_int;
941 typedef boost::integral_constant<bool, p_t::value >= std::numeric_limits<T>::digits> is_default_value;
942 return series_factor_calc<T, p_t, is_small_int, is_default_value>::get();
943 }
944
945 template <class T, class Policy>
get_epsilon_imp(boost::false_type const &)946 inline BOOST_MATH_CONSTEXPR T get_epsilon_imp(boost::false_type const&) BOOST_MATH_NOEXCEPT(T)
947 {
948 return tools::epsilon<T>();
949 }
950
951 } // namespace detail
952
953 template <class T, class Policy>
get_epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE (T))954 inline BOOST_MATH_CONSTEXPR T get_epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T)) BOOST_MATH_NOEXCEPT(T)
955 {
956 typedef boost::integral_constant<bool, (std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::radix == 2)) > tag_type;
957 return detail::get_epsilon_imp<T, Policy>(tag_type());
958 }
959
960 namespace detail{
961
962 template <class A1,
963 class A2,
964 class A3,
965 class A4,
966 class A5,
967 class A6,
968 class A7,
969 class A8,
970 class A9,
971 class A10,
972 class A11>
973 char test_is_policy(const policy<A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11>*);
974 double test_is_policy(...);
975
976 template <class P>
977 struct is_policy_imp
978 {
979 BOOST_STATIC_CONSTANT(bool, value = (sizeof(::boost::math::policies::detail::test_is_policy(static_cast<P*>(0))) == 1));
980 };
981
982 }
983
984 template <class P>
985 struct is_policy : public boost::integral_constant<bool, ::boost::math::policies::detail::is_policy_imp<P>::value> {};
986
987 //
988 // Helper traits class for distribution error handling:
989 //
990 template <class Policy>
991 struct constructor_error_check
992 {
993 typedef typename Policy::domain_error_type domain_error_type;
994 typedef typename mpl::if_c<
995 (domain_error_type::value == throw_on_error) || (domain_error_type::value == user_error) || (domain_error_type::value == errno_on_error),
996 boost::true_type,
997 boost::false_type>::type type;
998 };
999
1000 template <class Policy>
1001 struct method_error_check
1002 {
1003 typedef typename Policy::domain_error_type domain_error_type;
1004 typedef typename mpl::if_c<
1005 (domain_error_type::value == throw_on_error) && (domain_error_type::value != user_error),
1006 boost::false_type,
1007 boost::true_type>::type type;
1008 };
1009 //
1010 // Does the Policy ever throw on error?
1011 //
1012 template <class Policy>
1013 struct is_noexcept_error_policy
1014 {
1015 typedef typename Policy::domain_error_type t1;
1016 typedef typename Policy::pole_error_type t2;
1017 typedef typename Policy::overflow_error_type t3;
1018 typedef typename Policy::underflow_error_type t4;
1019 typedef typename Policy::denorm_error_type t5;
1020 typedef typename Policy::evaluation_error_type t6;
1021 typedef typename Policy::rounding_error_type t7;
1022 typedef typename Policy::indeterminate_result_error_type t8;
1023
1024 BOOST_STATIC_CONSTANT(bool, value =
1025 ((t1::value != throw_on_error) && (t1::value != user_error)
1026 && (t2::value != throw_on_error) && (t2::value != user_error)
1027 && (t3::value != throw_on_error) && (t3::value != user_error)
1028 && (t4::value != throw_on_error) && (t4::value != user_error)
1029 && (t5::value != throw_on_error) && (t5::value != user_error)
1030 && (t6::value != throw_on_error) && (t6::value != user_error)
1031 && (t7::value != throw_on_error) && (t7::value != user_error)
1032 && (t8::value != throw_on_error) && (t8::value != user_error)));
1033 };
1034
1035 }}} // namespaces
1036
1037 #endif // BOOST_MATH_POLICY_HPP
1038
1039