|
PPL
0.12.1
|
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)