|
PPL
0.12.1
|
00001 /* IEC 559 floating point format related functions: 00002 non-inline template functions. 00003 Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it> 00004 Copyright (C) 2010-2012 BUGSENG srl (http://bugseng.com) 00005 00006 This file is part of the Parma Polyhedra Library (PPL). 00007 00008 The PPL is free software; you can redistribute it and/or modify it 00009 under the terms of the GNU General Public License as published by the 00010 Free Software Foundation; either version 3 of the License, or (at your 00011 option) any later version. 00012 00013 The PPL is distributed in the hope that it will be useful, but WITHOUT 00014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00015 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 00016 for more details. 00017 00018 You should have received a copy of the GNU General Public License 00019 along with this program; if not, write to the Free Software Foundation, 00020 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA. 00021 00022 For the most up-to-date information see the Parma Polyhedra Library 00023 site: http://bugseng.com/products/ppl/ . */ 00024 00025 #ifndef PPL_Float_templates_hh 00026 #define PPL_Float_templates_hh 1 00027 00028 #include "Variable.defs.hh" 00029 #include "Linear_Form.defs.hh" 00030 #include <cmath> 00031 00032 namespace Parma_Polyhedra_Library { 00033 00034 template <typename FP_Interval_Type> 00035 const FP_Interval_Type& compute_absolute_error( 00036 const Floating_Point_Format analyzed_format) { 00037 typedef typename FP_Interval_Type::boundary_type analyzer_format; 00038 00039 // FIXME: check if initializing caches with EMPTY is better. 00040 static const FP_Interval_Type ZERO_INTERVAL = FP_Interval_Type(0); 00041 // Cached results for each different analyzed format. 00042 static FP_Interval_Type ieee754_half_result = ZERO_INTERVAL; 00043 static FP_Interval_Type ieee754_single_result = ZERO_INTERVAL; 00044 static FP_Interval_Type ieee754_double_result = ZERO_INTERVAL; 00045 static FP_Interval_Type ibm_single_result = ZERO_INTERVAL; 00046 static FP_Interval_Type ieee754_quad_result = ZERO_INTERVAL; 00047 static FP_Interval_Type intel_double_extended_result = ZERO_INTERVAL; 00048 00049 FP_Interval_Type* to_compute = NULL; 00050 // Get the necessary information on the analyzed's format. 00051 unsigned int f_base; 00052 int f_exponent_bias; 00053 unsigned int f_mantissa_bits; 00054 switch (analyzed_format) { 00055 case IEEE754_HALF: 00056 if (ieee754_half_result != ZERO_INTERVAL) 00057 return ieee754_half_result; 00058 00059 to_compute = &ieee754_half_result; 00060 f_base = float_ieee754_half::BASE; 00061 f_exponent_bias = float_ieee754_half::EXPONENT_BIAS; 00062 f_mantissa_bits = float_ieee754_half::MANTISSA_BITS; 00063 break; 00064 case IEEE754_SINGLE: 00065 if (ieee754_single_result != ZERO_INTERVAL) 00066 return ieee754_single_result; 00067 00068 to_compute = &ieee754_single_result; 00069 f_base = float_ieee754_single::BASE; 00070 f_exponent_bias = float_ieee754_single::EXPONENT_BIAS; 00071 f_mantissa_bits = float_ieee754_single::MANTISSA_BITS; 00072 break; 00073 case IEEE754_DOUBLE: 00074 if (ieee754_double_result != ZERO_INTERVAL) 00075 return ieee754_double_result; 00076 00077 to_compute = &ieee754_double_result; 00078 f_base = float_ieee754_double::BASE; 00079 f_exponent_bias = float_ieee754_double::EXPONENT_BIAS; 00080 f_mantissa_bits = float_ieee754_double::MANTISSA_BITS; 00081 break; 00082 case IBM_SINGLE: 00083 if (ibm_single_result != ZERO_INTERVAL) 00084 return ibm_single_result; 00085 00086 to_compute = &ibm_single_result; 00087 f_base = float_ibm_single::BASE; 00088 f_exponent_bias = float_ibm_single::EXPONENT_BIAS; 00089 f_mantissa_bits = float_ibm_single::MANTISSA_BITS; 00090 break; 00091 case IEEE754_QUAD: 00092 if (ieee754_quad_result != ZERO_INTERVAL) 00093 return ieee754_quad_result; 00094 00095 to_compute = &ieee754_quad_result; 00096 f_base = float_ieee754_quad::BASE; 00097 f_exponent_bias = float_ieee754_quad::EXPONENT_BIAS; 00098 f_mantissa_bits = float_ieee754_quad::MANTISSA_BITS; 00099 break; 00100 case INTEL_DOUBLE_EXTENDED: 00101 if (intel_double_extended_result != ZERO_INTERVAL) 00102 return intel_double_extended_result; 00103 00104 to_compute = &intel_double_extended_result; 00105 f_base = float_intel_double_extended::BASE; 00106 f_exponent_bias = float_intel_double_extended::EXPONENT_BIAS; 00107 f_mantissa_bits = float_intel_double_extended::MANTISSA_BITS; 00108 break; 00109 default: 00110 PPL_UNREACHABLE; 00111 break; 00112 } 00113 00114 PPL_ASSERT(to_compute != NULL); 00115 00116 // We assume that f_base is a power of 2. 00117 analyzer_format omega; 00118 int power = static_cast<int>(msb_position(f_base)) 00119 * ((1 - f_exponent_bias) - static_cast<int>(f_mantissa_bits)); 00120 omega = std::max(static_cast<analyzer_format>(ldexp(1.0, power)), 00121 std::numeric_limits<analyzer_format>::denorm_min()); 00122 00123 to_compute->build(i_constraint(GREATER_OR_EQUAL, -omega), 00124 i_constraint(LESS_OR_EQUAL, omega)); 00125 return *to_compute; 00126 } 00127 00128 template <typename FP_Interval_Type> 00129 void discard_occurrences(std::map<dimension_type, 00130 Linear_Form<FP_Interval_Type> >& lf_store, 00131 Variable var) { 00132 typedef typename FP_Interval_Type::boundary_type analyzer_format; 00133 typedef Linear_Form<FP_Interval_Type> FP_Linear_Form; 00134 typedef Box<FP_Interval_Type> FP_Interval_Abstract_Store; 00135 typedef std::map<dimension_type, FP_Linear_Form> FP_Linear_Form_Abstract_Store; 00136 00137 typename FP_Linear_Form_Abstract_Store::iterator i = lf_store.begin(); 00138 typename FP_Linear_Form_Abstract_Store::iterator ls_end = lf_store.end(); 00139 while (i != ls_end) { 00140 if((i->second).coefficient(var) != 0) 00141 lf_store.erase(i++); 00142 else 00143 ++i; 00144 } 00145 } 00146 00147 /* FIXME: improve efficiency by adding the list of potentially conflicting 00148 variables as an argument. */ 00149 template <typename FP_Interval_Type> 00150 void upper_bound_assign(std::map<dimension_type, 00151 Linear_Form<FP_Interval_Type> >& ls1, 00152 const std::map<dimension_type, 00153 Linear_Form<FP_Interval_Type> >& ls2) { 00154 typedef typename FP_Interval_Type::boundary_type analyzer_format; 00155 typedef Linear_Form<FP_Interval_Type> FP_Linear_Form; 00156 typedef Box<FP_Interval_Type> FP_Interval_Abstract_Store; 00157 typedef std::map<dimension_type, FP_Linear_Form> FP_Linear_Form_Abstract_Store; 00158 00159 typename FP_Linear_Form_Abstract_Store::iterator i1 = ls1.begin(); 00160 typename FP_Linear_Form_Abstract_Store::iterator i1_end = ls1.end(); 00161 typename FP_Linear_Form_Abstract_Store::const_iterator i2_end = ls2.end(); 00162 while (i1 != i1_end) { 00163 typename FP_Linear_Form_Abstract_Store::const_iterator 00164 i2 = ls2.find(i1->first); 00165 if ((i2 == i2_end) || (i1->second != i2->second)) 00166 ls1.erase(i1++); 00167 else 00168 ++i1; 00169 } 00170 } 00171 00172 } // namespace Parma_Polyhedra_Library 00173 00174 #endif // !defined(PPL_Float_templates_hh)