annotate DEPENDENCIES/generic/include/boost/multiprecision/detail/default_ops.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 ///////////////////////////////////////////////////////////////////////////////
Chris@16 2 // Copyright 2011 John Maddock. Distributed under the Boost
Chris@16 3 // Software License, Version 1.0. (See accompanying file
Chris@16 4 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 5
Chris@16 6 #ifndef BOOST_MATH_BIG_NUM_DEF_OPS
Chris@16 7 #define BOOST_MATH_BIG_NUM_DEF_OPS
Chris@16 8
Chris@16 9 #include <boost/math/policies/error_handling.hpp>
Chris@16 10 #include <boost/multiprecision/detail/number_base.hpp>
Chris@16 11 #include <boost/math/special_functions/fpclassify.hpp>
Chris@16 12 #include <boost/utility/enable_if.hpp>
Chris@16 13 #include <boost/mpl/front.hpp>
Chris@16 14 #include <boost/mpl/fold.hpp>
Chris@16 15 #include <boost/cstdint.hpp>
Chris@16 16 #include <boost/type_traits/make_unsigned.hpp>
Chris@16 17
Chris@16 18 #ifndef INSTRUMENT_BACKEND
Chris@16 19 #ifndef BOOST_MP_INSTRUMENT
Chris@16 20 #define INSTRUMENT_BACKEND(x)
Chris@16 21 #else
Chris@16 22 #define INSTRUMENT_BACKEND(x)\
Chris@16 23 std::cout << BOOST_STRINGIZE(x) << " = " << x.str(0, std::ios_base::scientific) << std::endl;
Chris@16 24 #endif
Chris@16 25 #endif
Chris@16 26
Chris@16 27
Chris@16 28 namespace boost{ namespace multiprecision{ namespace default_ops{
Chris@16 29
Chris@16 30 #ifdef BOOST_MSVC
Chris@16 31 // warning C4127: conditional expression is constant
Chris@16 32 #pragma warning(push)
Chris@16 33 #pragma warning(disable:4127)
Chris@16 34 #endif
Chris@16 35 //
Chris@16 36 // Default versions of mixed arithmetic, these just construct a temporary
Chris@16 37 // from the arithmetic value and then do the arithmetic on that, two versions
Chris@16 38 // of each depending on whether the backend can be directly constructed from type V.
Chris@16 39 //
Chris@16 40 // Note that we have to provide *all* the template parameters to class number when used in
Chris@16 41 // enable_if as MSVC-10 won't compile the code if we rely on a computed-default parameter.
Chris@16 42 // Since the result of the test doesn't depend on whether expression templates are on or off
Chris@16 43 // we just use et_on everywhere. We could use a BOOST_WORKAROUND but that just obfuscates the
Chris@16 44 // code even more....
Chris@16 45 //
Chris@16 46 template <class T, class V>
Chris@16 47 inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value >::type
Chris@16 48 eval_add(T& result, V const& v)
Chris@16 49 {
Chris@16 50 T t;
Chris@16 51 t = v;
Chris@16 52 eval_add(result, t);
Chris@16 53 }
Chris@16 54 template <class T, class V>
Chris@16 55 inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value >::type
Chris@16 56 eval_add(T& result, V const& v)
Chris@16 57 {
Chris@16 58 T t(v);
Chris@16 59 eval_add(result, t);
Chris@16 60 }
Chris@16 61 template <class T, class V>
Chris@16 62 inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
Chris@16 63 eval_subtract(T& result, V const& v)
Chris@16 64 {
Chris@16 65 T t;
Chris@16 66 t = v;
Chris@16 67 eval_subtract(result, t);
Chris@16 68 }
Chris@16 69 template <class T, class V>
Chris@16 70 inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
Chris@16 71 eval_subtract(T& result, V const& v)
Chris@16 72 {
Chris@16 73 T t(v);
Chris@16 74 eval_subtract(result, t);
Chris@16 75 }
Chris@16 76 template <class T, class V>
Chris@16 77 inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
Chris@16 78 eval_multiply(T& result, V const& v)
Chris@16 79 {
Chris@16 80 T t;
Chris@16 81 t = v;
Chris@16 82 eval_multiply(result, t);
Chris@16 83 }
Chris@16 84 template <class T, class V>
Chris@16 85 inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
Chris@16 86 eval_multiply(T& result, V const& v)
Chris@16 87 {
Chris@16 88 T t(v);
Chris@16 89 eval_multiply(result, t);
Chris@16 90 }
Chris@16 91
Chris@16 92 template <class T, class U, class V>
Chris@16 93 void eval_multiply(T& t, const U& u, const V& v);
Chris@16 94
Chris@16 95 template <class T, class U, class V>
Chris@16 96 inline typename disable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_add(T& t, const U& u, const V& v)
Chris@16 97 {
Chris@16 98 T z;
Chris@16 99 eval_multiply(z, u, v);
Chris@16 100 eval_add(t, z);
Chris@16 101 }
Chris@16 102 template <class T, class U, class V>
Chris@16 103 inline typename enable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_add(T& t, const U& u, const V& v)
Chris@16 104 {
Chris@16 105 eval_multiply_add(t, v, u);
Chris@16 106 }
Chris@16 107 template <class T, class U, class V>
Chris@16 108 inline typename disable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_subtract(T& t, const U& u, const V& v)
Chris@16 109 {
Chris@16 110 T z;
Chris@16 111 eval_multiply(z, u, v);
Chris@16 112 eval_subtract(t, z);
Chris@16 113 }
Chris@16 114 template <class T, class U, class V>
Chris@16 115 inline typename enable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_subtract(T& t, const U& u, const V& v)
Chris@16 116 {
Chris@16 117 eval_multiply_subtract(t, v, u);
Chris@16 118 }
Chris@16 119 template <class T, class V>
Chris@16 120 inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
Chris@16 121 eval_divide(T& result, V const& v)
Chris@16 122 {
Chris@16 123 T t;
Chris@16 124 t = v;
Chris@16 125 eval_divide(result, t);
Chris@16 126 }
Chris@16 127 template <class T, class V>
Chris@16 128 inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
Chris@16 129 eval_divide(T& result, V const& v)
Chris@16 130 {
Chris@16 131 T t(v);
Chris@16 132 eval_divide(result, t);
Chris@16 133 }
Chris@16 134 template <class T, class V>
Chris@16 135 inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
Chris@16 136 eval_modulus(T& result, V const& v)
Chris@16 137 {
Chris@16 138 T t;
Chris@16 139 t = v;
Chris@16 140 eval_modulus(result, t);
Chris@16 141 }
Chris@16 142 template <class T, class V>
Chris@16 143 inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value&& is_convertible<V, T>::value>::type
Chris@16 144 eval_modulus(T& result, V const& v)
Chris@16 145 {
Chris@16 146 T t(v);
Chris@16 147 eval_modulus(result, t);
Chris@16 148 }
Chris@16 149 template <class T, class V>
Chris@16 150 inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
Chris@16 151 eval_bitwise_and(T& result, V const& v)
Chris@16 152 {
Chris@16 153 T t;
Chris@16 154 t = v;
Chris@16 155 eval_bitwise_and(result, t);
Chris@16 156 }
Chris@16 157 template <class T, class V>
Chris@16 158 inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
Chris@16 159 eval_bitwise_and(T& result, V const& v)
Chris@16 160 {
Chris@16 161 T t(v);
Chris@16 162 eval_bitwise_and(result, t);
Chris@16 163 }
Chris@16 164 template <class T, class V>
Chris@16 165 inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
Chris@16 166 eval_bitwise_or(T& result, V const& v)
Chris@16 167 {
Chris@16 168 T t;
Chris@16 169 t = v;
Chris@16 170 eval_bitwise_or(result, t);
Chris@16 171 }
Chris@16 172 template <class T, class V>
Chris@16 173 inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
Chris@16 174 eval_bitwise_or(T& result, V const& v)
Chris@16 175 {
Chris@16 176 T t(v);
Chris@16 177 eval_bitwise_or(result, t);
Chris@16 178 }
Chris@16 179 template <class T, class V>
Chris@16 180 inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
Chris@16 181 eval_bitwise_xor(T& result, V const& v)
Chris@16 182 {
Chris@16 183 T t;
Chris@16 184 t = v;
Chris@16 185 eval_bitwise_xor(result, t);
Chris@16 186 }
Chris@16 187 template <class T, class V>
Chris@16 188 inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
Chris@16 189 eval_bitwise_xor(T& result, V const& v)
Chris@16 190 {
Chris@16 191 T t(v);
Chris@16 192 eval_bitwise_xor(result, t);
Chris@16 193 }
Chris@16 194
Chris@16 195 template <class T, class V>
Chris@16 196 inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
Chris@16 197 eval_complement(T& result, V const& v)
Chris@16 198 {
Chris@16 199 T t;
Chris@16 200 t = v;
Chris@16 201 eval_complement(result, t);
Chris@16 202 }
Chris@16 203 template <class T, class V>
Chris@16 204 inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
Chris@16 205 eval_complement(T& result, V const& v)
Chris@16 206 {
Chris@16 207 T t(v);
Chris@16 208 eval_complement(result, t);
Chris@16 209 }
Chris@16 210
Chris@16 211 //
Chris@16 212 // Default versions of 3-arg arithmetic functions, these mostly just forward to the 2 arg versions:
Chris@16 213 //
Chris@16 214 template <class T, class U, class V>
Chris@16 215 void eval_add(T& t, const U& u, const V& v);
Chris@16 216
Chris@16 217 template <class T>
Chris@16 218 inline void eval_add_default(T& t, const T& u, const T& v)
Chris@16 219 {
Chris@16 220 if(&t == &v)
Chris@16 221 {
Chris@16 222 eval_add(t, u);
Chris@16 223 }
Chris@16 224 else if(&t == &u)
Chris@16 225 {
Chris@16 226 eval_add(t, v);
Chris@16 227 }
Chris@16 228 else
Chris@16 229 {
Chris@16 230 t = u;
Chris@16 231 eval_add(t, v);
Chris@16 232 }
Chris@16 233 }
Chris@16 234 template <class T, class U>
Chris@16 235 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_add_default(T& t, const T& u, const U& v)
Chris@16 236 {
Chris@16 237 T vv;
Chris@16 238 vv = v;
Chris@16 239 eval_add(t, u, vv);
Chris@16 240 }
Chris@16 241 template <class T, class U>
Chris@16 242 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_add_default(T& t, const T& u, const U& v)
Chris@16 243 {
Chris@16 244 T vv(v);
Chris@16 245 eval_add(t, u, vv);
Chris@16 246 }
Chris@16 247 template <class T, class U>
Chris@16 248 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value>::type eval_add_default(T& t, const U& u, const T& v)
Chris@16 249 {
Chris@16 250 eval_add(t, v, u);
Chris@16 251 }
Chris@16 252 template <class T, class U, class V>
Chris@16 253 inline void eval_add_default(T& t, const U& u, const V& v)
Chris@16 254 {
Chris@16 255 if(is_same<T, V>::value && ((void*)&t == (void*)&v))
Chris@16 256 {
Chris@16 257 eval_add(t, u);
Chris@16 258 }
Chris@16 259 else
Chris@16 260 {
Chris@16 261 t = u;
Chris@16 262 eval_add(t, v);
Chris@16 263 }
Chris@16 264 }
Chris@16 265 template <class T, class U, class V>
Chris@16 266 inline void eval_add(T& t, const U& u, const V& v)
Chris@16 267 {
Chris@16 268 eval_add_default(t, u, v);
Chris@16 269 }
Chris@16 270
Chris@16 271 template <class T, class U, class V>
Chris@16 272 void eval_subtract(T& t, const U& u, const V& v);
Chris@16 273
Chris@16 274 template <class T>
Chris@16 275 inline void eval_subtract_default(T& t, const T& u, const T& v)
Chris@16 276 {
Chris@16 277 if((&t == &v) && is_signed_number<T>::value)
Chris@16 278 {
Chris@16 279 eval_subtract(t, u);
Chris@16 280 t.negate();
Chris@16 281 }
Chris@16 282 else if(&t == &u)
Chris@16 283 {
Chris@16 284 eval_subtract(t, v);
Chris@16 285 }
Chris@16 286 else
Chris@16 287 {
Chris@16 288 t = u;
Chris@16 289 eval_subtract(t, v);
Chris@16 290 }
Chris@16 291 }
Chris@16 292 template <class T, class U>
Chris@16 293 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_subtract_default(T& t, const T& u, const U& v)
Chris@16 294 {
Chris@16 295 T vv;
Chris@16 296 vv = v;
Chris@16 297 eval_subtract(t, u, vv);
Chris@16 298 }
Chris@16 299 template <class T, class U>
Chris@16 300 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_subtract_default(T& t, const T& u, const U& v)
Chris@16 301 {
Chris@16 302 T vv(v);
Chris@16 303 eval_subtract(t, u, vv);
Chris@16 304 }
Chris@16 305 template <class T, class U>
Chris@16 306 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_signed_number<T>::value>::type eval_subtract_default(T& t, const U& u, const T& v)
Chris@16 307 {
Chris@16 308 eval_subtract(t, v, u);
Chris@16 309 t.negate();
Chris@16 310 }
Chris@16 311 template <class T, class U>
Chris@16 312 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_unsigned_number<T>::value>::type eval_subtract_default(T& t, const U& u, const T& v)
Chris@16 313 {
Chris@16 314 T temp(u);
Chris@16 315 eval_subtract(t, temp, v);
Chris@16 316 }
Chris@16 317 template <class T, class U, class V>
Chris@16 318 inline void eval_subtract_default(T& t, const U& u, const V& v)
Chris@16 319 {
Chris@16 320 if(is_same<T, V>::value && ((void*)&t == (void*)&v))
Chris@16 321 {
Chris@16 322 eval_subtract(t, u);
Chris@16 323 t.negate();
Chris@16 324 }
Chris@16 325 else
Chris@16 326 {
Chris@16 327 t = u;
Chris@16 328 eval_subtract(t, v);
Chris@16 329 }
Chris@16 330 }
Chris@16 331 template <class T, class U, class V>
Chris@16 332 inline void eval_subtract(T& t, const U& u, const V& v)
Chris@16 333 {
Chris@16 334 eval_subtract_default(t, u, v);
Chris@16 335 }
Chris@16 336
Chris@16 337 template <class T>
Chris@16 338 inline void eval_multiply_default(T& t, const T& u, const T& v)
Chris@16 339 {
Chris@16 340 if(&t == &v)
Chris@16 341 {
Chris@16 342 eval_multiply(t, u);
Chris@16 343 }
Chris@16 344 else if(&t == &u)
Chris@16 345 {
Chris@16 346 eval_multiply(t, v);
Chris@16 347 }
Chris@16 348 else
Chris@16 349 {
Chris@16 350 t = u;
Chris@16 351 eval_multiply(t, v);
Chris@16 352 }
Chris@16 353 }
Chris@16 354 template <class T, class U>
Chris@16 355 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_multiply_default(T& t, const T& u, const U& v)
Chris@16 356 {
Chris@16 357 T vv;
Chris@16 358 vv = v;
Chris@16 359 eval_multiply(t, u, vv);
Chris@16 360 }
Chris@16 361 template <class T, class U>
Chris@16 362 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_multiply_default(T& t, const T& u, const U& v)
Chris@16 363 {
Chris@16 364 T vv(v);
Chris@16 365 eval_multiply(t, u, vv);
Chris@16 366 }
Chris@16 367 template <class T, class U>
Chris@16 368 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value>::type eval_multiply_default(T& t, const U& u, const T& v)
Chris@16 369 {
Chris@16 370 eval_multiply(t, v, u);
Chris@16 371 }
Chris@16 372 template <class T, class U, class V>
Chris@16 373 inline void eval_multiply_default(T& t, const U& u, const V& v)
Chris@16 374 {
Chris@16 375 if(is_same<T, V>::value && ((void*)&t == (void*)&v))
Chris@16 376 {
Chris@16 377 eval_multiply(t, u);
Chris@16 378 }
Chris@16 379 else
Chris@16 380 {
Chris@16 381 t = u;
Chris@16 382 eval_multiply(t, v);
Chris@16 383 }
Chris@16 384 }
Chris@16 385 template <class T, class U, class V>
Chris@16 386 inline void eval_multiply(T& t, const U& u, const V& v)
Chris@16 387 {
Chris@16 388 eval_multiply_default(t, u, v);
Chris@16 389 }
Chris@16 390
Chris@16 391 template <class T, class U, class V, class X>
Chris@16 392 inline typename disable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_add(T& t, const U& u, const V& v, const X& x)
Chris@16 393 {
Chris@16 394 if((void*)&x == (void*)&t)
Chris@16 395 {
Chris@16 396 T z;
Chris@16 397 z = x;
Chris@16 398 eval_multiply_add(t, u, v, z);
Chris@16 399 }
Chris@16 400 else
Chris@16 401 {
Chris@16 402 eval_multiply(t, u, v);
Chris@16 403 eval_add(t, x);
Chris@16 404 }
Chris@16 405 }
Chris@16 406 template <class T, class U, class V, class X>
Chris@16 407 inline typename enable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_add(T& t, const U& u, const V& v, const X& x)
Chris@16 408 {
Chris@16 409 eval_multiply_add(t, v, u, x);
Chris@16 410 }
Chris@16 411 template <class T, class U, class V, class X>
Chris@16 412 inline typename disable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_subtract(T& t, const U& u, const V& v, const X& x)
Chris@16 413 {
Chris@16 414 if((void*)&x == (void*)&t)
Chris@16 415 {
Chris@16 416 T z;
Chris@16 417 z = x;
Chris@16 418 eval_multiply_subtract(t, u, v, z);
Chris@16 419 }
Chris@16 420 else
Chris@16 421 {
Chris@16 422 eval_multiply(t, u, v);
Chris@16 423 eval_subtract(t, x);
Chris@16 424 }
Chris@16 425 }
Chris@16 426 template <class T, class U, class V, class X>
Chris@16 427 inline typename enable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_subtract(T& t, const U& u, const V& v, const X& x)
Chris@16 428 {
Chris@16 429 eval_multiply_subtract(t, v, u, x);
Chris@16 430 }
Chris@16 431
Chris@16 432 template <class T, class U, class V>
Chris@16 433 void eval_divide(T& t, const U& u, const V& v);
Chris@16 434
Chris@16 435 template <class T>
Chris@16 436 inline void eval_divide_default(T& t, const T& u, const T& v)
Chris@16 437 {
Chris@16 438 if(&t == &u)
Chris@16 439 eval_divide(t, v);
Chris@16 440 else if(&t == &v)
Chris@16 441 {
Chris@16 442 T temp;
Chris@16 443 eval_divide(temp, u, v);
Chris@16 444 temp.swap(t);
Chris@16 445 }
Chris@16 446 else
Chris@16 447 {
Chris@16 448 t = u;
Chris@16 449 eval_divide(t, v);
Chris@16 450 }
Chris@16 451 }
Chris@16 452 template <class T, class U>
Chris@16 453 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_divide_default(T& t, const T& u, const U& v)
Chris@16 454 {
Chris@16 455 T vv;
Chris@16 456 vv = v;
Chris@16 457 eval_divide(t, u, vv);
Chris@16 458 }
Chris@16 459 template <class T, class U>
Chris@16 460 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_divide_default(T& t, const T& u, const U& v)
Chris@16 461 {
Chris@16 462 T vv(v);
Chris@16 463 eval_divide(t, u, vv);
Chris@16 464 }
Chris@16 465 template <class T, class U>
Chris@16 466 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_divide_default(T& t, const U& u, const T& v)
Chris@16 467 {
Chris@16 468 T uu;
Chris@16 469 uu = u;
Chris@16 470 eval_divide(t, uu, v);
Chris@16 471 }
Chris@16 472 template <class T, class U>
Chris@16 473 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_divide_default(T& t, const U& u, const T& v)
Chris@16 474 {
Chris@16 475 T uu(u);
Chris@16 476 eval_divide(t, uu, v);
Chris@16 477 }
Chris@16 478 template <class T, class U, class V>
Chris@16 479 inline void eval_divide_default(T& t, const U& u, const V& v)
Chris@16 480 {
Chris@16 481 if(is_same<T, V>::value && ((void*)&t == (void*)&v))
Chris@16 482 {
Chris@16 483 T temp(u);
Chris@16 484 eval_divide(temp, v);
Chris@16 485 t = temp;
Chris@16 486 }
Chris@16 487 else
Chris@16 488 {
Chris@16 489 t = u;
Chris@16 490 eval_divide(t, v);
Chris@16 491 }
Chris@16 492 }
Chris@16 493 template <class T, class U, class V>
Chris@16 494 inline void eval_divide(T& t, const U& u, const V& v)
Chris@16 495 {
Chris@16 496 eval_divide_default(t, u, v);
Chris@16 497 }
Chris@16 498
Chris@16 499 template <class T, class U, class V>
Chris@16 500 void eval_modulus(T& t, const U& u, const V& v);
Chris@16 501
Chris@16 502 template <class T>
Chris@16 503 inline void eval_modulus_default(T& t, const T& u, const T& v)
Chris@16 504 {
Chris@16 505 if(&t == &u)
Chris@16 506 eval_modulus(t, v);
Chris@16 507 else if(&t == &v)
Chris@16 508 {
Chris@16 509 T temp;
Chris@16 510 eval_modulus(temp, u, v);
Chris@16 511 temp.swap(t);
Chris@16 512 }
Chris@16 513 else
Chris@16 514 {
Chris@16 515 t = u;
Chris@16 516 eval_modulus(t, v);
Chris@16 517 }
Chris@16 518 }
Chris@16 519 template <class T, class U>
Chris@16 520 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_modulus_default(T& t, const T& u, const U& v)
Chris@16 521 {
Chris@16 522 T vv;
Chris@16 523 vv = v;
Chris@16 524 eval_modulus(t, u, vv);
Chris@16 525 }
Chris@16 526 template <class T, class U>
Chris@16 527 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_modulus_default(T& t, const T& u, const U& v)
Chris@16 528 {
Chris@16 529 T vv(v);
Chris@16 530 eval_modulus(t, u, vv);
Chris@16 531 }
Chris@16 532 template <class T, class U>
Chris@16 533 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_modulus_default(T& t, const U& u, const T& v)
Chris@16 534 {
Chris@16 535 T uu;
Chris@16 536 uu = u;
Chris@16 537 eval_modulus(t, uu, v);
Chris@16 538 }
Chris@16 539 template <class T, class U>
Chris@16 540 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_modulus_default(T& t, const U& u, const T& v)
Chris@16 541 {
Chris@16 542 T uu(u);
Chris@16 543 eval_modulus(t, uu, v);
Chris@16 544 }
Chris@16 545 template <class T, class U, class V>
Chris@16 546 inline void eval_modulus_default(T& t, const U& u, const V& v)
Chris@16 547 {
Chris@16 548 if(is_same<T, V>::value && ((void*)&t == (void*)&v))
Chris@16 549 {
Chris@16 550 T temp(u);
Chris@16 551 eval_modulus(temp, v);
Chris@16 552 t = temp;
Chris@16 553 }
Chris@16 554 else
Chris@16 555 {
Chris@16 556 t = u;
Chris@16 557 eval_modulus(t, v);
Chris@16 558 }
Chris@16 559 }
Chris@16 560 template <class T, class U, class V>
Chris@16 561 inline void eval_modulus(T& t, const U& u, const V& v)
Chris@16 562 {
Chris@16 563 eval_modulus_default(t, u, v);
Chris@16 564 }
Chris@16 565
Chris@16 566 template <class T, class U, class V>
Chris@16 567 void eval_bitwise_and(T& t, const U& u, const V& v);
Chris@16 568
Chris@16 569 template <class T>
Chris@16 570 inline void eval_bitwise_and_default(T& t, const T& u, const T& v)
Chris@16 571 {
Chris@16 572 if(&t == &v)
Chris@16 573 {
Chris@16 574 eval_bitwise_and(t, u);
Chris@16 575 }
Chris@16 576 else if(&t == &u)
Chris@16 577 {
Chris@16 578 eval_bitwise_and(t, v);
Chris@16 579 }
Chris@16 580 else
Chris@16 581 {
Chris@16 582 t = u;
Chris@16 583 eval_bitwise_and(t, v);
Chris@16 584 }
Chris@16 585 }
Chris@16 586 template <class T, class U>
Chris@16 587 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_bitwise_and_default(T& t, const T& u, const U& v)
Chris@16 588 {
Chris@16 589 T vv;
Chris@16 590 vv = v;
Chris@16 591 eval_bitwise_and(t, u, vv);
Chris@16 592 }
Chris@16 593 template <class T, class U>
Chris@16 594 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_bitwise_and_default(T& t, const T& u, const U& v)
Chris@16 595 {
Chris@16 596 T vv(v);
Chris@16 597 eval_bitwise_and(t, u, vv);
Chris@16 598 }
Chris@16 599 template <class T, class U>
Chris@16 600 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value>::type eval_bitwise_and_default(T& t, const U& u, const T& v)
Chris@16 601 {
Chris@16 602 eval_bitwise_and(t, v, u);
Chris@16 603 }
Chris@16 604 template <class T, class U, class V>
Chris@16 605 inline void eval_bitwise_and_default(T& t, const U& u, const V& v)
Chris@16 606 {
Chris@16 607 if(is_same<T, V>::value && ((void*)&t == (void*)&v))
Chris@16 608 {
Chris@16 609 eval_bitwise_and(t, u);
Chris@16 610 }
Chris@16 611 else
Chris@16 612 {
Chris@16 613 t = u;
Chris@16 614 eval_bitwise_and(t, v);
Chris@16 615 }
Chris@16 616 }
Chris@16 617 template <class T, class U, class V>
Chris@16 618 inline void eval_bitwise_and(T& t, const U& u, const V& v)
Chris@16 619 {
Chris@16 620 eval_bitwise_and_default(t, u, v);
Chris@16 621 }
Chris@16 622
Chris@16 623 template <class T, class U, class V>
Chris@16 624 void eval_bitwise_or(T& t, const U& u, const V& v);
Chris@16 625
Chris@16 626 template <class T>
Chris@16 627 inline void eval_bitwise_or_default(T& t, const T& u, const T& v)
Chris@16 628 {
Chris@16 629 if(&t == &v)
Chris@16 630 {
Chris@16 631 eval_bitwise_or(t, u);
Chris@16 632 }
Chris@16 633 else if(&t == &u)
Chris@16 634 {
Chris@16 635 eval_bitwise_or(t, v);
Chris@16 636 }
Chris@16 637 else
Chris@16 638 {
Chris@16 639 t = u;
Chris@16 640 eval_bitwise_or(t, v);
Chris@16 641 }
Chris@16 642 }
Chris@16 643 template <class T, class U>
Chris@16 644 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_bitwise_or_default(T& t, const T& u, const U& v)
Chris@16 645 {
Chris@16 646 T vv;
Chris@16 647 vv = v;
Chris@16 648 eval_bitwise_or(t, u, vv);
Chris@16 649 }
Chris@16 650 template <class T, class U>
Chris@16 651 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_bitwise_or_default(T& t, const T& u, const U& v)
Chris@16 652 {
Chris@16 653 T vv(v);
Chris@16 654 eval_bitwise_or(t, u, vv);
Chris@16 655 }
Chris@16 656 template <class T, class U>
Chris@16 657 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value>::type eval_bitwise_or_default(T& t, const U& u, const T& v)
Chris@16 658 {
Chris@16 659 eval_bitwise_or(t, v, u);
Chris@16 660 }
Chris@16 661 template <class T, class U, class V>
Chris@16 662 inline void eval_bitwise_or_default(T& t, const U& u, const V& v)
Chris@16 663 {
Chris@16 664 if(is_same<T, V>::value && ((void*)&t == (void*)&v))
Chris@16 665 {
Chris@16 666 eval_bitwise_or(t, u);
Chris@16 667 }
Chris@16 668 else
Chris@16 669 {
Chris@16 670 t = u;
Chris@16 671 eval_bitwise_or(t, v);
Chris@16 672 }
Chris@16 673 }
Chris@16 674 template <class T, class U, class V>
Chris@16 675 inline void eval_bitwise_or(T& t, const U& u, const V& v)
Chris@16 676 {
Chris@16 677 eval_bitwise_or_default(t, u, v);
Chris@16 678 }
Chris@16 679
Chris@16 680 template <class T, class U, class V>
Chris@16 681 void eval_bitwise_xor(T& t, const U& u, const V& v);
Chris@16 682
Chris@16 683 template <class T>
Chris@16 684 inline void eval_bitwise_xor_default(T& t, const T& u, const T& v)
Chris@16 685 {
Chris@16 686 if(&t == &v)
Chris@16 687 {
Chris@16 688 eval_bitwise_xor(t, u);
Chris@16 689 }
Chris@16 690 else if(&t == &u)
Chris@16 691 {
Chris@16 692 eval_bitwise_xor(t, v);
Chris@16 693 }
Chris@16 694 else
Chris@16 695 {
Chris@16 696 t = u;
Chris@16 697 eval_bitwise_xor(t, v);
Chris@16 698 }
Chris@16 699 }
Chris@16 700 template <class T, class U>
Chris@16 701 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_bitwise_xor_default(T& t, const T& u, const U& v)
Chris@16 702 {
Chris@16 703 T vv;
Chris@16 704 vv = v;
Chris@16 705 eval_bitwise_xor(t, u, vv);
Chris@16 706 }
Chris@16 707 template <class T, class U>
Chris@16 708 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_bitwise_xor_default(T& t, const T& u, const U& v)
Chris@16 709 {
Chris@16 710 T vv(v);
Chris@16 711 eval_bitwise_xor(t, u, vv);
Chris@16 712 }
Chris@16 713 template <class T, class U>
Chris@16 714 inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value>::type eval_bitwise_xor_default(T& t, const U& u, const T& v)
Chris@16 715 {
Chris@16 716 eval_bitwise_xor(t, v, u);
Chris@16 717 }
Chris@16 718 template <class T, class U, class V>
Chris@16 719 inline void eval_bitwise_xor_default(T& t, const U& u, const V& v)
Chris@16 720 {
Chris@16 721 if(is_same<T, V>::value && ((void*)&t == (void*)&v))
Chris@16 722 {
Chris@16 723 eval_bitwise_xor(t, u);
Chris@16 724 }
Chris@16 725 else
Chris@16 726 {
Chris@16 727 t = u;
Chris@16 728 eval_bitwise_xor(t, v);
Chris@16 729 }
Chris@16 730 }
Chris@16 731 template <class T, class U, class V>
Chris@16 732 inline void eval_bitwise_xor(T& t, const U& u, const V& v)
Chris@16 733 {
Chris@16 734 eval_bitwise_xor_default(t, u, v);
Chris@16 735 }
Chris@16 736
Chris@16 737 template <class T>
Chris@16 738 inline void eval_increment(T& val)
Chris@16 739 {
Chris@16 740 typedef typename mpl::front<typename T::unsigned_types>::type ui_type;
Chris@16 741 eval_add(val, static_cast<ui_type>(1u));
Chris@16 742 }
Chris@16 743 template <class T>
Chris@16 744 inline void eval_decrement(T& val)
Chris@16 745 {
Chris@16 746 typedef typename mpl::front<typename T::unsigned_types>::type ui_type;
Chris@16 747 eval_subtract(val, static_cast<ui_type>(1u));
Chris@16 748 }
Chris@16 749
Chris@16 750 template <class T, class V>
Chris@16 751 inline void eval_left_shift(T& result, const T& arg, const V val)
Chris@16 752 {
Chris@16 753 result = arg;
Chris@16 754 eval_left_shift(result, val);
Chris@16 755 }
Chris@16 756
Chris@16 757 template <class T, class V>
Chris@16 758 inline void eval_right_shift(T& result, const T& arg, const V val)
Chris@16 759 {
Chris@16 760 result = arg;
Chris@16 761 eval_right_shift(result, val);
Chris@16 762 }
Chris@16 763
Chris@16 764 template <class T>
Chris@16 765 inline bool eval_is_zero(const T& val)
Chris@16 766 {
Chris@16 767 typedef typename mpl::front<typename T::unsigned_types>::type ui_type;
Chris@16 768 return val.compare(static_cast<ui_type>(0)) == 0;
Chris@16 769 }
Chris@16 770 template <class T>
Chris@16 771 inline int eval_get_sign(const T& val)
Chris@16 772 {
Chris@16 773 typedef typename mpl::front<typename T::unsigned_types>::type ui_type;
Chris@16 774 return val.compare(static_cast<ui_type>(0));
Chris@16 775 }
Chris@16 776
Chris@16 777 template <class T, class V>
Chris@16 778 inline void assign_components_imp(T& result, const V& v1, const V& v2, const mpl::int_<number_kind_rational>&)
Chris@16 779 {
Chris@16 780 result = v1;
Chris@16 781 T t;
Chris@16 782 t = v2;
Chris@16 783 eval_divide(result, t);
Chris@16 784 }
Chris@16 785
Chris@16 786 template <class T, class V>
Chris@16 787 inline void assign_components(T& result, const V& v1, const V& v2)
Chris@16 788 {
Chris@16 789 return assign_components_imp(result, v1, v2, typename number_category<T>::type());
Chris@16 790 }
Chris@16 791
Chris@16 792 template <class R, int b>
Chris@16 793 struct has_enough_bits
Chris@16 794 {
Chris@16 795 template <class T>
Chris@16 796 struct type : public mpl::and_<mpl::not_<is_same<R, T> >, mpl::bool_<std::numeric_limits<T>::digits >= b> >{};
Chris@16 797 };
Chris@16 798
Chris@16 799 template <class R>
Chris@16 800 struct terminal
Chris@16 801 {
Chris@16 802 terminal(const R& v) : value(v){}
Chris@16 803 terminal(){}
Chris@16 804 terminal& operator = (R val) { value = val; }
Chris@16 805 R value;
Chris@16 806 operator R()const { return value; }
Chris@16 807 };
Chris@16 808
Chris@16 809 template<class R, class B>
Chris@16 810 struct calculate_next_larger_type
Chris@16 811 {
Chris@16 812 // Find which list we're looking through:
Chris@16 813 typedef typename mpl::if_<
Chris@16 814 is_signed<R>,
Chris@16 815 typename B::signed_types,
Chris@16 816 typename mpl::if_<
Chris@16 817 is_unsigned<R>,
Chris@16 818 typename B::unsigned_types,
Chris@16 819 typename B::float_types
Chris@16 820 >::type
Chris@16 821 >::type list_type;
Chris@16 822 // A predicate to find a type with enough bits:
Chris@16 823 typedef typename has_enough_bits<R, std::numeric_limits<R>::digits>::template type<mpl::_> pred_type;
Chris@16 824 // See if the last type is in the list, if so we have to start after this:
Chris@16 825 typedef typename mpl::find_if<
Chris@16 826 list_type,
Chris@16 827 is_same<R, mpl::_>
Chris@16 828 >::type start_last;
Chris@16 829 // Where we're starting from, either the start of the sequence or the last type found:
Chris@16 830 typedef typename mpl::if_<is_same<start_last, typename mpl::end<list_type>::type>, typename mpl::begin<list_type>::type, start_last>::type start_seq;
Chris@16 831 // The range we're searching:
Chris@16 832 typedef mpl::iterator_range<start_seq, typename mpl::end<list_type>::type> range;
Chris@16 833 // Find the next type:
Chris@16 834 typedef typename mpl::find_if<
Chris@16 835 range,
Chris@16 836 pred_type
Chris@16 837 >::type iter_type;
Chris@16 838 // Either the next type, or a "terminal" to indicate we've run out of types to search:
Chris@16 839 typedef typename mpl::eval_if<
Chris@16 840 is_same<typename mpl::end<list_type>::type, iter_type>,
Chris@16 841 mpl::identity<terminal<R> >,
Chris@16 842 mpl::deref<iter_type>
Chris@16 843 >::type type;
Chris@16 844 };
Chris@16 845
Chris@16 846 template <class R, class T>
Chris@16 847 inline bool check_in_range(const T& t)
Chris@16 848 {
Chris@16 849 // Can t fit in an R?
Chris@16 850 if(std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::is_bounded && (t > (std::numeric_limits<R>::max)()))
Chris@16 851 return true;
Chris@16 852 return false;
Chris@16 853 }
Chris@16 854
Chris@16 855 template <class R, class T>
Chris@16 856 inline bool check_in_range(const terminal<T>&)
Chris@16 857 {
Chris@16 858 return false;
Chris@16 859 }
Chris@16 860
Chris@16 861 template <class R, class B>
Chris@16 862 inline void eval_convert_to(R* result, const B& backend)
Chris@16 863 {
Chris@16 864 typedef typename calculate_next_larger_type<R, B>::type next_type;
Chris@16 865 next_type n;
Chris@16 866 eval_convert_to(&n, backend);
Chris@16 867 if(check_in_range<R>(n))
Chris@16 868 {
Chris@16 869 *result = (std::numeric_limits<R>::max)();
Chris@16 870 }
Chris@16 871 else
Chris@16 872 *result = static_cast<R>(n);
Chris@16 873 }
Chris@16 874
Chris@16 875 template <class R, class B>
Chris@16 876 inline void eval_convert_to(terminal<R>* result, const B& backend)
Chris@16 877 {
Chris@16 878 //
Chris@16 879 // We ran out of types to try for the conversion, try
Chris@16 880 // a lexical_cast and hope for the best:
Chris@16 881 //
Chris@16 882 result->value = boost::lexical_cast<R>(backend.str(0, std::ios_base::fmtflags(0)));
Chris@16 883 }
Chris@16 884
Chris@16 885 template <class B>
Chris@16 886 inline void eval_convert_to(std::string* result, const B& backend)
Chris@16 887 {
Chris@16 888 *result = backend.str(0, std::ios_base::fmtflags(0));
Chris@16 889 }
Chris@16 890 //
Chris@16 891 // Functions:
Chris@16 892 //
Chris@16 893 template <class T>
Chris@16 894 void eval_abs(T& result, const T& arg)
Chris@16 895 {
Chris@16 896 typedef typename T::signed_types type_list;
Chris@16 897 typedef typename mpl::front<type_list>::type front;
Chris@16 898 result = arg;
Chris@16 899 if(arg.compare(front(0)) < 0)
Chris@16 900 result.negate();
Chris@16 901 }
Chris@16 902 template <class T>
Chris@16 903 void eval_fabs(T& result, const T& arg)
Chris@16 904 {
Chris@16 905 BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The fabs function is only valid for floating point types.");
Chris@16 906 typedef typename T::signed_types type_list;
Chris@16 907 typedef typename mpl::front<type_list>::type front;
Chris@16 908 result = arg;
Chris@16 909 if(arg.compare(front(0)) < 0)
Chris@16 910 result.negate();
Chris@16 911 }
Chris@16 912
Chris@16 913 template <class Backend>
Chris@16 914 inline int eval_fpclassify(const Backend& arg)
Chris@16 915 {
Chris@16 916 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_floating_point, "The fpclassify function is only valid for floating point types.");
Chris@16 917 return eval_is_zero(arg) ? FP_ZERO : FP_NORMAL;
Chris@16 918 }
Chris@16 919
Chris@16 920 template <class T>
Chris@16 921 inline void eval_fmod(T& result, const T& a, const T& b)
Chris@16 922 {
Chris@16 923 BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The fmod function is only valid for floating point types.");
Chris@16 924 if((&result == &a) || (&result == &b))
Chris@16 925 {
Chris@16 926 T temp;
Chris@16 927 eval_fmod(temp, a, b);
Chris@16 928 result = temp;
Chris@16 929 return;
Chris@16 930 }
Chris@16 931 T n;
Chris@16 932 eval_divide(result, a, b);
Chris@16 933 if(eval_get_sign(a) < 0)
Chris@16 934 eval_ceil(n, result);
Chris@16 935 else
Chris@16 936 eval_floor(n, result);
Chris@16 937 eval_multiply(n, b);
Chris@16 938 eval_subtract(result, a, n);
Chris@16 939 }
Chris@16 940 template<class T, class A>
Chris@16 941 inline typename enable_if<is_arithmetic<A>, void>::type eval_fmod(T& result, const T& x, const A& a)
Chris@16 942 {
Chris@16 943 typedef typename boost::multiprecision::detail::canonical<A, T>::type canonical_type;
Chris@16 944 typedef typename mpl::if_<is_same<A, canonical_type>, T, canonical_type>::type cast_type;
Chris@16 945 cast_type c;
Chris@16 946 c = a;
Chris@16 947 eval_fmod(result, x, c);
Chris@16 948 }
Chris@16 949
Chris@16 950 template<class T, class A>
Chris@16 951 inline typename enable_if<is_arithmetic<A>, void>::type eval_fmod(T& result, const A& x, const T& a)
Chris@16 952 {
Chris@16 953 typedef typename boost::multiprecision::detail::canonical<A, T>::type canonical_type;
Chris@16 954 typedef typename mpl::if_<is_same<A, canonical_type>, T, canonical_type>::type cast_type;
Chris@16 955 cast_type c;
Chris@16 956 c = x;
Chris@16 957 eval_fmod(result, c, a);
Chris@16 958 }
Chris@16 959
Chris@16 960 template <class T>
Chris@16 961 inline void eval_trunc(T& result, const T& a)
Chris@16 962 {
Chris@16 963 BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The trunc function is only valid for floating point types.");
Chris@16 964 int c = eval_fpclassify(a);
Chris@101 965 if(c == (int)FP_NAN || c == (int)FP_INFINITE)
Chris@16 966 {
Chris@16 967 result = boost::math::policies::raise_rounding_error("boost::multiprecision::trunc<%1%>(%1%)", 0, number<T>(a), number<T>(a), boost::math::policies::policy<>()).backend();
Chris@16 968 return;
Chris@16 969 }
Chris@16 970 if(eval_get_sign(a) < 0)
Chris@16 971 eval_ceil(result, a);
Chris@16 972 else
Chris@16 973 eval_floor(result, a);
Chris@16 974 }
Chris@16 975
Chris@16 976 template <class T>
Chris@16 977 inline void eval_round(T& result, const T& a)
Chris@16 978 {
Chris@16 979 BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The round function is only valid for floating point types.");
Chris@16 980 typedef typename boost::multiprecision::detail::canonical<float, T>::type fp_type;
Chris@16 981 int c = eval_fpclassify(a);
Chris@101 982 if((c == (int)FP_NAN) || (c == (int)FP_INFINITE))
Chris@16 983 {
Chris@16 984 result = boost::math::policies::raise_rounding_error("boost::multiprecision::round<%1%>(%1%)", 0, number<T>(a), number<T>(a), boost::math::policies::policy<>()).backend();
Chris@16 985 return;
Chris@16 986 }
Chris@16 987 if(eval_get_sign(a) < 0)
Chris@16 988 {
Chris@16 989 eval_subtract(result, a, fp_type(0.5f));
Chris@16 990 eval_ceil(result, result);
Chris@16 991 }
Chris@16 992 else
Chris@16 993 {
Chris@16 994 eval_add(result, a, fp_type(0.5f));
Chris@16 995 eval_floor(result, result);
Chris@16 996 }
Chris@16 997 }
Chris@16 998
Chris@16 999 template <class B>
Chris@16 1000 void eval_lcm(B& result, const B& a, const B& b);
Chris@16 1001 template <class B>
Chris@16 1002 void eval_gcd(B& result, const B& a, const B& b);
Chris@16 1003
Chris@16 1004 template <class T, class Arithmetic>
Chris@16 1005 inline typename enable_if<is_integral<Arithmetic> >::type eval_gcd(T& result, const T& a, const Arithmetic& b)
Chris@16 1006 {
Chris@16 1007 typedef typename boost::multiprecision::detail::canonical<Arithmetic, T>::type si_type;
Chris@16 1008 using default_ops::eval_gcd;
Chris@16 1009 T t;
Chris@16 1010 t = static_cast<si_type>(b);
Chris@16 1011 eval_gcd(result, a, t);
Chris@16 1012 }
Chris@16 1013 template <class T, class Arithmetic>
Chris@16 1014 inline typename enable_if<is_integral<Arithmetic> >::type eval_gcd(T& result, const Arithmetic& a, const T& b)
Chris@16 1015 {
Chris@16 1016 eval_gcd(result, b, a);
Chris@16 1017 }
Chris@16 1018 template <class T, class Arithmetic>
Chris@16 1019 inline typename enable_if<is_integral<Arithmetic> >::type eval_lcm(T& result, const T& a, const Arithmetic& b)
Chris@16 1020 {
Chris@16 1021 typedef typename boost::multiprecision::detail::canonical<Arithmetic, T>::type si_type;
Chris@16 1022 using default_ops::eval_lcm;
Chris@16 1023 T t;
Chris@16 1024 t = static_cast<si_type>(b);
Chris@16 1025 eval_lcm(result, a, t);
Chris@16 1026 }
Chris@16 1027 template <class T, class Arithmetic>
Chris@16 1028 inline typename enable_if<is_integral<Arithmetic> >::type eval_lcm(T& result, const Arithmetic& a, const T& b)
Chris@16 1029 {
Chris@16 1030 eval_lcm(result, b, a);
Chris@16 1031 }
Chris@16 1032
Chris@16 1033 template <class T>
Chris@16 1034 inline unsigned eval_lsb(const T& val)
Chris@16 1035 {
Chris@16 1036 typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
Chris@16 1037 int c = eval_get_sign(val);
Chris@16 1038 if(c == 0)
Chris@16 1039 {
Chris@16 1040 BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
Chris@16 1041 }
Chris@16 1042 if(c < 0)
Chris@16 1043 {
Chris@16 1044 BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
Chris@16 1045 }
Chris@16 1046 unsigned result = 0;
Chris@16 1047 T mask, t;
Chris@16 1048 mask = ui_type(1);
Chris@16 1049 do
Chris@16 1050 {
Chris@16 1051 eval_bitwise_and(t, mask, val);
Chris@16 1052 ++result;
Chris@16 1053 eval_left_shift(mask, 1);
Chris@16 1054 }
Chris@16 1055 while(eval_is_zero(t));
Chris@16 1056
Chris@16 1057 return --result;
Chris@16 1058 }
Chris@16 1059
Chris@16 1060 template <class T>
Chris@16 1061 inline int eval_msb(const T& val)
Chris@16 1062 {
Chris@16 1063 int c = eval_get_sign(val);
Chris@16 1064 if(c == 0)
Chris@16 1065 {
Chris@16 1066 BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
Chris@16 1067 }
Chris@16 1068 if(c < 0)
Chris@16 1069 {
Chris@16 1070 BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
Chris@16 1071 }
Chris@16 1072 //
Chris@16 1073 // This implementation is really really rubbish - it does
Chris@16 1074 // a linear scan for the most-significant-bit. We should really
Chris@16 1075 // do a binary search, but as none of our backends actually needs
Chris@16 1076 // this implementation, we'll leave it for now. In fact for most
Chris@16 1077 // backends it's likely that there will always be a more efficient
Chris@16 1078 // native implementation possible.
Chris@16 1079 //
Chris@16 1080 unsigned result = 0;
Chris@16 1081 T t(val);
Chris@16 1082 while(!eval_is_zero(t))
Chris@16 1083 {
Chris@16 1084 eval_right_shift(t, 1);
Chris@16 1085 ++result;
Chris@16 1086 }
Chris@16 1087 return --result;
Chris@16 1088 }
Chris@16 1089
Chris@16 1090 template <class T>
Chris@16 1091 inline bool eval_bit_test(const T& val, unsigned index)
Chris@16 1092 {
Chris@16 1093 typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
Chris@16 1094 T mask, t;
Chris@16 1095 mask = ui_type(1);
Chris@16 1096 eval_left_shift(mask, index);
Chris@16 1097 eval_bitwise_and(t, mask, val);
Chris@16 1098 return !eval_is_zero(t);
Chris@16 1099 }
Chris@16 1100
Chris@16 1101 template <class T>
Chris@16 1102 inline void eval_bit_set(T& val, unsigned index)
Chris@16 1103 {
Chris@16 1104 typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
Chris@16 1105 T mask;
Chris@16 1106 mask = ui_type(1);
Chris@16 1107 eval_left_shift(mask, index);
Chris@16 1108 eval_bitwise_or(val, mask);
Chris@16 1109 }
Chris@16 1110
Chris@16 1111 template <class T>
Chris@16 1112 inline void eval_bit_flip(T& val, unsigned index)
Chris@16 1113 {
Chris@16 1114 typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
Chris@16 1115 T mask;
Chris@16 1116 mask = ui_type(1);
Chris@16 1117 eval_left_shift(mask, index);
Chris@16 1118 eval_bitwise_xor(val, mask);
Chris@16 1119 }
Chris@16 1120
Chris@16 1121 template <class T>
Chris@16 1122 inline void eval_bit_unset(T& val, unsigned index)
Chris@16 1123 {
Chris@16 1124 typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
Chris@16 1125 T mask, t;
Chris@16 1126 mask = ui_type(1);
Chris@16 1127 eval_left_shift(mask, index);
Chris@16 1128 eval_bitwise_and(t, mask, val);
Chris@16 1129 if(!eval_is_zero(t))
Chris@16 1130 eval_bitwise_xor(val, mask);
Chris@16 1131 }
Chris@16 1132
Chris@16 1133 template <class B>
Chris@16 1134 void eval_integer_sqrt(B& s, B& r, const B& x)
Chris@16 1135 {
Chris@16 1136 //
Chris@16 1137 // This is slow bit-by-bit integer square root, see for example
Chris@16 1138 // http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Binary_numeral_system_.28base_2.29
Chris@16 1139 // There are better methods such as http://hal.inria.fr/docs/00/07/28/54/PDF/RR-3805.pdf
Chris@16 1140 // and http://hal.inria.fr/docs/00/07/21/13/PDF/RR-4475.pdf which should be implemented
Chris@16 1141 // at some point.
Chris@16 1142 //
Chris@16 1143 typedef typename boost::multiprecision::detail::canonical<unsigned char, B>::type ui_type;
Chris@16 1144
Chris@16 1145 s = ui_type(0u);
Chris@16 1146 if(eval_get_sign(x) == 0)
Chris@16 1147 {
Chris@16 1148 r = ui_type(0u);
Chris@16 1149 return;
Chris@16 1150 }
Chris@16 1151 int g = eval_msb(x);
Chris@16 1152 if(g == 0)
Chris@16 1153 {
Chris@16 1154 r = ui_type(1);
Chris@16 1155 return;
Chris@16 1156 }
Chris@16 1157
Chris@16 1158 B t;
Chris@16 1159 r = x;
Chris@16 1160 g /= 2;
Chris@16 1161 int org_g = g;
Chris@16 1162 eval_bit_set(s, g);
Chris@16 1163 eval_bit_set(t, 2 * g);
Chris@16 1164 eval_subtract(r, x, t);
Chris@16 1165 --g;
Chris@16 1166 if(eval_get_sign(r) == 0)
Chris@16 1167 return;
Chris@16 1168 int msbr = eval_msb(r);
Chris@16 1169 do
Chris@16 1170 {
Chris@16 1171 if(msbr >= org_g + g + 1)
Chris@16 1172 {
Chris@16 1173 t = s;
Chris@16 1174 eval_left_shift(t, g + 1);
Chris@16 1175 eval_bit_set(t, 2 * g);
Chris@16 1176 if(t.compare(r) <= 0)
Chris@16 1177 {
Chris@16 1178 eval_bit_set(s, g);
Chris@16 1179 eval_subtract(r, t);
Chris@16 1180 if(eval_get_sign(r) == 0)
Chris@16 1181 return;
Chris@16 1182 msbr = eval_msb(r);
Chris@16 1183 }
Chris@16 1184 }
Chris@16 1185 --g;
Chris@16 1186 }
Chris@16 1187 while(g >= 0);
Chris@16 1188 }
Chris@16 1189
Chris@16 1190 //
Chris@16 1191 // These have to implemented by the backend, declared here so that our macro generated code compiles OK.
Chris@16 1192 //
Chris@16 1193 template <class T>
Chris@16 1194 typename enable_if_c<sizeof(T) == 0>::type eval_floor();
Chris@16 1195 template <class T>
Chris@16 1196 typename enable_if_c<sizeof(T) == 0>::type eval_ceil();
Chris@16 1197 template <class T>
Chris@16 1198 typename enable_if_c<sizeof(T) == 0>::type eval_trunc();
Chris@16 1199 template <class T>
Chris@16 1200 typename enable_if_c<sizeof(T) == 0>::type eval_sqrt();
Chris@16 1201 template <class T>
Chris@16 1202 typename enable_if_c<sizeof(T) == 0>::type eval_ldexp();
Chris@16 1203 template <class T>
Chris@16 1204 typename enable_if_c<sizeof(T) == 0>::type eval_frexp();
Chris@101 1205
Chris@101 1206 //
Chris@101 1207 // eval_logb and eval_scalbn simply assume base 2 and forward to
Chris@101 1208 // eval_ldexp and eval_frexp:
Chris@101 1209 //
Chris@101 1210 template <class B>
Chris@101 1211 inline typename B::exponent_type eval_ilogb(const B& val)
Chris@101 1212 {
Chris@101 1213 BOOST_STATIC_ASSERT_MSG(!std::numeric_limits<number<B> >::is_specialized || (std::numeric_limits<number<B> >::radix == 2), "The default implementation of ilogb requires a base 2 number type");
Chris@101 1214 typename B::exponent_type e;
Chris@101 1215 B result;
Chris@101 1216 eval_frexp(result, val, &e);
Chris@101 1217 return e - 1;
Chris@101 1218 }
Chris@101 1219 template <class B>
Chris@101 1220 inline void eval_logb(B& result, const B& val)
Chris@101 1221 {
Chris@101 1222 typedef typename boost::mpl::if_c<boost::is_same<boost::intmax_t, long>::value, long long, boost::intmax_t>::type max_t;
Chris@101 1223 result = static_cast<max_t>(eval_ilogb(val));
Chris@101 1224 }
Chris@101 1225 template <class B, class A>
Chris@101 1226 inline void eval_scalbn(B& result, const B& val, A e)
Chris@101 1227 {
Chris@101 1228 BOOST_STATIC_ASSERT_MSG(!std::numeric_limits<number<B> >::is_specialized || (std::numeric_limits<number<B> >::radix == 2), "The default implementation of scalbn requires a base 2 number type");
Chris@101 1229 eval_ldexp(result, val, static_cast<typename B::exponent_type>(e));
Chris@101 1230 }
Chris@16 1231 //
Chris@16 1232 // These functions are implemented in separate files, but expanded inline here,
Chris@16 1233 // DO NOT CHANGE THE ORDER OF THESE INCLUDES:
Chris@16 1234 //
Chris@16 1235 #include <boost/multiprecision/detail/functions/constants.hpp>
Chris@16 1236 #include <boost/multiprecision/detail/functions/pow.hpp>
Chris@16 1237 #include <boost/multiprecision/detail/functions/trig.hpp>
Chris@16 1238
Chris@16 1239 }
Chris@16 1240
Chris@16 1241 } // namespace multiprecision
Chris@16 1242 namespace math{
Chris@16 1243 //
Chris@16 1244 // Default versions of floating point classification routines:
Chris@16 1245 //
Chris@16 1246 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
Chris@16 1247 inline int fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
Chris@16 1248 {
Chris@16 1249 using multiprecision::default_ops::eval_fpclassify;
Chris@16 1250 return eval_fpclassify(arg.backend());
Chris@16 1251 }
Chris@16 1252 template <class tag, class A1, class A2, class A3, class A4>
Chris@16 1253 inline int fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
Chris@16 1254 {
Chris@16 1255 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
Chris@16 1256 return (fpclassify)(value_type(arg));
Chris@16 1257 }
Chris@16 1258 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
Chris@16 1259 inline bool isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
Chris@16 1260 {
Chris@16 1261 int v = (fpclassify)(arg);
Chris@101 1262 return (v != (int)FP_INFINITE) && (v != (int)FP_NAN);
Chris@16 1263 }
Chris@16 1264 template <class tag, class A1, class A2, class A3, class A4>
Chris@16 1265 inline bool isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
Chris@16 1266 {
Chris@16 1267 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
Chris@16 1268 return (isfinite)(value_type(arg));
Chris@16 1269 }
Chris@16 1270 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
Chris@16 1271 inline bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
Chris@16 1272 {
Chris@101 1273 return (fpclassify)(arg) == (int)FP_NAN;
Chris@16 1274 }
Chris@16 1275 template <class tag, class A1, class A2, class A3, class A4>
Chris@16 1276 inline bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
Chris@16 1277 {
Chris@16 1278 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
Chris@16 1279 return (isnan)(value_type(arg));
Chris@16 1280 }
Chris@16 1281 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
Chris@16 1282 inline bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
Chris@16 1283 {
Chris@101 1284 return (fpclassify)(arg) == (int)FP_INFINITE;
Chris@16 1285 }
Chris@16 1286 template <class tag, class A1, class A2, class A3, class A4>
Chris@16 1287 inline bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
Chris@16 1288 {
Chris@16 1289 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
Chris@16 1290 return (isinf)(value_type(arg));
Chris@16 1291 }
Chris@16 1292 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
Chris@16 1293 inline bool isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
Chris@16 1294 {
Chris@101 1295 return (fpclassify)(arg) == (int)FP_NORMAL;
Chris@16 1296 }
Chris@16 1297 template <class tag, class A1, class A2, class A3, class A4>
Chris@16 1298 inline bool isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
Chris@16 1299 {
Chris@16 1300 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
Chris@16 1301 return (isnormal)(value_type(arg));
Chris@16 1302 }
Chris@16 1303
Chris@16 1304 } // namespace math
Chris@16 1305 namespace multiprecision{
Chris@16 1306
Chris@16 1307 template <class B1, class B2, class B3, expression_template_option ET1, expression_template_option ET2, expression_template_option ET3>
Chris@16 1308 inline number<B1, ET1>& add(number<B1, ET1>& result, const number<B2, ET2>& a, const number<B3, ET3>& b)
Chris@16 1309 {
Chris@16 1310 BOOST_STATIC_ASSERT_MSG((is_convertible<B2, B1>::value), "No conversion to the target of a mixed precision addition exists");
Chris@16 1311 BOOST_STATIC_ASSERT_MSG((is_convertible<B3, B1>::value), "No conversion to the target of a mixed precision addition exists");
Chris@16 1312 using default_ops::eval_add;
Chris@16 1313 eval_add(result.backend(), a.backend(), b.backend());
Chris@16 1314 return result;
Chris@16 1315 }
Chris@16 1316
Chris@16 1317 template <class B1, class B2, class B3, expression_template_option ET1, expression_template_option ET2, expression_template_option ET3>
Chris@16 1318 inline number<B1, ET1>& subtract(number<B1, ET1>& result, const number<B2, ET2>& a, const number<B3, ET3>& b)
Chris@16 1319 {
Chris@16 1320 BOOST_STATIC_ASSERT_MSG((is_convertible<B2, B1>::value), "No conversion to the target of a mixed precision addition exists");
Chris@16 1321 BOOST_STATIC_ASSERT_MSG((is_convertible<B3, B1>::value), "No conversion to the target of a mixed precision addition exists");
Chris@16 1322 using default_ops::eval_subtract;
Chris@16 1323 eval_subtract(result.backend(), a.backend(), b.backend());
Chris@16 1324 return result;
Chris@16 1325 }
Chris@16 1326
Chris@16 1327 template <class B1, class B2, class B3, expression_template_option ET1, expression_template_option ET2, expression_template_option ET3>
Chris@16 1328 inline number<B1, ET1>& multiply(number<B1, ET1>& result, const number<B2, ET2>& a, const number<B3, ET3>& b)
Chris@16 1329 {
Chris@16 1330 BOOST_STATIC_ASSERT_MSG((is_convertible<B2, B1>::value), "No conversion to the target of a mixed precision addition exists");
Chris@16 1331 BOOST_STATIC_ASSERT_MSG((is_convertible<B3, B1>::value), "No conversion to the target of a mixed precision addition exists");
Chris@16 1332 using default_ops::eval_multiply;
Chris@16 1333 eval_multiply(result.backend(), a.backend(), b.backend());
Chris@16 1334 return result;
Chris@16 1335 }
Chris@16 1336
Chris@16 1337 template <class B, expression_template_option ET, class I>
Chris@16 1338 inline typename enable_if_c<is_integral<I>::value, number<B, ET>&>::type
Chris@16 1339 add(number<B, ET>& result, const I& a, const I& b)
Chris@16 1340 {
Chris@16 1341 using default_ops::eval_add;
Chris@16 1342 typedef typename detail::canonical<I, B>::type canonical_type;
Chris@16 1343 eval_add(result.backend(), static_cast<canonical_type>(a), static_cast<canonical_type>(b));
Chris@16 1344 return result;
Chris@16 1345 }
Chris@16 1346
Chris@16 1347 template <class B, expression_template_option ET, class I>
Chris@16 1348 inline typename enable_if_c<is_integral<I>::value, number<B, ET>&>::type
Chris@16 1349 subtract(number<B, ET>& result, const I& a, const I& b)
Chris@16 1350 {
Chris@16 1351 using default_ops::eval_subtract;
Chris@16 1352 typedef typename detail::canonical<I, B>::type canonical_type;
Chris@16 1353 eval_subtract(result.backend(), static_cast<canonical_type>(a), static_cast<canonical_type>(b));
Chris@16 1354 return result;
Chris@16 1355 }
Chris@16 1356
Chris@16 1357 template <class B, expression_template_option ET, class I>
Chris@16 1358 inline typename enable_if_c<is_integral<I>::value, number<B, ET>&>::type
Chris@16 1359 multiply(number<B, ET>& result, const I& a, const I& b)
Chris@16 1360 {
Chris@16 1361 using default_ops::eval_multiply;
Chris@16 1362 typedef typename detail::canonical<I, B>::type canonical_type;
Chris@16 1363 eval_multiply(result.backend(), static_cast<canonical_type>(a), static_cast<canonical_type>(b));
Chris@16 1364 return result;
Chris@16 1365 }
Chris@16 1366
Chris@16 1367 template <class tag, class A1, class A2, class A3, class A4, class Policy>
Chris@16 1368 inline typename detail::expression<tag, A1, A2, A3, A4>::result_type trunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
Chris@16 1369 {
Chris@16 1370 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
Chris@16 1371 return BOOST_MP_MOVE(trunc(number_type(v), pol));
Chris@16 1372 }
Chris@16 1373
Chris@16 1374 template <class Backend, expression_template_option ExpressionTemplates, class Policy>
Chris@16 1375 inline number<Backend, ExpressionTemplates> trunc(const number<Backend, ExpressionTemplates>& v, const Policy&)
Chris@16 1376 {
Chris@16 1377 using default_ops::eval_trunc;
Chris@16 1378 number<Backend, ExpressionTemplates> result;
Chris@16 1379 eval_trunc(result.backend(), v.backend());
Chris@16 1380 return BOOST_MP_MOVE(result);
Chris@16 1381 }
Chris@16 1382
Chris@16 1383 template <class tag, class A1, class A2, class A3, class A4, class Policy>
Chris@16 1384 inline int itrunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
Chris@16 1385 {
Chris@16 1386 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
Chris@16 1387 number_type r = trunc(v, pol);
Chris@16 1388 if((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !(boost::math::isfinite)(v))
Chris@16 1389 return boost::math::policies::raise_rounding_error("boost::multiprecision::itrunc<%1%>(%1%)", 0, number_type(v), 0, pol);
Chris@16 1390 return r.template convert_to<int>();
Chris@16 1391 }
Chris@16 1392 template <class tag, class A1, class A2, class A3, class A4>
Chris@16 1393 inline int itrunc(const detail::expression<tag, A1, A2, A3, A4>& v)
Chris@16 1394 {
Chris@16 1395 return itrunc(v, boost::math::policies::policy<>());
Chris@16 1396 }
Chris@16 1397 template <class Backend, expression_template_option ExpressionTemplates, class Policy>
Chris@16 1398 inline int itrunc(const number<Backend, ExpressionTemplates>& v, const Policy& pol)
Chris@16 1399 {
Chris@16 1400 number<Backend, ExpressionTemplates> r = trunc(v, pol);
Chris@16 1401 if((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !(boost::math::isfinite)(v))
Chris@16 1402 return boost::math::policies::raise_rounding_error("boost::multiprecision::itrunc<%1%>(%1%)", 0, v, 0, pol);
Chris@16 1403 return r.template convert_to<int>();
Chris@16 1404 }
Chris@16 1405 template <class Backend, expression_template_option ExpressionTemplates>
Chris@16 1406 inline int itrunc(const number<Backend, ExpressionTemplates>& v)
Chris@16 1407 {
Chris@16 1408 return itrunc(v, boost::math::policies::policy<>());
Chris@16 1409 }
Chris@16 1410 template <class tag, class A1, class A2, class A3, class A4, class Policy>
Chris@16 1411 inline long ltrunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
Chris@16 1412 {
Chris@16 1413 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
Chris@16 1414 number_type r = trunc(v, pol);
Chris@16 1415 if((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !(boost::math::isfinite)(v))
Chris@16 1416 return boost::math::policies::raise_rounding_error("boost::multiprecision::ltrunc<%1%>(%1%)", 0, number_type(v), 0L, pol);
Chris@16 1417 return r.template convert_to<long>();
Chris@16 1418 }
Chris@16 1419 template <class tag, class A1, class A2, class A3, class A4>
Chris@16 1420 inline long ltrunc(const detail::expression<tag, A1, A2, A3, A4>& v)
Chris@16 1421 {
Chris@16 1422 return ltrunc(v, boost::math::policies::policy<>());
Chris@16 1423 }
Chris@16 1424 template <class T, expression_template_option ExpressionTemplates, class Policy>
Chris@16 1425 inline long ltrunc(const number<T, ExpressionTemplates>& v, const Policy& pol)
Chris@16 1426 {
Chris@16 1427 number<T, ExpressionTemplates> r = trunc(v, pol);
Chris@16 1428 if((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !(boost::math::isfinite)(v))
Chris@16 1429 return boost::math::policies::raise_rounding_error("boost::multiprecision::ltrunc<%1%>(%1%)", 0, v, 0L, pol);
Chris@16 1430 return r.template convert_to<long>();
Chris@16 1431 }
Chris@16 1432 template <class T, expression_template_option ExpressionTemplates>
Chris@16 1433 inline long ltrunc(const number<T, ExpressionTemplates>& v)
Chris@16 1434 {
Chris@16 1435 return ltrunc(v, boost::math::policies::policy<>());
Chris@16 1436 }
Chris@16 1437 #ifndef BOOST_NO_LONG_LONG
Chris@16 1438 template <class tag, class A1, class A2, class A3, class A4, class Policy>
Chris@16 1439 inline long long lltrunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
Chris@16 1440 {
Chris@16 1441 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
Chris@16 1442 number_type r = trunc(v, pol);
Chris@16 1443 if((r > (std::numeric_limits<long long>::max)()) || r < (std::numeric_limits<long long>::min)() || !(boost::math::isfinite)(v))
Chris@16 1444 return boost::math::policies::raise_rounding_error("boost::multiprecision::lltrunc<%1%>(%1%)", 0, number_type(v), 0LL, pol);
Chris@16 1445 return r.template convert_to<long long>();
Chris@16 1446 }
Chris@16 1447 template <class tag, class A1, class A2, class A3, class A4>
Chris@16 1448 inline long long lltrunc(const detail::expression<tag, A1, A2, A3, A4>& v)
Chris@16 1449 {
Chris@16 1450 return lltrunc(v, boost::math::policies::policy<>());
Chris@16 1451 }
Chris@16 1452 template <class T, expression_template_option ExpressionTemplates, class Policy>
Chris@16 1453 inline long long lltrunc(const number<T, ExpressionTemplates>& v, const Policy& pol)
Chris@16 1454 {
Chris@16 1455 number<T, ExpressionTemplates> r = trunc(v, pol);
Chris@16 1456 if((r > (std::numeric_limits<long long>::max)()) || r < (std::numeric_limits<long long>::min)() || !(boost::math::isfinite)(v))
Chris@16 1457 return boost::math::policies::raise_rounding_error("boost::multiprecision::lltrunc<%1%>(%1%)", 0, v, 0LL, pol);
Chris@16 1458 return r.template convert_to<long long>();
Chris@16 1459 }
Chris@16 1460 template <class T, expression_template_option ExpressionTemplates>
Chris@16 1461 inline long long lltrunc(const number<T, ExpressionTemplates>& v)
Chris@16 1462 {
Chris@16 1463 return lltrunc(v, boost::math::policies::policy<>());
Chris@16 1464 }
Chris@16 1465 #endif
Chris@16 1466 template <class tag, class A1, class A2, class A3, class A4, class Policy>
Chris@16 1467 inline typename detail::expression<tag, A1, A2, A3, A4>::result_type round(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
Chris@16 1468 {
Chris@16 1469 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
Chris@16 1470 return BOOST_MP_MOVE(round(static_cast<number_type>(v), pol));
Chris@16 1471 }
Chris@16 1472 template <class T, expression_template_option ExpressionTemplates, class Policy>
Chris@16 1473 inline number<T, ExpressionTemplates> round(const number<T, ExpressionTemplates>& v, const Policy&)
Chris@16 1474 {
Chris@16 1475 using default_ops::eval_round;
Chris@16 1476 number<T, ExpressionTemplates> result;
Chris@16 1477 eval_round(result.backend(), v.backend());
Chris@16 1478 return BOOST_MP_MOVE(result);
Chris@16 1479 }
Chris@16 1480
Chris@16 1481 template <class tag, class A1, class A2, class A3, class A4, class Policy>
Chris@16 1482 inline int iround(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
Chris@16 1483 {
Chris@16 1484 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
Chris@16 1485 number_type r = round(v, pol);
Chris@16 1486 if((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !(boost::math::isfinite)(v))
Chris@16 1487 return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, number_type(v), 0, pol);
Chris@16 1488 return r.template convert_to<int>();
Chris@16 1489 }
Chris@16 1490 template <class tag, class A1, class A2, class A3, class A4>
Chris@16 1491 inline int iround(const detail::expression<tag, A1, A2, A3, A4>& v)
Chris@16 1492 {
Chris@16 1493 return iround(v, boost::math::policies::policy<>());
Chris@16 1494 }
Chris@16 1495 template <class T, expression_template_option ExpressionTemplates, class Policy>
Chris@16 1496 inline int iround(const number<T, ExpressionTemplates>& v, const Policy& pol)
Chris@16 1497 {
Chris@16 1498 number<T, ExpressionTemplates> r = round(v, pol);
Chris@16 1499 if((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !(boost::math::isfinite)(v))
Chris@16 1500 return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, v, 0, pol);
Chris@16 1501 return r.template convert_to<int>();
Chris@16 1502 }
Chris@16 1503 template <class T, expression_template_option ExpressionTemplates>
Chris@16 1504 inline int iround(const number<T, ExpressionTemplates>& v)
Chris@16 1505 {
Chris@16 1506 return iround(v, boost::math::policies::policy<>());
Chris@16 1507 }
Chris@16 1508 template <class tag, class A1, class A2, class A3, class A4, class Policy>
Chris@16 1509 inline long lround(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
Chris@16 1510 {
Chris@16 1511 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
Chris@16 1512 number_type r = round(v, pol);
Chris@16 1513 if((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !(boost::math::isfinite)(v))
Chris@16 1514 return boost::math::policies::raise_rounding_error("boost::multiprecision::lround<%1%>(%1%)", 0, number_type(v), 0L, pol);
Chris@16 1515 return r.template convert_to<long>();
Chris@16 1516 }
Chris@16 1517 template <class tag, class A1, class A2, class A3, class A4>
Chris@16 1518 inline long lround(const detail::expression<tag, A1, A2, A3, A4>& v)
Chris@16 1519 {
Chris@16 1520 return lround(v, boost::math::policies::policy<>());
Chris@16 1521 }
Chris@16 1522 template <class T, expression_template_option ExpressionTemplates, class Policy>
Chris@16 1523 inline long lround(const number<T, ExpressionTemplates>& v, const Policy& pol)
Chris@16 1524 {
Chris@16 1525 number<T, ExpressionTemplates> r = round(v, pol);
Chris@16 1526 if((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !(boost::math::isfinite)(v))
Chris@16 1527 return boost::math::policies::raise_rounding_error("boost::multiprecision::lround<%1%>(%1%)", 0, v, 0L, pol);
Chris@16 1528 return r.template convert_to<long>();
Chris@16 1529 }
Chris@16 1530 template <class T, expression_template_option ExpressionTemplates>
Chris@16 1531 inline long lround(const number<T, ExpressionTemplates>& v)
Chris@16 1532 {
Chris@16 1533 return lround(v, boost::math::policies::policy<>());
Chris@16 1534 }
Chris@16 1535 #ifndef BOOST_NO_LONG_LONG
Chris@16 1536 template <class tag, class A1, class A2, class A3, class A4, class Policy>
Chris@16 1537 inline long long llround(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
Chris@16 1538 {
Chris@16 1539 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
Chris@16 1540 number_type r = round(v, pol);
Chris@16 1541 if((r > (std::numeric_limits<long long>::max)()) || r < (std::numeric_limits<long long>::min)() || !(boost::math::isfinite)(v))
Chris@16 1542 return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, number_type(v), 0LL, pol);
Chris@16 1543 return r.template convert_to<long long>();
Chris@16 1544 }
Chris@16 1545 template <class tag, class A1, class A2, class A3, class A4>
Chris@16 1546 inline long long llround(const detail::expression<tag, A1, A2, A3, A4>& v)
Chris@16 1547 {
Chris@16 1548 return llround(v, boost::math::policies::policy<>());
Chris@16 1549 }
Chris@16 1550 template <class T, expression_template_option ExpressionTemplates, class Policy>
Chris@16 1551 inline long long llround(const number<T, ExpressionTemplates>& v, const Policy& pol)
Chris@16 1552 {
Chris@16 1553 number<T, ExpressionTemplates> r = round(v, pol);
Chris@16 1554 if((r > (std::numeric_limits<long long>::max)()) || r < (std::numeric_limits<long long>::min)() || !(boost::math::isfinite)(v))
Chris@16 1555 return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, v, 0LL, pol);
Chris@16 1556 return r.template convert_to<long long>();
Chris@16 1557 }
Chris@16 1558 template <class T, expression_template_option ExpressionTemplates>
Chris@16 1559 inline long long llround(const number<T, ExpressionTemplates>& v)
Chris@16 1560 {
Chris@16 1561 return llround(v, boost::math::policies::policy<>());
Chris@16 1562 }
Chris@16 1563 #endif
Chris@101 1564 //
Chris@101 1565 // frexp does not return an expression template since we require the
Chris@101 1566 // integer argument to be evaluated even if the returned value is
Chris@101 1567 // not assigned to anything...
Chris@101 1568 //
Chris@101 1569 template <class T, expression_template_option ExpressionTemplates>
Chris@101 1570 inline typename enable_if_c<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, short* pint)
Chris@101 1571 {
Chris@101 1572 using default_ops::eval_frexp;
Chris@101 1573 number<T, ExpressionTemplates> result;
Chris@101 1574 eval_frexp(result.backend(), v.backend(), pint);
Chris@101 1575 return BOOST_MP_MOVE(result);
Chris@101 1576 }
Chris@101 1577 template <class tag, class A1, class A2, class A3, class A4>
Chris@101 1578 inline typename enable_if_c<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
Chris@101 1579 frexp(const detail::expression<tag, A1, A2, A3, A4>& v, short* pint)
Chris@101 1580 {
Chris@101 1581 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
Chris@101 1582 return BOOST_MP_MOVE(frexp(static_cast<number_type>(v), pint));
Chris@101 1583 }
Chris@101 1584 template <class T, expression_template_option ExpressionTemplates>
Chris@101 1585 inline typename enable_if_c<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, int* pint)
Chris@101 1586 {
Chris@101 1587 using default_ops::eval_frexp;
Chris@101 1588 number<T, ExpressionTemplates> result;
Chris@101 1589 eval_frexp(result.backend(), v.backend(), pint);
Chris@101 1590 return BOOST_MP_MOVE(result);
Chris@101 1591 }
Chris@101 1592 template <class tag, class A1, class A2, class A3, class A4>
Chris@101 1593 inline typename enable_if_c<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
Chris@101 1594 frexp(const detail::expression<tag, A1, A2, A3, A4>& v, int* pint)
Chris@101 1595 {
Chris@101 1596 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
Chris@101 1597 return BOOST_MP_MOVE(frexp(static_cast<number_type>(v), pint));
Chris@101 1598 }
Chris@101 1599 template <class T, expression_template_option ExpressionTemplates>
Chris@101 1600 inline typename enable_if_c<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, long* pint)
Chris@101 1601 {
Chris@101 1602 using default_ops::eval_frexp;
Chris@101 1603 number<T, ExpressionTemplates> result;
Chris@101 1604 eval_frexp(result.backend(), v.backend(), pint);
Chris@101 1605 return BOOST_MP_MOVE(result);
Chris@101 1606 }
Chris@101 1607 template <class tag, class A1, class A2, class A3, class A4>
Chris@101 1608 inline typename enable_if_c<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
Chris@101 1609 frexp(const detail::expression<tag, A1, A2, A3, A4>& v, long* pint)
Chris@101 1610 {
Chris@101 1611 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
Chris@101 1612 return BOOST_MP_MOVE(frexp(static_cast<number_type>(v), pint));
Chris@101 1613 }
Chris@101 1614 template <class T, expression_template_option ExpressionTemplates>
Chris@101 1615 inline typename enable_if_c<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, long long* pint)
Chris@101 1616 {
Chris@101 1617 using default_ops::eval_frexp;
Chris@101 1618 number<T, ExpressionTemplates> result;
Chris@101 1619 eval_frexp(result.backend(), v.backend(), pint);
Chris@101 1620 return BOOST_MP_MOVE(result);
Chris@101 1621 }
Chris@101 1622 template <class tag, class A1, class A2, class A3, class A4>
Chris@101 1623 inline typename enable_if_c<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
Chris@101 1624 frexp(const detail::expression<tag, A1, A2, A3, A4>& v, long long* pint)
Chris@101 1625 {
Chris@101 1626 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
Chris@101 1627 return BOOST_MP_MOVE(frexp(static_cast<number_type>(v), pint));
Chris@101 1628 }
Chris@16 1629
Chris@16 1630 template <class B, expression_template_option ExpressionTemplates>
Chris@16 1631 inline typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, ExpressionTemplates> >::type
Chris@16 1632 sqrt(const number<B, ExpressionTemplates>& x)
Chris@16 1633 {
Chris@16 1634 using default_ops::eval_integer_sqrt;
Chris@16 1635 number<B, ExpressionTemplates> s, r;
Chris@16 1636 eval_integer_sqrt(s.backend(), r.backend(), x.backend());
Chris@16 1637 return s;
Chris@16 1638 }
Chris@16 1639
Chris@16 1640 template <class B, expression_template_option ExpressionTemplates>
Chris@16 1641 inline typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, ExpressionTemplates> >::type
Chris@16 1642 sqrt(const number<B, ExpressionTemplates>& x, number<B, ExpressionTemplates>& r)
Chris@16 1643 {
Chris@16 1644 using default_ops::eval_integer_sqrt;
Chris@16 1645 number<B, ExpressionTemplates> s;
Chris@16 1646 eval_integer_sqrt(s.backend(), r.backend(), x.backend());
Chris@16 1647 return s;
Chris@16 1648 }
Chris@16 1649
Chris@16 1650 #define UNARY_OP_FUNCTOR(func, category)\
Chris@16 1651 namespace detail{\
Chris@16 1652 template <class Backend> \
Chris@16 1653 struct BOOST_JOIN(func, _funct)\
Chris@16 1654 {\
Chris@16 1655 void operator()(Backend& result, const Backend& arg)const\
Chris@16 1656 {\
Chris@16 1657 using default_ops::BOOST_JOIN(eval_,func);\
Chris@16 1658 BOOST_JOIN(eval_,func)(result, arg);\
Chris@16 1659 }\
Chris@16 1660 };\
Chris@16 1661 \
Chris@16 1662 }\
Chris@16 1663 \
Chris@16 1664 template <class tag, class A1, class A2, class A3, class A4> \
Chris@16 1665 inline typename enable_if_c<number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category,\
Chris@16 1666 detail::expression<\
Chris@16 1667 detail::function\
Chris@16 1668 , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
Chris@16 1669 , detail::expression<tag, A1, A2, A3, A4> > \
Chris@16 1670 >::type \
Chris@16 1671 func(const detail::expression<tag, A1, A2, A3, A4>& arg)\
Chris@16 1672 {\
Chris@16 1673 return detail::expression<\
Chris@16 1674 detail::function\
Chris@16 1675 , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
Chris@16 1676 , detail::expression<tag, A1, A2, A3, A4> \
Chris@16 1677 > (\
Chris@16 1678 detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>() \
Chris@16 1679 , arg \
Chris@16 1680 );\
Chris@16 1681 }\
Chris@16 1682 template <class Backend> \
Chris@16 1683 inline typename enable_if_c<number_category<Backend>::value == category,\
Chris@16 1684 detail::expression<\
Chris@16 1685 detail::function\
Chris@16 1686 , detail::BOOST_JOIN(func, _funct)<Backend> \
Chris@16 1687 , number<Backend, et_on> > \
Chris@16 1688 >::type \
Chris@16 1689 func(const number<Backend, et_on>& arg)\
Chris@16 1690 {\
Chris@16 1691 return detail::expression<\
Chris@16 1692 detail::function\
Chris@16 1693 , detail::BOOST_JOIN(func, _funct)<Backend> \
Chris@16 1694 , number<Backend, et_on> \
Chris@16 1695 >(\
Chris@16 1696 detail::BOOST_JOIN(func, _funct)<Backend>() \
Chris@16 1697 , arg \
Chris@16 1698 );\
Chris@16 1699 }\
Chris@16 1700 template <class Backend> \
Chris@16 1701 inline typename boost::enable_if_c<\
Chris@16 1702 boost::multiprecision::number_category<Backend>::value == category,\
Chris@16 1703 number<Backend, et_off> >::type \
Chris@16 1704 func(const number<Backend, et_off>& arg)\
Chris@16 1705 {\
Chris@16 1706 number<Backend, et_off> result;\
Chris@16 1707 using default_ops::BOOST_JOIN(eval_,func);\
Chris@16 1708 BOOST_JOIN(eval_,func)(result.backend(), arg.backend());\
Chris@16 1709 return BOOST_MP_MOVE(result);\
Chris@16 1710 }
Chris@16 1711
Chris@16 1712 #define BINARY_OP_FUNCTOR(func, category)\
Chris@16 1713 namespace detail{\
Chris@16 1714 template <class Backend> \
Chris@16 1715 struct BOOST_JOIN(func, _funct)\
Chris@16 1716 {\
Chris@16 1717 void operator()(Backend& result, const Backend& arg, const Backend& a)const\
Chris@16 1718 {\
Chris@16 1719 using default_ops:: BOOST_JOIN(eval_,func);\
Chris@16 1720 BOOST_JOIN(eval_,func)(result, arg, a);\
Chris@16 1721 }\
Chris@16 1722 template <class Arithmetic> \
Chris@16 1723 void operator()(Backend& result, const Backend& arg, const Arithmetic& a)const\
Chris@16 1724 {\
Chris@16 1725 using default_ops:: BOOST_JOIN(eval_,func);\
Chris@16 1726 BOOST_JOIN(eval_,func)(result, arg, a);\
Chris@16 1727 }\
Chris@16 1728 template <class Arithmetic> \
Chris@16 1729 void operator()(Backend& result, const Arithmetic& arg, const Backend& a)const\
Chris@16 1730 {\
Chris@16 1731 using default_ops:: BOOST_JOIN(eval_,func);\
Chris@16 1732 BOOST_JOIN(eval_,func)(result, arg, a);\
Chris@16 1733 }\
Chris@16 1734 };\
Chris@16 1735 \
Chris@16 1736 }\
Chris@16 1737 template <class Backend> \
Chris@16 1738 inline typename enable_if_c<number_category<Backend>::value == category,\
Chris@16 1739 detail::expression<\
Chris@16 1740 detail::function\
Chris@16 1741 , detail::BOOST_JOIN(func, _funct)<Backend> \
Chris@16 1742 , number<Backend, et_on> \
Chris@16 1743 , number<Backend, et_on> > \
Chris@16 1744 >::type \
Chris@16 1745 func(const number<Backend, et_on>& arg, const number<Backend, et_on>& a)\
Chris@16 1746 {\
Chris@16 1747 return detail::expression<\
Chris@16 1748 detail::function\
Chris@16 1749 , detail::BOOST_JOIN(func, _funct)<Backend> \
Chris@16 1750 , number<Backend, et_on> \
Chris@16 1751 , number<Backend, et_on> \
Chris@16 1752 >(\
Chris@16 1753 detail::BOOST_JOIN(func, _funct)<Backend>() \
Chris@16 1754 , arg,\
Chris@16 1755 a\
Chris@16 1756 );\
Chris@16 1757 }\
Chris@16 1758 template <class Backend, class tag, class A1, class A2, class A3, class A4> \
Chris@16 1759 inline typename enable_if_c<\
Chris@16 1760 (number_category<Backend>::value == category) && (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category),\
Chris@16 1761 detail::expression<\
Chris@16 1762 detail::function\
Chris@16 1763 , detail::BOOST_JOIN(func, _funct)<Backend> \
Chris@16 1764 , number<Backend, et_on> \
Chris@16 1765 , detail::expression<tag, A1, A2, A3, A4> > \
Chris@16 1766 >::type \
Chris@16 1767 func(const number<Backend, et_on>& arg, const detail::expression<tag, A1, A2, A3, A4>& a)\
Chris@16 1768 {\
Chris@16 1769 return detail::expression<\
Chris@16 1770 detail::function\
Chris@16 1771 , detail::BOOST_JOIN(func, _funct)<Backend> \
Chris@16 1772 , number<Backend, et_on> \
Chris@16 1773 , detail::expression<tag, A1, A2, A3, A4> \
Chris@16 1774 >(\
Chris@16 1775 detail::BOOST_JOIN(func, _funct)<Backend>() \
Chris@16 1776 , arg,\
Chris@16 1777 a\
Chris@16 1778 );\
Chris@16 1779 }\
Chris@16 1780 template <class tag, class A1, class A2, class A3, class A4, class Backend> \
Chris@16 1781 inline typename enable_if_c<\
Chris@16 1782 (number_category<Backend>::value == category) && (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category),\
Chris@16 1783 detail::expression<\
Chris@16 1784 detail::function\
Chris@16 1785 , detail::BOOST_JOIN(func, _funct)<Backend> \
Chris@16 1786 , detail::expression<tag, A1, A2, A3, A4> \
Chris@16 1787 , number<Backend, et_on> > \
Chris@16 1788 >::type \
Chris@16 1789 func(const detail::expression<tag, A1, A2, A3, A4>& arg, const number<Backend, et_on>& a)\
Chris@16 1790 {\
Chris@16 1791 return detail::expression<\
Chris@16 1792 detail::function\
Chris@16 1793 , detail::BOOST_JOIN(func, _funct)<Backend> \
Chris@16 1794 , detail::expression<tag, A1, A2, A3, A4> \
Chris@16 1795 , number<Backend, et_on> \
Chris@16 1796 >(\
Chris@16 1797 detail::BOOST_JOIN(func, _funct)<Backend>() \
Chris@16 1798 , arg,\
Chris@16 1799 a\
Chris@16 1800 );\
Chris@16 1801 }\
Chris@16 1802 template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b> \
Chris@16 1803 inline typename enable_if_c<\
Chris@16 1804 (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category) && (number_category<detail::expression<tagb, A1b, A2b, A3b, A4b> >::value == category),\
Chris@16 1805 detail::expression<\
Chris@16 1806 detail::function\
Chris@16 1807 , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
Chris@16 1808 , detail::expression<tag, A1, A2, A3, A4> \
Chris@16 1809 , detail::expression<tagb, A1b, A2b, A3b, A4b> > \
Chris@16 1810 >::type \
Chris@16 1811 func(const detail::expression<tag, A1, A2, A3, A4>& arg, const detail::expression<tagb, A1b, A2b, A3b, A4b>& a)\
Chris@16 1812 {\
Chris@16 1813 return detail::expression<\
Chris@16 1814 detail::function\
Chris@16 1815 , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
Chris@16 1816 , detail::expression<tag, A1, A2, A3, A4> \
Chris@16 1817 , detail::expression<tagb, A1b, A2b, A3b, A4b> \
Chris@16 1818 >(\
Chris@16 1819 detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>() \
Chris@16 1820 , arg,\
Chris@16 1821 a\
Chris@16 1822 );\
Chris@16 1823 }\
Chris@16 1824 template <class Backend, class Arithmetic> \
Chris@16 1825 inline typename enable_if_c<\
Chris@16 1826 is_arithmetic<Arithmetic>::value && (number_category<Backend>::value == category),\
Chris@16 1827 detail::expression<\
Chris@16 1828 detail::function\
Chris@16 1829 , detail::BOOST_JOIN(func, _funct)<Backend> \
Chris@16 1830 , number<Backend, et_on> \
Chris@16 1831 , Arithmetic\
Chris@16 1832 > \
Chris@16 1833 >::type \
Chris@16 1834 func(const number<Backend, et_on>& arg, const Arithmetic& a)\
Chris@16 1835 {\
Chris@16 1836 return detail::expression<\
Chris@16 1837 detail::function\
Chris@16 1838 , detail::BOOST_JOIN(func, _funct)<Backend> \
Chris@16 1839 , number<Backend, et_on> \
Chris@16 1840 , Arithmetic\
Chris@16 1841 >(\
Chris@16 1842 detail::BOOST_JOIN(func, _funct)<Backend>() \
Chris@16 1843 , arg,\
Chris@16 1844 a\
Chris@16 1845 );\
Chris@16 1846 }\
Chris@16 1847 template <class tag, class A1, class A2, class A3, class A4, class Arithmetic> \
Chris@16 1848 inline typename enable_if_c<\
Chris@16 1849 is_arithmetic<Arithmetic>::value && (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category),\
Chris@16 1850 detail::expression<\
Chris@16 1851 detail::function\
Chris@16 1852 , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
Chris@16 1853 , detail::expression<tag, A1, A2, A3, A4> \
Chris@16 1854 , Arithmetic\
Chris@16 1855 > \
Chris@16 1856 >::type \
Chris@16 1857 func(const detail::expression<tag, A1, A2, A3, A4>& arg, const Arithmetic& a)\
Chris@16 1858 {\
Chris@16 1859 return detail::expression<\
Chris@16 1860 detail::function\
Chris@16 1861 , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
Chris@16 1862 , detail::expression<tag, A1, A2, A3, A4> \
Chris@16 1863 , Arithmetic\
Chris@16 1864 >(\
Chris@16 1865 detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>() \
Chris@16 1866 , arg,\
Chris@16 1867 a\
Chris@16 1868 );\
Chris@16 1869 }\
Chris@16 1870 template <class Backend, class Arithmetic> \
Chris@16 1871 inline typename enable_if_c<\
Chris@16 1872 is_arithmetic<Arithmetic>::value && (number_category<Backend>::value == category),\
Chris@16 1873 detail::expression<\
Chris@16 1874 detail::function\
Chris@16 1875 , detail::BOOST_JOIN(func, _funct)<Backend> \
Chris@16 1876 , Arithmetic \
Chris@16 1877 , number<Backend, et_on> \
Chris@16 1878 > \
Chris@16 1879 >::type \
Chris@16 1880 func(const Arithmetic& arg, const number<Backend, et_on>& a)\
Chris@16 1881 {\
Chris@16 1882 return detail::expression<\
Chris@16 1883 detail::function\
Chris@16 1884 , detail::BOOST_JOIN(func, _funct)<Backend> \
Chris@16 1885 , Arithmetic \
Chris@16 1886 , number<Backend, et_on> \
Chris@16 1887 >(\
Chris@16 1888 detail::BOOST_JOIN(func, _funct)<Backend>() \
Chris@16 1889 , arg,\
Chris@16 1890 a\
Chris@16 1891 );\
Chris@16 1892 }\
Chris@16 1893 template <class tag, class A1, class A2, class A3, class A4, class Arithmetic> \
Chris@16 1894 inline typename enable_if_c<\
Chris@16 1895 is_arithmetic<Arithmetic>::value && (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category),\
Chris@16 1896 detail::expression<\
Chris@16 1897 detail::function\
Chris@16 1898 , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
Chris@16 1899 , Arithmetic \
Chris@16 1900 , detail::expression<tag, A1, A2, A3, A4> \
Chris@16 1901 > \
Chris@16 1902 >::type \
Chris@16 1903 func(const Arithmetic& arg, const detail::expression<tag, A1, A2, A3, A4>& a)\
Chris@16 1904 {\
Chris@16 1905 return detail::expression<\
Chris@16 1906 detail::function\
Chris@16 1907 , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
Chris@16 1908 , Arithmetic \
Chris@16 1909 , detail::expression<tag, A1, A2, A3, A4> \
Chris@16 1910 >(\
Chris@16 1911 detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>() \
Chris@16 1912 , arg,\
Chris@16 1913 a\
Chris@16 1914 );\
Chris@16 1915 }\
Chris@16 1916 template <class Backend> \
Chris@16 1917 inline typename enable_if_c<(number_category<Backend>::value == category),\
Chris@16 1918 number<Backend, et_off> >::type \
Chris@16 1919 func(const number<Backend, et_off>& arg, const number<Backend, et_off>& a)\
Chris@16 1920 {\
Chris@16 1921 number<Backend, et_off> result;\
Chris@16 1922 using default_ops:: BOOST_JOIN(eval_,func);\
Chris@16 1923 BOOST_JOIN(eval_,func)(result.backend(), arg.backend(), a.backend());\
Chris@16 1924 return BOOST_MP_MOVE(result);\
Chris@16 1925 }\
Chris@16 1926 template <class Backend, class Arithmetic> \
Chris@16 1927 inline typename enable_if_c<\
Chris@16 1928 is_arithmetic<Arithmetic>::value && (number_category<Backend>::value == category),\
Chris@16 1929 number<Backend, et_off> \
Chris@16 1930 >::type \
Chris@16 1931 func(const number<Backend, et_off>& arg, const Arithmetic& a)\
Chris@16 1932 {\
Chris@16 1933 typedef typename detail::canonical<Arithmetic, Backend>::type canonical_type;\
Chris@16 1934 number<Backend, et_off> result;\
Chris@16 1935 using default_ops:: BOOST_JOIN(eval_,func);\
Chris@16 1936 BOOST_JOIN(eval_,func)(result.backend(), arg.backend(), static_cast<canonical_type>(a));\
Chris@16 1937 return BOOST_MP_MOVE(result);\
Chris@16 1938 }\
Chris@16 1939 template <class Backend, class Arithmetic> \
Chris@16 1940 inline typename enable_if_c<\
Chris@16 1941 is_arithmetic<Arithmetic>::value && (number_category<Backend>::value == category),\
Chris@16 1942 number<Backend, et_off> \
Chris@16 1943 >::type \
Chris@16 1944 func(const Arithmetic& a, const number<Backend, et_off>& arg)\
Chris@16 1945 {\
Chris@16 1946 typedef typename detail::canonical<Arithmetic, Backend>::type canonical_type;\
Chris@16 1947 number<Backend, et_off> result;\
Chris@16 1948 using default_ops:: BOOST_JOIN(eval_,func);\
Chris@16 1949 BOOST_JOIN(eval_,func)(result.backend(), static_cast<canonical_type>(a), arg.backend());\
Chris@16 1950 return BOOST_MP_MOVE(result);\
Chris@16 1951 }\
Chris@16 1952
Chris@16 1953
Chris@16 1954 #define HETERO_BINARY_OP_FUNCTOR_B(func, Arg2, category)\
Chris@16 1955 template <class tag, class A1, class A2, class A3, class A4> \
Chris@16 1956 inline typename enable_if_c<\
Chris@16 1957 (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category),\
Chris@16 1958 detail::expression<\
Chris@16 1959 detail::function\
Chris@16 1960 , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
Chris@16 1961 , detail::expression<tag, A1, A2, A3, A4> \
Chris@16 1962 , Arg2> \
Chris@16 1963 >::type \
Chris@16 1964 func(const detail::expression<tag, A1, A2, A3, A4>& arg, Arg2 const& a)\
Chris@16 1965 {\
Chris@16 1966 return detail::expression<\
Chris@16 1967 detail::function\
Chris@16 1968 , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
Chris@16 1969 , detail::expression<tag, A1, A2, A3, A4> \
Chris@16 1970 , Arg2\
Chris@16 1971 >(\
Chris@16 1972 detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>() \
Chris@16 1973 , arg, a \
Chris@16 1974 );\
Chris@16 1975 }\
Chris@16 1976 template <class Backend> \
Chris@16 1977 inline typename enable_if_c<\
Chris@16 1978 (number_category<Backend>::value == category),\
Chris@16 1979 detail::expression<\
Chris@16 1980 detail::function\
Chris@16 1981 , detail::BOOST_JOIN(func, _funct)<Backend> \
Chris@16 1982 , number<Backend, et_on> \
Chris@16 1983 , Arg2> \
Chris@16 1984 >::type \
Chris@16 1985 func(const number<Backend, et_on>& arg, Arg2 const& a)\
Chris@16 1986 {\
Chris@16 1987 return detail::expression<\
Chris@16 1988 detail::function\
Chris@16 1989 , detail::BOOST_JOIN(func, _funct)<Backend> \
Chris@16 1990 , number<Backend, et_on> \
Chris@16 1991 , Arg2\
Chris@16 1992 >(\
Chris@16 1993 detail::BOOST_JOIN(func, _funct)<Backend>() \
Chris@16 1994 , arg,\
Chris@16 1995 a\
Chris@16 1996 );\
Chris@16 1997 }\
Chris@16 1998 template <class Backend> \
Chris@16 1999 inline typename enable_if_c<\
Chris@16 2000 (number_category<Backend>::value == category),\
Chris@16 2001 number<Backend, et_off> >::type \
Chris@16 2002 func(const number<Backend, et_off>& arg, Arg2 const& a)\
Chris@16 2003 {\
Chris@16 2004 number<Backend, et_off> result;\
Chris@16 2005 using default_ops:: BOOST_JOIN(eval_,func);\
Chris@16 2006 BOOST_JOIN(eval_,func)(result.backend(), arg.backend(), a);\
Chris@16 2007 return BOOST_MP_MOVE(result);\
Chris@16 2008 }\
Chris@16 2009
Chris@16 2010 #define HETERO_BINARY_OP_FUNCTOR(func, Arg2, category)\
Chris@16 2011 namespace detail{\
Chris@16 2012 template <class Backend> \
Chris@16 2013 struct BOOST_JOIN(func, _funct)\
Chris@16 2014 {\
Chris@16 2015 template <class Arg>\
Chris@16 2016 void operator()(Backend& result, Backend const& arg, Arg a)const\
Chris@16 2017 {\
Chris@16 2018 using default_ops:: BOOST_JOIN(eval_,func);\
Chris@16 2019 BOOST_JOIN(eval_,func)(result, arg, a);\
Chris@16 2020 }\
Chris@16 2021 };\
Chris@16 2022 \
Chris@16 2023 }\
Chris@16 2024 \
Chris@16 2025 HETERO_BINARY_OP_FUNCTOR_B(func, Arg2, category)
Chris@16 2026
Chris@16 2027 namespace detail{
Chris@16 2028 template <class Backend>
Chris@16 2029 struct abs_funct
Chris@16 2030 {
Chris@16 2031 void operator()(Backend& result, const Backend& arg)const
Chris@16 2032 {
Chris@16 2033 using default_ops::eval_abs;
Chris@16 2034 eval_abs(result, arg);
Chris@16 2035 }
Chris@16 2036 };
Chris@16 2037
Chris@16 2038 }
Chris@16 2039
Chris@16 2040 template <class tag, class A1, class A2, class A3, class A4>
Chris@16 2041 inline detail::expression<
Chris@16 2042 detail::function
Chris@16 2043 , detail::abs_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>
Chris@16 2044 , detail::expression<tag, A1, A2, A3, A4> >
Chris@16 2045 abs(const detail::expression<tag, A1, A2, A3, A4>& arg)
Chris@16 2046 {
Chris@16 2047 return detail::expression<
Chris@16 2048 detail::function
Chris@16 2049 , detail::abs_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>
Chris@16 2050 , detail::expression<tag, A1, A2, A3, A4>
Chris@16 2051 > (
Chris@16 2052 detail::abs_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>()
Chris@16 2053 , arg
Chris@16 2054 );
Chris@16 2055 }
Chris@16 2056 template <class Backend>
Chris@16 2057 inline detail::expression<
Chris@16 2058 detail::function
Chris@16 2059 , detail::abs_funct<Backend>
Chris@16 2060 , number<Backend, et_on> >
Chris@16 2061 abs(const number<Backend, et_on>& arg)
Chris@16 2062 {
Chris@16 2063 return detail::expression<
Chris@16 2064 detail::function
Chris@16 2065 , detail::abs_funct<Backend>
Chris@16 2066 , number<Backend, et_on>
Chris@16 2067 >(
Chris@16 2068 detail::abs_funct<Backend>()
Chris@16 2069 , arg
Chris@16 2070 );
Chris@16 2071 }
Chris@16 2072 template <class Backend>
Chris@16 2073 inline number<Backend, et_off>
Chris@16 2074 abs(const number<Backend, et_off>& arg)
Chris@16 2075 {
Chris@16 2076 number<Backend, et_off> result;
Chris@16 2077 using default_ops::eval_abs;
Chris@16 2078 eval_abs(result.backend(), arg.backend());
Chris@16 2079 return BOOST_MP_MOVE(result);
Chris@16 2080 }
Chris@16 2081
Chris@16 2082 UNARY_OP_FUNCTOR(fabs, number_kind_floating_point)
Chris@16 2083 UNARY_OP_FUNCTOR(sqrt, number_kind_floating_point)
Chris@16 2084 UNARY_OP_FUNCTOR(floor, number_kind_floating_point)
Chris@16 2085 UNARY_OP_FUNCTOR(ceil, number_kind_floating_point)
Chris@16 2086 UNARY_OP_FUNCTOR(trunc, number_kind_floating_point)
Chris@16 2087 UNARY_OP_FUNCTOR(round, number_kind_floating_point)
Chris@16 2088 UNARY_OP_FUNCTOR(exp, number_kind_floating_point)
Chris@16 2089 UNARY_OP_FUNCTOR(log, number_kind_floating_point)
Chris@16 2090 UNARY_OP_FUNCTOR(log10, number_kind_floating_point)
Chris@16 2091 UNARY_OP_FUNCTOR(cos, number_kind_floating_point)
Chris@16 2092 UNARY_OP_FUNCTOR(sin, number_kind_floating_point)
Chris@16 2093 UNARY_OP_FUNCTOR(tan, number_kind_floating_point)
Chris@16 2094 UNARY_OP_FUNCTOR(asin, number_kind_floating_point)
Chris@16 2095 UNARY_OP_FUNCTOR(acos, number_kind_floating_point)
Chris@16 2096 UNARY_OP_FUNCTOR(atan, number_kind_floating_point)
Chris@16 2097 UNARY_OP_FUNCTOR(cosh, number_kind_floating_point)
Chris@16 2098 UNARY_OP_FUNCTOR(sinh, number_kind_floating_point)
Chris@16 2099 UNARY_OP_FUNCTOR(tanh, number_kind_floating_point)
Chris@16 2100
Chris@101 2101 HETERO_BINARY_OP_FUNCTOR(ldexp, short, number_kind_floating_point)
Chris@101 2102 //HETERO_BINARY_OP_FUNCTOR(frexp, short*, number_kind_floating_point)
Chris@101 2103 HETERO_BINARY_OP_FUNCTOR_B(ldexp, int, number_kind_floating_point)
Chris@101 2104 //HETERO_BINARY_OP_FUNCTOR_B(frexp, int*, number_kind_floating_point)
Chris@16 2105 HETERO_BINARY_OP_FUNCTOR_B(ldexp, long, number_kind_floating_point)
Chris@101 2106 //HETERO_BINARY_OP_FUNCTOR_B(frexp, long*, number_kind_floating_point)
Chris@16 2107 HETERO_BINARY_OP_FUNCTOR_B(ldexp, long long, number_kind_floating_point)
Chris@101 2108 //HETERO_BINARY_OP_FUNCTOR_B(frexp, long long*, number_kind_floating_point)
Chris@16 2109 BINARY_OP_FUNCTOR(pow, number_kind_floating_point)
Chris@16 2110 BINARY_OP_FUNCTOR(fmod, number_kind_floating_point)
Chris@16 2111 BINARY_OP_FUNCTOR(atan2, number_kind_floating_point)
Chris@16 2112
Chris@101 2113 UNARY_OP_FUNCTOR(logb, number_kind_floating_point)
Chris@101 2114 HETERO_BINARY_OP_FUNCTOR(scalbn, short, number_kind_floating_point)
Chris@101 2115 HETERO_BINARY_OP_FUNCTOR_B(scalbn, int, number_kind_floating_point)
Chris@101 2116 HETERO_BINARY_OP_FUNCTOR_B(scalbn, long, number_kind_floating_point)
Chris@101 2117 HETERO_BINARY_OP_FUNCTOR_B(scalbn, long long, number_kind_floating_point)
Chris@101 2118
Chris@16 2119 //
Chris@16 2120 // Integer functions:
Chris@16 2121 //
Chris@16 2122 BINARY_OP_FUNCTOR(gcd, number_kind_integer)
Chris@16 2123 BINARY_OP_FUNCTOR(lcm, number_kind_integer)
Chris@16 2124 HETERO_BINARY_OP_FUNCTOR_B(pow, unsigned, number_kind_integer)
Chris@16 2125
Chris@16 2126 #undef BINARY_OP_FUNCTOR
Chris@16 2127 #undef UNARY_OP_FUNCTOR
Chris@16 2128
Chris@101 2129 //
Chris@101 2130 // ilogb:
Chris@101 2131 //
Chris@101 2132 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
Chris@101 2133 inline typename enable_if_c<number_category<Backend>::value == number_kind_floating_point, typename Backend::exponent_type>::type
Chris@101 2134 ilogb(const multiprecision::number<Backend, ExpressionTemplates>& val)
Chris@101 2135 {
Chris@101 2136 using default_ops::eval_ilogb;
Chris@101 2137 return eval_ilogb(val.backend());
Chris@101 2138 }
Chris@101 2139
Chris@101 2140 template <class tag, class A1, class A2, class A3, class A4>
Chris@101 2141 inline typename enable_if_c<number_category<detail::expression<tag, A1, A2, A3, A4> >::value == number_kind_floating_point, typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type::backend_type::exponent_type>::type
Chris@101 2142 ilogb(const detail::expression<tag, A1, A2, A3, A4>& val)
Chris@101 2143 {
Chris@101 2144 using default_ops::eval_ilogb;
Chris@101 2145 typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type arg(val);
Chris@101 2146 return eval_ilogb(arg.backend());
Chris@101 2147 }
Chris@101 2148
Chris@16 2149 } //namespace multiprecision
Chris@16 2150
Chris@16 2151 namespace math{
Chris@16 2152 //
Chris@16 2153 // Overload of Boost.Math functions that find the wrong overload when used with number:
Chris@16 2154 //
Chris@16 2155 namespace detail{
Chris@16 2156 template <class T> T sinc_pi_imp(T);
Chris@16 2157 template <class T> T sinhc_pi_imp(T);
Chris@16 2158 }
Chris@16 2159 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
Chris@16 2160 inline multiprecision::number<Backend, ExpressionTemplates> sinc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x)
Chris@16 2161 {
Chris@16 2162 return BOOST_MP_MOVE(detail::sinc_pi_imp(x));
Chris@16 2163 }
Chris@16 2164
Chris@16 2165 template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class Policy>
Chris@16 2166 inline multiprecision::number<Backend, ExpressionTemplates> sinc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x, const Policy&)
Chris@16 2167 {
Chris@16 2168 return BOOST_MP_MOVE(detail::sinc_pi_imp(x));
Chris@16 2169 }
Chris@16 2170
Chris@16 2171 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
Chris@16 2172 inline multiprecision::number<Backend, ExpressionTemplates> sinhc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x)
Chris@16 2173 {
Chris@16 2174 return BOOST_MP_MOVE(detail::sinhc_pi_imp(x));
Chris@16 2175 }
Chris@16 2176
Chris@16 2177 template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class Policy>
Chris@16 2178 inline multiprecision::number<Backend, ExpressionTemplates> sinhc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x, const Policy&)
Chris@16 2179 {
Chris@16 2180 return BOOST_MP_MOVE(boost::math::sinhc_pi(x));
Chris@16 2181 }
Chris@16 2182
Chris@16 2183 #ifdef BOOST_MSVC
Chris@16 2184 #pragma warning(pop)
Chris@16 2185 #endif
Chris@16 2186 } // namespace math
Chris@16 2187 } // namespace boost
Chris@16 2188
Chris@16 2189 //
Chris@16 2190 // This has to come last of all:
Chris@16 2191 //
Chris@16 2192 #include <boost/multiprecision/detail/no_et_ops.hpp>
Chris@16 2193 #include <boost/multiprecision/detail/et_ops.hpp>
Chris@16 2194
Chris@16 2195 #endif
Chris@16 2196