]>
Commit | Line | Data |
---|---|---|
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 | |
19 | namespace boost{ | |
20 | namespace multiprecision{ | |
21 | namespace backends{ | |
22 | ||
23 | #ifdef BOOST_MSVC | |
24 | # pragma warning(push) | |
25 | # pragma warning(disable:4389 4244 4018 4244 4127) | |
26 | #endif | |
27 | ||
28 | template <class Arithmetic> | |
29 | struct 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; } | |
115 | private: | |
116 | Arithmetic m_value; | |
117 | }; | |
118 | ||
119 | template <class R, class Arithmetic> | |
11fdf7f2 TL |
120 | inline 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 | ||
136 | template <class R, class Arithmetic> | |
137 | inline 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 | ||
142 | template <class Arithmetic> | |
143 | inline bool eval_eq(const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b) | |
144 | { | |
145 | return a.data() == b.data(); | |
146 | } | |
147 | template <class Arithmetic, class A2> | |
148 | inline 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 | } | |
152 | template <class Arithmetic> | |
153 | inline bool eval_lt(const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b) | |
154 | { | |
155 | return a.data() < b.data(); | |
156 | } | |
157 | template <class Arithmetic, class A2> | |
158 | inline 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 | } | |
162 | template <class Arithmetic> | |
163 | inline bool eval_gt(const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b) | |
164 | { | |
165 | return a.data() > b.data(); | |
166 | } | |
167 | template <class Arithmetic, class A2> | |
168 | inline 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 | ||
173 | template <class Arithmetic> | |
174 | inline void eval_add(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o) | |
175 | { | |
176 | result.data() += o.data(); | |
177 | } | |
178 | template <class Arithmetic> | |
179 | inline void eval_subtract(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o) | |
180 | { | |
181 | result.data() -= o.data(); | |
182 | } | |
183 | template <class Arithmetic> | |
184 | inline void eval_multiply(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o) | |
185 | { | |
186 | result.data() *= o.data(); | |
187 | } | |
188 | template <class Arithmetic> | |
189 | inline 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 | } | |
193 | template <class Arithmetic> | |
194 | inline 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 | ||
201 | template <class Arithmetic, class A2> | |
202 | inline typename enable_if<is_arithmetic<A2> >::type eval_add(arithmetic_backend<Arithmetic>& result, const A2& o) | |
203 | { | |
204 | result.data() += o; | |
205 | } | |
206 | template <class Arithmetic, class A2> | |
207 | inline typename enable_if<is_arithmetic<A2> >::type eval_subtract(arithmetic_backend<Arithmetic>& result, const A2& o) | |
208 | { | |
209 | result.data() -= o; | |
210 | } | |
211 | template <class Arithmetic, class A2> | |
212 | inline typename enable_if<is_arithmetic<A2> >::type eval_multiply(arithmetic_backend<Arithmetic>& result, const A2& o) | |
213 | { | |
214 | result.data() *= o; | |
215 | } | |
216 | template <class Arithmetic, class A2> | |
217 | inline 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 | } | |
224 | template <class Arithmetic, class A2> | |
225 | inline 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 | ||
231 | template <class Arithmetic> | |
232 | inline 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 | } | |
236 | template <class Arithmetic> | |
237 | inline 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 | } | |
241 | template <class Arithmetic> | |
242 | inline 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 | } | |
246 | template <class Arithmetic> | |
247 | 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) | |
248 | { | |
249 | result.data() = a.data() / b.data(); | |
250 | } | |
251 | template <class Arithmetic> | |
252 | 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) | |
253 | { | |
254 | if(!b.data()) | |
255 | BOOST_THROW_EXCEPTION(std::overflow_error("Divide by zero")); | |
256 | result.data() = a.data() / b.data(); | |
257 | } | |
258 | ||
259 | template <class Arithmetic, class A2> | |
260 | inline 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 | } | |
264 | template <class Arithmetic, class A2> | |
265 | inline 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 | } | |
269 | template <class Arithmetic, class A2> | |
270 | inline 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 | } | |
274 | template <class Arithmetic, class A2> | |
275 | inline 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 | } | |
282 | template <class Arithmetic, class A2> | |
283 | inline 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 | ||
289 | template <class Arithmetic> | |
290 | inline bool eval_is_zero(const arithmetic_backend<Arithmetic>& val) | |
291 | { | |
292 | return val.data() == 0; | |
293 | } | |
294 | ||
295 | template <class Arithmetic> | |
296 | inline 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 | } | |
303 | template <class Arithmetic> | |
304 | inline 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 | ||
312 | template <class T> | |
313 | inline typename enable_if<is_unsigned<T>, T>::type abs(T v) { return v; } | |
314 | ||
315 | template <class Arithmetic> | |
316 | inline 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 | ||
323 | template <class Arithmetic> | |
324 | inline void eval_fabs(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o) | |
325 | { | |
326 | result.data() = std::abs(o.data()); | |
327 | } | |
328 | ||
329 | template <class Arithmetic> | |
330 | inline 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 | ||
336 | template <class Arithmetic> | |
337 | inline 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 | ||
343 | template <class Arithmetic> | |
344 | inline 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 | ||
350 | template <class Arithmetic> | |
351 | inline int eval_fpclassify(const arithmetic_backend<Arithmetic>& o) | |
352 | { | |
353 | return (boost::math::fpclassify)(o.data()); | |
354 | } | |
355 | ||
356 | template <class Arithmetic> | |
357 | inline 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 | ||
363 | template <class Arithmetic> | |
364 | inline 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 | ||
370 | template <class Arithmetic> | |
371 | inline 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 | ||
377 | template <class Arithmetic> | |
378 | inline 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 | ||
384 | template <class Arithmetic> | |
385 | inline 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 | ||
391 | template <class Arithmetic> | |
392 | inline 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 | ||
398 | template <class Arithmetic> | |
399 | inline 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 | ||
405 | template <class Arithmetic> | |
406 | inline 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 | ||
412 | template <class Arithmetic> | |
413 | inline 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 | ||
419 | template <class Arithmetic> | |
420 | inline 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 | ||
426 | template <class Arithmetic> | |
427 | inline 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 | ||
433 | template <class Arithmetic> | |
434 | inline 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 | ||
440 | template <class Arithmetic> | |
441 | inline 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 | ||
447 | template <class Arithmetic> | |
448 | inline 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 | ||
454 | template <class Arithmetic> | |
455 | inline 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 | ||
461 | template <class Arithmetic> | |
462 | inline 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 | ||
468 | template <class Arithmetic> | |
469 | inline 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 | ||
475 | template <class Arithmetic> | |
476 | inline 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 | ||
482 | template <class Arithmetic> | |
483 | inline 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 | ||
489 | template <class Arithmetic, class I> | |
490 | inline void eval_left_shift(arithmetic_backend<Arithmetic>& result, I val) | |
491 | { | |
492 | result.data() <<= val; | |
493 | } | |
494 | ||
495 | template <class Arithmetic, class I> | |
496 | inline void eval_right_shift(arithmetic_backend<Arithmetic>& result, I val) | |
497 | { | |
498 | result.data() >>= val; | |
499 | } | |
500 | ||
501 | template <class Arithmetic> | |
502 | inline void eval_modulus(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a) | |
503 | { | |
504 | result.data() %= a.data(); | |
505 | } | |
506 | ||
507 | template <class Arithmetic> | |
508 | inline void eval_bitwise_and(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a) | |
509 | { | |
510 | result.data() &= a.data(); | |
511 | } | |
512 | ||
513 | template <class Arithmetic> | |
514 | inline void eval_bitwise_or(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a) | |
515 | { | |
516 | result.data() |= a.data(); | |
517 | } | |
518 | ||
519 | template <class Arithmetic> | |
520 | inline void eval_bitwise_xor(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a) | |
521 | { | |
522 | result.data() ^= a.data(); | |
523 | } | |
524 | ||
525 | template <class Arithmetic> | |
526 | inline void eval_complement(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a) | |
527 | { | |
528 | result.data() = ~a.data(); | |
529 | } | |
530 | ||
531 | template <class Arithmetic> | |
532 | inline 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 | ||
537 | template <class Arithmetic> | |
538 | inline 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 | ||
549 | using boost::multiprecision::backends::arithmetic_backend; | |
550 | ||
551 | template <class Arithmetic> | |
552 | struct number_category<arithmetic_backend<Arithmetic> > : public mpl::int_<is_integral<Arithmetic>::value ? number_kind_integer : number_kind_floating_point>{}; | |
553 | ||
554 | namespace detail{ | |
555 | ||
556 | template <class Backend> | |
557 | struct double_precision_type; | |
558 | ||
559 | template<class Arithmetic, boost::multiprecision::expression_template_option ET> | |
560 | struct double_precision_type<number<arithmetic_backend<Arithmetic>, ET> > | |
561 | { | |
562 | typedef number<arithmetic_backend<typename double_precision_type<Arithmetic>::type>, ET> type; | |
563 | }; | |
564 | template<> | |
565 | struct 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 | // | |
581 | namespace 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 | ||
622 | namespace std{ | |
623 | ||
624 | template <class Arithmetic, boost::multiprecision::expression_template_option ExpressionTemplates> | |
625 | class 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; | |
629 | public: | |
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 | ||
641 | template<> | |
642 | class 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; | |
646 | public: | |
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 |