]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /////////////////////////////////////////////////////////////// |
2 | // Copyright 2012 John Maddock. Distributed under the Boost | |
3 | // Software License, Version 1.0. (See accompanying file | |
92f5a8d4 | 4 | // LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt |
7c673cae FG |
5 | |
6 | #ifndef BOOST_MATH_FLOAT_BACKEND_HPP | |
7 | #define BOOST_MATH_FLOAT_BACKEND_HPP | |
8 | ||
9 | #include <iostream> | |
10 | #include <iomanip> | |
11 | #include <sstream> | |
12 | #include <boost/cstdint.hpp> | |
13 | #include <boost/lexical_cast.hpp> | |
14 | #include <boost/math/concepts/real_concept.hpp> | |
15 | #include <boost/multiprecision/number.hpp> | |
92f5a8d4 | 16 | #include <boost/integer/common_factor_rt.hpp> |
11fdf7f2 | 17 | #include <boost/type_traits/common_type.hpp> |
92f5a8d4 | 18 | #include <boost/container_hash/hash.hpp> |
7c673cae | 19 | |
92f5a8d4 TL |
20 | namespace boost { |
21 | namespace multiprecision { | |
22 | namespace backends { | |
7c673cae FG |
23 | |
24 | #ifdef BOOST_MSVC | |
92f5a8d4 TL |
25 | #pragma warning(push) |
26 | #pragma warning(disable : 4389 4244 4018 4244 4127) | |
7c673cae FG |
27 | #endif |
28 | ||
29 | template <class Arithmetic> | |
30 | struct arithmetic_backend | |
31 | { | |
92f5a8d4 TL |
32 | typedef mpl::list<short, int, long, long long> signed_types; |
33 | typedef mpl::list<unsigned short, unsigned, unsigned long, unsigned long long> unsigned_types; | |
34 | typedef mpl::list<float, double, long double> float_types; | |
35 | typedef int exponent_type; | |
7c673cae | 36 | |
92f5a8d4 TL |
37 | BOOST_MP_CXX14_CONSTEXPR arithmetic_backend() : m_value(0) {} |
38 | BOOST_MP_CXX14_CONSTEXPR arithmetic_backend(const arithmetic_backend& o) : m_value(o.m_value) {} | |
7c673cae | 39 | template <class A> |
92f5a8d4 | 40 | BOOST_MP_CXX14_CONSTEXPR arithmetic_backend(const A& o, const typename enable_if<is_arithmetic<A> >::type* = 0) : m_value(o) {} |
7c673cae | 41 | template <class A> |
92f5a8d4 TL |
42 | BOOST_MP_CXX14_CONSTEXPR arithmetic_backend(const arithmetic_backend<A>& o) : m_value(o.data()) {} |
43 | BOOST_MP_CXX14_CONSTEXPR arithmetic_backend& operator=(const arithmetic_backend& o) | |
7c673cae FG |
44 | { |
45 | m_value = o.m_value; | |
46 | return *this; | |
47 | } | |
48 | template <class A> | |
92f5a8d4 | 49 | BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A>, arithmetic_backend&>::type operator=(A i) |
7c673cae FG |
50 | { |
51 | m_value = i; | |
52 | return *this; | |
53 | } | |
54 | template <class A> | |
92f5a8d4 | 55 | BOOST_MP_CXX14_CONSTEXPR arithmetic_backend& operator=(const arithmetic_backend<A>& i) |
7c673cae FG |
56 | { |
57 | m_value = i.data(); | |
58 | return *this; | |
59 | } | |
92f5a8d4 | 60 | arithmetic_backend& operator=(const char* s) |
7c673cae FG |
61 | { |
62 | #ifndef BOOST_NO_EXCEPTIONS | |
63 | try | |
64 | { | |
65 | #endif | |
66 | m_value = boost::lexical_cast<Arithmetic>(s); | |
67 | #ifndef BOOST_NO_EXCEPTIONS | |
68 | } | |
92f5a8d4 | 69 | catch (const bad_lexical_cast&) |
7c673cae FG |
70 | { |
71 | throw std::runtime_error(std::string("Unable to interpret the string provided: \"") + s + std::string("\" as a compatible number type.")); | |
72 | } | |
73 | #endif | |
74 | return *this; | |
75 | } | |
92f5a8d4 | 76 | BOOST_MP_CXX14_CONSTEXPR void swap(arithmetic_backend& o) |
7c673cae FG |
77 | { |
78 | std::swap(m_value, o.m_value); | |
79 | } | |
92f5a8d4 | 80 | std::string str(std::streamsize digits, std::ios_base::fmtflags f) const |
7c673cae FG |
81 | { |
82 | std::stringstream ss; | |
83 | ss.flags(f); | |
84 | ss << std::setprecision(digits ? digits : std::numeric_limits<Arithmetic>::digits10 + 4) << m_value; | |
85 | return ss.str(); | |
86 | } | |
92f5a8d4 | 87 | BOOST_MP_CXX14_CONSTEXPR void do_negate(const mpl::true_&) |
7c673cae FG |
88 | { |
89 | m_value = 1 + ~m_value; | |
90 | } | |
92f5a8d4 | 91 | BOOST_MP_CXX14_CONSTEXPR void do_negate(const mpl::false_&) |
7c673cae FG |
92 | { |
93 | m_value = -m_value; | |
94 | } | |
92f5a8d4 | 95 | BOOST_MP_CXX14_CONSTEXPR void negate() |
7c673cae | 96 | { |
92f5a8d4 | 97 | do_negate(mpl::bool_<is_unsigned<Arithmetic>::value>()); |
7c673cae | 98 | } |
92f5a8d4 | 99 | BOOST_MP_CXX14_CONSTEXPR int compare(const arithmetic_backend& o) const |
7c673cae FG |
100 | { |
101 | return m_value > o.m_value ? 1 : (m_value < o.m_value ? -1 : 0); | |
102 | } | |
103 | template <class A> | |
92f5a8d4 | 104 | BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A>, int>::type compare(A i) const |
7c673cae FG |
105 | { |
106 | return m_value > static_cast<Arithmetic>(i) ? 1 : (m_value < static_cast<Arithmetic>(i) ? -1 : 0); | |
107 | } | |
92f5a8d4 TL |
108 | BOOST_MP_CXX14_CONSTEXPR Arithmetic& data() { return m_value; } |
109 | BOOST_MP_CXX14_CONSTEXPR const Arithmetic& data() const { return m_value; } | |
110 | ||
111 | private: | |
7c673cae FG |
112 | Arithmetic m_value; |
113 | }; | |
114 | ||
115 | template <class R, class Arithmetic> | |
92f5a8d4 | 116 | inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<boost::is_integral<R>::value>::type eval_convert_to(R* result, const arithmetic_backend<Arithmetic>& backend) |
11fdf7f2 TL |
117 | { |
118 | typedef typename boost::common_type<R, Arithmetic>::type c_type; | |
92f5a8d4 TL |
119 | BOOST_CONSTEXPR const c_type max = static_cast<c_type>((std::numeric_limits<R>::max)()); |
120 | BOOST_CONSTEXPR const c_type min = static_cast<c_type>((std::numeric_limits<R>::min)()); | |
121 | c_type ct = static_cast<c_type>(backend.data()); | |
11fdf7f2 TL |
122 | if ((backend.data() < 0) && !std::numeric_limits<R>::is_signed) |
123 | BOOST_THROW_EXCEPTION(std::range_error("Attempt to convert negative number to unsigned type.")); | |
124 | if (ct > max) | |
92f5a8d4 | 125 | *result = boost::is_signed<R>::value ? (std::numeric_limits<R>::max)() : backend.data(); |
11fdf7f2 TL |
126 | else if (std::numeric_limits<Arithmetic>::is_signed && (ct < min)) |
127 | *result = (std::numeric_limits<R>::min)(); | |
128 | else | |
129 | *result = backend.data(); | |
130 | } | |
131 | ||
132 | template <class R, class Arithmetic> | |
92f5a8d4 | 133 | inline BOOST_MP_CXX14_CONSTEXPR typename disable_if_c<boost::is_integral<R>::value>::type eval_convert_to(R* result, const arithmetic_backend<Arithmetic>& backend) |
7c673cae FG |
134 | { |
135 | *result = backend.data(); | |
136 | } | |
137 | ||
138 | template <class Arithmetic> | |
92f5a8d4 | 139 | inline BOOST_MP_CXX14_CONSTEXPR bool eval_eq(const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b) |
7c673cae FG |
140 | { |
141 | return a.data() == b.data(); | |
142 | } | |
143 | template <class Arithmetic, class A2> | |
92f5a8d4 | 144 | inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A2>, bool>::type eval_eq(const arithmetic_backend<Arithmetic>& a, const A2& b) |
7c673cae FG |
145 | { |
146 | return a.data() == static_cast<Arithmetic>(b); | |
147 | } | |
148 | template <class Arithmetic> | |
92f5a8d4 | 149 | inline BOOST_MP_CXX14_CONSTEXPR bool eval_lt(const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b) |
7c673cae FG |
150 | { |
151 | return a.data() < b.data(); | |
152 | } | |
153 | template <class Arithmetic, class A2> | |
92f5a8d4 | 154 | inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A2>, bool>::type eval_lt(const arithmetic_backend<Arithmetic>& a, const A2& b) |
7c673cae FG |
155 | { |
156 | return a.data() < static_cast<Arithmetic>(b); | |
157 | } | |
158 | template <class Arithmetic> | |
92f5a8d4 | 159 | inline BOOST_MP_CXX14_CONSTEXPR bool eval_gt(const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b) |
7c673cae FG |
160 | { |
161 | return a.data() > b.data(); | |
162 | } | |
163 | template <class Arithmetic, class A2> | |
92f5a8d4 | 164 | inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A2>, bool>::type eval_gt(const arithmetic_backend<Arithmetic>& a, const A2& b) |
7c673cae FG |
165 | { |
166 | return a.data() > static_cast<Arithmetic>(b); | |
167 | } | |
168 | ||
169 | template <class Arithmetic> | |
92f5a8d4 | 170 | inline BOOST_MP_CXX14_CONSTEXPR void eval_add(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o) |
7c673cae FG |
171 | { |
172 | result.data() += o.data(); | |
173 | } | |
174 | template <class Arithmetic> | |
92f5a8d4 | 175 | inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o) |
7c673cae FG |
176 | { |
177 | result.data() -= o.data(); | |
178 | } | |
179 | template <class Arithmetic> | |
92f5a8d4 | 180 | inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o) |
7c673cae FG |
181 | { |
182 | result.data() *= o.data(); | |
183 | } | |
184 | template <class Arithmetic> | |
92f5a8d4 | 185 | inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<std::numeric_limits<Arithmetic>::has_infinity>::type eval_divide(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o) |
7c673cae FG |
186 | { |
187 | result.data() /= o.data(); | |
188 | } | |
189 | template <class Arithmetic> | |
92f5a8d4 | 190 | inline BOOST_MP_CXX14_CONSTEXPR typename disable_if_c<std::numeric_limits<Arithmetic>::has_infinity>::type eval_divide(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o) |
7c673cae | 191 | { |
92f5a8d4 | 192 | if (!o.data()) |
7c673cae FG |
193 | BOOST_THROW_EXCEPTION(std::overflow_error("Divide by zero")); |
194 | result.data() /= o.data(); | |
195 | } | |
196 | ||
197 | template <class Arithmetic, class A2> | |
92f5a8d4 | 198 | inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A2> >::type eval_add(arithmetic_backend<Arithmetic>& result, const A2& o) |
7c673cae FG |
199 | { |
200 | result.data() += o; | |
201 | } | |
202 | template <class Arithmetic, class A2> | |
92f5a8d4 | 203 | inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A2> >::type eval_subtract(arithmetic_backend<Arithmetic>& result, const A2& o) |
7c673cae FG |
204 | { |
205 | result.data() -= o; | |
206 | } | |
207 | template <class Arithmetic, class A2> | |
92f5a8d4 | 208 | inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A2> >::type eval_multiply(arithmetic_backend<Arithmetic>& result, const A2& o) |
7c673cae FG |
209 | { |
210 | result.data() *= o; | |
211 | } | |
212 | template <class Arithmetic, class A2> | |
92f5a8d4 TL |
213 | inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<(is_arithmetic<A2>::value && !std::numeric_limits<Arithmetic>::has_infinity)>::type |
214 | eval_divide(arithmetic_backend<Arithmetic>& result, const A2& o) | |
7c673cae | 215 | { |
92f5a8d4 | 216 | if (!o) |
7c673cae FG |
217 | BOOST_THROW_EXCEPTION(std::overflow_error("Divide by zero")); |
218 | result.data() /= o; | |
219 | } | |
220 | template <class Arithmetic, class A2> | |
92f5a8d4 TL |
221 | inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<(is_arithmetic<A2>::value && std::numeric_limits<Arithmetic>::has_infinity)>::type |
222 | eval_divide(arithmetic_backend<Arithmetic>& result, const A2& o) | |
7c673cae FG |
223 | { |
224 | result.data() /= o; | |
225 | } | |
226 | ||
227 | template <class Arithmetic> | |
92f5a8d4 | 228 | inline BOOST_MP_CXX14_CONSTEXPR void eval_add(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b) |
7c673cae FG |
229 | { |
230 | result.data() = a.data() + b.data(); | |
231 | } | |
232 | template <class Arithmetic> | |
92f5a8d4 | 233 | inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b) |
7c673cae FG |
234 | { |
235 | result.data() = a.data() - b.data(); | |
236 | } | |
237 | template <class Arithmetic> | |
92f5a8d4 | 238 | inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b) |
7c673cae FG |
239 | { |
240 | result.data() = a.data() * b.data(); | |
241 | } | |
242 | template <class Arithmetic> | |
92f5a8d4 | 243 | inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<std::numeric_limits<Arithmetic>::has_infinity>::type eval_divide(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b) |
7c673cae FG |
244 | { |
245 | result.data() = a.data() / b.data(); | |
246 | } | |
247 | template <class Arithmetic> | |
92f5a8d4 | 248 | inline BOOST_MP_CXX14_CONSTEXPR typename disable_if_c<std::numeric_limits<Arithmetic>::has_infinity>::type eval_divide(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b) |
7c673cae | 249 | { |
92f5a8d4 | 250 | if (!b.data()) |
7c673cae FG |
251 | BOOST_THROW_EXCEPTION(std::overflow_error("Divide by zero")); |
252 | result.data() = a.data() / b.data(); | |
253 | } | |
254 | ||
255 | template <class Arithmetic, class A2> | |
92f5a8d4 | 256 | inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A2> >::type eval_add(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const A2& b) |
7c673cae FG |
257 | { |
258 | result.data() = a.data() + b; | |
259 | } | |
260 | template <class Arithmetic, class A2> | |
92f5a8d4 | 261 | inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A2> >::type eval_subtract(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const A2& b) |
7c673cae FG |
262 | { |
263 | result.data() = a.data() - b; | |
264 | } | |
265 | template <class Arithmetic, class A2> | |
92f5a8d4 | 266 | inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A2> >::type eval_multiply(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const A2& b) |
7c673cae FG |
267 | { |
268 | result.data() = a.data() * b; | |
269 | } | |
270 | template <class Arithmetic, class A2> | |
92f5a8d4 TL |
271 | inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<(is_arithmetic<A2>::value && !std::numeric_limits<Arithmetic>::has_infinity)>::type |
272 | eval_divide(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const A2& b) | |
7c673cae | 273 | { |
92f5a8d4 | 274 | if (!b) |
7c673cae FG |
275 | BOOST_THROW_EXCEPTION(std::overflow_error("Divide by zero")); |
276 | result.data() = a.data() / b; | |
277 | } | |
278 | template <class Arithmetic, class A2> | |
92f5a8d4 TL |
279 | inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<(is_arithmetic<A2>::value && std::numeric_limits<Arithmetic>::has_infinity)>::type |
280 | eval_divide(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const A2& b) | |
7c673cae FG |
281 | { |
282 | result.data() = a.data() / b; | |
283 | } | |
284 | ||
285 | template <class Arithmetic> | |
92f5a8d4 | 286 | inline BOOST_MP_CXX14_CONSTEXPR bool eval_is_zero(const arithmetic_backend<Arithmetic>& val) |
7c673cae FG |
287 | { |
288 | return val.data() == 0; | |
289 | } | |
290 | ||
291 | template <class Arithmetic> | |
92f5a8d4 TL |
292 | inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c< |
293 | (!std::numeric_limits<Arithmetic>::is_specialized || std::numeric_limits<Arithmetic>::is_signed), int>::type | |
294 | eval_get_sign(const arithmetic_backend<Arithmetic>& val) | |
7c673cae FG |
295 | { |
296 | return val.data() == 0 ? 0 : val.data() < 0 ? -1 : 1; | |
297 | } | |
298 | template <class Arithmetic> | |
92f5a8d4 TL |
299 | inline BOOST_MP_CXX14_CONSTEXPR typename disable_if_c< |
300 | (std::numeric_limits<Arithmetic>::is_specialized || std::numeric_limits<Arithmetic>::is_signed), int>::type | |
301 | eval_get_sign(const arithmetic_backend<Arithmetic>& val) | |
7c673cae FG |
302 | { |
303 | return val.data() == 0 ? 0 : 1; | |
304 | } | |
305 | ||
306 | template <class T> | |
92f5a8d4 | 307 | inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_unsigned<T>, T>::type abs(T v) { return v; } |
7c673cae FG |
308 | |
309 | template <class Arithmetic> | |
92f5a8d4 | 310 | inline BOOST_MP_CXX14_CONSTEXPR void eval_abs(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o) |
7c673cae | 311 | { |
7c673cae | 312 | using boost::multiprecision::backends::abs; |
92f5a8d4 | 313 | using std::abs; |
7c673cae FG |
314 | result.data() = abs(o.data()); |
315 | } | |
316 | ||
317 | template <class Arithmetic> | |
92f5a8d4 | 318 | inline BOOST_MP_CXX14_CONSTEXPR void eval_fabs(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o) |
7c673cae FG |
319 | { |
320 | result.data() = std::abs(o.data()); | |
321 | } | |
322 | ||
323 | template <class Arithmetic> | |
92f5a8d4 | 324 | inline BOOST_MP_CXX14_CONSTEXPR void eval_floor(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o) |
7c673cae FG |
325 | { |
326 | BOOST_MATH_STD_USING | |
327 | result.data() = floor(o.data()); | |
328 | } | |
329 | ||
330 | template <class Arithmetic> | |
92f5a8d4 | 331 | inline BOOST_MP_CXX14_CONSTEXPR void eval_ceil(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o) |
7c673cae FG |
332 | { |
333 | BOOST_MATH_STD_USING | |
334 | result.data() = ceil(o.data()); | |
335 | } | |
336 | ||
337 | template <class Arithmetic> | |
92f5a8d4 | 338 | inline BOOST_MP_CXX14_CONSTEXPR void eval_sqrt(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o) |
7c673cae FG |
339 | { |
340 | BOOST_MATH_STD_USING | |
341 | result.data() = sqrt(o.data()); | |
342 | } | |
343 | ||
344 | template <class Arithmetic> | |
92f5a8d4 | 345 | inline BOOST_MP_CXX14_CONSTEXPR int eval_fpclassify(const arithmetic_backend<Arithmetic>& o) |
7c673cae FG |
346 | { |
347 | return (boost::math::fpclassify)(o.data()); | |
348 | } | |
349 | ||
350 | template <class Arithmetic> | |
92f5a8d4 | 351 | inline BOOST_MP_CXX14_CONSTEXPR void eval_trunc(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o) |
7c673cae FG |
352 | { |
353 | BOOST_MATH_STD_USING | |
354 | result.data() = trunc(o.data()); | |
355 | } | |
356 | ||
357 | template <class Arithmetic> | |
92f5a8d4 | 358 | inline BOOST_MP_CXX14_CONSTEXPR void eval_round(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o) |
7c673cae FG |
359 | { |
360 | BOOST_MATH_STD_USING | |
361 | result.data() = round(o.data()); | |
362 | } | |
363 | ||
364 | template <class Arithmetic> | |
92f5a8d4 | 365 | inline BOOST_MP_CXX14_CONSTEXPR void eval_frexp(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, int* v) |
7c673cae FG |
366 | { |
367 | BOOST_MATH_STD_USING | |
368 | result.data() = frexp(a.data(), v); | |
369 | } | |
370 | ||
371 | template <class Arithmetic> | |
92f5a8d4 | 372 | inline BOOST_MP_CXX14_CONSTEXPR void eval_ldexp(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, int v) |
7c673cae FG |
373 | { |
374 | BOOST_MATH_STD_USING | |
375 | result.data() = ldexp(a.data(), v); | |
376 | } | |
377 | ||
378 | template <class Arithmetic> | |
92f5a8d4 | 379 | inline BOOST_MP_CXX14_CONSTEXPR void eval_exp(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o) |
7c673cae FG |
380 | { |
381 | BOOST_MATH_STD_USING | |
382 | result.data() = exp(o.data()); | |
383 | } | |
384 | ||
385 | template <class Arithmetic> | |
92f5a8d4 | 386 | inline BOOST_MP_CXX14_CONSTEXPR void eval_log(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o) |
7c673cae FG |
387 | { |
388 | BOOST_MATH_STD_USING | |
389 | result.data() = log(o.data()); | |
390 | } | |
391 | ||
392 | template <class Arithmetic> | |
92f5a8d4 | 393 | inline BOOST_MP_CXX14_CONSTEXPR void eval_log10(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o) |
7c673cae FG |
394 | { |
395 | BOOST_MATH_STD_USING | |
396 | result.data() = log10(o.data()); | |
397 | } | |
398 | ||
399 | template <class Arithmetic> | |
92f5a8d4 | 400 | inline BOOST_MP_CXX14_CONSTEXPR void eval_sin(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o) |
7c673cae FG |
401 | { |
402 | BOOST_MATH_STD_USING | |
403 | result.data() = sin(o.data()); | |
404 | } | |
405 | ||
406 | template <class Arithmetic> | |
92f5a8d4 | 407 | inline BOOST_MP_CXX14_CONSTEXPR void eval_cos(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o) |
7c673cae FG |
408 | { |
409 | BOOST_MATH_STD_USING | |
410 | result.data() = cos(o.data()); | |
411 | } | |
412 | ||
413 | template <class Arithmetic> | |
92f5a8d4 | 414 | inline BOOST_MP_CXX14_CONSTEXPR void eval_tan(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o) |
7c673cae FG |
415 | { |
416 | BOOST_MATH_STD_USING | |
417 | result.data() = tan(o.data()); | |
418 | } | |
419 | ||
420 | template <class Arithmetic> | |
92f5a8d4 | 421 | inline BOOST_MP_CXX14_CONSTEXPR void eval_acos(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o) |
7c673cae FG |
422 | { |
423 | BOOST_MATH_STD_USING | |
424 | result.data() = acos(o.data()); | |
425 | } | |
426 | ||
427 | template <class Arithmetic> | |
92f5a8d4 | 428 | inline BOOST_MP_CXX14_CONSTEXPR void eval_asin(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o) |
7c673cae FG |
429 | { |
430 | BOOST_MATH_STD_USING | |
431 | result.data() = asin(o.data()); | |
432 | } | |
433 | ||
434 | template <class Arithmetic> | |
92f5a8d4 | 435 | inline BOOST_MP_CXX14_CONSTEXPR void eval_atan(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o) |
7c673cae FG |
436 | { |
437 | BOOST_MATH_STD_USING | |
438 | result.data() = atan(o.data()); | |
439 | } | |
440 | ||
441 | template <class Arithmetic> | |
92f5a8d4 | 442 | inline BOOST_MP_CXX14_CONSTEXPR void eval_sinh(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o) |
7c673cae FG |
443 | { |
444 | BOOST_MATH_STD_USING | |
445 | result.data() = sinh(o.data()); | |
446 | } | |
447 | ||
448 | template <class Arithmetic> | |
92f5a8d4 | 449 | inline BOOST_MP_CXX14_CONSTEXPR void eval_cosh(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o) |
7c673cae FG |
450 | { |
451 | BOOST_MATH_STD_USING | |
452 | result.data() = cosh(o.data()); | |
453 | } | |
454 | ||
455 | template <class Arithmetic> | |
92f5a8d4 | 456 | inline BOOST_MP_CXX14_CONSTEXPR void eval_tanh(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o) |
7c673cae FG |
457 | { |
458 | BOOST_MATH_STD_USING | |
459 | result.data() = tanh(o.data()); | |
460 | } | |
461 | ||
462 | template <class Arithmetic> | |
92f5a8d4 | 463 | inline BOOST_MP_CXX14_CONSTEXPR void eval_fmod(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b) |
7c673cae FG |
464 | { |
465 | BOOST_MATH_STD_USING | |
466 | result.data() = fmod(a.data(), b.data()); | |
467 | } | |
468 | ||
469 | template <class Arithmetic> | |
92f5a8d4 | 470 | inline BOOST_MP_CXX14_CONSTEXPR void eval_pow(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b) |
7c673cae FG |
471 | { |
472 | BOOST_MATH_STD_USING | |
473 | result.data() = pow(a.data(), b.data()); | |
474 | } | |
475 | ||
476 | template <class Arithmetic> | |
92f5a8d4 | 477 | inline BOOST_MP_CXX14_CONSTEXPR void eval_atan2(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b) |
7c673cae FG |
478 | { |
479 | BOOST_MATH_STD_USING | |
480 | result.data() = atan2(a.data(), b.data()); | |
481 | } | |
482 | ||
483 | template <class Arithmetic, class I> | |
92f5a8d4 | 484 | inline BOOST_MP_CXX14_CONSTEXPR void eval_left_shift(arithmetic_backend<Arithmetic>& result, I val) |
7c673cae FG |
485 | { |
486 | result.data() <<= val; | |
487 | } | |
488 | ||
489 | template <class Arithmetic, class I> | |
92f5a8d4 | 490 | inline BOOST_MP_CXX14_CONSTEXPR void eval_right_shift(arithmetic_backend<Arithmetic>& result, I val) |
7c673cae FG |
491 | { |
492 | result.data() >>= val; | |
493 | } | |
494 | ||
495 | template <class Arithmetic> | |
92f5a8d4 | 496 | inline BOOST_MP_CXX14_CONSTEXPR void eval_modulus(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a) |
7c673cae FG |
497 | { |
498 | result.data() %= a.data(); | |
499 | } | |
500 | ||
501 | template <class Arithmetic> | |
92f5a8d4 | 502 | inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_and(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a) |
7c673cae FG |
503 | { |
504 | result.data() &= a.data(); | |
505 | } | |
506 | ||
507 | template <class Arithmetic> | |
92f5a8d4 | 508 | inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_or(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a) |
7c673cae FG |
509 | { |
510 | result.data() |= a.data(); | |
511 | } | |
512 | ||
513 | template <class Arithmetic> | |
92f5a8d4 | 514 | inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_xor(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a) |
7c673cae FG |
515 | { |
516 | result.data() ^= a.data(); | |
517 | } | |
518 | ||
519 | template <class Arithmetic> | |
92f5a8d4 | 520 | inline BOOST_MP_CXX14_CONSTEXPR void eval_complement(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a) |
7c673cae FG |
521 | { |
522 | result.data() = ~a.data(); | |
523 | } | |
524 | ||
525 | template <class Arithmetic> | |
92f5a8d4 TL |
526 | inline BOOST_MP_CXX14_CONSTEXPR void eval_gcd(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b) |
527 | { | |
528 | result.data() = boost::integer::gcd(a.data(), b.data()); | |
529 | } | |
530 | ||
531 | template <class Arithmetic> | |
532 | inline BOOST_MP_CXX14_CONSTEXPR void eval_lcm(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b) | |
7c673cae | 533 | { |
92f5a8d4 | 534 | result.data() = boost::integer::lcm(a.data(), b.data()); |
7c673cae FG |
535 | } |
536 | ||
537 | template <class Arithmetic> | |
92f5a8d4 | 538 | inline BOOST_MP_CXX14_CONSTEXPR std::size_t hash_value(const arithmetic_backend<Arithmetic>& a) |
7c673cae | 539 | { |
92f5a8d4 TL |
540 | boost::hash<Arithmetic> hasher; |
541 | return hasher(a.data()); | |
7c673cae FG |
542 | } |
543 | ||
544 | #ifdef BOOST_MSVC | |
92f5a8d4 | 545 | #pragma warning(pop) |
7c673cae FG |
546 | #endif |
547 | ||
548 | } // namespace backends | |
549 | ||
550 | using boost::multiprecision::backends::arithmetic_backend; | |
551 | ||
552 | template <class Arithmetic> | |
92f5a8d4 TL |
553 | struct number_category<arithmetic_backend<Arithmetic> > : public mpl::int_<is_integral<Arithmetic>::value ? number_kind_integer : number_kind_floating_point> |
554 | {}; | |
7c673cae | 555 | |
92f5a8d4 | 556 | namespace detail { |
7c673cae FG |
557 | |
558 | template <class Backend> | |
559 | struct double_precision_type; | |
560 | ||
92f5a8d4 | 561 | template <class Arithmetic, boost::multiprecision::expression_template_option ET> |
7c673cae FG |
562 | struct double_precision_type<number<arithmetic_backend<Arithmetic>, ET> > |
563 | { | |
564 | typedef number<arithmetic_backend<typename double_precision_type<Arithmetic>::type>, ET> type; | |
565 | }; | |
92f5a8d4 | 566 | template <> |
7c673cae FG |
567 | struct double_precision_type<arithmetic_backend<boost::int32_t> > |
568 | { | |
569 | typedef arithmetic_backend<boost::int64_t> type; | |
570 | }; | |
571 | ||
92f5a8d4 | 572 | } // namespace detail |
7c673cae | 573 | |
92f5a8d4 | 574 | }} // namespace boost::multiprecision |
7c673cae FG |
575 | #if !(defined(__SGI_STL_PORT) || defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS)) |
576 | // | |
577 | // We shouldn't need these to get code to compile, however for the sake of | |
578 | // "level playing field" performance comparisons they avoid the very slow | |
579 | // lexical_cast's that would otherwise take place. Definition has to be guarded | |
580 | // by the inverse of pp-logic in real_concept.hpp which defines these as a workaround | |
581 | // for STLPort plus some other old/broken standartd libraries. | |
582 | // | |
92f5a8d4 | 583 | namespace boost { namespace math { namespace tools { |
7c673cae | 584 | |
92f5a8d4 TL |
585 | template <> |
586 | inline unsigned int real_cast<unsigned int, concepts::real_concept>(concepts::real_concept r) | |
587 | { | |
588 | return static_cast<unsigned int>(r.value()); | |
589 | } | |
7c673cae | 590 | |
92f5a8d4 TL |
591 | template <> |
592 | inline int real_cast<int, concepts::real_concept>(concepts::real_concept r) | |
593 | { | |
594 | return static_cast<int>(r.value()); | |
595 | } | |
7c673cae | 596 | |
92f5a8d4 TL |
597 | template <> |
598 | inline long real_cast<long, concepts::real_concept>(concepts::real_concept r) | |
599 | { | |
600 | return static_cast<long>(r.value()); | |
601 | } | |
7c673cae | 602 | |
92f5a8d4 | 603 | // Converts from T to narrower floating-point types, float, double & long double. |
7c673cae | 604 | |
92f5a8d4 TL |
605 | template <> |
606 | inline float real_cast<float, concepts::real_concept>(concepts::real_concept r) | |
607 | { | |
608 | return static_cast<float>(r.value()); | |
609 | } | |
610 | template <> | |
611 | inline double real_cast<double, concepts::real_concept>(concepts::real_concept r) | |
612 | { | |
613 | return static_cast<double>(r.value()); | |
614 | } | |
615 | template <> | |
616 | inline long double real_cast<long double, concepts::real_concept>(concepts::real_concept r) | |
617 | { | |
618 | return r.value(); | |
619 | } | |
7c673cae | 620 | |
92f5a8d4 | 621 | }}} // namespace boost::math::tools |
7c673cae FG |
622 | #endif |
623 | ||
92f5a8d4 | 624 | namespace std { |
7c673cae FG |
625 | |
626 | template <class Arithmetic, boost::multiprecision::expression_template_option ExpressionTemplates> | |
92f5a8d4 | 627 | class numeric_limits<boost::multiprecision::number<boost::multiprecision::arithmetic_backend<Arithmetic>, ExpressionTemplates> > : public std::numeric_limits<Arithmetic> |
7c673cae | 628 | { |
92f5a8d4 | 629 | typedef std::numeric_limits<Arithmetic> base_type; |
7c673cae | 630 | typedef boost::multiprecision::number<boost::multiprecision::arithmetic_backend<Arithmetic>, ExpressionTemplates> number_type; |
92f5a8d4 TL |
631 | |
632 | public: | |
633 | BOOST_STATIC_CONSTEXPR number_type(min)() BOOST_NOEXCEPT { return (base_type::min)(); } | |
634 | BOOST_STATIC_CONSTEXPR number_type(max)() BOOST_NOEXCEPT { return (base_type::max)(); } | |
7c673cae FG |
635 | BOOST_STATIC_CONSTEXPR number_type lowest() BOOST_NOEXCEPT { return -(max)(); } |
636 | BOOST_STATIC_CONSTEXPR number_type epsilon() BOOST_NOEXCEPT { return base_type::epsilon(); } | |
637 | BOOST_STATIC_CONSTEXPR number_type round_error() BOOST_NOEXCEPT { return epsilon() / 2; } | |
638 | BOOST_STATIC_CONSTEXPR number_type infinity() BOOST_NOEXCEPT { return base_type::infinity(); } | |
639 | BOOST_STATIC_CONSTEXPR number_type quiet_NaN() BOOST_NOEXCEPT { return base_type::quiet_NaN(); } | |
640 | BOOST_STATIC_CONSTEXPR number_type signaling_NaN() BOOST_NOEXCEPT { return base_type::signaling_NaN(); } | |
641 | BOOST_STATIC_CONSTEXPR number_type denorm_min() BOOST_NOEXCEPT { return base_type::denorm_min(); } | |
642 | }; | |
643 | ||
92f5a8d4 | 644 | template <> |
7c673cae FG |
645 | class numeric_limits<boost::math::concepts::real_concept> : public std::numeric_limits<long double> |
646 | { | |
92f5a8d4 | 647 | typedef std::numeric_limits<long double> base_type; |
7c673cae | 648 | typedef boost::math::concepts::real_concept number_type; |
92f5a8d4 TL |
649 | |
650 | public: | |
651 | static const number_type(min)() BOOST_NOEXCEPT { return (base_type::min)(); } | |
652 | static const number_type(max)() BOOST_NOEXCEPT { return (base_type::max)(); } | |
7c673cae FG |
653 | static const number_type lowest() BOOST_NOEXCEPT { return -(max)(); } |
654 | static const number_type epsilon() BOOST_NOEXCEPT { return base_type::epsilon(); } | |
655 | static const number_type round_error() BOOST_NOEXCEPT { return epsilon() / 2; } | |
656 | static const number_type infinity() BOOST_NOEXCEPT { return base_type::infinity(); } | |
657 | static const number_type quiet_NaN() BOOST_NOEXCEPT { return base_type::quiet_NaN(); } | |
658 | static const number_type signaling_NaN() BOOST_NOEXCEPT { return base_type::signaling_NaN(); } | |
659 | static const number_type denorm_min() BOOST_NOEXCEPT { return base_type::denorm_min(); } | |
660 | }; | |
661 | ||
92f5a8d4 | 662 | } // namespace std |
7c673cae FG |
663 | |
664 | #include <boost/multiprecision/detail/integer_ops.hpp> | |
665 | ||
666 | #endif |