PPL  0.12.1
checked_float.inlines.hh
Go to the documentation of this file.
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)