1 /* Floating_Point_Expression class implementation:
2    non-inline template functions.
3    Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it>
4    Copyright (C) 2010-2016 BUGSENG srl (http://bugseng.com)
5 
6 This file is part of the Parma Polyhedra Library (PPL).
7 
8 The PPL is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
12 
13 The PPL is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software Foundation,
20 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.
21 
22 For the most up-to-date information see the Parma Polyhedra Library
23 site: http://bugseng.com/products/ppl/ . */
24 
25 #ifndef PPL_Floating_Point_Expression_templates_hh
26 #define PPL_Floating_Point_Expression_templates_hh 1
27 
28 #include "Linear_Form_defs.hh"
29 #include <cmath>
30 
31 namespace Parma_Polyhedra_Library {
32 
33 template<typename FP_Interval_Type, typename FP_Format>
34 void
35 Floating_Point_Expression<FP_Interval_Type, FP_Format>
relative_error(const FP_Linear_Form & lf,FP_Linear_Form & result)36 ::relative_error(const FP_Linear_Form& lf, FP_Linear_Form& result) {
37 
38   FP_Interval_Type error_propagator;
39   boundary_type lb = -pow(FP_Format::BASE,
40   -static_cast<typename Floating_Point_Expression<FP_Interval_Type, FP_Format>
41   ::boundary_type>(FP_Format::MANTISSA_BITS));
42   error_propagator.build(i_constraint(GREATER_OR_EQUAL, lb),
43                          i_constraint(LESS_OR_EQUAL, -lb));
44 
45   // Handle the inhomogeneous term.
46   const FP_Interval_Type* current_term = &lf.inhomogeneous_term();
47   assert(current_term->is_bounded());
48 
49   FP_Interval_Type
50     current_multiplier(std::max(std::abs(current_term->lower()),
51                                 std::abs(current_term->upper())));
52   FP_Linear_Form current_result_term(current_multiplier);
53   current_result_term *= error_propagator;
54   result = FP_Linear_Form(current_result_term);
55 
56   // Handle the other terms.
57   dimension_type dimension = lf.space_dimension();
58   for (dimension_type i = 0; i < dimension; ++i) {
59     current_term = &lf.coefficient(Variable(i));
60     assert(current_term->is_bounded());
61     current_multiplier
62       = FP_Interval_Type(std::max(std::abs(current_term->lower()),
63                                   std::abs(current_term->upper())));
64     current_result_term = FP_Linear_Form(Variable(i));
65     current_result_term *= current_multiplier;
66     current_result_term *= error_propagator;
67     result += current_result_term;
68   }
69 
70   return;
71 }
72 
73 template<typename FP_Interval_Type, typename FP_Format>
74 void
75 Floating_Point_Expression<FP_Interval_Type, FP_Format>
intervalize(const FP_Linear_Form & lf,const FP_Interval_Abstract_Store & store,FP_Interval_Type & result)76 ::intervalize(const FP_Linear_Form& lf,
77               const FP_Interval_Abstract_Store& store,
78               FP_Interval_Type& result) {
79   result = FP_Interval_Type(lf.inhomogeneous_term());
80   dimension_type dimension = lf.space_dimension();
81   assert(dimension <= store.space_dimension());
82   for (dimension_type i = 0; i < dimension; ++i) {
83     FP_Interval_Type current_addend = lf.coefficient(Variable(i));
84     const FP_Interval_Type& curr_int = store.get_interval(Variable(i));
85     current_addend *= curr_int;
86     result += current_addend;
87   }
88 
89   return;
90 }
91 
92 template<typename FP_Interval_Type, typename FP_Format>
93 FP_Interval_Type
94 Floating_Point_Expression<FP_Interval_Type, FP_Format>
95 ::compute_absolute_error() {
96   typedef typename Floating_Point_Expression<FP_Interval_Type, FP_Format>
97     ::boundary_type Boundary;
98   boundary_type omega;
99   omega = std::max(pow(static_cast<Boundary>(FP_Format::BASE),
100                        static_cast<Boundary>(1 - FP_Format::EXPONENT_BIAS
101                                              - FP_Format::MANTISSA_BITS)),
102                    std::numeric_limits<Boundary>::denorm_min());
103   FP_Interval_Type result;
104   result.build(i_constraint(GREATER_OR_EQUAL, -omega),
105                i_constraint(LESS_OR_EQUAL, omega));
106   return result;
107 }
108 
109 } // namespace Parma_Polyhedra_Library
110 
111 #endif // !defined(PPL_Floating_Point_Expression_templates_hh)
112