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