PPL  0.12.1
Float.defs.hh
Go to the documentation of this file.
00001 /* IEC 559 floating point format related functions.
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_Float_defs_hh
00025 #define PPL_Float_defs_hh 1
00026 
00027 #include "globals.types.hh"
00028 #include "meta_programming.hh"
00029 #include "compiler.hh"
00030 #include "assert.hh"
00031 #include "Concrete_Expression.types.hh"
00032 #include "Variable.types.hh"
00033 #include "Linear_Form.types.hh"
00034 #include <set>
00035 #include <cmath>
00036 #include <map>
00037 #include <gmp.h>
00038 
00039 #ifdef NAN
00040 #define PPL_NAN NAN
00041 #else
00042 #define PPL_NAN (HUGE_VAL - HUGE_VAL)
00043 #endif
00044 
00045 namespace Parma_Polyhedra_Library {
00046 
00047 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
00048 
00049 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
00050 struct float_ieee754_half {
00051   uint16_t word;
00052   static const uint16_t SGN_MASK = 0x8000U;
00053   static const uint16_t EXP_MASK = 0xfc00U;
00054   static const uint16_t POS_INF = 0xfc00U;
00055   static const uint16_t NEG_INF = 0x7c00U;
00056   static const uint16_t POS_ZERO = 0x0000U;
00057   static const uint16_t NEG_ZERO = 0x8000U;
00058   static const unsigned int BASE = 2;
00059   static const unsigned int EXPONENT_BITS = 5;
00060   static const unsigned int MANTISSA_BITS = 10;
00061   static const int EXPONENT_MAX = (1 << (EXPONENT_BITS - 1)) - 1;
00062   static const int EXPONENT_BIAS = EXPONENT_MAX;
00063   static const int EXPONENT_MIN = -EXPONENT_MAX + 1;
00064   static const int EXPONENT_MIN_DENORM = EXPONENT_MIN
00065                                         - static_cast<int>(MANTISSA_BITS);
00066   static const Floating_Point_Format floating_point_format = IEEE754_HALF;
00067   int inf_sign() const;
00068   bool is_nan() const;
00069   int zero_sign() const;
00070   bool sign_bit() const;
00071   void negate();
00072   void dec();
00073   void inc();
00074   void set_max(bool negative);
00075   void build(bool negative, mpz_t mantissa, int exponent);
00076 
00077 };
00078 
00079 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
00080 
00081 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
00082 struct float_ieee754_single {
00083   uint32_t word;
00084   static const uint32_t SGN_MASK = 0x80000000U;
00085   static const uint32_t EXP_MASK = 0x7f800000U;
00086   static const uint32_t POS_INF = 0x7f800000U;
00087   static const uint32_t NEG_INF = 0xff800000U;
00088   static const uint32_t POS_ZERO = 0x00000000U;
00089   static const uint32_t NEG_ZERO = 0x80000000U;
00090   static const unsigned int BASE = 2;
00091   static const unsigned int EXPONENT_BITS = 8;
00092   static const unsigned int MANTISSA_BITS = 23;
00093   static const int EXPONENT_MAX = (1 << (EXPONENT_BITS - 1)) - 1;
00094   static const int EXPONENT_BIAS = EXPONENT_MAX;
00095   static const int EXPONENT_MIN = -EXPONENT_MAX + 1;
00096   static const int EXPONENT_MIN_DENORM = EXPONENT_MIN
00097                                         - static_cast<int>(MANTISSA_BITS);
00098   static const Floating_Point_Format floating_point_format = IEEE754_SINGLE;
00099   int inf_sign() const;
00100   bool is_nan() const;
00101   int zero_sign() const;
00102   bool sign_bit() const;
00103   void negate();
00104   void dec();
00105   void inc();
00106   void set_max(bool negative);
00107   void build(bool negative, mpz_t mantissa, int exponent);
00108 };
00109 
00110 #ifdef WORDS_BIGENDIAN
00111 #ifndef PPL_WORDS_BIGENDIAN
00112 #define PPL_WORDS_BIGENDIAN
00113 #endif
00114 #endif
00115 
00116 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
00117 
00118 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
00119 struct float_ieee754_double {
00120 #ifdef PPL_WORDS_BIGENDIAN
00121   uint32_t msp;
00122   uint32_t lsp;
00123 #else
00124   uint32_t lsp;
00125   uint32_t msp;
00126 #endif
00127   static const uint32_t MSP_SGN_MASK = 0x80000000U;
00128   static const uint32_t MSP_POS_INF = 0x7ff00000U;
00129   static const uint32_t MSP_NEG_INF = 0xfff00000U;
00130   static const uint32_t MSP_POS_ZERO = 0x00000000U;
00131   static const uint32_t MSP_NEG_ZERO = 0x80000000U;
00132   static const uint32_t LSP_INF = 0;
00133   static const uint32_t LSP_ZERO = 0;
00134   static const uint32_t LSP_MAX = 0xffffffffU;
00135   static const unsigned int BASE = 2;
00136   static const unsigned int EXPONENT_BITS = 11;
00137   static const unsigned int MANTISSA_BITS = 52;
00138   static const int EXPONENT_MAX = (1 << (EXPONENT_BITS - 1)) - 1;
00139   static const int EXPONENT_BIAS = EXPONENT_MAX;
00140   static const int EXPONENT_MIN = -EXPONENT_MAX + 1;
00141   static const int EXPONENT_MIN_DENORM = EXPONENT_MIN
00142                                         - static_cast<int>(MANTISSA_BITS);
00143   static const Floating_Point_Format floating_point_format = IEEE754_DOUBLE;
00144   int inf_sign() const;
00145   bool is_nan() const;
00146   int zero_sign() const;
00147   bool sign_bit() const;
00148   void negate();
00149   void dec();
00150   void inc();
00151   void set_max(bool negative);
00152   void build(bool negative, mpz_t mantissa, int exponent);
00153 };
00154 
00155 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
00156 
00157 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
00158 struct float_ibm_single {
00159   uint32_t word;
00160   static const uint32_t SGN_MASK = 0x80000000U;
00161   static const uint32_t EXP_MASK = 0x7f000000U;
00162   static const uint32_t POS_INF = 0x7f000000U;
00163   static const uint32_t NEG_INF = 0xff000000U;
00164   static const uint32_t POS_ZERO = 0x00000000U;
00165   static const uint32_t NEG_ZERO = 0x80000000U;
00166   static const unsigned int BASE = 16;
00167   static const unsigned int EXPONENT_BITS = 7;
00168   static const unsigned int MANTISSA_BITS = 24;
00169   static const int EXPONENT_BIAS = 64;
00170   static const int EXPONENT_MAX = (1 << (EXPONENT_BITS - 1)) - 1;
00171   static const int EXPONENT_MIN = -EXPONENT_MAX + 1;
00172   static const int EXPONENT_MIN_DENORM = EXPONENT_MIN
00173                                         - static_cast<int>(MANTISSA_BITS);
00174   static const Floating_Point_Format floating_point_format = IBM_SINGLE;
00175   int inf_sign() const;
00176   bool is_nan() const;
00177   int zero_sign() const;
00178   bool sign_bit() const;
00179   void negate();
00180   void dec();
00181   void inc();
00182   void set_max(bool negative);
00183   void build(bool negative, mpz_t mantissa, int exponent);
00184 };
00185 
00186 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
00187 
00188 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
00189 struct float_ibm_double {
00190   static const unsigned int BASE = 16;
00191   static const unsigned int EXPONENT_BITS = 7;
00192   static const unsigned int MANTISSA_BITS = 56;
00193   static const int EXPONENT_BIAS = 64;
00194 };
00195 
00196 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
00197 
00198 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
00199 struct float_intel_double_extended {
00200 #ifdef PPL_WORDS_BIGENDIAN
00201   uint32_t msp;
00202   uint64_t lsp;
00203 #else
00204   uint64_t lsp;
00205   uint32_t msp;
00206 #endif
00207   static const uint32_t MSP_SGN_MASK = 0x00008000U;
00208   static const uint32_t MSP_POS_INF = 0x00007fffU;
00209   static const uint32_t MSP_NEG_INF = 0x0000ffffU;
00210   static const uint32_t MSP_POS_ZERO = 0x00000000U;
00211   static const uint32_t MSP_NEG_ZERO = 0x00008000U;
00212   static const uint64_t LSP_INF = static_cast<uint64_t>(0x8000000000000000ULL);
00213   static const uint64_t LSP_ZERO = 0;
00214   static const uint64_t LSP_DMAX = static_cast<uint64_t>(0x7fffffffffffffffULL);
00215   static const uint64_t LSP_NMAX = static_cast<uint64_t>(0xffffffffffffffffULL);
00216   static const unsigned int BASE = 2;
00217   static const unsigned int EXPONENT_BITS = 15;
00218   static const unsigned int MANTISSA_BITS = 63;
00219   static const int EXPONENT_MAX = (1 << (EXPONENT_BITS - 1)) - 1;
00220   static const int EXPONENT_BIAS = EXPONENT_MAX;
00221   static const int EXPONENT_MIN = -EXPONENT_MAX + 1;
00222   static const int EXPONENT_MIN_DENORM = EXPONENT_MIN
00223                                         - static_cast<int>(MANTISSA_BITS);
00224   static const Floating_Point_Format floating_point_format =
00225                                      INTEL_DOUBLE_EXTENDED;
00226   int inf_sign() const;
00227   bool is_nan() const;
00228   int zero_sign() const;
00229   bool sign_bit() const;
00230   void negate();
00231   void dec();
00232   void inc();
00233   void set_max(bool negative);
00234   void build(bool negative, mpz_t mantissa, int exponent);
00235 };
00236 
00237 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
00238 
00239 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
00240 struct float_ieee754_quad {
00241 #ifdef PPL_WORDS_BIGENDIAN
00242   uint64_t msp;
00243   uint64_t lsp;
00244 #else
00245   uint64_t lsp;
00246   uint64_t msp;
00247 #endif
00248   static const uint64_t MSP_SGN_MASK = static_cast<uint64_t>(0x8000000000000000ULL);
00249   static const uint64_t MSP_POS_INF = static_cast<uint64_t>(0x7fff000000000000ULL);
00250   static const uint64_t MSP_NEG_INF = static_cast<uint64_t>(0xffff000000000000ULL);
00251   static const uint64_t MSP_POS_ZERO = static_cast<uint64_t>(0x0000000000000000ULL);
00252   static const uint64_t MSP_NEG_ZERO = static_cast<uint64_t>(0x8000000000000000ULL);
00253   static const uint64_t LSP_INF = 0;
00254   static const uint64_t LSP_ZERO = 0;
00255   static const uint64_t LSP_MAX = static_cast<uint64_t>(0xffffffffffffffffULL);
00256   static const unsigned int BASE = 2;
00257   static const unsigned int EXPONENT_BITS = 15;
00258   static const unsigned int MANTISSA_BITS = 112;
00259   static const int EXPONENT_MAX = (1 << (EXPONENT_BITS - 1)) - 1;
00260   static const int EXPONENT_BIAS = EXPONENT_MAX;
00261   static const int EXPONENT_MIN = -EXPONENT_MAX + 1;
00262   static const int EXPONENT_MIN_DENORM = EXPONENT_MIN
00263                                         - static_cast<int>(MANTISSA_BITS);
00264   int inf_sign() const;
00265   bool is_nan() const;
00266   int zero_sign() const;
00267   bool sign_bit() const;
00268   void negate();
00269   void dec();
00270   void inc();
00271   void set_max(bool negative);
00272   void build(bool negative, mpz_t mantissa, int exponent);
00273 };
00274 
00275 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
00276 
00277 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
00278 template <typename T>
00279 class Float : public False { };
00280 
00281 #if PPL_SUPPORTED_FLOAT
00282 template <>
00283 class Float<float> : public True {
00284 public:
00285 #if PPL_CXX_FLOAT_BINARY_FORMAT == PPL_FLOAT_IEEE754_HALF
00286   typedef float_ieee754_half Binary;
00287 #elif PPL_CXX_FLOAT_BINARY_FORMAT == PPL_FLOAT_IEEE754_SINGLE
00288   typedef float_ieee754_single Binary;
00289 #elif PPL_CXX_FLOAT_BINARY_FORMAT == PPL_FLOAT_IEEE754_DOUBLE
00290   typedef float_ieee754_double Binary;
00291 #elif PPL_CXX_FLOAT_BINARY_FORMAT == PPL_FLOAT_IBM_SINGLE
00292   typedef float_ibm_single Binary;
00293 #elif PPL_CXX_FLOAT_BINARY_FORMAT == PPL_FLOAT_IEEE754_QUAD
00294   typedef float_ieee754_quad Binary;
00295 #elif PPL_CXX_FLOAT_BINARY_FORMAT == PPL_FLOAT_INTEL_DOUBLE_EXTENDED
00296   typedef float_intel_double_extended Binary;
00297 #else
00298 #error "Invalid value for PPL_CXX_FLOAT_BINARY_FORMAT"
00299 #endif
00300   union {
00301     float number;
00302     Binary binary;
00303   } u;
00304   Float();
00305   Float(float v);
00306   float value();
00307 };
00308 #endif
00309 
00310 #if PPL_SUPPORTED_DOUBLE
00311 template <>
00312 class Float<double> : public True {
00313 public:
00314 #if PPL_CXX_DOUBLE_BINARY_FORMAT == PPL_FLOAT_IEEE754_HALF
00315   typedef float_ieee754_half Binary;
00316 #elif PPL_CXX_DOUBLE_BINARY_FORMAT == PPL_FLOAT_IEEE754_SINGLE
00317   typedef float_ieee754_single Binary;
00318 #elif PPL_CXX_DOUBLE_BINARY_FORMAT == PPL_FLOAT_IEEE754_DOUBLE
00319   typedef float_ieee754_double Binary;
00320 #elif PPL_CXX_DOUBLE_BINARY_FORMAT == PPL_FLOAT_IBM_SINGLE
00321   typedef float_ibm_single Binary;
00322 #elif PPL_CXX_DOUBLE_BINARY_FORMAT == PPL_FLOAT_IEEE754_QUAD
00323   typedef float_ieee754_quad Binary;
00324 #elif PPL_CXX_DOUBLE_BINARY_FORMAT == PPL_FLOAT_INTEL_DOUBLE_EXTENDED
00325   typedef float_intel_double_extended Binary;
00326 #else
00327 #error "Invalid value for PPL_CXX_DOUBLE_BINARY_FORMAT"
00328 #endif
00329   union {
00330     double number;
00331     Binary binary;
00332   } u;
00333   Float();
00334   Float(double v);
00335   double value();
00336 };
00337 #endif
00338 
00339 #if PPL_SUPPORTED_LONG_DOUBLE
00340 template <>
00341 class Float<long double> : public True {
00342 public:
00343 #if PPL_CXX_LONG_DOUBLE_BINARY_FORMAT == PPL_FLOAT_IEEE754_HALF
00344   typedef float_ieee754_half Binary;
00345 #elif PPL_CXX_LONG_DOUBLE_BINARY_FORMAT == PPL_FLOAT_IEEE754_SINGLE
00346   typedef float_ieee754_single Binary;
00347 #elif PPL_CXX_LONG_DOUBLE_BINARY_FORMAT == PPL_FLOAT_IEEE754_DOUBLE
00348   typedef float_ieee754_double Binary;
00349 #elif PPL_CXX_LONG_DOUBLE_BINARY_FORMAT == PPL_FLOAT_IBM_SINGLE
00350   typedef float_ibm_single Binary;
00351 #elif PPL_CXX_LONG_DOUBLE_BINARY_FORMAT == PPL_FLOAT_IEEE754_QUAD
00352   typedef float_ieee754_quad Binary;
00353 #elif PPL_CXX_LONG_DOUBLE_BINARY_FORMAT == PPL_FLOAT_INTEL_DOUBLE_EXTENDED
00354   typedef float_intel_double_extended Binary;
00355 #else
00356 #error "Invalid value for PPL_CXX_LONG_DOUBLE_BINARY_FORMAT"
00357 #endif
00358   union {
00359     long double number;
00360     Binary binary;
00361   } u;
00362   Float();
00363   Float(long double v);
00364   long double value();
00365 };
00366 #endif
00367 
00368 // FIXME: is this the right place for this function?
00369 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
00370 
00376 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
00377 unsigned int msb_position(unsigned long long v);
00378 
00392 template <typename Target, typename FP_Interval_Type>
00393 class FP_Oracle {
00394 public:
00395   /*
00396     FIXME: the const qualifiers on expressions may raise CLANG
00397     compatibility issues. It may be necessary to omit them.
00398   */
00399 
00408   virtual bool get_interval(dimension_type dim, FP_Interval_Type& result) const
00409     = 0;
00410 
00419   virtual bool get_fp_constant_value(
00420                const Floating_Point_Constant<Target>& expr,
00421                      FP_Interval_Type& result) const = 0;
00422 
00431   virtual bool get_integer_expr_value(const Concrete_Expression<Target>& expr,
00432                                       FP_Interval_Type& result) const = 0;
00433 
00444   virtual bool get_associated_dimensions(
00445           const Approximable_Reference<Target>& expr,
00446           std::set<dimension_type>& result) const = 0;
00447 
00448 };
00449 
00450 /* FIXME: some of the following  documentation should probably be
00451    under PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS */
00452 
00457 bool is_less_precise_than(Floating_Point_Format f1, Floating_Point_Format f2);
00458 
00475 template <typename FP_Interval_Type>
00476 const FP_Interval_Type&
00477 compute_absolute_error(Floating_Point_Format analyzed_format);
00478 
00483 template <typename FP_Interval_Type>
00484 void
00485 discard_occurrences(std::map<dimension_type,
00486                              Linear_Form<FP_Interval_Type> >& lf_store,
00487                     Variable var);
00488 
00493 template <typename FP_Interval_Type>
00494 void
00495 affine_form_image(std::map<dimension_type,
00496                            Linear_Form<FP_Interval_Type> >& lf_store,
00497                   Variable var,
00498                   const Linear_Form<FP_Interval_Type>& lf);
00499 
00504 template <typename FP_Interval_Type>
00505 void
00506 upper_bound_assign(std::map<dimension_type,
00507                             Linear_Form<FP_Interval_Type> >& ls1,
00508                    const std::map<dimension_type,
00509                                   Linear_Form<FP_Interval_Type> >& ls2);
00510 
00511 } // namespace Parma_Polyhedra_Library
00512 
00513 #include "Float.inlines.hh"
00514 #include "Float.templates.hh"
00515 
00516 #endif // !defined(PPL_Float_defs_hh)