]> git.donarmstrong.com Git - rsem.git/blob - boost/math/tools/precision.hpp
RSEM Source Codes
[rsem.git] / boost / math / tools / precision.hpp
1 //  Copyright John Maddock 2005-2006.
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_TOOLS_PRECISION_INCLUDED
7 #define BOOST_MATH_TOOLS_PRECISION_INCLUDED
8
9 #ifdef _MSC_VER
10 #pragma once
11 #endif
12
13 #include <boost/limits.hpp>
14 #include <boost/assert.hpp>
15 #include <boost/static_assert.hpp>
16 #include <boost/mpl/int.hpp>
17 #include <boost/mpl/bool.hpp>
18 #include <boost/mpl/if.hpp>
19 #include <boost/math/policies/policy.hpp>
20
21 #include <iostream>
22 #include <iomanip>
23 // These two are for LDBL_MAN_DIG:
24 #include <limits.h>
25 #include <math.h>
26
27 namespace boost{ namespace math
28 {
29 namespace tools
30 {
31 // If T is not specialized, the functions digits, max_value and min_value,
32 // all get synthesised automatically from std::numeric_limits.
33 // However, if numeric_limits is not specialised for type RealType,
34 // for example with NTL::RR type, then you will get a compiler error
35 // when code tries to use these functions, unless you explicitly specialise them.
36
37 // For example if the precision of RealType varies at runtime,
38 // then numeric_limits support may not be appropriate,
39 // see boost/math/tools/ntl.hpp  for examples like
40 // template <> NTL::RR max_value<NTL::RR> ...
41 // See  Conceptual Requirements for Real Number Types.
42
43 template <class T>
44 inline int digits(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(T))
45 {
46 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
47    BOOST_STATIC_ASSERT( ::std::numeric_limits<T>::is_specialized);
48 #else
49    BOOST_ASSERT(::std::numeric_limits<T>::is_specialized);
50 #endif
51    return std::numeric_limits<T>::digits;
52 }
53
54 template <class T>
55 inline T max_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T))
56 {
57 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
58    BOOST_STATIC_ASSERT( ::std::numeric_limits<T>::is_specialized);
59 #else
60    BOOST_ASSERT(::std::numeric_limits<T>::is_specialized);
61 #endif
62    return (std::numeric_limits<T>::max)();
63 } // Also used as a finite 'infinite' value for - and +infinity, for example:
64 // -max_value<double> = -1.79769e+308, max_value<double> = 1.79769e+308.
65
66 template <class T>
67 inline T min_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T))
68 {
69 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
70    BOOST_STATIC_ASSERT( ::std::numeric_limits<T>::is_specialized);
71 #else
72    BOOST_ASSERT(::std::numeric_limits<T>::is_specialized);
73 #endif
74    return (std::numeric_limits<T>::min)();
75 }
76
77 namespace detail{
78 //
79 // Logarithmic limits come next, note that although
80 // we can compute these from the log of the max value
81 // that is not in general thread safe (if we cache the value)
82 // so it's better to specialise these:
83 //
84 // For type float first:
85 //
86 template <class T>
87 inline T log_max_value(const mpl::int_<128>& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T))
88 {
89    return 88.0f;
90 }
91
92 template <class T>
93 inline T log_min_value(const mpl::int_<128>& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T))
94 {
95    return -87.0f;
96 }
97 //
98 // Now double:
99 //
100 template <class T>
101 inline T log_max_value(const mpl::int_<1024>& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T))
102 {
103    return 709.0;
104 }
105
106 template <class T>
107 inline T log_min_value(const mpl::int_<1024>& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T))
108 {
109    return -708.0;
110 }
111 //
112 // 80 and 128-bit long doubles:
113 //
114 template <class T>
115 inline T log_max_value(const mpl::int_<16384>& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T))
116 {
117    return 11356.0L;
118 }
119
120 template <class T>
121 inline T log_min_value(const mpl::int_<16384>& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T))
122 {
123    return -11355.0L;
124 }
125
126 template <class T>
127 inline T log_max_value(const mpl::int_<0>& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T))
128 {
129 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
130    BOOST_STATIC_ASSERT( ::std::numeric_limits<T>::is_specialized);
131 #else
132    BOOST_ASSERT(::std::numeric_limits<T>::is_specialized);
133 #endif
134    BOOST_MATH_STD_USING
135    static const T val = log((std::numeric_limits<T>::max)());
136    return val;
137 }
138
139 template <class T>
140 inline T log_min_value(const mpl::int_<0>& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T))
141 {
142 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
143    BOOST_STATIC_ASSERT( ::std::numeric_limits<T>::is_specialized);
144 #else
145    BOOST_ASSERT(::std::numeric_limits<T>::is_specialized);
146 #endif
147    BOOST_MATH_STD_USING
148    static const T val = log((std::numeric_limits<T>::max)());
149    return val;
150 }
151
152 template <class T>
153 inline T epsilon(const mpl::true_& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T))
154 {
155    return std::numeric_limits<T>::epsilon();
156 }
157
158 #if (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)) && ((LDBL_MANT_DIG == 106) || (__LDBL_MANT_DIG__ == 106))
159 template <>
160 inline long double epsilon<long double>(const mpl::true_& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(long double))
161 {
162    // numeric_limits on Darwin tells lies here.
163    // This static assert fails for some unknown reason, so
164    // disabled for now...
165    // BOOST_STATIC_ASSERT(std::numeric_limits<long double>::digits == 106);
166    return 2.4651903288156618919116517665087e-32L;
167 }
168 #endif
169
170 template <class T>
171 inline T epsilon(const mpl::false_& BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE(T))
172 {
173    BOOST_MATH_STD_USING  // for ADL of std names
174    static const T eps = ldexp(static_cast<T>(1), 1-policies::digits<T, policies::policy<> >());
175    return eps;
176 }
177
178 } // namespace detail
179
180 template <class T>
181 inline T log_max_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T))
182 {
183 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
184    typedef typename mpl::if_c<
185       std::numeric_limits<T>::max_exponent == 128
186       || std::numeric_limits<T>::max_exponent == 1024
187       || std::numeric_limits<T>::max_exponent == 16384,
188       mpl::int_<std::numeric_limits<T>::max_exponent>,
189       mpl::int_<0>
190    >::type tag_type;
191    BOOST_STATIC_ASSERT( ::std::numeric_limits<T>::is_specialized);
192    return detail::log_max_value<T>(tag_type());
193 #else
194    BOOST_ASSERT(::std::numeric_limits<T>::is_specialized);
195    BOOST_MATH_STD_USING
196    static const T val = log((std::numeric_limits<T>::max)());
197    return val;
198 #endif
199 }
200
201 template <class T>
202 inline T log_min_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T))
203 {
204 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
205    typedef typename mpl::if_c<
206       std::numeric_limits<T>::max_exponent == 128
207       || std::numeric_limits<T>::max_exponent == 1024
208       || std::numeric_limits<T>::max_exponent == 16384,
209       mpl::int_<std::numeric_limits<T>::max_exponent>,
210       mpl::int_<0>
211    >::type tag_type;
212
213    BOOST_STATIC_ASSERT( ::std::numeric_limits<T>::is_specialized);
214    return detail::log_min_value<T>(tag_type());
215 #else
216    BOOST_ASSERT(::std::numeric_limits<T>::is_specialized);
217    BOOST_MATH_STD_USING
218    static const T val = log((std::numeric_limits<T>::min)());
219    return val;
220 #endif
221 }
222
223 template <class T>
224 inline T epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(T))
225 {
226 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
227    return detail::epsilon<T>(mpl::bool_< ::std::numeric_limits<T>::is_specialized>());
228 #else
229    return ::std::numeric_limits<T>::is_specialized ?
230       detail::epsilon<T>(mpl::true_()) :
231       detail::epsilon<T>(mpl::false_());
232 #endif
233 }
234
235 namespace detail{
236
237 template <class T>
238 inline T root_epsilon_imp(const mpl::int_<24>&)
239 {
240    return static_cast<T>(0.00034526698300124390839884978618400831996329879769945L);
241 }
242
243 template <class T>
244 inline T root_epsilon_imp(const T*, const mpl::int_<53>&)
245 {
246    return static_cast<T>(0.1490116119384765625e-7L);
247 }
248
249 template <class T>
250 inline T root_epsilon_imp(const T*, const mpl::int_<64>&)
251 {
252    return static_cast<T>(0.32927225399135962333569506281281311031656150598474e-9L);
253 }
254
255 template <class T>
256 inline T root_epsilon_imp(const T*, const mpl::int_<113>&)
257 {
258    return static_cast<T>(0.1387778780781445675529539585113525390625e-16L);
259 }
260
261 template <class T, class Tag>
262 inline T root_epsilon_imp(const T*, const Tag&)
263 {
264    BOOST_MATH_STD_USING
265    static const T r_eps = sqrt(tools::epsilon<T>());
266    return r_eps;
267 }
268
269 template <class T>
270 inline T forth_root_epsilon_imp(const T*, const mpl::int_<24>&)
271 {
272    return static_cast<T>(0.018581361171917516667460937040007436176452688944747L);
273 }
274
275 template <class T>
276 inline T forth_root_epsilon_imp(const T*, const mpl::int_<53>&)
277 {
278    return static_cast<T>(0.0001220703125L);
279 }
280
281 template <class T>
282 inline T forth_root_epsilon_imp(const T*, const mpl::int_<64>&)
283 {
284    return static_cast<T>(0.18145860519450699870567321328132261891067079047605e-4L);
285 }
286
287 template <class T>
288 inline T forth_root_epsilon_imp(const T*, const mpl::int_<113>&)
289 {
290    return static_cast<T>(0.37252902984619140625e-8L);
291 }
292
293 template <class T, class Tag>
294 inline T forth_root_epsilon_imp(const T*, const Tag&)
295 {
296    BOOST_MATH_STD_USING
297    static const T r_eps = sqrt(sqrt(tools::epsilon<T>()));
298    return r_eps;
299 }
300
301 }
302
303 template <class T>
304 inline T root_epsilon()
305 {
306    typedef mpl::int_<std::numeric_limits<T>::digits> tag_type;
307    return detail::root_epsilon_imp(static_cast<T const*>(0), tag_type());
308 }
309
310 template <class T>
311 inline T forth_root_epsilon()
312 {
313    typedef mpl::int_<std::numeric_limits<T>::digits> tag_type;
314    return detail::forth_root_epsilon_imp(static_cast<T const*>(0), tag_type());
315 }
316
317 } // namespace tools
318 } // namespace math
319 } // namespace boost
320
321 #endif // BOOST_MATH_TOOLS_PRECISION_INCLUDED
322