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