00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef PPL_checked_float_inlines_hh
00025 #define PPL_checked_float_inlines_hh 1
00026
00027 #include "compiler.hh"
00028 #ifndef __alpha
00029 #include <cmath>
00030 #endif
00031
00032 namespace Parma_Polyhedra_Library {
00033
00034 namespace Checked {
00035
00036 inline float
00037 fma(float x, float y, float z) {
00038 #if PPL_HAVE_DECL_FMAF && defined(FP_FAST_FMAF) \
00039 && !defined(__alpha) && !defined(__FreeBSD__)
00040 return ::fmaf(x, y, z);
00041 #else
00042 return x*y + z;
00043 #endif
00044 }
00045
00046 inline double
00047 fma(double x, double y, double z) {
00048 #if PPL_HAVE_DECL_FMA && defined(FP_FAST_FMA) \
00049 && !defined(__alpha) && !defined(__FreeBSD__)
00050 return ::fma(x, y, z);
00051 #else
00052 return x*y + z;
00053 #endif
00054 }
00055
00056 inline long double
00057 fma(long double x, long double y, long double z) {
00058 #if PPL_HAVE_DECL_FMAL && defined(FP_FAST_FMAL) \
00059 && !defined(__alpha) && !defined(__FreeBSD__)
00060 return ::fmal(x, y, z);
00061 #else
00062 return x*y + z;
00063 #endif
00064 }
00065
00066 #if PPL_HAVE_DECL_RINTF
00067 inline float
00068 rint(float x) {
00069 return ::rintf(x);
00070 }
00071 #endif
00072
00073 inline double
00074 rint(double x) {
00075 return ::rint(x);
00076 }
00077
00078 #if PPL_HAVE_DECL_RINTL
00079 inline long double
00080 rint(long double x) {
00081 return ::rintl(x);
00082 }
00083 #elif !PPL_CXX_PROVIDES_PROPER_LONG_DOUBLE
00084
00085
00086 inline long double
00087 rint(long double x) {
00088 return ::rint(x);
00089 }
00090 #elif defined(__i386__) && (defined(__GNUC__) || defined(__INTEL_COMPILER))
00091
00092
00093 inline long double
00094 rint(long double x) {
00095 long double i;
00096 __asm__ ("frndint" : "=t" (i) : "0" (x));
00097 return i;
00098 }
00099 #endif
00100
00101 inline bool
00102 fpu_direct_rounding(Rounding_Dir dir) {
00103 return round_direct(dir) || round_not_requested(dir);
00104 }
00105
00106 inline bool
00107 fpu_inverse_rounding(Rounding_Dir dir) {
00108 return round_inverse(dir);
00109 }
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135 inline void
00136 limit_precision(const float& v) {
00137 cc_flush(v);
00138 }
00139
00140 inline void
00141 limit_precision(const double& v) {
00142 cc_flush(v);
00143 }
00144
00145 inline void
00146 limit_precision(const long double&) {
00147 }
00148
00149 template <typename Policy, typename T>
00150 inline Result
00151 classify_float(const T v, bool nan, bool inf, bool sign) {
00152 Float<T> f(v);
00153 if ((nan || sign) && CHECK_P(Policy::has_nan, f.u.binary.is_nan()))
00154 return V_NAN;
00155 if (inf) {
00156 int i = CHECK_P(Policy::has_infinity, f.u.binary.is_inf());
00157 if (i < 0)
00158 return V_EQ_MINUS_INFINITY;
00159 if (i > 0)
00160 return V_EQ_PLUS_INFINITY;
00161 }
00162 if (sign) {
00163 if (v < 0)
00164 return V_LT;
00165 if (v > 0)
00166 return V_GT;
00167 return V_EQ;
00168 }
00169 return V_LGE;
00170 }
00171
00172 template <typename Policy, typename T>
00173 inline bool
00174 is_nan_float(const T v) {
00175 Float<T> f(v);
00176 return CHECK_P(Policy::has_nan, f.u.binary.is_nan());
00177 }
00178
00179 template <typename Policy, typename T>
00180 inline int
00181 is_inf_float(const T v) {
00182 Float<T> f(v);
00183 return CHECK_P(Policy::has_infinity, f.u.binary.is_inf());
00184 }
00185 template <typename Policy, typename T>
00186 inline bool
00187 is_minf_float(const T v) {
00188 return is_inf_float<Policy>(v) < 0;
00189 }
00190
00191 template <typename Policy, typename T>
00192 inline bool
00193 is_pinf_float(const T v) {
00194 return is_inf_float<Policy>(v) > 0;
00195 }
00196
00197
00198 template <typename Policy, typename T>
00199 inline bool
00200 is_int_float(const T v) {
00201 return rint(v) == v;
00202 }
00203
00204 template <typename Policy, typename T>
00205 inline Result
00206 assign_special_float(T& v, Result_Class c, Rounding_Dir) {
00207 switch (c) {
00208 case VC_MINUS_INFINITY:
00209 v = -HUGE_VAL;
00210 return V_EQ_MINUS_INFINITY;
00211 case VC_PLUS_INFINITY:
00212 v = HUGE_VAL;
00213 return V_EQ_PLUS_INFINITY;
00214 case VC_NAN:
00215 v = PPL_NAN;
00216 return V_NAN;
00217 default:
00218 PPL_ASSERT(false);
00219 return V_NAN | V_UNREPRESENTABLE;
00220 }
00221 }
00222
00223 template <typename T>
00224 inline void
00225 pred_float(T& v) {
00226 Float<T> f(v);
00227 PPL_ASSERT(!f.u.binary.is_nan());
00228 PPL_ASSERT(f.u.binary.is_inf() >= 0);
00229 if (f.u.binary.is_zero() > 0) {
00230 f.u.binary.negate();
00231 f.u.binary.inc();
00232 }
00233 else if (f.u.binary.sign_bit()) {
00234 f.u.binary.inc();
00235 }
00236 else {
00237 f.u.binary.dec();
00238 }
00239 v = f.value();
00240 }
00241
00242 template <typename T>
00243 inline void
00244 succ_float(T& v) {
00245 Float<T> f(v);
00246 PPL_ASSERT(!f.u.binary.is_nan());
00247 PPL_ASSERT(f.u.binary.is_inf() <= 0);
00248 if (f.u.binary.is_zero() < 0) {
00249 f.u.binary.negate();
00250 f.u.binary.inc();
00251 }
00252 else if (!f.u.binary.sign_bit()) {
00253 f.u.binary.inc();
00254 }
00255 else {
00256 f.u.binary.dec();
00257 }
00258 v = f.value();
00259 }
00260
00261 template <typename Policy, typename To>
00262 inline Result
00263 round_lt_float(To& to, Rounding_Dir dir) {
00264 if (round_down(dir)) {
00265 pred_float(to);
00266 return V_GT;
00267 }
00268 return V_LT;
00269 }
00270
00271 template <typename Policy, typename To>
00272 inline Result
00273 round_gt_float(To& to, Rounding_Dir dir) {
00274 if (round_up(dir)) {
00275 succ_float(to);
00276 return V_LT;
00277 }
00278 return V_GT;
00279 }
00280
00281
00282 template <typename Policy>
00283 inline void
00284 prepare_inexact(Rounding_Dir dir) {
00285 if (Policy::fpu_check_inexact
00286 && !round_not_needed(dir) && round_strict_relation(dir))
00287 fpu_reset_inexact();
00288 }
00289
00290 template <typename Policy>
00291 inline Result
00292 result_relation(Rounding_Dir dir) {
00293 if (Policy::fpu_check_inexact
00294 && !round_not_needed(dir) && round_strict_relation(dir)) {
00295 switch (fpu_check_inexact()) {
00296 case 0:
00297 return V_EQ;
00298 case -1:
00299 goto unknown;
00300 case 1:
00301 break;
00302 }
00303 switch (round_dir(dir)) {
00304 case ROUND_DOWN:
00305 return V_GT;
00306 case ROUND_UP:
00307 return V_LT;
00308 default:
00309 return V_NE;
00310 }
00311 }
00312 else {
00313 unknown:
00314 switch (round_dir(dir)) {
00315 case ROUND_DOWN:
00316 return V_GE;
00317 case ROUND_UP:
00318 return V_LE;
00319 default:
00320 return V_LGE;
00321 }
00322 }
00323 }
00324
00325 template <typename To_Policy, typename From_Policy, typename To, typename From>
00326 inline Result
00327 assign_float_float_exact(To& to, const From from, Rounding_Dir) {
00328 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from))
00329 return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
00330 to = from;
00331 return V_EQ;
00332 }
00333
00334 template <typename To_Policy, typename From_Policy, typename To, typename From>
00335 inline Result
00336 assign_float_float_inexact(To& to, const From from, Rounding_Dir dir) {
00337 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from))
00338 return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
00339 prepare_inexact<To_Policy>(dir);
00340 if (fpu_direct_rounding(dir))
00341 to = from;
00342 else if (fpu_inverse_rounding(dir)) {
00343 From tmp = -from;
00344 to = tmp;
00345 limit_precision(to);
00346 to = -to;
00347 }
00348 else {
00349 fpu_rounding_control_word_type old
00350 = fpu_save_rounding_direction(round_fpu_dir(dir));
00351 limit_precision(from);
00352 to = from;
00353 limit_precision(to);
00354 fpu_restore_rounding_direction(old);
00355 }
00356 return result_relation<To_Policy>(dir);
00357 }
00358
00359 template <typename To_Policy, typename From_Policy, typename To, typename From>
00360 inline Result
00361 assign_float_float(To& to, const From from, Rounding_Dir dir) {
00362 if (sizeof(From) > sizeof(To))
00363 return assign_float_float_inexact<To_Policy, From_Policy>(to, from, dir);
00364 else
00365 return assign_float_float_exact<To_Policy, From_Policy>(to, from, dir);
00366 }
00367
00368 template <typename To_Policy, typename From_Policy, typename Type>
00369 inline Result
00370 floor_float(Type& to, const Type from, Rounding_Dir) {
00371 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from))
00372 return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
00373 if (fpu_direct_rounding(ROUND_DOWN))
00374 to = rint(from);
00375 else if (fpu_inverse_rounding(ROUND_DOWN)) {
00376 to = rint(-from);
00377 limit_precision(to);
00378 to = -to;
00379 }
00380 else {
00381 fpu_rounding_control_word_type old
00382 = fpu_save_rounding_direction(round_fpu_dir(ROUND_DOWN));
00383 limit_precision(from);
00384 to = rint(from);
00385 limit_precision(to);
00386 fpu_restore_rounding_direction(old);
00387 }
00388 return V_EQ;
00389 }
00390
00391 template <typename To_Policy, typename From_Policy, typename Type>
00392 inline Result
00393 ceil_float(Type& to, const Type from, Rounding_Dir) {
00394 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from))
00395 return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
00396 if (fpu_direct_rounding(ROUND_UP))
00397 to = rint(from);
00398 else if (fpu_inverse_rounding(ROUND_UP)) {
00399 to = rint(-from);
00400 limit_precision(to);
00401 to = -to;
00402 }
00403 else {
00404 fpu_rounding_control_word_type old
00405 = fpu_save_rounding_direction(round_fpu_dir(ROUND_UP));
00406 limit_precision(from);
00407 to = rint(from);
00408 limit_precision(to);
00409 fpu_restore_rounding_direction(old);
00410 }
00411 return V_EQ;
00412 }
00413
00414 template <typename To_Policy, typename From_Policy, typename Type>
00415 inline Result
00416 trunc_float(Type& to, const Type from, Rounding_Dir dir) {
00417 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from))
00418 return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
00419 if (from >= 0)
00420 return floor<To_Policy, From_Policy>(to, from, dir);
00421 else
00422 return ceil<To_Policy, From_Policy>(to, from, dir);
00423 }
00424
00425 template <typename To_Policy, typename From_Policy, typename Type>
00426 inline Result
00427 neg_float(Type& to, const Type from, Rounding_Dir) {
00428 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from))
00429 return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
00430 to = -from;
00431 return V_EQ;
00432 }
00433
00434 template <typename To_Policy, typename From1_Policy, typename From2_Policy,
00435 typename Type>
00436 inline Result
00437 add_float(Type& to, const Type x, const Type y, Rounding_Dir dir) {
00438 if (To_Policy::check_inf_add_inf
00439 && is_inf_float<From1_Policy>(x) && x == -y) {
00440 return assign_nan<To_Policy>(to, V_INF_ADD_INF);
00441 }
00442 prepare_inexact<To_Policy>(dir);
00443 if (fpu_direct_rounding(dir))
00444 to = x + y;
00445 else if (fpu_inverse_rounding(dir)) {
00446 to = -x - y;
00447 limit_precision(to);
00448 to = -to;
00449 }
00450 else {
00451 fpu_rounding_control_word_type old
00452 = fpu_save_rounding_direction(round_fpu_dir(dir));
00453 limit_precision(x);
00454 limit_precision(y);
00455 to = x + y;
00456 limit_precision(to);
00457 fpu_restore_rounding_direction(old);
00458 }
00459 if (To_Policy::fpu_check_nan_result && is_nan<To_Policy>(to))
00460 return V_NAN;
00461 return result_relation<To_Policy>(dir);
00462 }
00463
00464 template <typename To_Policy, typename From1_Policy, typename From2_Policy,
00465 typename Type>
00466 inline Result
00467 sub_float(Type& to, const Type x, const Type y, Rounding_Dir dir) {
00468 if (To_Policy::check_inf_sub_inf
00469 && is_inf_float<From1_Policy>(x) && x == y) {
00470 return assign_nan<To_Policy>(to, V_INF_SUB_INF);
00471 }
00472 prepare_inexact<To_Policy>(dir);
00473 if (fpu_direct_rounding(dir))
00474 to = x - y;
00475 else if (fpu_inverse_rounding(dir)) {
00476 to = y - x;
00477 limit_precision(to);
00478 to = -to;
00479 }
00480 else {
00481 fpu_rounding_control_word_type old
00482 = fpu_save_rounding_direction(round_fpu_dir(dir));
00483 limit_precision(x);
00484 limit_precision(y);
00485 to = x - y;
00486 limit_precision(to);
00487 fpu_restore_rounding_direction(old);
00488 }
00489 if (To_Policy::fpu_check_nan_result && is_nan<To_Policy>(to))
00490 return V_NAN;
00491 return result_relation<To_Policy>(dir);
00492 }
00493
00494 template <typename To_Policy, typename From1_Policy, typename From2_Policy,
00495 typename Type>
00496 inline Result
00497 mul_float(Type& to, const Type x, const Type y, Rounding_Dir dir) {
00498 if (To_Policy::check_inf_mul_zero
00499 && ((x == 0 && is_inf_float<From2_Policy>(y))
00500 ||
00501 (y == 0 && is_inf_float<From1_Policy>(x)))) {
00502 return assign_nan<To_Policy>(to, V_INF_MUL_ZERO);
00503 }
00504 prepare_inexact<To_Policy>(dir);
00505 if (fpu_direct_rounding(dir))
00506 to = x * y;
00507 else if (fpu_inverse_rounding(dir)) {
00508 to = x * -y;
00509 limit_precision(to);
00510 to = -to;
00511 }
00512 else {
00513 fpu_rounding_control_word_type old
00514 = fpu_save_rounding_direction(round_fpu_dir(dir));
00515 limit_precision(x);
00516 limit_precision(y);
00517 to = x * y;
00518 limit_precision(to);
00519 fpu_restore_rounding_direction(old);
00520 }
00521 if (To_Policy::fpu_check_nan_result && is_nan<To_Policy>(to))
00522 return V_NAN;
00523 return result_relation<To_Policy>(dir);
00524 }
00525
00526 template <typename To_Policy, typename From1_Policy, typename From2_Policy,
00527 typename Type>
00528 inline Result
00529 div_float(Type& to, const Type x, const Type y, Rounding_Dir dir) {
00530 if (To_Policy::check_inf_div_inf
00531 && is_inf_float<From1_Policy>(x) && is_inf_float<From2_Policy>(y)) {
00532 return assign_nan<To_Policy>(to, V_INF_DIV_INF);
00533 }
00534 if (To_Policy::check_div_zero && y == 0) {
00535 return assign_nan<To_Policy>(to, V_DIV_ZERO);
00536 }
00537 prepare_inexact<To_Policy>(dir);
00538 if (fpu_direct_rounding(dir))
00539 to = x / y;
00540 else if (fpu_inverse_rounding(dir)) {
00541 to = x / -y;
00542 limit_precision(to);
00543 to = -to;
00544 }
00545 else {
00546 fpu_rounding_control_word_type old
00547 = fpu_save_rounding_direction(round_fpu_dir(dir));
00548 limit_precision(x);
00549 limit_precision(y);
00550 to = x / y;
00551 limit_precision(to);
00552 fpu_restore_rounding_direction(old);
00553 }
00554 if (To_Policy::fpu_check_nan_result && is_nan<To_Policy>(to))
00555 return V_NAN;
00556 return result_relation<To_Policy>(dir);
00557 }
00558
00559 template <typename To_Policy, typename From1_Policy, typename From2_Policy,
00560 typename Type>
00561 inline Result
00562 idiv_float(Type& to, const Type x, const Type y, Rounding_Dir dir) {
00563 Type temp;
00564
00565 dir = round_dir(dir);
00566 Result r = div<To_Policy, From1_Policy, From2_Policy>(temp, x, y, dir);
00567 if (result_class(r) != VC_NORMAL) {
00568 to = temp;
00569 return r;
00570 }
00571 Result r1 = trunc<To_Policy, To_Policy>(to, temp, ROUND_NOT_NEEDED);
00572 PPL_ASSERT(r1 == V_EQ);
00573 if (r == V_EQ || to != temp)
00574 return r1;
00575
00576 return dir == ROUND_UP ? V_LE : V_GE;
00577 }
00578
00579 template <typename To_Policy, typename From1_Policy, typename From2_Policy,
00580 typename Type>
00581 inline Result
00582 rem_float(Type& to, const Type x, const Type y, Rounding_Dir) {
00583 if (To_Policy::check_inf_mod && is_inf_float<From1_Policy>(x)) {
00584 return assign_nan<To_Policy>(to, V_INF_MOD);
00585 }
00586 if (To_Policy::check_div_zero && y == 0) {
00587 return assign_nan<To_Policy>(to, V_MOD_ZERO);
00588 }
00589 to = std::fmod(x, y);
00590 if (To_Policy::fpu_check_nan_result && is_nan<To_Policy>(to))
00591 return V_NAN;
00592 return V_EQ;
00593 }
00594
00595 struct Float_2exp {
00596 const_bool_nodef(has_nan, false);
00597 const_bool_nodef(has_infinity, false);
00598 };
00599
00600 template <typename To_Policy, typename From_Policy, typename Type>
00601 inline Result
00602 add_2exp_float(Type& to, const Type x, unsigned int exp, Rounding_Dir dir) {
00603 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(x))
00604 return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
00605 PPL_ASSERT(exp < sizeof(unsigned long long) * CHAR_BIT);
00606 return
00607 add<To_Policy, From_Policy, Float_2exp>(to,
00608 x,
00609 Type(1ULL << exp),
00610 dir);
00611 }
00612
00613 template <typename To_Policy, typename From_Policy, typename Type>
00614 inline Result
00615 sub_2exp_float(Type& to, const Type x, unsigned int exp, Rounding_Dir dir) {
00616 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(x))
00617 return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
00618 PPL_ASSERT(exp < sizeof(unsigned long long) * CHAR_BIT);
00619 return
00620 sub<To_Policy, From_Policy, Float_2exp>(to,
00621 x,
00622 Type(1ULL << exp),
00623 dir);
00624 }
00625
00626 template <typename To_Policy, typename From_Policy, typename Type>
00627 inline Result
00628 mul_2exp_float(Type& to, const Type x, unsigned int exp, Rounding_Dir dir) {
00629 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(x))
00630 return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
00631 PPL_ASSERT(exp < sizeof(unsigned long long) * CHAR_BIT);
00632 return
00633 mul<To_Policy, From_Policy, Float_2exp>(to,
00634 x,
00635 Type(1ULL << exp),
00636 dir);
00637 }
00638
00639 template <typename To_Policy, typename From_Policy, typename Type>
00640 inline Result
00641 div_2exp_float(Type& to, const Type x, unsigned int exp, Rounding_Dir dir) {
00642 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(x))
00643 return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
00644 PPL_ASSERT(exp < sizeof(unsigned long long) * CHAR_BIT);
00645 return
00646 div<To_Policy, From_Policy, Float_2exp>(to,
00647 x,
00648 Type(1ULL << exp),
00649 dir);
00650 }
00651
00652 template <typename To_Policy, typename From_Policy, typename Type>
00653 inline Result
00654 smod_2exp_float(Type& to, const Type x, unsigned int exp, Rounding_Dir dir) {
00655 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(x))
00656 return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
00657 if (To_Policy::check_inf_mod && is_inf_float<From_Policy>(x)) {
00658 return assign_nan<To_Policy>(to, V_INF_MOD);
00659 }
00660 PPL_ASSERT(exp < sizeof(unsigned long long) * CHAR_BIT);
00661 Type m = 1ULL << exp;
00662 rem_float<To_Policy, From_Policy, Float_2exp>(to, x, m, ROUND_IGNORE);
00663 Type m2 = m / 2;
00664 if (to < -m2)
00665 return add_float<To_Policy, From_Policy, Float_2exp>(to, to, m, dir);
00666 else if (to >= m2)
00667 return sub_float<To_Policy, From_Policy, Float_2exp>(to, to, m, dir);
00668 return V_EQ;
00669 }
00670
00671 template <typename To_Policy, typename From_Policy, typename Type>
00672 inline Result
00673 umod_2exp_float(Type& to, const Type x, unsigned int exp, Rounding_Dir dir) {
00674 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(x))
00675 return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
00676 if (To_Policy::check_inf_mod && is_inf_float<From_Policy>(x)) {
00677 return assign_nan<To_Policy>(to, V_INF_MOD);
00678 }
00679 PPL_ASSERT(exp < sizeof(unsigned long long) * CHAR_BIT);
00680 Type m = 1ULL << exp;
00681 rem_float<To_Policy, From_Policy, Float_2exp>(to, x, m, ROUND_IGNORE);
00682 if (to < 0)
00683 return add_float<To_Policy, From_Policy, Float_2exp>(to, to, m, dir);
00684 return V_EQ;
00685 }
00686
00687 template <typename To_Policy, typename From_Policy, typename Type>
00688 inline Result
00689 abs_float(Type& to, const Type from, Rounding_Dir) {
00690 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from))
00691 return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
00692 to = std::abs(from);
00693 return V_EQ;
00694 }
00695
00696 template <typename To_Policy, typename From_Policy, typename Type>
00697 inline Result
00698 sqrt_float(Type& to, const Type from, Rounding_Dir dir) {
00699 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from))
00700 return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
00701 if (To_Policy::check_sqrt_neg && from < 0) {
00702 return assign_nan<To_Policy>(to, V_SQRT_NEG);
00703 }
00704 prepare_inexact<To_Policy>(dir);
00705 if (fpu_direct_rounding(dir))
00706 to = std::sqrt(from);
00707 else {
00708 fpu_rounding_control_word_type old
00709 = fpu_save_rounding_direction(round_fpu_dir(dir));
00710 limit_precision(from);
00711 to = std::sqrt(from);
00712 limit_precision(to);
00713 fpu_restore_rounding_direction(old);
00714 }
00715 return result_relation<To_Policy>(dir);
00716 }
00717
00718 template <typename Policy, typename Type>
00719 inline Result_Relation
00720 sgn_float(const Type x) {
00721 if (x > 0)
00722 return VR_GT;
00723 if (x < 0)
00724 return VR_LT;
00725 if (x == 0)
00726 return VR_EQ;
00727 return VR_EMPTY;
00728 }
00729
00730 template <typename Policy1, typename Policy2, typename Type>
00731 inline Result_Relation
00732 cmp_float(const Type x, const Type y) {
00733 if (x > y)
00734 return VR_GT;
00735 if (x < y)
00736 return VR_LT;
00737 if (x == y)
00738 return VR_EQ;
00739 return VR_EMPTY;
00740 }
00741
00742 template <typename To_Policy, typename From_Policy, typename To, typename From>
00743 inline Result
00744 assign_float_int_inexact(To& to, const From from, Rounding_Dir dir) {
00745 prepare_inexact<To_Policy>(dir);
00746 if (fpu_direct_rounding(dir))
00747 to = from;
00748 else {
00749 fpu_rounding_control_word_type old
00750 = fpu_save_rounding_direction(round_fpu_dir(dir));
00751 to = from;
00752 limit_precision(to);
00753 fpu_restore_rounding_direction(old);
00754 }
00755 return result_relation<To_Policy>(dir);
00756 }
00757
00758 template <typename To_Policy, typename From_Policy, typename To, typename From>
00759 inline Result
00760 assign_float_int(To& to, const From from, Rounding_Dir dir) {
00761 if (sizeof(From) * CHAR_BIT > Float<To>::Binary::MANTISSA_BITS)
00762 return assign_float_int_inexact<To_Policy, From_Policy>(to, from, dir);
00763 else
00764 return assign_exact<To_Policy, From_Policy>(to, from, dir);
00765 }
00766
00767 template <typename Policy, typename T>
00768 inline Result
00769 set_neg_overflow_float(T& to, Rounding_Dir dir) {
00770 switch (round_dir(dir)) {
00771 case ROUND_UP:
00772 {
00773 Float<T> f;
00774 f.u.binary.set_max(true);
00775 to = f.value();
00776 return V_LT_INF;
00777 }
00778 default:
00779 to = -HUGE_VAL;
00780 return V_GT_MINUS_INFINITY;
00781 }
00782 }
00783
00784 template <typename Policy, typename T>
00785 inline Result
00786 set_pos_overflow_float(T& to, Rounding_Dir dir) {
00787 switch (round_dir(dir)) {
00788 case ROUND_DOWN:
00789 {
00790 Float<T> f;
00791 f.u.binary.set_max(false);
00792 to = f.value();
00793 return V_GT_SUP;
00794 }
00795 default:
00796 to = HUGE_VAL;
00797 return V_LT_PLUS_INFINITY;
00798 }
00799 }
00800
00801 template <typename To_Policy, typename From_Policy, typename T>
00802 inline Result
00803 assign_float_mpz(T& to, const mpz_class& _from, Rounding_Dir dir)
00804 {
00805 mpz_srcptr from = _from.get_mpz_t();
00806 int sign = mpz_sgn(from);
00807 if (sign == 0) {
00808 to = 0;
00809 return V_EQ;
00810 }
00811 size_t exponent = mpz_sizeinbase(from, 2) - 1;
00812 if (exponent > size_t(Float<T>::Binary::EXPONENT_MAX)) {
00813 if (sign < 0)
00814 return set_neg_overflow_float<To_Policy>(to, dir);
00815 else
00816 return set_pos_overflow_float<To_Policy>(to, dir);
00817 }
00818 unsigned long zeroes = mpn_scan1(from->_mp_d, 0);
00819 size_t meaningful_bits = exponent - zeroes;
00820 mpz_t mantissa;
00821 mpz_init(mantissa);
00822 if (exponent > Float<T>::Binary::MANTISSA_BITS)
00823 mpz_tdiv_q_2exp(mantissa,
00824 from,
00825 exponent - Float<T>::Binary::MANTISSA_BITS);
00826 else
00827 mpz_mul_2exp(mantissa, from, Float<T>::Binary::MANTISSA_BITS - exponent);
00828 Float<T> f;
00829 f.u.binary.build(sign < 0, mantissa, exponent);
00830 mpz_clear(mantissa);
00831 to = f.value();
00832 if (meaningful_bits > Float<T>::Binary::MANTISSA_BITS) {
00833 if (sign < 0)
00834 return round_lt_float<To_Policy>(to, dir);
00835 else
00836 return round_gt_float<To_Policy>(to, dir);
00837 }
00838 return V_EQ;
00839 }
00840
00841 template <typename To_Policy, typename From_Policy, typename T>
00842 inline Result
00843 assign_float_mpq(T& to, const mpq_class& from, Rounding_Dir dir)
00844 {
00845 const mpz_class& _num = from.get_num();
00846 const mpz_class& _den = from.get_den();
00847 if (_den == 1)
00848 return assign_float_mpz<To_Policy, From_Policy>(to, _num, dir);
00849 mpz_srcptr num = _num.get_mpz_t();
00850 mpz_srcptr den = _den.get_mpz_t();
00851 int sign = mpz_sgn(num);
00852 signed long exponent = mpz_sizeinbase(num, 2) - mpz_sizeinbase(den, 2);
00853 if (exponent < Float<T>::Binary::EXPONENT_MIN_DENORM) {
00854 to = 0;
00855 inexact:
00856 if (sign < 0)
00857 return round_lt_float<To_Policy>(to, dir);
00858 else
00859 return round_gt_float<To_Policy>(to, dir);
00860 }
00861 if (exponent > int(Float<T>::Binary::EXPONENT_MAX + 1)) {
00862 overflow:
00863 if (sign < 0)
00864 return set_neg_overflow_float<To_Policy>(to, dir);
00865 else
00866 return set_pos_overflow_float<To_Policy>(to, dir);
00867 }
00868 unsigned int needed_bits = Float<T>::Binary::MANTISSA_BITS + 1;
00869 if (exponent < Float<T>::Binary::EXPONENT_MIN)
00870 needed_bits -= Float<T>::Binary::EXPONENT_MIN - exponent;
00871 mpz_t mantissa;
00872 mpz_init(mantissa);
00873 signed long shift = needed_bits - exponent;
00874 if (shift > 0) {
00875 mpz_mul_2exp(mantissa, num, shift);
00876 num = mantissa;
00877 }
00878 else if (shift < 0) {
00879 mpz_mul_2exp(mantissa, den, -shift);
00880 den = mantissa;
00881 }
00882 mpz_t r;
00883 mpz_init(r);
00884 mpz_tdiv_qr(mantissa, r, num, den);
00885 size_t bits = mpz_sizeinbase(mantissa, 2);
00886 bool inexact = (mpz_sgn(r) != 0);
00887 mpz_clear(r);
00888 if (bits == needed_bits + 1) {
00889 inexact = (inexact || mpz_odd_p(mantissa));
00890 mpz_tdiv_q_2exp(mantissa, mantissa, 1);
00891 }
00892 else
00893 --exponent;
00894 if (exponent > int(Float<T>::Binary::EXPONENT_MAX)) {
00895 mpz_clear(mantissa);
00896 goto overflow;
00897 }
00898 else if (exponent < Float<T>::Binary::EXPONENT_MIN - 1) {
00899
00900 exponent = Float<T>::Binary::EXPONENT_MIN - 1;
00901 }
00902 Float<T> f;
00903 f.u.binary.build(sign < 0, mantissa, exponent);
00904 mpz_clear(mantissa);
00905 to = f.value();
00906 if (inexact)
00907 goto inexact;
00908 return V_EQ;
00909 }
00910
00911 template <typename To_Policy, typename From1_Policy, typename From2_Policy,
00912 typename Type>
00913 inline Result
00914 add_mul_float(Type& to, const Type x, const Type y, Rounding_Dir dir) {
00915 if (To_Policy::check_inf_mul_zero
00916 && ((x == 0 && is_inf_float<From2_Policy>(y))
00917 ||
00918 (y == 0 && is_inf_float<From1_Policy>(x)))) {
00919 return assign_nan<To_Policy>(to, V_INF_MUL_ZERO);
00920 }
00921
00922 prepare_inexact<To_Policy>(dir);
00923 if (fpu_direct_rounding(dir))
00924 to = fma(x, y, to);
00925 else if (fpu_inverse_rounding(dir)) {
00926 to = fma(-x, y, -to);
00927 limit_precision(to);
00928 to = -to;
00929 }
00930 else {
00931 fpu_rounding_control_word_type old
00932 = fpu_save_rounding_direction(round_fpu_dir(dir));
00933 limit_precision(x);
00934 limit_precision(y);
00935 limit_precision(to);
00936 to = fma(x, y, to);
00937 limit_precision(to);
00938 fpu_restore_rounding_direction(old);
00939 }
00940 if (To_Policy::fpu_check_nan_result && is_nan<To_Policy>(to))
00941 return V_NAN;
00942 return result_relation<To_Policy>(dir);
00943 }
00944
00945 template <typename To_Policy, typename From1_Policy, typename From2_Policy, typename Type>
00946 inline Result
00947 sub_mul_float(Type& to, const Type x, const Type y, Rounding_Dir dir) {
00948 if (To_Policy::check_inf_mul_zero
00949 && ((x == 0 && is_inf_float<From2_Policy>(y))
00950 ||
00951 (y == 0 && is_inf_float<From1_Policy>(x)))) {
00952 return assign_nan<To_Policy>(to, V_INF_MUL_ZERO);
00953 }
00954
00955 prepare_inexact<To_Policy>(dir);
00956 if (fpu_direct_rounding(dir))
00957 to = fma(x, -y, to);
00958 else if (fpu_inverse_rounding(dir)) {
00959 to = fma(x, y, -to);
00960 limit_precision(to);
00961 to = -to;
00962 }
00963 else {
00964 fpu_rounding_control_word_type old
00965 = fpu_save_rounding_direction(round_fpu_dir(dir));
00966 limit_precision(x);
00967 limit_precision(y);
00968 limit_precision(to);
00969 to = fma(x, -y, to);
00970 limit_precision(to);
00971 fpu_restore_rounding_direction(old);
00972 }
00973 if (To_Policy::fpu_check_nan_result && is_nan<To_Policy>(to))
00974 return V_NAN;
00975 return result_relation<To_Policy>(dir);
00976 }
00977
00978 template <typename Policy, typename Type>
00979 inline Result
00980 output_float(std::ostream& os, const Type from, const Numeric_Format&,
00981 Rounding_Dir) {
00982 if (from == 0)
00983 os << "0";
00984 else if (is_minf<Policy>(from))
00985 os << "-inf";
00986 else if (is_pinf<Policy>(from))
00987 os << "+inf";
00988 else if (is_nan<Policy>(from))
00989 os << "nan";
00990 else {
00991 int old_precision = os.precision(10000);
00992
00993
00994
00995
00996
00997 os << from;
00998 os.precision(old_precision);
00999 }
01000 return V_EQ;
01001 }
01002
01003 #if PPL_SUPPORTED_FLOAT
01004 PPL_SPECIALIZE_ASSIGN(assign_float_float_exact, float, float)
01005 #if PPL_SUPPORTED_DOUBLE
01006 PPL_SPECIALIZE_ASSIGN(assign_float_float, float, double)
01007 PPL_SPECIALIZE_ASSIGN(assign_float_float_exact, double, float)
01008 #endif
01009 #if PPL_SUPPORTED_LONG_DOUBLE
01010 PPL_SPECIALIZE_ASSIGN(assign_float_float, float, long double)
01011 PPL_SPECIALIZE_ASSIGN(assign_float_float_exact, long double, float)
01012 #endif
01013 #endif
01014
01015 #if PPL_SUPPORTED_DOUBLE
01016 PPL_SPECIALIZE_ASSIGN(assign_float_float_exact, double, double)
01017 #if PPL_SUPPORTED_LONG_DOUBLE
01018 PPL_SPECIALIZE_ASSIGN(assign_float_float, double, long double)
01019 PPL_SPECIALIZE_ASSIGN(assign_float_float_exact, long double, double)
01020 #endif
01021 #endif
01022
01023 #if PPL_SUPPORTED_LONG_DOUBLE
01024 PPL_SPECIALIZE_ASSIGN(assign_float_float_exact, long double, long double)
01025 #endif
01026
01027 #if PPL_SUPPORTED_FLOAT
01028 PPL_SPECIALIZE_CLASSIFY(classify_float, float)
01029 PPL_SPECIALIZE_IS_NAN(is_nan_float, float)
01030 PPL_SPECIALIZE_IS_MINF(is_minf_float, float)
01031 PPL_SPECIALIZE_IS_PINF(is_pinf_float, float)
01032 PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_float, float)
01033 PPL_SPECIALIZE_ASSIGN(assign_float_int, float, char)
01034 PPL_SPECIALIZE_ASSIGN(assign_float_int, float, signed char)
01035 PPL_SPECIALIZE_ASSIGN(assign_float_int, float, signed short)
01036 PPL_SPECIALIZE_ASSIGN(assign_float_int, float, signed int)
01037 PPL_SPECIALIZE_ASSIGN(assign_float_int, float, signed long)
01038 PPL_SPECIALIZE_ASSIGN(assign_float_int, float, signed long long)
01039 PPL_SPECIALIZE_ASSIGN(assign_float_int, float, unsigned char)
01040 PPL_SPECIALIZE_ASSIGN(assign_float_int, float, unsigned short)
01041 PPL_SPECIALIZE_ASSIGN(assign_float_int, float, unsigned int)
01042 PPL_SPECIALIZE_ASSIGN(assign_float_int, float, unsigned long)
01043 PPL_SPECIALIZE_ASSIGN(assign_float_int, float, unsigned long long)
01044 PPL_SPECIALIZE_ASSIGN(assign_float_mpz, float, mpz_class)
01045 PPL_SPECIALIZE_ASSIGN(assign_float_mpq, float, mpq_class)
01046 PPL_SPECIALIZE_COPY(copy_generic, float)
01047 PPL_SPECIALIZE_IS_INT(is_int_float, float)
01048 PPL_SPECIALIZE_FLOOR(floor_float, float, float)
01049 PPL_SPECIALIZE_CEIL(ceil_float, float, float)
01050 PPL_SPECIALIZE_TRUNC(trunc_float, float, float)
01051 PPL_SPECIALIZE_NEG(neg_float, float, float)
01052 PPL_SPECIALIZE_ABS(abs_float, float, float)
01053 PPL_SPECIALIZE_ADD(add_float, float, float, float)
01054 PPL_SPECIALIZE_SUB(sub_float, float, float, float)
01055 PPL_SPECIALIZE_MUL(mul_float, float, float, float)
01056 PPL_SPECIALIZE_DIV(div_float, float, float, float)
01057 PPL_SPECIALIZE_REM(rem_float, float, float, float)
01058 PPL_SPECIALIZE_ADD_2EXP(add_2exp_float, float, float)
01059 PPL_SPECIALIZE_SUB_2EXP(sub_2exp_float, float, float)
01060 PPL_SPECIALIZE_MUL_2EXP(mul_2exp_float, float, float)
01061 PPL_SPECIALIZE_DIV_2EXP(div_2exp_float, float, float)
01062 PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_float, float, float)
01063 PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_float, float, float)
01064 PPL_SPECIALIZE_SQRT(sqrt_float, float, float)
01065 PPL_SPECIALIZE_GCD(gcd_exact, float, float, float)
01066 PPL_SPECIALIZE_GCDEXT(gcdext_exact, float, float, float, float, float)
01067 PPL_SPECIALIZE_LCM(lcm_gcd_exact, float, float, float)
01068 PPL_SPECIALIZE_SGN(sgn_float, float)
01069 PPL_SPECIALIZE_CMP(cmp_float, float, float)
01070 PPL_SPECIALIZE_ADD_MUL(add_mul_float, float, float, float)
01071 PPL_SPECIALIZE_SUB_MUL(sub_mul_float, float, float, float)
01072 PPL_SPECIALIZE_INPUT(input_generic, float)
01073 PPL_SPECIALIZE_OUTPUT(output_float, float)
01074 #endif
01075
01076 #if PPL_SUPPORTED_DOUBLE
01077 PPL_SPECIALIZE_CLASSIFY(classify_float, double)
01078 PPL_SPECIALIZE_IS_NAN(is_nan_float, double)
01079 PPL_SPECIALIZE_IS_MINF(is_minf_float, double)
01080 PPL_SPECIALIZE_IS_PINF(is_pinf_float, double)
01081 PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_float, double)
01082 PPL_SPECIALIZE_ASSIGN(assign_float_int, double, char)
01083 PPL_SPECIALIZE_ASSIGN(assign_float_int, double, signed char)
01084 PPL_SPECIALIZE_ASSIGN(assign_float_int, double, signed short)
01085 PPL_SPECIALIZE_ASSIGN(assign_float_int, double, signed int)
01086 PPL_SPECIALIZE_ASSIGN(assign_float_int, double, signed long)
01087 PPL_SPECIALIZE_ASSIGN(assign_float_int, double, signed long long)
01088 PPL_SPECIALIZE_ASSIGN(assign_float_int, double, unsigned char)
01089 PPL_SPECIALIZE_ASSIGN(assign_float_int, double, unsigned short)
01090 PPL_SPECIALIZE_ASSIGN(assign_float_int, double, unsigned int)
01091 PPL_SPECIALIZE_ASSIGN(assign_float_int, double, unsigned long)
01092 PPL_SPECIALIZE_ASSIGN(assign_float_int, double, unsigned long long)
01093 PPL_SPECIALIZE_ASSIGN(assign_float_mpz, double, mpz_class)
01094 PPL_SPECIALIZE_ASSIGN(assign_float_mpq, double, mpq_class)
01095 PPL_SPECIALIZE_COPY(copy_generic, double)
01096 PPL_SPECIALIZE_IS_INT(is_int_float, double)
01097 PPL_SPECIALIZE_FLOOR(floor_float, double, double)
01098 PPL_SPECIALIZE_CEIL(ceil_float, double, double)
01099 PPL_SPECIALIZE_TRUNC(trunc_float, double, double)
01100 PPL_SPECIALIZE_NEG(neg_float, double, double)
01101 PPL_SPECIALIZE_ABS(abs_float, double, double)
01102 PPL_SPECIALIZE_ADD(add_float, double, double, double)
01103 PPL_SPECIALIZE_SUB(sub_float, double, double, double)
01104 PPL_SPECIALIZE_MUL(mul_float, double, double, double)
01105 PPL_SPECIALIZE_DIV(div_float, double, double, double)
01106 PPL_SPECIALIZE_REM(rem_float, double, double, double)
01107 PPL_SPECIALIZE_ADD_2EXP(add_2exp_float, double, double)
01108 PPL_SPECIALIZE_SUB_2EXP(sub_2exp_float, double, double)
01109 PPL_SPECIALIZE_MUL_2EXP(mul_2exp_float, double, double)
01110 PPL_SPECIALIZE_DIV_2EXP(div_2exp_float, double, double)
01111 PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_float, double, double)
01112 PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_float, double, double)
01113 PPL_SPECIALIZE_SQRT(sqrt_float, double, double)
01114 PPL_SPECIALIZE_GCD(gcd_exact, double, double, double)
01115 PPL_SPECIALIZE_GCDEXT(gcdext_exact, double, double, double, double, double)
01116 PPL_SPECIALIZE_LCM(lcm_gcd_exact, double, double, double)
01117 PPL_SPECIALIZE_SGN(sgn_float, double)
01118 PPL_SPECIALIZE_CMP(cmp_float, double, double)
01119 PPL_SPECIALIZE_ADD_MUL(add_mul_float, double, double, double)
01120 PPL_SPECIALIZE_SUB_MUL(sub_mul_float, double, double, double)
01121 PPL_SPECIALIZE_INPUT(input_generic, double)
01122 PPL_SPECIALIZE_OUTPUT(output_float, double)
01123 #endif
01124
01125 #if PPL_SUPPORTED_LONG_DOUBLE
01126 PPL_SPECIALIZE_CLASSIFY(classify_float, long double)
01127 PPL_SPECIALIZE_IS_NAN(is_nan_float, long double)
01128 PPL_SPECIALIZE_IS_MINF(is_minf_float, long double)
01129 PPL_SPECIALIZE_IS_PINF(is_pinf_float, long double)
01130 PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_float, long double)
01131 PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, char)
01132 PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, signed char)
01133 PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, signed short)
01134 PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, signed int)
01135 PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, signed long)
01136 PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, signed long long)
01137 PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, unsigned char)
01138 PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, unsigned short)
01139 PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, unsigned int)
01140 PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, unsigned long)
01141 PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, unsigned long long)
01142 PPL_SPECIALIZE_ASSIGN(assign_float_mpz, long double, mpz_class)
01143 PPL_SPECIALIZE_ASSIGN(assign_float_mpq, long double, mpq_class)
01144 PPL_SPECIALIZE_COPY(copy_generic, long double)
01145 PPL_SPECIALIZE_IS_INT(is_int_float, long double)
01146 PPL_SPECIALIZE_FLOOR(floor_float, long double, long double)
01147 PPL_SPECIALIZE_CEIL(ceil_float, long double, long double)
01148 PPL_SPECIALIZE_TRUNC(trunc_float, long double, long double)
01149 PPL_SPECIALIZE_NEG(neg_float, long double, long double)
01150 PPL_SPECIALIZE_ABS(abs_float, long double, long double)
01151 PPL_SPECIALIZE_ADD(add_float, long double, long double, long double)
01152 PPL_SPECIALIZE_SUB(sub_float, long double, long double, long double)
01153 PPL_SPECIALIZE_MUL(mul_float, long double, long double, long double)
01154 PPL_SPECIALIZE_DIV(div_float, long double, long double, long double)
01155 PPL_SPECIALIZE_REM(rem_float, long double, long double, long double)
01156 PPL_SPECIALIZE_ADD_2EXP(add_2exp_float, long double, long double)
01157 PPL_SPECIALIZE_SUB_2EXP(sub_2exp_float, long double, long double)
01158 PPL_SPECIALIZE_MUL_2EXP(mul_2exp_float, long double, long double)
01159 PPL_SPECIALIZE_DIV_2EXP(div_2exp_float, long double, long double)
01160 PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_float, long double, long double)
01161 PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_float, long double, long double)
01162 PPL_SPECIALIZE_SQRT(sqrt_float, long double, long double)
01163 PPL_SPECIALIZE_GCD(gcd_exact, long double, long double, long double)
01164 PPL_SPECIALIZE_GCDEXT(gcdext_exact, long double, long double, long double,
01165 long double, long double)
01166 PPL_SPECIALIZE_LCM(lcm_gcd_exact, long double, long double, long double)
01167 PPL_SPECIALIZE_SGN(sgn_float, long double)
01168 PPL_SPECIALIZE_CMP(cmp_float, long double, long double)
01169 PPL_SPECIALIZE_ADD_MUL(add_mul_float, long double, long double, long double)
01170 PPL_SPECIALIZE_SUB_MUL(sub_mul_float, long double, long double, long double)
01171 PPL_SPECIALIZE_INPUT(input_generic, long double)
01172 PPL_SPECIALIZE_OUTPUT(output_float, long double)
01173 #endif
01174
01175 }
01176
01177 }
01178
01179 #endif // !defined(PPL_checked_int_inlines_hh)