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