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