|
PPL
0.12.1
|
00001 /* Specialized "checked" functions for native floating-point numbers. 00002 Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it> 00003 Copyright (C) 2010-2012 BUGSENG srl (http://bugseng.com) 00004 00005 This file is part of the Parma Polyhedra Library (PPL). 00006 00007 The PPL is free software; you can redistribute it and/or modify it 00008 under the terms of the GNU General Public License as published by the 00009 Free Software Foundation; either version 3 of the License, or (at your 00010 option) any later version. 00011 00012 The PPL is distributed in the hope that it will be useful, but WITHOUT 00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00014 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 00015 for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with this program; if not, write to the Free Software Foundation, 00019 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA. 00020 00021 For the most up-to-date information see the Parma Polyhedra Library 00022 site: http://bugseng.com/products/ppl/ . */ 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 multiply_add(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 multiply_add(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 multiply_add(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 round_to_integer(float x) { 00069 return rintf(x); 00070 } 00071 #endif 00072 00073 inline double 00074 round_to_integer(double x) { 00075 return rint(x); 00076 } 00077 00078 #if PPL_HAVE_DECL_RINTL 00079 inline long double 00080 round_to_integer(long double x) { 00081 return rintl(x); 00082 } 00083 #elif !PPL_CXX_PROVIDES_PROPER_LONG_DOUBLE 00084 // If proper long doubles are not provided, this is most likely 00085 // because long double and double are the same type: use rint(). 00086 inline long double 00087 round_to_integer(long double x) { 00088 return rint(x); 00089 } 00090 #elif defined(__i386__) && (defined(__GNUC__) || defined(__INTEL_COMPILER)) 00091 // On Cygwin, we have proper long doubles but rintl() is not defined: 00092 // luckily, one machine instruction is enough to save the day. 00093 inline long double 00094 round_to_integer(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 // The FPU mode is "round down". 00112 // 00113 // The result of the rounded down multiplication is thus computed directly. 00114 // 00115 // a = 0.3 00116 // b = 0.1 00117 // c_i = a * b = 0.03 00118 // c = c_i = 0.0 00119 // 00120 // To obtain the result of the rounded up multiplication 00121 // we do -(-a * b). 00122 // 00123 // a = 0.3 00124 // b = 0.1 00125 // c_i = -a * b = -0.03 00126 // 00127 // Here c_i should be forced to lose excess precision, otherwise the 00128 // FPU will truncate using the rounding mode in force, which is "round down". 00129 // 00130 // c_i = -c_i = 0.03 00131 // c = c_i = 0.0 00132 // 00133 // Wrong result: we should have obtained c = 0.1. 00134 00135 inline void 00136 limit_precision(const float& v) { 00137 PPL_CC_FLUSH(v); 00138 } 00139 00140 inline void 00141 limit_precision(const double& v) { 00142 PPL_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 if (Policy::has_infinity) { 00157 int sign_inf = f.u.binary.inf_sign(); 00158 if (sign_inf < 0) 00159 return V_EQ_MINUS_INFINITY; 00160 if (sign_inf > 0) 00161 return V_EQ_PLUS_INFINITY; 00162 } 00163 else 00164 PPL_ASSERT(f.u.binary.inf_sign() == 0); 00165 } 00166 if (sign) { 00167 if (v < 0) 00168 return V_LT; 00169 if (v > 0) 00170 return V_GT; 00171 return V_EQ; 00172 } 00173 return V_LGE; 00174 } 00175 00176 template <typename Policy, typename T> 00177 inline bool 00178 is_nan_float(const T v) { 00179 Float<T> f(v); 00180 return CHECK_P(Policy::has_nan, f.u.binary.is_nan()); 00181 } 00182 00183 template <typename Policy, typename T> 00184 inline bool 00185 is_inf_float(const T v) { 00186 Float<T> f(v); 00187 return CHECK_P(Policy::has_infinity, (f.u.binary.inf_sign() != 0)); 00188 } 00189 template <typename Policy, typename T> 00190 inline bool 00191 is_minf_float(const T v) { 00192 Float<T> f(v); 00193 return CHECK_P(Policy::has_infinity, (f.u.binary.inf_sign() < 0)); 00194 } 00195 00196 template <typename Policy, typename T> 00197 inline bool 00198 is_pinf_float(const T v) { 00199 Float<T> f(v); 00200 return CHECK_P(Policy::has_infinity, (f.u.binary.inf_sign() > 0)); 00201 } 00202 00203 00204 template <typename Policy, typename T> 00205 inline bool 00206 is_int_float(const T v) { 00207 return round_to_integer(v) == v; 00208 } 00209 00210 template <typename Policy, typename T> 00211 inline Result 00212 assign_special_float(T& v, Result_Class c, Rounding_Dir) { 00213 PPL_ASSERT(c == VC_MINUS_INFINITY || c == VC_PLUS_INFINITY || c == VC_NAN); 00214 switch (c) { 00215 case VC_MINUS_INFINITY: 00216 v = -HUGE_VAL; 00217 return V_EQ_MINUS_INFINITY; 00218 case VC_PLUS_INFINITY: 00219 v = HUGE_VAL; 00220 return V_EQ_PLUS_INFINITY; 00221 case VC_NAN: 00222 v = PPL_NAN; 00223 return V_NAN; 00224 default: 00225 PPL_UNREACHABLE; 00226 return V_NAN | V_UNREPRESENTABLE; 00227 } 00228 } 00229 00230 template <typename T> 00231 inline void 00232 pred_float(T& v) { 00233 Float<T> f(v); 00234 PPL_ASSERT(!f.u.binary.is_nan()); 00235 PPL_ASSERT(f.u.binary.inf_sign() >= 0); 00236 if (f.u.binary.zero_sign() > 0) { 00237 f.u.binary.negate(); 00238 f.u.binary.inc(); 00239 } 00240 else if (f.u.binary.sign_bit()) { 00241 f.u.binary.inc(); 00242 } 00243 else { 00244 f.u.binary.dec(); 00245 } 00246 v = f.value(); 00247 } 00248 00249 template <typename T> 00250 inline void 00251 succ_float(T& v) { 00252 Float<T> f(v); 00253 PPL_ASSERT(!f.u.binary.is_nan()); 00254 PPL_ASSERT(f.u.binary.inf_sign() <= 0); 00255 if (f.u.binary.zero_sign() < 0) { 00256 f.u.binary.negate(); 00257 f.u.binary.inc(); 00258 } 00259 else if (!f.u.binary.sign_bit()) { 00260 f.u.binary.inc(); 00261 } 00262 else { 00263 f.u.binary.dec(); 00264 } 00265 v = f.value(); 00266 } 00267 00268 template <typename Policy, typename To> 00269 inline Result 00270 round_lt_float(To& to, Rounding_Dir dir) { 00271 if (round_down(dir)) { 00272 pred_float(to); 00273 return V_GT; 00274 } 00275 return V_LT; 00276 } 00277 00278 template <typename Policy, typename To> 00279 inline Result 00280 round_gt_float(To& to, Rounding_Dir dir) { 00281 if (round_up(dir)) { 00282 succ_float(to); 00283 return V_LT; 00284 } 00285 return V_GT; 00286 } 00287 00288 00289 template <typename Policy> 00290 inline void 00291 prepare_inexact(Rounding_Dir dir) { 00292 if (Policy::fpu_check_inexact 00293 && !round_not_needed(dir) && round_strict_relation(dir)) 00294 fpu_reset_inexact(); 00295 } 00296 00297 template <typename Policy> 00298 inline Result 00299 result_relation(Rounding_Dir dir) { 00300 if (Policy::fpu_check_inexact 00301 && !round_not_needed(dir) && round_strict_relation(dir)) { 00302 switch (fpu_check_inexact()) { 00303 case 0: 00304 return V_EQ; 00305 case -1: 00306 goto unknown; 00307 case 1: 00308 break; 00309 } 00310 switch (round_dir(dir)) { 00311 case ROUND_DOWN: 00312 return V_GT; 00313 case ROUND_UP: 00314 return V_LT; 00315 default: 00316 return V_NE; 00317 } 00318 } 00319 else { 00320 unknown: 00321 switch (round_dir(dir)) { 00322 case ROUND_DOWN: 00323 return V_GE; 00324 case ROUND_UP: 00325 return V_LE; 00326 default: 00327 return V_LGE; 00328 } 00329 } 00330 } 00331 00332 template <typename To_Policy, typename From_Policy, typename To, typename From> 00333 inline Result 00334 assign_float_float_exact(To& to, const From from, Rounding_Dir) { 00335 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from)) 00336 return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE); 00337 to = from; 00338 return V_EQ; 00339 } 00340 00341 template <typename To_Policy, typename From_Policy, typename To, typename From> 00342 inline Result 00343 assign_float_float_inexact(To& to, const From from, Rounding_Dir dir) { 00344 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from)) 00345 return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE); 00346 prepare_inexact<To_Policy>(dir); 00347 if (fpu_direct_rounding(dir)) 00348 to = from; 00349 else if (fpu_inverse_rounding(dir)) { 00350 From tmp = -from; 00351 to = tmp; 00352 limit_precision(to); 00353 to = -to; 00354 } 00355 else { 00356 fpu_rounding_control_word_type old 00357 = fpu_save_rounding_direction(round_fpu_dir(dir)); 00358 limit_precision(from); 00359 to = from; 00360 limit_precision(to); 00361 fpu_restore_rounding_direction(old); 00362 } 00363 return result_relation<To_Policy>(dir); 00364 } 00365 00366 template <typename To_Policy, typename From_Policy, typename To, typename From> 00367 inline Result 00368 assign_float_float(To& to, const From from, Rounding_Dir dir) { 00369 if (sizeof(From) > sizeof(To)) 00370 return assign_float_float_inexact<To_Policy, From_Policy>(to, from, dir); 00371 else 00372 return assign_float_float_exact<To_Policy, From_Policy>(to, from, dir); 00373 } 00374 00375 template <typename To_Policy, typename From_Policy, typename Type> 00376 inline Result 00377 floor_float(Type& to, const Type from, Rounding_Dir) { 00378 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from)) 00379 return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE); 00380 if (fpu_direct_rounding(ROUND_DOWN)) 00381 to = round_to_integer(from); 00382 else if (fpu_inverse_rounding(ROUND_DOWN)) { 00383 to = round_to_integer(-from); 00384 limit_precision(to); 00385 to = -to; 00386 } 00387 else { 00388 fpu_rounding_control_word_type old 00389 = fpu_save_rounding_direction(round_fpu_dir(ROUND_DOWN)); 00390 limit_precision(from); 00391 to = round_to_integer(from); 00392 limit_precision(to); 00393 fpu_restore_rounding_direction(old); 00394 } 00395 return V_EQ; 00396 } 00397 00398 template <typename To_Policy, typename From_Policy, typename Type> 00399 inline Result 00400 ceil_float(Type& to, const Type from, Rounding_Dir) { 00401 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from)) 00402 return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE); 00403 if (fpu_direct_rounding(ROUND_UP)) 00404 to = round_to_integer(from); 00405 else if (fpu_inverse_rounding(ROUND_UP)) { 00406 to = round_to_integer(-from); 00407 limit_precision(to); 00408 to = -to; 00409 } 00410 else { 00411 fpu_rounding_control_word_type old 00412 = fpu_save_rounding_direction(round_fpu_dir(ROUND_UP)); 00413 limit_precision(from); 00414 to = round_to_integer(from); 00415 limit_precision(to); 00416 fpu_restore_rounding_direction(old); 00417 } 00418 return V_EQ; 00419 } 00420 00421 template <typename To_Policy, typename From_Policy, typename Type> 00422 inline Result 00423 trunc_float(Type& to, const Type from, Rounding_Dir dir) { 00424 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from)) 00425 return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE); 00426 if (from >= 0) 00427 return floor<To_Policy, From_Policy>(to, from, dir); 00428 else 00429 return ceil<To_Policy, From_Policy>(to, from, dir); 00430 } 00431 00432 template <typename To_Policy, typename From_Policy, typename Type> 00433 inline Result 00434 neg_float(Type& to, const Type from, Rounding_Dir) { 00435 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from)) 00436 return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE); 00437 to = -from; 00438 return V_EQ; 00439 } 00440 00441 template <typename To_Policy, typename From1_Policy, typename From2_Policy, 00442 typename Type> 00443 inline Result 00444 add_float(Type& to, const Type x, const Type y, Rounding_Dir dir) { 00445 if (To_Policy::check_inf_add_inf 00446 && is_inf_float<From1_Policy>(x) && x == -y) { 00447 return assign_nan<To_Policy>(to, V_INF_ADD_INF); 00448 } 00449 prepare_inexact<To_Policy>(dir); 00450 if (fpu_direct_rounding(dir)) 00451 to = x + y; 00452 else if (fpu_inverse_rounding(dir)) { 00453 to = -x - y; 00454 limit_precision(to); 00455 to = -to; 00456 } 00457 else { 00458 fpu_rounding_control_word_type old 00459 = fpu_save_rounding_direction(round_fpu_dir(dir)); 00460 limit_precision(x); 00461 limit_precision(y); 00462 to = x + y; 00463 limit_precision(to); 00464 fpu_restore_rounding_direction(old); 00465 } 00466 if (To_Policy::fpu_check_nan_result && is_nan<To_Policy>(to)) 00467 return V_NAN; 00468 return result_relation<To_Policy>(dir); 00469 } 00470 00471 template <typename To_Policy, typename From1_Policy, typename From2_Policy, 00472 typename Type> 00473 inline Result 00474 sub_float(Type& to, const Type x, const Type y, Rounding_Dir dir) { 00475 if (To_Policy::check_inf_sub_inf 00476 && is_inf_float<From1_Policy>(x) && x == y) { 00477 return assign_nan<To_Policy>(to, V_INF_SUB_INF); 00478 } 00479 prepare_inexact<To_Policy>(dir); 00480 if (fpu_direct_rounding(dir)) 00481 to = x - y; 00482 else if (fpu_inverse_rounding(dir)) { 00483 to = y - x; 00484 limit_precision(to); 00485 to = -to; 00486 } 00487 else { 00488 fpu_rounding_control_word_type old 00489 = fpu_save_rounding_direction(round_fpu_dir(dir)); 00490 limit_precision(x); 00491 limit_precision(y); 00492 to = x - y; 00493 limit_precision(to); 00494 fpu_restore_rounding_direction(old); 00495 } 00496 if (To_Policy::fpu_check_nan_result && is_nan<To_Policy>(to)) 00497 return V_NAN; 00498 return result_relation<To_Policy>(dir); 00499 } 00500 00501 template <typename To_Policy, typename From1_Policy, typename From2_Policy, 00502 typename Type> 00503 inline Result 00504 mul_float(Type& to, const Type x, const Type y, Rounding_Dir dir) { 00505 if (To_Policy::check_inf_mul_zero 00506 && ((x == 0 && is_inf_float<From2_Policy>(y)) 00507 || 00508 (y == 0 && is_inf_float<From1_Policy>(x)))) { 00509 return assign_nan<To_Policy>(to, V_INF_MUL_ZERO); 00510 } 00511 prepare_inexact<To_Policy>(dir); 00512 if (fpu_direct_rounding(dir)) 00513 to = x * y; 00514 else if (fpu_inverse_rounding(dir)) { 00515 to = x * -y; 00516 limit_precision(to); 00517 to = -to; 00518 } 00519 else { 00520 fpu_rounding_control_word_type old 00521 = fpu_save_rounding_direction(round_fpu_dir(dir)); 00522 limit_precision(x); 00523 limit_precision(y); 00524 to = x * y; 00525 limit_precision(to); 00526 fpu_restore_rounding_direction(old); 00527 } 00528 if (To_Policy::fpu_check_nan_result && is_nan<To_Policy>(to)) 00529 return V_NAN; 00530 return result_relation<To_Policy>(dir); 00531 } 00532 00533 template <typename To_Policy, typename From1_Policy, typename From2_Policy, 00534 typename Type> 00535 inline Result 00536 div_float(Type& to, const Type x, const Type y, Rounding_Dir dir) { 00537 if (To_Policy::check_inf_div_inf 00538 && is_inf_float<From1_Policy>(x) && is_inf_float<From2_Policy>(y)) { 00539 return assign_nan<To_Policy>(to, V_INF_DIV_INF); 00540 } 00541 if (To_Policy::check_div_zero && y == 0) { 00542 return assign_nan<To_Policy>(to, V_DIV_ZERO); 00543 } 00544 prepare_inexact<To_Policy>(dir); 00545 if (fpu_direct_rounding(dir)) 00546 to = x / y; 00547 else if (fpu_inverse_rounding(dir)) { 00548 to = x / -y; 00549 limit_precision(to); 00550 to = -to; 00551 } 00552 else { 00553 fpu_rounding_control_word_type old 00554 = fpu_save_rounding_direction(round_fpu_dir(dir)); 00555 limit_precision(x); 00556 limit_precision(y); 00557 to = x / y; 00558 limit_precision(to); 00559 fpu_restore_rounding_direction(old); 00560 } 00561 if (To_Policy::fpu_check_nan_result && is_nan<To_Policy>(to)) 00562 return V_NAN; 00563 return result_relation<To_Policy>(dir); 00564 } 00565 00566 template <typename To_Policy, typename From1_Policy, typename From2_Policy, 00567 typename Type> 00568 inline Result 00569 idiv_float(Type& to, const Type x, const Type y, Rounding_Dir dir) { 00570 Type temp; 00571 // The inexact check is useless 00572 dir = round_dir(dir); 00573 Result r = div<To_Policy, From1_Policy, From2_Policy>(temp, x, y, dir); 00574 if (result_class(r) != VC_NORMAL) { 00575 to = temp; 00576 return r; 00577 } 00578 Result r1 = trunc<To_Policy, To_Policy>(to, temp, ROUND_NOT_NEEDED); 00579 PPL_ASSERT(r1 == V_EQ); 00580 if (r == V_EQ || to != temp) 00581 return r1; 00582 // FIXME: Prove that it is impossible to return a strict relation 00583 return (dir == ROUND_UP) ? V_LE : V_GE; 00584 } 00585 00586 template <typename To_Policy, typename From1_Policy, typename From2_Policy, 00587 typename Type> 00588 inline Result 00589 rem_float(Type& to, const Type x, const Type y, Rounding_Dir) { 00590 if (To_Policy::check_inf_mod && is_inf_float<From1_Policy>(x)) { 00591 return assign_nan<To_Policy>(to, V_INF_MOD); 00592 } 00593 if (To_Policy::check_div_zero && y == 0) { 00594 return assign_nan<To_Policy>(to, V_MOD_ZERO); 00595 } 00596 to = std::fmod(x, y); 00597 if (To_Policy::fpu_check_nan_result && is_nan<To_Policy>(to)) 00598 return V_NAN; 00599 return V_EQ; 00600 } 00601 00602 struct Float_2exp { 00603 const_bool_nodef(has_nan, false); 00604 const_bool_nodef(has_infinity, false); 00605 }; 00606 00607 template <typename To_Policy, typename From_Policy, typename Type> 00608 inline Result 00609 add_2exp_float(Type& to, const Type x, unsigned int exp, Rounding_Dir dir) { 00610 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(x)) 00611 return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE); 00612 PPL_ASSERT(exp < sizeof_to_bits(sizeof(unsigned long long))); 00613 return 00614 add<To_Policy, From_Policy, Float_2exp>(to, 00615 x, 00616 Type(1ULL << exp), 00617 dir); 00618 } 00619 00620 template <typename To_Policy, typename From_Policy, typename Type> 00621 inline Result 00622 sub_2exp_float(Type& to, const Type x, unsigned int exp, Rounding_Dir dir) { 00623 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(x)) 00624 return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE); 00625 PPL_ASSERT(exp < sizeof_to_bits(sizeof(unsigned long long))); 00626 return 00627 sub<To_Policy, From_Policy, Float_2exp>(to, 00628 x, 00629 Type(1ULL << exp), 00630 dir); 00631 } 00632 00633 template <typename To_Policy, typename From_Policy, typename Type> 00634 inline Result 00635 mul_2exp_float(Type& to, const Type x, unsigned int exp, Rounding_Dir dir) { 00636 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(x)) 00637 return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE); 00638 PPL_ASSERT(exp < sizeof_to_bits(sizeof(unsigned long long))); 00639 return 00640 mul<To_Policy, From_Policy, Float_2exp>(to, 00641 x, 00642 Type(1ULL << exp), 00643 dir); 00644 } 00645 00646 template <typename To_Policy, typename From_Policy, typename Type> 00647 inline Result 00648 div_2exp_float(Type& to, const Type x, unsigned int exp, Rounding_Dir dir) { 00649 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(x)) 00650 return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE); 00651 PPL_ASSERT(exp < sizeof_to_bits(sizeof(unsigned long long))); 00652 return 00653 div<To_Policy, From_Policy, Float_2exp>(to, 00654 x, 00655 Type(1ULL << exp), 00656 dir); 00657 } 00658 00659 template <typename To_Policy, typename From_Policy, typename Type> 00660 inline Result 00661 smod_2exp_float(Type& to, const Type x, unsigned int exp, Rounding_Dir dir) { 00662 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(x)) 00663 return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE); 00664 if (To_Policy::check_inf_mod && is_inf_float<From_Policy>(x)) { 00665 return assign_nan<To_Policy>(to, V_INF_MOD); 00666 } 00667 PPL_ASSERT(exp < sizeof_to_bits(sizeof(unsigned long long))); 00668 Type m = 1ULL << exp; 00669 rem_float<To_Policy, From_Policy, Float_2exp>(to, x, m, ROUND_IGNORE); 00670 Type m2 = m / 2; 00671 if (to < -m2) 00672 return add_float<To_Policy, From_Policy, Float_2exp>(to, to, m, dir); 00673 else if (to >= m2) 00674 return sub_float<To_Policy, From_Policy, Float_2exp>(to, to, m, dir); 00675 return V_EQ; 00676 } 00677 00678 template <typename To_Policy, typename From_Policy, typename Type> 00679 inline Result 00680 umod_2exp_float(Type& to, const Type x, unsigned int exp, Rounding_Dir dir) { 00681 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(x)) 00682 return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE); 00683 if (To_Policy::check_inf_mod && is_inf_float<From_Policy>(x)) { 00684 return assign_nan<To_Policy>(to, V_INF_MOD); 00685 } 00686 PPL_ASSERT(exp < sizeof_to_bits(sizeof(unsigned long long))); 00687 Type m = 1ULL << exp; 00688 rem_float<To_Policy, From_Policy, Float_2exp>(to, x, m, ROUND_IGNORE); 00689 if (to < 0) 00690 return add_float<To_Policy, From_Policy, Float_2exp>(to, to, m, dir); 00691 return V_EQ; 00692 } 00693 00694 template <typename To_Policy, typename From_Policy, typename Type> 00695 inline Result 00696 abs_float(Type& to, const Type from, Rounding_Dir) { 00697 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from)) 00698 return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE); 00699 to = std::abs(from); 00700 return V_EQ; 00701 } 00702 00703 template <typename To_Policy, typename From_Policy, typename Type> 00704 inline Result 00705 sqrt_float(Type& to, const Type from, Rounding_Dir dir) { 00706 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from)) 00707 return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE); 00708 if (To_Policy::check_sqrt_neg && from < 0) { 00709 return assign_nan<To_Policy>(to, V_SQRT_NEG); 00710 } 00711 prepare_inexact<To_Policy>(dir); 00712 if (fpu_direct_rounding(dir)) 00713 to = std::sqrt(from); 00714 else { 00715 fpu_rounding_control_word_type old 00716 = fpu_save_rounding_direction(round_fpu_dir(dir)); 00717 limit_precision(from); 00718 to = std::sqrt(from); 00719 limit_precision(to); 00720 fpu_restore_rounding_direction(old); 00721 } 00722 return result_relation<To_Policy>(dir); 00723 } 00724 00725 template <typename Policy, typename Type> 00726 inline Result_Relation 00727 sgn_float(const Type x) { 00728 if (x > 0) 00729 return VR_GT; 00730 if (x < 0) 00731 return VR_LT; 00732 if (x == 0) 00733 return VR_EQ; 00734 return VR_EMPTY; 00735 } 00736 00737 template <typename Policy1, typename Policy2, typename Type> 00738 inline Result_Relation 00739 cmp_float(const Type x, const Type y) { 00740 if (x > y) 00741 return VR_GT; 00742 if (x < y) 00743 return VR_LT; 00744 if (x == y) 00745 return VR_EQ; 00746 return VR_EMPTY; 00747 } 00748 00749 template <typename To_Policy, typename From_Policy, typename To, typename From> 00750 inline Result 00751 assign_float_int_inexact(To& to, const From from, Rounding_Dir dir) { 00752 prepare_inexact<To_Policy>(dir); 00753 if (fpu_direct_rounding(dir)) 00754 to = from; 00755 else { 00756 fpu_rounding_control_word_type old 00757 = fpu_save_rounding_direction(round_fpu_dir(dir)); 00758 to = from; 00759 limit_precision(to); 00760 fpu_restore_rounding_direction(old); 00761 } 00762 return result_relation<To_Policy>(dir); 00763 } 00764 00765 template <typename To_Policy, typename From_Policy, typename To, typename From> 00766 inline Result 00767 assign_float_int(To& to, const From from, Rounding_Dir dir) { 00768 if (sizeof_to_bits(sizeof(From)) > Float<To>::Binary::MANTISSA_BITS) 00769 return assign_float_int_inexact<To_Policy, From_Policy>(to, from, dir); 00770 else 00771 return assign_exact<To_Policy, From_Policy>(to, from, dir); 00772 } 00773 00774 template <typename Policy, typename T> 00775 inline Result 00776 set_neg_overflow_float(T& to, Rounding_Dir dir) { 00777 switch (round_dir(dir)) { 00778 case ROUND_UP: 00779 { 00780 Float<T> f; 00781 f.u.binary.set_max(true); 00782 to = f.value(); 00783 return V_LT_INF; 00784 } 00785 case ROUND_DOWN: // Fall through. 00786 case ROUND_IGNORE: 00787 to = -HUGE_VAL; 00788 return V_GT_MINUS_INFINITY; 00789 default: 00790 PPL_UNREACHABLE; 00791 return V_GT_MINUS_INFINITY; 00792 } 00793 } 00794 00795 template <typename Policy, typename T> 00796 inline Result 00797 set_pos_overflow_float(T& to, Rounding_Dir dir) { 00798 switch (round_dir(dir)) { 00799 case ROUND_DOWN: 00800 { 00801 Float<T> f; 00802 f.u.binary.set_max(false); 00803 to = f.value(); 00804 return V_GT_SUP; 00805 } 00806 case ROUND_UP: // Fall through. 00807 case ROUND_IGNORE: 00808 to = HUGE_VAL; 00809 return V_LT_PLUS_INFINITY; 00810 default: 00811 PPL_UNREACHABLE; 00812 return V_LT_PLUS_INFINITY; 00813 } 00814 } 00815 00816 template <typename To_Policy, typename From_Policy, typename T> 00817 inline Result 00818 assign_float_mpz(T& to, const mpz_class& from, Rounding_Dir dir) { 00819 int sign = sgn(from); 00820 if (sign == 0) { 00821 to = 0; 00822 return V_EQ; 00823 } 00824 mpz_srcptr from_z = from.get_mpz_t(); 00825 size_t exponent = mpz_sizeinbase(from_z, 2) - 1; 00826 if (exponent > size_t(Float<T>::Binary::EXPONENT_MAX)) { 00827 if (sign < 0) 00828 return set_neg_overflow_float<To_Policy>(to, dir); 00829 else 00830 return set_pos_overflow_float<To_Policy>(to, dir); 00831 } 00832 unsigned long zeroes = mpn_scan1(from_z->_mp_d, 0); 00833 size_t meaningful_bits = exponent - zeroes; 00834 mpz_t mantissa; 00835 mpz_init(mantissa); 00836 if (exponent > Float<T>::Binary::MANTISSA_BITS) 00837 mpz_tdiv_q_2exp(mantissa, 00838 from_z, 00839 exponent - Float<T>::Binary::MANTISSA_BITS); 00840 else 00841 mpz_mul_2exp(mantissa, from_z, Float<T>::Binary::MANTISSA_BITS - exponent); 00842 Float<T> f; 00843 f.u.binary.build(sign < 0, mantissa, static_cast<long>(exponent)); 00844 mpz_clear(mantissa); 00845 to = f.value(); 00846 if (meaningful_bits > Float<T>::Binary::MANTISSA_BITS) { 00847 if (sign < 0) 00848 return round_lt_float<To_Policy>(to, dir); 00849 else 00850 return round_gt_float<To_Policy>(to, dir); 00851 } 00852 return V_EQ; 00853 } 00854 00855 template <typename To_Policy, typename From_Policy, typename T> 00856 inline Result 00857 assign_float_mpq(T& to, const mpq_class& from, Rounding_Dir dir) { 00858 const mpz_class& numer = from.get_num(); 00859 const mpz_class& denom = from.get_den(); 00860 if (denom == 1) 00861 return assign_float_mpz<To_Policy, From_Policy>(to, numer, dir); 00862 mpz_srcptr numer_z = numer.get_mpz_t(); 00863 mpz_srcptr denom_z = denom.get_mpz_t(); 00864 int sign = sgn(numer); 00865 long exponent = static_cast<long>(mpz_sizeinbase(numer_z, 2)) 00866 - static_cast<long>(mpz_sizeinbase(denom_z, 2)); 00867 if (exponent < Float<T>::Binary::EXPONENT_MIN_DENORM) { 00868 to = 0; 00869 inexact: 00870 if (sign < 0) 00871 return round_lt_float<To_Policy>(to, dir); 00872 else 00873 return round_gt_float<To_Policy>(to, dir); 00874 } 00875 if (exponent > Float<T>::Binary::EXPONENT_MAX + 1) { 00876 overflow: 00877 if (sign < 0) 00878 return set_neg_overflow_float<To_Policy>(to, dir); 00879 else 00880 return set_pos_overflow_float<To_Policy>(to, dir); 00881 } 00882 unsigned int needed_bits = Float<T>::Binary::MANTISSA_BITS + 1; 00883 if (exponent < Float<T>::Binary::EXPONENT_MIN) { 00884 long diff = Float<T>::Binary::EXPONENT_MIN - exponent; 00885 needed_bits -= static_cast<unsigned int>(diff); 00886 } 00887 mpz_t mantissa; 00888 mpz_init(mantissa); 00889 { 00890 long shift = static_cast<long>(needed_bits) - exponent; 00891 if (shift > 0) { 00892 mpz_mul_2exp(mantissa, numer_z, static_cast<unsigned long>(shift)); 00893 numer_z = mantissa; 00894 } 00895 else if (shift < 0) { 00896 shift = -shift; 00897 mpz_mul_2exp(mantissa, denom_z, static_cast<unsigned long>(shift)); 00898 denom_z = mantissa; 00899 } 00900 } 00901 mpz_t r; 00902 mpz_init(r); 00903 mpz_tdiv_qr(mantissa, r, numer_z, denom_z); 00904 size_t bits = mpz_sizeinbase(mantissa, 2); 00905 bool inexact = (mpz_sgn(r) != 0); 00906 mpz_clear(r); 00907 if (bits == needed_bits + 1) { 00908 inexact = (inexact || mpz_odd_p(mantissa)); 00909 mpz_tdiv_q_2exp(mantissa, mantissa, 1); 00910 } 00911 else 00912 --exponent; 00913 if (exponent > Float<T>::Binary::EXPONENT_MAX) { 00914 mpz_clear(mantissa); 00915 goto overflow; 00916 } 00917 else if (exponent < Float<T>::Binary::EXPONENT_MIN - 1) { 00918 // Denormalized. 00919 exponent = Float<T>::Binary::EXPONENT_MIN - 1; 00920 } 00921 Float<T> f; 00922 f.u.binary.build(sign < 0, mantissa, exponent); 00923 mpz_clear(mantissa); 00924 to = f.value(); 00925 if (inexact) 00926 goto inexact; 00927 return V_EQ; 00928 } 00929 00930 template <typename To_Policy, typename From1_Policy, typename From2_Policy, 00931 typename Type> 00932 inline Result 00933 add_mul_float(Type& to, const Type x, const Type y, Rounding_Dir dir) { 00934 if (To_Policy::check_inf_mul_zero 00935 && ((x == 0 && is_inf_float<From2_Policy>(y)) 00936 || 00937 (y == 0 && is_inf_float<From1_Policy>(x)))) { 00938 return assign_nan<To_Policy>(to, V_INF_MUL_ZERO); 00939 } 00940 // FIXME: missing check_inf_add_inf 00941 prepare_inexact<To_Policy>(dir); 00942 if (fpu_direct_rounding(dir)) 00943 to = multiply_add(x, y, to); 00944 else if (fpu_inverse_rounding(dir)) { 00945 to = multiply_add(-x, y, -to); 00946 limit_precision(to); 00947 to = -to; 00948 } 00949 else { 00950 fpu_rounding_control_word_type old 00951 = fpu_save_rounding_direction(round_fpu_dir(dir)); 00952 limit_precision(x); 00953 limit_precision(y); 00954 limit_precision(to); 00955 to = multiply_add(x, y, to); 00956 limit_precision(to); 00957 fpu_restore_rounding_direction(old); 00958 } 00959 if (To_Policy::fpu_check_nan_result && is_nan<To_Policy>(to)) 00960 return V_NAN; 00961 return result_relation<To_Policy>(dir); 00962 } 00963 00964 template <typename To_Policy, typename From1_Policy, typename From2_Policy, typename Type> 00965 inline Result 00966 sub_mul_float(Type& to, const Type x, const Type y, Rounding_Dir dir) { 00967 if (To_Policy::check_inf_mul_zero 00968 && ((x == 0 && is_inf_float<From2_Policy>(y)) 00969 || 00970 (y == 0 && is_inf_float<From1_Policy>(x)))) { 00971 return assign_nan<To_Policy>(to, V_INF_MUL_ZERO); 00972 } 00973 // FIXME: missing check_inf_add_inf 00974 prepare_inexact<To_Policy>(dir); 00975 if (fpu_direct_rounding(dir)) 00976 to = multiply_add(x, -y, to); 00977 else if (fpu_inverse_rounding(dir)) { 00978 to = multiply_add(x, y, -to); 00979 limit_precision(to); 00980 to = -to; 00981 } 00982 else { 00983 fpu_rounding_control_word_type old 00984 = fpu_save_rounding_direction(round_fpu_dir(dir)); 00985 limit_precision(x); 00986 limit_precision(y); 00987 limit_precision(to); 00988 to = multiply_add(x, -y, to); 00989 limit_precision(to); 00990 fpu_restore_rounding_direction(old); 00991 } 00992 if (To_Policy::fpu_check_nan_result && is_nan<To_Policy>(to)) 00993 return V_NAN; 00994 return result_relation<To_Policy>(dir); 00995 } 00996 00997 template <typename Policy, typename Type> 00998 inline Result 00999 output_float(std::ostream& os, const Type from, const Numeric_Format&, 01000 Rounding_Dir) { 01001 if (from == 0) 01002 os << "0"; 01003 else if (is_minf<Policy>(from)) 01004 os << "-inf"; 01005 else if (is_pinf<Policy>(from)) 01006 os << "+inf"; 01007 else if (is_nan<Policy>(from)) 01008 os << "nan"; 01009 else { 01010 std::streamsize old_precision = os.precision(10000); 01011 // FIXME: here correctness depends on the behavior of the standard 01012 // output operator which, in turn, may depend on the behavior 01013 // of printf(). The C99 standard, 7.19.16.1#13, does not give 01014 // enough guarantees. We could not find something similar 01015 // in the C++ standard, so there is a concrete danger here. 01016 os << from; 01017 os.precision(old_precision); 01018 } 01019 return V_EQ; 01020 } 01021 01022 #if PPL_SUPPORTED_FLOAT 01023 PPL_SPECIALIZE_ASSIGN(assign_float_float_exact, float, float) 01024 #if PPL_SUPPORTED_DOUBLE 01025 PPL_SPECIALIZE_ASSIGN(assign_float_float, float, double) 01026 PPL_SPECIALIZE_ASSIGN(assign_float_float_exact, double, float) 01027 #endif 01028 #if PPL_SUPPORTED_LONG_DOUBLE 01029 PPL_SPECIALIZE_ASSIGN(assign_float_float, float, long double) 01030 PPL_SPECIALIZE_ASSIGN(assign_float_float_exact, long double, float) 01031 #endif 01032 #endif 01033 01034 #if PPL_SUPPORTED_DOUBLE 01035 PPL_SPECIALIZE_ASSIGN(assign_float_float_exact, double, double) 01036 #if PPL_SUPPORTED_LONG_DOUBLE 01037 PPL_SPECIALIZE_ASSIGN(assign_float_float, double, long double) 01038 PPL_SPECIALIZE_ASSIGN(assign_float_float_exact, long double, double) 01039 #endif 01040 #endif 01041 01042 #if PPL_SUPPORTED_LONG_DOUBLE 01043 PPL_SPECIALIZE_ASSIGN(assign_float_float_exact, long double, long double) 01044 #endif 01045 01046 #if PPL_SUPPORTED_FLOAT 01047 PPL_SPECIALIZE_CLASSIFY(classify_float, float) 01048 PPL_SPECIALIZE_IS_NAN(is_nan_float, float) 01049 PPL_SPECIALIZE_IS_MINF(is_minf_float, float) 01050 PPL_SPECIALIZE_IS_PINF(is_pinf_float, float) 01051 PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_float, float) 01052 PPL_SPECIALIZE_ASSIGN(assign_float_int, float, char) 01053 PPL_SPECIALIZE_ASSIGN(assign_float_int, float, signed char) 01054 PPL_SPECIALIZE_ASSIGN(assign_float_int, float, signed short) 01055 PPL_SPECIALIZE_ASSIGN(assign_float_int, float, signed int) 01056 PPL_SPECIALIZE_ASSIGN(assign_float_int, float, signed long) 01057 PPL_SPECIALIZE_ASSIGN(assign_float_int, float, signed long long) 01058 PPL_SPECIALIZE_ASSIGN(assign_float_int, float, unsigned char) 01059 PPL_SPECIALIZE_ASSIGN(assign_float_int, float, unsigned short) 01060 PPL_SPECIALIZE_ASSIGN(assign_float_int, float, unsigned int) 01061 PPL_SPECIALIZE_ASSIGN(assign_float_int, float, unsigned long) 01062 PPL_SPECIALIZE_ASSIGN(assign_float_int, float, unsigned long long) 01063 PPL_SPECIALIZE_ASSIGN(assign_float_mpz, float, mpz_class) 01064 PPL_SPECIALIZE_ASSIGN(assign_float_mpq, float, mpq_class) 01065 PPL_SPECIALIZE_COPY(copy_generic, float) 01066 PPL_SPECIALIZE_IS_INT(is_int_float, float) 01067 PPL_SPECIALIZE_FLOOR(floor_float, float, float) 01068 PPL_SPECIALIZE_CEIL(ceil_float, float, float) 01069 PPL_SPECIALIZE_TRUNC(trunc_float, float, float) 01070 PPL_SPECIALIZE_NEG(neg_float, float, float) 01071 PPL_SPECIALIZE_ABS(abs_float, float, float) 01072 PPL_SPECIALIZE_ADD(add_float, float, float, float) 01073 PPL_SPECIALIZE_SUB(sub_float, float, float, float) 01074 PPL_SPECIALIZE_MUL(mul_float, float, float, float) 01075 PPL_SPECIALIZE_DIV(div_float, float, float, float) 01076 PPL_SPECIALIZE_REM(rem_float, float, float, float) 01077 PPL_SPECIALIZE_ADD_2EXP(add_2exp_float, float, float) 01078 PPL_SPECIALIZE_SUB_2EXP(sub_2exp_float, float, float) 01079 PPL_SPECIALIZE_MUL_2EXP(mul_2exp_float, float, float) 01080 PPL_SPECIALIZE_DIV_2EXP(div_2exp_float, float, float) 01081 PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_float, float, float) 01082 PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_float, float, float) 01083 PPL_SPECIALIZE_SQRT(sqrt_float, float, float) 01084 PPL_SPECIALIZE_GCD(gcd_exact, float, float, float) 01085 PPL_SPECIALIZE_GCDEXT(gcdext_exact, float, float, float, float, float) 01086 PPL_SPECIALIZE_LCM(lcm_gcd_exact, float, float, float) 01087 PPL_SPECIALIZE_SGN(sgn_float, float) 01088 PPL_SPECIALIZE_CMP(cmp_float, float, float) 01089 PPL_SPECIALIZE_ADD_MUL(add_mul_float, float, float, float) 01090 PPL_SPECIALIZE_SUB_MUL(sub_mul_float, float, float, float) 01091 PPL_SPECIALIZE_INPUT(input_generic, float) 01092 PPL_SPECIALIZE_OUTPUT(output_float, float) 01093 #endif 01094 01095 #if PPL_SUPPORTED_DOUBLE 01096 PPL_SPECIALIZE_CLASSIFY(classify_float, double) 01097 PPL_SPECIALIZE_IS_NAN(is_nan_float, double) 01098 PPL_SPECIALIZE_IS_MINF(is_minf_float, double) 01099 PPL_SPECIALIZE_IS_PINF(is_pinf_float, double) 01100 PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_float, double) 01101 PPL_SPECIALIZE_ASSIGN(assign_float_int, double, char) 01102 PPL_SPECIALIZE_ASSIGN(assign_float_int, double, signed char) 01103 PPL_SPECIALIZE_ASSIGN(assign_float_int, double, signed short) 01104 PPL_SPECIALIZE_ASSIGN(assign_float_int, double, signed int) 01105 PPL_SPECIALIZE_ASSIGN(assign_float_int, double, signed long) 01106 PPL_SPECIALIZE_ASSIGN(assign_float_int, double, signed long long) 01107 PPL_SPECIALIZE_ASSIGN(assign_float_int, double, unsigned char) 01108 PPL_SPECIALIZE_ASSIGN(assign_float_int, double, unsigned short) 01109 PPL_SPECIALIZE_ASSIGN(assign_float_int, double, unsigned int) 01110 PPL_SPECIALIZE_ASSIGN(assign_float_int, double, unsigned long) 01111 PPL_SPECIALIZE_ASSIGN(assign_float_int, double, unsigned long long) 01112 PPL_SPECIALIZE_ASSIGN(assign_float_mpz, double, mpz_class) 01113 PPL_SPECIALIZE_ASSIGN(assign_float_mpq, double, mpq_class) 01114 PPL_SPECIALIZE_COPY(copy_generic, double) 01115 PPL_SPECIALIZE_IS_INT(is_int_float, double) 01116 PPL_SPECIALIZE_FLOOR(floor_float, double, double) 01117 PPL_SPECIALIZE_CEIL(ceil_float, double, double) 01118 PPL_SPECIALIZE_TRUNC(trunc_float, double, double) 01119 PPL_SPECIALIZE_NEG(neg_float, double, double) 01120 PPL_SPECIALIZE_ABS(abs_float, double, double) 01121 PPL_SPECIALIZE_ADD(add_float, double, double, double) 01122 PPL_SPECIALIZE_SUB(sub_float, double, double, double) 01123 PPL_SPECIALIZE_MUL(mul_float, double, double, double) 01124 PPL_SPECIALIZE_DIV(div_float, double, double, double) 01125 PPL_SPECIALIZE_REM(rem_float, double, double, double) 01126 PPL_SPECIALIZE_ADD_2EXP(add_2exp_float, double, double) 01127 PPL_SPECIALIZE_SUB_2EXP(sub_2exp_float, double, double) 01128 PPL_SPECIALIZE_MUL_2EXP(mul_2exp_float, double, double) 01129 PPL_SPECIALIZE_DIV_2EXP(div_2exp_float, double, double) 01130 PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_float, double, double) 01131 PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_float, double, double) 01132 PPL_SPECIALIZE_SQRT(sqrt_float, double, double) 01133 PPL_SPECIALIZE_GCD(gcd_exact, double, double, double) 01134 PPL_SPECIALIZE_GCDEXT(gcdext_exact, double, double, double, double, double) 01135 PPL_SPECIALIZE_LCM(lcm_gcd_exact, double, double, double) 01136 PPL_SPECIALIZE_SGN(sgn_float, double) 01137 PPL_SPECIALIZE_CMP(cmp_float, double, double) 01138 PPL_SPECIALIZE_ADD_MUL(add_mul_float, double, double, double) 01139 PPL_SPECIALIZE_SUB_MUL(sub_mul_float, double, double, double) 01140 PPL_SPECIALIZE_INPUT(input_generic, double) 01141 PPL_SPECIALIZE_OUTPUT(output_float, double) 01142 #endif 01143 01144 #if PPL_SUPPORTED_LONG_DOUBLE 01145 PPL_SPECIALIZE_CLASSIFY(classify_float, long double) 01146 PPL_SPECIALIZE_IS_NAN(is_nan_float, long double) 01147 PPL_SPECIALIZE_IS_MINF(is_minf_float, long double) 01148 PPL_SPECIALIZE_IS_PINF(is_pinf_float, long double) 01149 PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_float, long double) 01150 PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, char) 01151 PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, signed char) 01152 PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, signed short) 01153 PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, signed int) 01154 PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, signed long) 01155 PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, signed long long) 01156 PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, unsigned char) 01157 PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, unsigned short) 01158 PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, unsigned int) 01159 PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, unsigned long) 01160 PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, unsigned long long) 01161 PPL_SPECIALIZE_ASSIGN(assign_float_mpz, long double, mpz_class) 01162 PPL_SPECIALIZE_ASSIGN(assign_float_mpq, long double, mpq_class) 01163 PPL_SPECIALIZE_COPY(copy_generic, long double) 01164 PPL_SPECIALIZE_IS_INT(is_int_float, long double) 01165 PPL_SPECIALIZE_FLOOR(floor_float, long double, long double) 01166 PPL_SPECIALIZE_CEIL(ceil_float, long double, long double) 01167 PPL_SPECIALIZE_TRUNC(trunc_float, long double, long double) 01168 PPL_SPECIALIZE_NEG(neg_float, long double, long double) 01169 PPL_SPECIALIZE_ABS(abs_float, long double, long double) 01170 PPL_SPECIALIZE_ADD(add_float, long double, long double, long double) 01171 PPL_SPECIALIZE_SUB(sub_float, long double, long double, long double) 01172 PPL_SPECIALIZE_MUL(mul_float, long double, long double, long double) 01173 PPL_SPECIALIZE_DIV(div_float, long double, long double, long double) 01174 PPL_SPECIALIZE_REM(rem_float, long double, long double, long double) 01175 PPL_SPECIALIZE_ADD_2EXP(add_2exp_float, long double, long double) 01176 PPL_SPECIALIZE_SUB_2EXP(sub_2exp_float, long double, long double) 01177 PPL_SPECIALIZE_MUL_2EXP(mul_2exp_float, long double, long double) 01178 PPL_SPECIALIZE_DIV_2EXP(div_2exp_float, long double, long double) 01179 PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_float, long double, long double) 01180 PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_float, long double, long double) 01181 PPL_SPECIALIZE_SQRT(sqrt_float, long double, long double) 01182 PPL_SPECIALIZE_GCD(gcd_exact, long double, long double, long double) 01183 PPL_SPECIALIZE_GCDEXT(gcdext_exact, long double, long double, long double, 01184 long double, long double) 01185 PPL_SPECIALIZE_LCM(lcm_gcd_exact, long double, long double, long double) 01186 PPL_SPECIALIZE_SGN(sgn_float, long double) 01187 PPL_SPECIALIZE_CMP(cmp_float, long double, long double) 01188 PPL_SPECIALIZE_ADD_MUL(add_mul_float, long double, long double, long double) 01189 PPL_SPECIALIZE_SUB_MUL(sub_mul_float, long double, long double, long double) 01190 PPL_SPECIALIZE_INPUT(input_generic, long double) 01191 PPL_SPECIALIZE_OUTPUT(output_float, long double) 01192 #endif 01193 01194 } // namespace Checked 01195 01196 } // namespace Parma_Polyhedra_Library 01197 01198 #endif // !defined(PPL_checked_int_inlines_hh)