00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef PPL_checked_float_inlines_hh
00024 #define PPL_checked_float_inlines_hh 1
00025
00026 #include "Float.defs.hh"
00027 #ifndef __alpha
00028 #include <cmath>
00029 #endif
00030
00031 namespace Parma_Polyhedra_Library {
00032
00033 namespace Checked {
00034
00035 inline float
00036 fma(float x, float y, float z) {
00037 #if HAVE_DECL_FMAF && !defined(__alpha)
00038 return ::fmaf(x, y, z);
00039 #else
00040 return x*y + z;
00041 #endif
00042 }
00043
00044 #if HAVE_DECL_RINTF
00045 inline float
00046 rint(float x) {
00047 return ::rintf(x);
00048 }
00049 #endif
00050
00051 inline double
00052 fma(double x, double y, double z) {
00053 #if HAVE_DECL_FMA && !defined(__alpha)
00054 return ::fma(x, y, z);
00055 #else
00056 return x*y + z;
00057 #endif
00058 }
00059
00060 inline double
00061 rint(double x) {
00062 return ::rint(x);
00063 }
00064
00065 inline long double
00066 fma(long double x, long double y, long double z) {
00067 #if HAVE_DECL_FMAL && !defined(__alpha)
00068 return ::fmal(x, y, z);
00069 #else
00070 return x*y + z;
00071 #endif
00072 }
00073
00074 #if HAVE_DECL_RINTL
00075 inline long double
00076 rint(long double x) {
00077 return ::rintl(x);
00078 }
00079 #endif
00080
00081 inline bool
00082 fpu_direct_rounding(Rounding_Dir dir) {
00083 return dir == ROUND_DIRECT || dir == ROUND_IGNORE;
00084 }
00085
00086 inline bool
00087 fpu_inverse_rounding(Rounding_Dir dir) {
00088 return dir == ROUND_INVERSE;
00089 }
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115 inline float
00116 limit_precision(float v) {
00117 volatile float x = v;
00118 return x;
00119 }
00120
00121 inline double
00122 limit_precision(double v) {
00123 volatile double x = v;
00124 return x;
00125 }
00126
00127 inline long double
00128 limit_precision(long double v) {
00129 #if __GNUC__ >= 4
00130 return v;
00131 #else
00132
00133
00134
00135
00136
00137 volatile long double x = v;
00138 return x;
00139 #endif
00140 }
00141
00142 template <typename Policy, typename T>
00143 inline Result
00144 classify_float(const T v, bool nan, bool inf, bool sign) {
00145 Float<T> f(v);
00146 if ((nan || sign) && f.u.binary.is_nan())
00147 return VC_NAN;
00148 if (inf) {
00149 int i = f.u.binary.is_inf();
00150 if (i < 0)
00151 return VC_MINUS_INFINITY;
00152 if (i > 0)
00153 return VC_PLUS_INFINITY;
00154 }
00155 if (sign) {
00156 if (v < 0)
00157 return V_LT;
00158 if (v > 0)
00159 return V_GT;
00160 return V_EQ;
00161 }
00162 return VC_NORMAL;
00163 }
00164
00165 template <typename Policy, typename T>
00166 inline bool
00167 is_nan_float(const T v) {
00168 Float<T> f(v);
00169 return f.u.binary.is_nan();
00170 }
00171
00172 template <typename Policy, typename T>
00173 inline bool
00174 is_minf_float(const T v) {
00175 Float<T> f(v);
00176 return f.u.binary.is_inf() < 0;
00177 }
00178
00179 template <typename Policy, typename T>
00180 inline bool
00181 is_pinf_float(const T v) {
00182 Float<T> f(v);
00183 return f.u.binary.is_inf() > 0;
00184 }
00185
00186 template <typename T>
00187 inline bool
00188 is_inf_float(const T v) {
00189 Float<T> f(v);
00190 return f.u.binary.is_inf() != 0;
00191 }
00192
00193 template <typename Policy, typename T>
00194 inline bool
00195 is_int_float(const T v) {
00196 return rint(v) == v;
00197 }
00198
00199 template <typename Policy, typename T>
00200 inline Result
00201 set_special_float(T& v, Result r) {
00202 switch (classify(r)) {
00203 case VC_MINUS_INFINITY:
00204 v = -HUGE_VAL;
00205 break;
00206 case VC_PLUS_INFINITY:
00207 v = HUGE_VAL;
00208 break;
00209 case VC_NAN:
00210 v = NAN;
00211 break;
00212 default:
00213 break;
00214 }
00215 return r;
00216 }
00217
00218 template <typename T>
00219 inline void
00220 pred_float(T& v) {
00221 Float<T> f(v);
00222 assert(!f.u.binary.is_nan());
00223 assert(f.u.binary.is_inf() >= 0);
00224 if (f.u.binary.is_zero() > 0) {
00225 f.u.binary.negate();
00226 f.u.binary.inc();
00227 }
00228 else if (f.u.binary.sign_bit()) {
00229 f.u.binary.inc();
00230 }
00231 else {
00232 f.u.binary.dec();
00233 }
00234 v = f.value();
00235 }
00236
00237 template <typename T>
00238 inline void
00239 succ_float(T& v) {
00240 Float<T> f(v);
00241 assert(!f.u.binary.is_nan());
00242 assert(f.u.binary.is_inf() <= 0);
00243 if (f.u.binary.is_zero() < 0) {
00244 f.u.binary.negate();
00245 f.u.binary.inc();
00246 }
00247 else if (!f.u.binary.sign_bit()) {
00248 f.u.binary.inc();
00249 }
00250 else {
00251 f.u.binary.dec();
00252 }
00253 v = f.value();
00254 }
00255
00256 template <typename Policy, typename To>
00257 inline Result
00258 round_lt_float(To& to, Rounding_Dir dir) {
00259 if (dir == ROUND_DOWN) {
00260 pred_float(to);
00261 return V_GT;
00262 }
00263 return V_LT;
00264 }
00265
00266 template <typename Policy, typename To>
00267 inline Result
00268 round_gt_float(To& to, Rounding_Dir dir) {
00269 if (dir == ROUND_UP) {
00270 succ_float(to);
00271 return V_LT;
00272 }
00273 return V_GT;
00274 }
00275
00276 template <typename Policy>
00277 inline void
00278 prepare_inexact(Rounding_Dir dir) {
00279 if (Policy::fpu_check_inexact && dir != ROUND_IGNORE)
00280 fpu_reset_inexact();
00281 }
00282
00283 template <typename Policy>
00284 inline Result
00285 result_relation(Rounding_Dir dir) {
00286 if (Policy::fpu_check_inexact) {
00287 if (!fpu_check_inexact())
00288 return V_EQ;
00289 switch (dir) {
00290 case ROUND_DOWN:
00291 return V_GT;
00292 case ROUND_UP:
00293 return V_LT;
00294 default:
00295 return V_NE;
00296 }
00297 }
00298 else {
00299 switch (dir) {
00300 case ROUND_DOWN:
00301 return V_GE;
00302 case ROUND_UP:
00303 return V_LE;
00304 default:
00305 return V_LGE;
00306 }
00307 }
00308 }
00309
00310 template <typename Policy, typename From, typename To>
00311 inline Result
00312 assign_float_float_exact(To& to, const From from, Rounding_Dir) {
00313 if (CHECK_P(Policy::check_nan_args, is_nan<Policy>(from)))
00314 return VC_NAN;
00315 to = from;
00316 return V_EQ;
00317 }
00318
00319 template <typename Policy, typename To, typename From>
00320 inline Result
00321 assign_float_float_inexact(To& to, const From from, Rounding_Dir dir) {
00322 if (CHECK_P(Policy::check_nan_args, is_nan<Policy>(from)))
00323 return VC_NAN;
00324 prepare_inexact<Policy>(dir);
00325 if (fpu_direct_rounding(dir))
00326 to = from;
00327 else if (fpu_inverse_rounding(dir))
00328 to = -limit_precision(-from);
00329 else {
00330 fpu_rounding_control_word_type old = fpu_save_rounding_direction(dir);
00331 to = from;
00332 fpu_restore_rounding_direction(old);
00333 }
00334 return result_relation<Policy>(dir);
00335 }
00336
00337 template <typename Policy, typename From, typename To>
00338 inline Result
00339 assign_float_float(To& to, const From from, Rounding_Dir dir) {
00340 if (sizeof(From) > sizeof(To))
00341 return assign_float_float_inexact<Policy>(to, from, dir);
00342 else
00343 return assign_float_float_exact<Policy>(to, from, dir);
00344 }
00345
00346 template <typename Policy, typename Type>
00347 inline Result
00348 neg_float(Type& to, const Type from, Rounding_Dir) {
00349 if (CHECK_P(Policy::check_nan_args, is_nan<Policy>(from)))
00350 return VC_NAN;
00351 to = -from;
00352 return V_EQ;
00353 }
00354
00355 template <typename Policy, typename Type>
00356 inline Result
00357 add_float(Type& to, const Type x, const Type y, Rounding_Dir dir) {
00358 if (CHECK_P(Policy::check_nan_args, is_nan<Policy>(x))
00359 || CHECK_P(Policy::check_nan_args, is_nan<Policy>(y)))
00360 return VC_NAN;
00361 if (CHECK_P(Policy::check_inf_add_inf, is_inf_float(x) && x == -y))
00362 return V_INF_ADD_INF;
00363 prepare_inexact<Policy>(dir);
00364 if (fpu_direct_rounding(dir))
00365 to = x + y;
00366 else if (fpu_inverse_rounding(dir))
00367 to = -limit_precision(-x - y);
00368 else {
00369 fpu_rounding_control_word_type old = fpu_save_rounding_direction(dir);
00370 to = x + y;
00371 fpu_restore_rounding_direction(old);
00372 }
00373 return result_relation<Policy>(dir);
00374 }
00375
00376 template <typename Policy, typename Type>
00377 inline Result
00378 sub_float(Type& to, const Type x, const Type y, Rounding_Dir dir) {
00379 if (CHECK_P(Policy::check_nan_args, is_nan<Policy>(x))
00380 || CHECK_P(Policy::check_nan_args, is_nan<Policy>(y)))
00381 return VC_NAN;
00382 if (CHECK_P(Policy::check_inf_sub_inf, is_inf_float(x) && x == y))
00383 return V_INF_SUB_INF;
00384 prepare_inexact<Policy>(dir);
00385 if (fpu_direct_rounding(dir))
00386 to = x - y;
00387 else if (fpu_inverse_rounding(dir))
00388 to = -limit_precision(y - x);
00389 else {
00390 fpu_rounding_control_word_type old = fpu_save_rounding_direction(dir);
00391 to = x - y;
00392 fpu_restore_rounding_direction(old);
00393 }
00394 return result_relation<Policy>(dir);
00395 }
00396
00397 template <typename Policy, typename Type>
00398 inline Result
00399 mul_float(Type& to, const Type x, const Type y, Rounding_Dir dir) {
00400 if (CHECK_P(Policy::check_nan_args, is_nan<Policy>(x))
00401 || CHECK_P(Policy::check_nan_args, is_nan<Policy>(y)))
00402 return VC_NAN;
00403 if (CHECK_P(Policy::check_inf_mul_zero, (x == 0 && is_inf_float(y)) ||
00404 (y == 0 && is_inf_float(x))))
00405 return V_INF_MUL_ZERO;
00406 prepare_inexact<Policy>(dir);
00407 if (fpu_direct_rounding(dir))
00408 to = x * y;
00409 else if (fpu_inverse_rounding(dir))
00410 to = -limit_precision(x * -y);
00411 else {
00412 fpu_rounding_control_word_type old = fpu_save_rounding_direction(dir);
00413 to = x * y;
00414 fpu_restore_rounding_direction(old);
00415 }
00416 return result_relation<Policy>(dir);
00417 }
00418
00419 template <typename Policy, typename Type>
00420 inline Result
00421 div_float(Type& to, const Type x, const Type y, Rounding_Dir dir) {
00422 if (CHECK_P(Policy::check_nan_args, is_nan<Policy>(x))
00423 || CHECK_P(Policy::check_nan_args, is_nan<Policy>(y)))
00424 return VC_NAN;
00425 if (CHECK_P(Policy::check_inf_div_inf, is_inf_float(x) && is_inf_float(y)))
00426 return V_INF_DIV_INF;
00427 if (CHECK_P(Policy::check_div_zero, y == 0)) {
00428 to = NAN;
00429 return V_DIV_ZERO;
00430 }
00431 prepare_inexact<Policy>(dir);
00432 if (fpu_direct_rounding(dir))
00433 to = x / y;
00434 else if (fpu_inverse_rounding(dir))
00435 to = -limit_precision(x / -y);
00436 else {
00437 fpu_rounding_control_word_type old = fpu_save_rounding_direction(dir);
00438 to = x / y;
00439 fpu_restore_rounding_direction(old);
00440 }
00441 return result_relation<Policy>(dir);
00442 }
00443
00444 template <typename Policy, typename Type>
00445 inline Result
00446 rem_float(Type& to, const Type x, const Type y, Rounding_Dir) {
00447 if (CHECK_P(Policy::check_nan_args, is_nan<Policy>(x))
00448 || CHECK_P(Policy::check_nan_args, is_nan<Policy>(y)))
00449 return VC_NAN;
00450 if (CHECK_P(Policy::check_inf_mod, is_inf_float(x)))
00451 return V_INF_MOD;
00452 if (CHECK_P(Policy::check_div_zero, y == 0)) {
00453 to = NAN;
00454 return V_MOD_ZERO;
00455 }
00456 to = std::fmod(x, y);
00457 return V_EQ;
00458 }
00459
00460 template <typename Policy, typename Type>
00461 inline Result
00462 mul2exp_float(Type& to, const Type x, int exp, Rounding_Dir dir) {
00463 if (exp < 0)
00464 return div2exp<Policy>(to, x, -exp, dir);
00465 assert(static_cast<unsigned int>(exp) < sizeof(unsigned long long) * 8);
00466 return mul<Policy>(to, x, static_cast<Type>(1ULL << exp), dir);
00467 }
00468
00469 template <typename Policy, typename Type>
00470 inline Result
00471 div2exp_float(Type& to, const Type x, int exp, Rounding_Dir dir) {
00472 if (exp < 0)
00473 return mul2exp<Policy>(to, x, -exp, dir);
00474 assert(static_cast<unsigned int>(exp) < sizeof(unsigned long long) * 8);
00475 return div<Policy>(to, x, static_cast<Type>(1ULL << exp), dir);
00476 }
00477
00478 template <typename Policy, typename Type>
00479 inline Result
00480 abs_float(Type& to, const Type from, Rounding_Dir) {
00481 if (CHECK_P(Policy::check_nan_args, is_nan<Policy>(from)))
00482 return VC_NAN;
00483 to = from < 0 ? -from : from;
00484 return V_EQ;
00485 }
00486
00487 template <typename Policy, typename Type>
00488 inline Result
00489 sqrt_float(Type& to, const Type from, Rounding_Dir dir) {
00490 if (CHECK_P(Policy::check_nan_args, is_nan<Policy>(from)))
00491 return VC_NAN;
00492 if (CHECK_P(Policy::check_sqrt_neg, from < 0)) {
00493 to = NAN;
00494 return V_SQRT_NEG;
00495 }
00496 prepare_inexact<Policy>(dir);
00497 if (fpu_direct_rounding(dir))
00498 to = std::sqrt(from);
00499 else {
00500 fpu_rounding_control_word_type old = fpu_save_rounding_direction(dir);
00501 to = std::sqrt(from);
00502 fpu_restore_rounding_direction(old);
00503 }
00504 return result_relation<Policy>(dir);
00505 }
00506
00507 template <typename Policy, typename Type>
00508 inline Result
00509 sgn_float(const Type x) {
00510 return classify<Policy>(x, false, false, true);
00511 }
00512
00513 template <typename Policy, typename Type>
00514 inline Result
00515 cmp_float(const Type x, const Type y) {
00516 if (x > y)
00517 return V_GT;
00518 if (x < y)
00519 return V_LT;
00520 if (x == y)
00521 return V_EQ;
00522 return V_UNORD_COMP;
00523 }
00524
00525 template <typename Policy, typename To, typename From>
00526 inline Result
00527 assign_float_int_exact(To& to, const From from, Rounding_Dir) {
00528 to = from;
00529 return V_EQ;
00530 }
00531
00532 template <typename Policy, typename To, typename From>
00533 inline Result
00534 assign_float_int_inexact(To& to, const From from, Rounding_Dir dir) {
00535 prepare_inexact<Policy>(dir);
00536 if (fpu_direct_rounding(dir))
00537 to = from;
00538 else {
00539 fpu_rounding_control_word_type old = fpu_save_rounding_direction(dir);
00540 to = from;
00541 fpu_restore_rounding_direction(old);
00542 }
00543 return result_relation<Policy>(dir);
00544 }
00545
00546 template <typename Policy, typename To, typename From>
00547 inline Result
00548 assign_float_int(To& to, const From from, Rounding_Dir dir) {
00549 if (sizeof(From) * 8 > Float<To>::Binary::MANTISSA_BITS)
00550 return assign_float_int_inexact<Policy>(to, from, dir);
00551 else
00552 return assign_float_int_exact<Policy>(to, from, dir);
00553 }
00554
00555 template <typename Policy, typename T>
00556 inline Result
00557 set_neg_overflow_float(T& to, Rounding_Dir dir) {
00558 switch (dir) {
00559 case ROUND_UP:
00560 {
00561 Float<T> f;
00562 f.u.binary.set_max(true);
00563 to = f.value();
00564 return V_LT;
00565 }
00566 default:
00567 to = -HUGE_VAL;
00568 return V_GT;
00569 }
00570 }
00571
00572 template <typename Policy, typename T>
00573 inline Result
00574 set_pos_overflow_float(T& to, Rounding_Dir dir) {
00575 switch (dir) {
00576 case ROUND_DOWN:
00577 {
00578 Float<T> f;
00579 f.u.binary.set_max(false);
00580 to = f.value();
00581 return V_GT;
00582 }
00583 default:
00584 to = HUGE_VAL;
00585 return V_LT;
00586 }
00587 }
00588
00589 template <typename Policy, typename T>
00590 inline Result
00591 assign_float_mpz(T& to, const mpz_class& _from, Rounding_Dir dir)
00592 {
00593 mpz_srcptr from = _from.get_mpz_t();
00594 int sign = mpz_sgn(from);
00595 if (sign == 0) {
00596 to = 0;
00597 return V_EQ;
00598 }
00599 size_t exponent = mpz_sizeinbase(from, 2) - 1;
00600 if (exponent > (size_t) Float<T>::Binary::EXPONENT_MAX) {
00601 if (sign < 0)
00602 return set_neg_overflow_float<Policy>(to, dir);
00603 else
00604 return set_pos_overflow_float<Policy>(to, dir);
00605 }
00606 unsigned long zeroes = mpn_scan1(from->_mp_d, 0);
00607 size_t meaningful_bits = exponent - zeroes;
00608 mpz_t mantissa;
00609 mpz_init(mantissa);
00610 if (exponent > Float<T>::Binary::MANTISSA_BITS)
00611 mpz_tdiv_q_2exp(mantissa,
00612 from,
00613 exponent - Float<T>::Binary::MANTISSA_BITS);
00614 else
00615 mpz_mul_2exp(mantissa, from, Float<T>::Binary::MANTISSA_BITS - exponent);
00616 Float<T> f(to);
00617 f.u.binary.build(sign < 0, mantissa, exponent);
00618 mpz_clear(mantissa);
00619 to = f.value();
00620 if (meaningful_bits > Float<T>::Binary::MANTISSA_BITS) {
00621 if (sign < 0)
00622 return round_lt_float<Policy>(to, dir);
00623 else
00624 return round_gt_float<Policy>(to, dir);
00625 }
00626 return V_EQ;
00627 }
00628
00629 template <typename Policy, typename T>
00630 inline Result
00631 assign_float_mpq(T& to, const mpq_class& from, Rounding_Dir dir)
00632 {
00633 const mpz_class& _num = from.get_num();
00634 const mpz_class& _den = from.get_den();
00635 if (_den == 1)
00636 return assign_float_mpz<Policy>(to, _num, dir);
00637 mpz_srcptr num = _num.get_mpz_t();
00638 mpz_srcptr den = _den.get_mpz_t();
00639 int sign = mpz_sgn(num);
00640 signed long exponent = mpz_sizeinbase(num, 2) - mpz_sizeinbase(den, 2);
00641 if (exponent < Float<T>::Binary::EXPONENT_MIN_DENORM) {
00642 to = 0;
00643 inexact:
00644 if (sign < 0)
00645 return round_lt_float<Policy>(to, dir);
00646 else
00647 return round_gt_float<Policy>(to, dir);
00648 }
00649 if (exponent > (signed int) Float<T>::Binary::EXPONENT_MAX + 1) {
00650 overflow:
00651 if (sign < 0)
00652 return set_neg_overflow_float<Policy>(to, dir);
00653 else
00654 return set_pos_overflow_float<Policy>(to, dir);
00655 }
00656 unsigned int needed_bits = Float<T>::Binary::MANTISSA_BITS + 1;
00657 if (exponent < Float<T>::Binary::EXPONENT_MIN)
00658 needed_bits -= Float<T>::Binary::EXPONENT_MIN - exponent;
00659 mpz_t mantissa;
00660 mpz_init(mantissa);
00661 signed long shift = needed_bits - exponent;
00662 if (shift > 0) {
00663 mpz_mul_2exp(mantissa, num, shift);
00664 num = mantissa;
00665 }
00666 else if (shift < 0) {
00667 mpz_mul_2exp(mantissa, den, -shift);
00668 den = mantissa;
00669 }
00670 mpz_t r;
00671 mpz_init(r);
00672 mpz_tdiv_qr(mantissa, r, num, den);
00673 size_t bits = mpz_sizeinbase(mantissa, 2);
00674 bool inexact = (mpz_sgn(r) != 0);
00675 mpz_clear(r);
00676 if (bits == needed_bits + 1) {
00677 inexact = (inexact || mpz_odd_p(mantissa));
00678 mpz_div_2exp(mantissa, mantissa, 1);
00679 }
00680 else
00681 --exponent;
00682 if (exponent > (signed int)Float<T>::Binary::EXPONENT_MAX) {
00683 mpz_clear(mantissa);
00684 goto overflow;
00685 } else if (exponent < Float<T>::Binary::EXPONENT_MIN - 1) {
00686
00687 exponent = Float<T>::Binary::EXPONENT_MIN - 1;
00688 }
00689 Float<T> f(to);
00690 f.u.binary.build(sign < 0, mantissa, exponent);
00691 mpz_clear(mantissa);
00692 to = f.value();
00693 if (inexact)
00694 goto inexact;
00695 return V_EQ;
00696 }
00697
00698 template <typename Policy, typename Type>
00699 inline Result
00700 add_mul_float(Type& to, const Type x, const Type y, Rounding_Dir dir) {
00701 if (CHECK_P(Policy::check_nan_args, is_nan<Policy>(to))
00702 || CHECK_P(Policy::check_nan_args, is_nan<Policy>(x))
00703 || CHECK_P(Policy::check_nan_args, is_nan<Policy>(y)))
00704 return VC_NAN;
00705 prepare_inexact<Policy>(dir);
00706 if (fpu_direct_rounding(dir))
00707 to = fma(x, y, to);
00708 else if (fpu_inverse_rounding(dir))
00709 to = -limit_precision(fma(-x, y, -to));
00710 else {
00711 fpu_rounding_control_word_type old = fpu_save_rounding_direction(dir);
00712 to = fma(x, y, to);
00713 fpu_restore_rounding_direction(old);
00714 }
00715 return result_relation<Policy>(dir);
00716 }
00717
00718 template <typename Policy, typename Type>
00719 inline Result
00720 sub_mul_float(Type& to, const Type x, const Type y, Rounding_Dir dir) {
00721 if (CHECK_P(Policy::check_nan_args, is_nan<Policy>(to))
00722 || CHECK_P(Policy::check_nan_args, is_nan<Policy>(x))
00723 || CHECK_P(Policy::check_nan_args, is_nan<Policy>(y)))
00724 return VC_NAN;
00725 prepare_inexact<Policy>(dir);
00726 if (fpu_direct_rounding(dir))
00727 to = fma(x, -y, to);
00728 else if (fpu_inverse_rounding(dir))
00729 to = -limit_precision(fma(x, y, -to));
00730 else {
00731 fpu_rounding_control_word_type old = fpu_save_rounding_direction(dir);
00732 to = fma(x, -y, to);
00733 fpu_restore_rounding_direction(old);
00734 }
00735 return result_relation<Policy>(dir);
00736 }
00737
00738 template <typename Policy, typename Type>
00739 inline Result
00740 output_float(std::ostream& os, const Type from, const Numeric_Format&,
00741 Rounding_Dir) {
00742 if (from == 0)
00743 os << "0";
00744 else if (is_minf<Policy>(from))
00745 os << "-inf";
00746 else if (is_pinf<Policy>(from))
00747 os << "+inf";
00748 else if (is_nan<Policy>(from))
00749 os << "nan";
00750 else {
00751 int old_precision = os.precision(10000);
00752 os << from;
00753 os.precision(old_precision);
00754 }
00755 return V_EQ;
00756 }
00757
00758 template <typename Policy, typename To>
00759 inline Result
00760 assign_float_minf(To& to, const Minus_Infinity&, Rounding_Dir) {
00761 to = -HUGE_VAL;
00762 return V_EQ;
00763 }
00764
00765 template <typename Policy, typename To>
00766 inline Result
00767 assign_float_pinf(To& to, const Plus_Infinity&, Rounding_Dir) {
00768 to = HUGE_VAL;
00769 return V_EQ;
00770 }
00771
00772 template <typename Policy, typename To>
00773 inline Result
00774 assign_float_nan(To& to, const Not_A_Number&, Rounding_Dir) {
00775 to = NAN;
00776 return V_EQ;
00777 }
00778
00779 #if PPL_SUPPORTED_FLOAT
00780 SPECIALIZE_ASSIGN(float_float_exact, float, float)
00781 #if PPL_SUPPORTED_DOUBLE
00782 SPECIALIZE_ASSIGN(float_float, float, double)
00783 SPECIALIZE_ASSIGN(float_float_exact, double, float)
00784 #endif
00785 #if PPL_SUPPORTED_LONG_DOUBLE
00786 SPECIALIZE_ASSIGN(float_float, float, long double)
00787 SPECIALIZE_ASSIGN(float_float_exact, long double, float)
00788 #endif
00789 #endif
00790
00791 #if PPL_SUPPORTED_DOUBLE
00792 SPECIALIZE_ASSIGN(float_float_exact, double, double)
00793 #if PPL_SUPPORTED_LONG_DOUBLE
00794 SPECIALIZE_ASSIGN(float_float, double, long double)
00795 SPECIALIZE_ASSIGN(float_float_exact, long double, double)
00796 #endif
00797 #endif
00798
00799 #if PPL_SUPPORTED_LONG_DOUBLE
00800 SPECIALIZE_ASSIGN(float_float_exact, long double, long double)
00801 #endif
00802
00803 #if PPL_SUPPORTED_FLOAT
00804 SPECIALIZE_CLASSIFY(float, float)
00805 SPECIALIZE_IS_NAN(float, float)
00806 SPECIALIZE_IS_MINF(float, float)
00807 SPECIALIZE_IS_PINF(float, float)
00808 SPECIALIZE_SET_SPECIAL(float, float)
00809 SPECIALIZE_ASSIGN(float_int, float, signed char)
00810 SPECIALIZE_ASSIGN(float_int, float, signed short)
00811 SPECIALIZE_ASSIGN(float_int, float, signed int)
00812 SPECIALIZE_ASSIGN(float_int, float, signed long)
00813 SPECIALIZE_ASSIGN(float_int, float, signed long long)
00814 SPECIALIZE_ASSIGN(float_int, float, unsigned char)
00815 SPECIALIZE_ASSIGN(float_int, float, unsigned short)
00816 SPECIALIZE_ASSIGN(float_int, float, unsigned int)
00817 SPECIALIZE_ASSIGN(float_int, float, unsigned long)
00818 SPECIALIZE_ASSIGN(float_int, float, unsigned long long)
00819 SPECIALIZE_ASSIGN(float_mpz, float, mpz_class)
00820 SPECIALIZE_ASSIGN(float_mpq, float, mpq_class)
00821 SPECIALIZE_COPY(generic, float)
00822 SPECIALIZE_IS_INT(float, float)
00823 SPECIALIZE_ASSIGN(float_minf, float, Minus_Infinity)
00824 SPECIALIZE_ASSIGN(float_pinf, float, Plus_Infinity)
00825 SPECIALIZE_ASSIGN(float_nan, float, Not_A_Number)
00826 SPECIALIZE_NEG(float, float, float)
00827 SPECIALIZE_ABS(float, float, float)
00828 SPECIALIZE_ADD(float, float, float, float)
00829 SPECIALIZE_SUB(float, float, float, float)
00830 SPECIALIZE_MUL(float, float, float, float)
00831 SPECIALIZE_DIV(float, float, float, float)
00832 SPECIALIZE_REM(float, float, float, float)
00833 SPECIALIZE_MUL2EXP(float, float, float)
00834 SPECIALIZE_DIV2EXP(float, float, float)
00835 SPECIALIZE_SQRT(float, float, float)
00836 SPECIALIZE_GCD(exact, float, float, float)
00837 SPECIALIZE_GCDEXT(exact, float, float, float, float, float)
00838 SPECIALIZE_LCM(gcd_exact, float, float, float)
00839 SPECIALIZE_SGN(float, float)
00840 SPECIALIZE_CMP(float, float, float)
00841 SPECIALIZE_ADD_MUL(float, float, float, float)
00842 SPECIALIZE_SUB_MUL(float, float, float, float)
00843 SPECIALIZE_INPUT(generic, float)
00844 SPECIALIZE_OUTPUT(float, float)
00845 #endif
00846
00847 #if PPL_SUPPORTED_DOUBLE
00848 SPECIALIZE_CLASSIFY(float, double)
00849 SPECIALIZE_IS_NAN(float, double)
00850 SPECIALIZE_IS_MINF(float, double)
00851 SPECIALIZE_IS_PINF(float, double)
00852 SPECIALIZE_SET_SPECIAL(float, double)
00853 SPECIALIZE_ASSIGN(float_int, double, signed char)
00854 SPECIALIZE_ASSIGN(float_int, double, signed short)
00855 SPECIALIZE_ASSIGN(float_int, double, signed int)
00856 SPECIALIZE_ASSIGN(float_int, double, signed long)
00857 SPECIALIZE_ASSIGN(float_int, double, signed long long)
00858 SPECIALIZE_ASSIGN(float_int, double, unsigned char)
00859 SPECIALIZE_ASSIGN(float_int, double, unsigned short)
00860 SPECIALIZE_ASSIGN(float_int, double, unsigned int)
00861 SPECIALIZE_ASSIGN(float_int, double, unsigned long)
00862 SPECIALIZE_ASSIGN(float_int, double, unsigned long long)
00863 SPECIALIZE_ASSIGN(float_mpz, double, mpz_class)
00864 SPECIALIZE_ASSIGN(float_mpq, double, mpq_class)
00865 SPECIALIZE_COPY(generic, double)
00866 SPECIALIZE_IS_INT(float, double)
00867 SPECIALIZE_ASSIGN(float_minf, double, Minus_Infinity)
00868 SPECIALIZE_ASSIGN(float_pinf, double, Plus_Infinity)
00869 SPECIALIZE_ASSIGN(float_nan, double, Not_A_Number)
00870 SPECIALIZE_NEG(float, double, double)
00871 SPECIALIZE_ABS(float, double, double)
00872 SPECIALIZE_ADD(float, double, double, double)
00873 SPECIALIZE_SUB(float, double, double, double)
00874 SPECIALIZE_MUL(float, double, double, double)
00875 SPECIALIZE_DIV(float, double, double, double)
00876 SPECIALIZE_REM(float, double, double, double)
00877 SPECIALIZE_MUL2EXP(float, double, double)
00878 SPECIALIZE_DIV2EXP(float, double, double)
00879 SPECIALIZE_SQRT(float, double, double)
00880 SPECIALIZE_GCD(exact, double, double, double)
00881 SPECIALIZE_GCDEXT(exact, double, double, double, double, double)
00882 SPECIALIZE_LCM(gcd_exact, double, double, double)
00883 SPECIALIZE_SGN(float, double)
00884 SPECIALIZE_CMP(float, double, double)
00885 SPECIALIZE_ADD_MUL(float, double, double, double)
00886 SPECIALIZE_SUB_MUL(float, double, double, double)
00887 SPECIALIZE_INPUT(generic, double)
00888 SPECIALIZE_OUTPUT(float, double)
00889 #endif
00890
00891 #if PPL_SUPPORTED_LONG_DOUBLE
00892 SPECIALIZE_CLASSIFY(float, long double)
00893 SPECIALIZE_IS_NAN(float, long double)
00894 SPECIALIZE_IS_MINF(float, long double)
00895 SPECIALIZE_IS_PINF(float, long double)
00896 SPECIALIZE_SET_SPECIAL(float, long double)
00897 SPECIALIZE_ASSIGN(float_int, long double, signed char)
00898 SPECIALIZE_ASSIGN(float_int, long double, signed short)
00899 SPECIALIZE_ASSIGN(float_int, long double, signed int)
00900 SPECIALIZE_ASSIGN(float_int, long double, signed long)
00901 SPECIALIZE_ASSIGN(float_int, long double, signed long long)
00902 SPECIALIZE_ASSIGN(float_int, long double, unsigned char)
00903 SPECIALIZE_ASSIGN(float_int, long double, unsigned short)
00904 SPECIALIZE_ASSIGN(float_int, long double, unsigned int)
00905 SPECIALIZE_ASSIGN(float_int, long double, unsigned long)
00906 SPECIALIZE_ASSIGN(float_int, long double, unsigned long long)
00907 SPECIALIZE_ASSIGN(float_mpz, long double, mpz_class)
00908 SPECIALIZE_ASSIGN(float_mpq, long double, mpq_class)
00909 SPECIALIZE_COPY(generic, long double)
00910 SPECIALIZE_IS_INT(float, long double)
00911 SPECIALIZE_ASSIGN(float_minf, long double, Minus_Infinity)
00912 SPECIALIZE_ASSIGN(float_pinf, long double, Plus_Infinity)
00913 SPECIALIZE_ASSIGN(float_nan, long double, Not_A_Number)
00914 SPECIALIZE_NEG(float, long double, long double)
00915 SPECIALIZE_ABS(float, long double, long double)
00916 SPECIALIZE_ADD(float, long double, long double, long double)
00917 SPECIALIZE_SUB(float, long double, long double, long double)
00918 SPECIALIZE_MUL(float, long double, long double, long double)
00919 SPECIALIZE_DIV(float, long double, long double, long double)
00920 SPECIALIZE_REM(float, long double, long double, long double)
00921 SPECIALIZE_MUL2EXP(float, long double, long double)
00922 SPECIALIZE_DIV2EXP(float, long double, long double)
00923 SPECIALIZE_SQRT(float, long double, long double)
00924 SPECIALIZE_GCD(exact, long double, long double, long double)
00925 SPECIALIZE_GCDEXT(exact, long double, long double, long double,
00926 long double, long double)
00927 SPECIALIZE_LCM(gcd_exact, long double, long double, long double)
00928 SPECIALIZE_SGN(float, long double)
00929 SPECIALIZE_CMP(float, long double, long double)
00930 SPECIALIZE_ADD_MUL(float, long double, long double, long double)
00931 SPECIALIZE_SUB_MUL(float, long double, long double, long double)
00932 SPECIALIZE_INPUT(generic, long double)
00933 SPECIALIZE_OUTPUT(float, long double)
00934 #endif
00935
00936 }
00937
00938 }
00939
00940 #endif // !defined(PPL_checked_int_inlines_hh)