1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
|
/* IEC 559 floating point format related functions.
Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it>
Copyright (C) 2010-2012 BUGSENG srl (http://bugseng.com)
This file is part of the Parma Polyhedra Library (PPL).
The PPL is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3 of the License, or (at your
option) any later version.
The PPL is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.
For the most up-to-date information see the Parma Polyhedra Library
site: http://bugseng.com/products/ppl/ . */
#ifndef PPL_Float_defs_hh
#define PPL_Float_defs_hh 1
#include "globals.types.hh"
#include "meta_programming.hh"
#include "compiler.hh"
#include "assert.hh"
#include "Concrete_Expression.types.hh"
#include "Variable.types.hh"
#include "Linear_Form.types.hh"
#include <set>
#include <cmath>
#include <map>
#include <gmp.h>
#ifdef NAN
#define PPL_NAN NAN
#else
#define PPL_NAN (HUGE_VAL - HUGE_VAL)
#endif
namespace Parma_Polyhedra_Library {
#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
/*! \ingroup PPL_CXX_interface */
#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
struct float_ieee754_half {
uint16_t word;
static const uint16_t SGN_MASK = 0x8000U;
static const uint16_t EXP_MASK = 0xfc00U;
static const uint16_t POS_INF = 0xfc00U;
static const uint16_t NEG_INF = 0x7c00U;
static const uint16_t POS_ZERO = 0x0000U;
static const uint16_t NEG_ZERO = 0x8000U;
static const unsigned int BASE = 2;
static const unsigned int EXPONENT_BITS = 5;
static const unsigned int MANTISSA_BITS = 10;
static const int EXPONENT_MAX = (1 << (EXPONENT_BITS - 1)) - 1;
static const int EXPONENT_BIAS = EXPONENT_MAX;
static const int EXPONENT_MIN = -EXPONENT_MAX + 1;
static const int EXPONENT_MIN_DENORM = EXPONENT_MIN
- static_cast<int>(MANTISSA_BITS);
static const Floating_Point_Format floating_point_format = IEEE754_HALF;
int inf_sign() const;
bool is_nan() const;
int zero_sign() const;
bool sign_bit() const;
void negate();
void dec();
void inc();
void set_max(bool negative);
void build(bool negative, mpz_t mantissa, int exponent);
};
#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
/*! \ingroup PPL_CXX_interface */
#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
struct float_ieee754_single {
uint32_t word;
static const uint32_t SGN_MASK = 0x80000000U;
static const uint32_t EXP_MASK = 0x7f800000U;
static const uint32_t POS_INF = 0x7f800000U;
static const uint32_t NEG_INF = 0xff800000U;
static const uint32_t POS_ZERO = 0x00000000U;
static const uint32_t NEG_ZERO = 0x80000000U;
static const unsigned int BASE = 2;
static const unsigned int EXPONENT_BITS = 8;
static const unsigned int MANTISSA_BITS = 23;
static const int EXPONENT_MAX = (1 << (EXPONENT_BITS - 1)) - 1;
static const int EXPONENT_BIAS = EXPONENT_MAX;
static const int EXPONENT_MIN = -EXPONENT_MAX + 1;
static const int EXPONENT_MIN_DENORM = EXPONENT_MIN
- static_cast<int>(MANTISSA_BITS);
static const Floating_Point_Format floating_point_format = IEEE754_SINGLE;
int inf_sign() const;
bool is_nan() const;
int zero_sign() const;
bool sign_bit() const;
void negate();
void dec();
void inc();
void set_max(bool negative);
void build(bool negative, mpz_t mantissa, int exponent);
};
#ifdef WORDS_BIGENDIAN
#ifndef PPL_WORDS_BIGENDIAN
#define PPL_WORDS_BIGENDIAN
#endif
#endif
#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
/*! \ingroup PPL_CXX_interface */
#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
struct float_ieee754_double {
#ifdef PPL_WORDS_BIGENDIAN
uint32_t msp;
uint32_t lsp;
#else
uint32_t lsp;
uint32_t msp;
#endif
static const uint32_t MSP_SGN_MASK = 0x80000000U;
static const uint32_t MSP_POS_INF = 0x7ff00000U;
static const uint32_t MSP_NEG_INF = 0xfff00000U;
static const uint32_t MSP_POS_ZERO = 0x00000000U;
static const uint32_t MSP_NEG_ZERO = 0x80000000U;
static const uint32_t LSP_INF = 0;
static const uint32_t LSP_ZERO = 0;
static const uint32_t LSP_MAX = 0xffffffffU;
static const unsigned int BASE = 2;
static const unsigned int EXPONENT_BITS = 11;
static const unsigned int MANTISSA_BITS = 52;
static const int EXPONENT_MAX = (1 << (EXPONENT_BITS - 1)) - 1;
static const int EXPONENT_BIAS = EXPONENT_MAX;
static const int EXPONENT_MIN = -EXPONENT_MAX + 1;
static const int EXPONENT_MIN_DENORM = EXPONENT_MIN
- static_cast<int>(MANTISSA_BITS);
static const Floating_Point_Format floating_point_format = IEEE754_DOUBLE;
int inf_sign() const;
bool is_nan() const;
int zero_sign() const;
bool sign_bit() const;
void negate();
void dec();
void inc();
void set_max(bool negative);
void build(bool negative, mpz_t mantissa, int exponent);
};
#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
/*! \ingroup PPL_CXX_interface */
#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
struct float_ibm_single {
uint32_t word;
static const uint32_t SGN_MASK = 0x80000000U;
static const uint32_t EXP_MASK = 0x7f000000U;
static const uint32_t POS_INF = 0x7f000000U;
static const uint32_t NEG_INF = 0xff000000U;
static const uint32_t POS_ZERO = 0x00000000U;
static const uint32_t NEG_ZERO = 0x80000000U;
static const unsigned int BASE = 16;
static const unsigned int EXPONENT_BITS = 7;
static const unsigned int MANTISSA_BITS = 24;
static const int EXPONENT_BIAS = 64;
static const int EXPONENT_MAX = (1 << (EXPONENT_BITS - 1)) - 1;
static const int EXPONENT_MIN = -EXPONENT_MAX + 1;
static const int EXPONENT_MIN_DENORM = EXPONENT_MIN
- static_cast<int>(MANTISSA_BITS);
static const Floating_Point_Format floating_point_format = IBM_SINGLE;
int inf_sign() const;
bool is_nan() const;
int zero_sign() const;
bool sign_bit() const;
void negate();
void dec();
void inc();
void set_max(bool negative);
void build(bool negative, mpz_t mantissa, int exponent);
};
#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
/*! \ingroup PPL_CXX_interface */
#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
struct float_ibm_double {
static const unsigned int BASE = 16;
static const unsigned int EXPONENT_BITS = 7;
static const unsigned int MANTISSA_BITS = 56;
static const int EXPONENT_BIAS = 64;
};
#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
/*! \ingroup PPL_CXX_interface */
#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
struct float_intel_double_extended {
#ifdef PPL_WORDS_BIGENDIAN
uint32_t msp;
uint64_t lsp;
#else
uint64_t lsp;
uint32_t msp;
#endif
static const uint32_t MSP_SGN_MASK = 0x00008000U;
static const uint32_t MSP_POS_INF = 0x00007fffU;
static const uint32_t MSP_NEG_INF = 0x0000ffffU;
static const uint32_t MSP_POS_ZERO = 0x00000000U;
static const uint32_t MSP_NEG_ZERO = 0x00008000U;
static const uint64_t LSP_INF = static_cast<uint64_t>(0x8000000000000000ULL);
static const uint64_t LSP_ZERO = 0;
static const uint64_t LSP_DMAX = static_cast<uint64_t>(0x7fffffffffffffffULL);
static const uint64_t LSP_NMAX = static_cast<uint64_t>(0xffffffffffffffffULL);
static const unsigned int BASE = 2;
static const unsigned int EXPONENT_BITS = 15;
static const unsigned int MANTISSA_BITS = 63;
static const int EXPONENT_MAX = (1 << (EXPONENT_BITS - 1)) - 1;
static const int EXPONENT_BIAS = EXPONENT_MAX;
static const int EXPONENT_MIN = -EXPONENT_MAX + 1;
static const int EXPONENT_MIN_DENORM = EXPONENT_MIN
- static_cast<int>(MANTISSA_BITS);
static const Floating_Point_Format floating_point_format =
INTEL_DOUBLE_EXTENDED;
int inf_sign() const;
bool is_nan() const;
int zero_sign() const;
bool sign_bit() const;
void negate();
void dec();
void inc();
void set_max(bool negative);
void build(bool negative, mpz_t mantissa, int exponent);
};
#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
/*! \ingroup PPL_CXX_interface */
#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
struct float_ieee754_quad {
#ifdef PPL_WORDS_BIGENDIAN
uint64_t msp;
uint64_t lsp;
#else
uint64_t lsp;
uint64_t msp;
#endif
static const uint64_t MSP_SGN_MASK = static_cast<uint64_t>(0x8000000000000000ULL);
static const uint64_t MSP_POS_INF = static_cast<uint64_t>(0x7fff000000000000ULL);
static const uint64_t MSP_NEG_INF = static_cast<uint64_t>(0xffff000000000000ULL);
static const uint64_t MSP_POS_ZERO = static_cast<uint64_t>(0x0000000000000000ULL);
static const uint64_t MSP_NEG_ZERO = static_cast<uint64_t>(0x8000000000000000ULL);
static const uint64_t LSP_INF = 0;
static const uint64_t LSP_ZERO = 0;
static const uint64_t LSP_MAX = static_cast<uint64_t>(0xffffffffffffffffULL);
static const unsigned int BASE = 2;
static const unsigned int EXPONENT_BITS = 15;
static const unsigned int MANTISSA_BITS = 112;
static const int EXPONENT_MAX = (1 << (EXPONENT_BITS - 1)) - 1;
static const int EXPONENT_BIAS = EXPONENT_MAX;
static const int EXPONENT_MIN = -EXPONENT_MAX + 1;
static const int EXPONENT_MIN_DENORM = EXPONENT_MIN
- static_cast<int>(MANTISSA_BITS);
int inf_sign() const;
bool is_nan() const;
int zero_sign() const;
bool sign_bit() const;
void negate();
void dec();
void inc();
void set_max(bool negative);
void build(bool negative, mpz_t mantissa, int exponent);
};
#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
/*! \ingroup PPL_CXX_interface */
#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
template <typename T>
class Float : public False { };
#if PPL_SUPPORTED_FLOAT
template <>
class Float<float> : public True {
public:
#if PPL_CXX_FLOAT_BINARY_FORMAT == PPL_FLOAT_IEEE754_HALF
typedef float_ieee754_half Binary;
#elif PPL_CXX_FLOAT_BINARY_FORMAT == PPL_FLOAT_IEEE754_SINGLE
typedef float_ieee754_single Binary;
#elif PPL_CXX_FLOAT_BINARY_FORMAT == PPL_FLOAT_IEEE754_DOUBLE
typedef float_ieee754_double Binary;
#elif PPL_CXX_FLOAT_BINARY_FORMAT == PPL_FLOAT_IBM_SINGLE
typedef float_ibm_single Binary;
#elif PPL_CXX_FLOAT_BINARY_FORMAT == PPL_FLOAT_IEEE754_QUAD
typedef float_ieee754_quad Binary;
#elif PPL_CXX_FLOAT_BINARY_FORMAT == PPL_FLOAT_INTEL_DOUBLE_EXTENDED
typedef float_intel_double_extended Binary;
#else
#error "Invalid value for PPL_CXX_FLOAT_BINARY_FORMAT"
#endif
union {
float number;
Binary binary;
} u;
Float();
Float(float v);
float value();
};
#endif
#if PPL_SUPPORTED_DOUBLE
template <>
class Float<double> : public True {
public:
#if PPL_CXX_DOUBLE_BINARY_FORMAT == PPL_FLOAT_IEEE754_HALF
typedef float_ieee754_half Binary;
#elif PPL_CXX_DOUBLE_BINARY_FORMAT == PPL_FLOAT_IEEE754_SINGLE
typedef float_ieee754_single Binary;
#elif PPL_CXX_DOUBLE_BINARY_FORMAT == PPL_FLOAT_IEEE754_DOUBLE
typedef float_ieee754_double Binary;
#elif PPL_CXX_DOUBLE_BINARY_FORMAT == PPL_FLOAT_IBM_SINGLE
typedef float_ibm_single Binary;
#elif PPL_CXX_DOUBLE_BINARY_FORMAT == PPL_FLOAT_IEEE754_QUAD
typedef float_ieee754_quad Binary;
#elif PPL_CXX_DOUBLE_BINARY_FORMAT == PPL_FLOAT_INTEL_DOUBLE_EXTENDED
typedef float_intel_double_extended Binary;
#else
#error "Invalid value for PPL_CXX_DOUBLE_BINARY_FORMAT"
#endif
union {
double number;
Binary binary;
} u;
Float();
Float(double v);
double value();
};
#endif
#if PPL_SUPPORTED_LONG_DOUBLE
template <>
class Float<long double> : public True {
public:
#if PPL_CXX_LONG_DOUBLE_BINARY_FORMAT == PPL_FLOAT_IEEE754_HALF
typedef float_ieee754_half Binary;
#elif PPL_CXX_LONG_DOUBLE_BINARY_FORMAT == PPL_FLOAT_IEEE754_SINGLE
typedef float_ieee754_single Binary;
#elif PPL_CXX_LONG_DOUBLE_BINARY_FORMAT == PPL_FLOAT_IEEE754_DOUBLE
typedef float_ieee754_double Binary;
#elif PPL_CXX_LONG_DOUBLE_BINARY_FORMAT == PPL_FLOAT_IBM_SINGLE
typedef float_ibm_single Binary;
#elif PPL_CXX_LONG_DOUBLE_BINARY_FORMAT == PPL_FLOAT_IEEE754_QUAD
typedef float_ieee754_quad Binary;
#elif PPL_CXX_LONG_DOUBLE_BINARY_FORMAT == PPL_FLOAT_INTEL_DOUBLE_EXTENDED
typedef float_intel_double_extended Binary;
#else
#error "Invalid value for PPL_CXX_LONG_DOUBLE_BINARY_FORMAT"
#endif
union {
long double number;
Binary binary;
} u;
Float();
Float(long double v);
long double value();
};
#endif
// FIXME: is this the right place for this function?
#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
/*! \brief
If \p v is nonzero, returns the position of the most significant bit
in \p a.
The behavior is undefined if \p v is zero.
*/
#endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
unsigned int msb_position(unsigned long long v);
/*! \brief
An abstract class to be implemented by an external analyzer such
as ECLAIR in order to provide to the PPL the necessary information
for performing the analysis of floating point computations.
\par Template type parameters
- The class template parameter \p Target specifies the implementation
of Concrete_Expression to be used.
- The class template parameter \p FP_Interval_Type represents the type
of the intervals used in the abstract domain. The interval bounds
should have a floating point type.
*/
template <typename Target, typename FP_Interval_Type>
class FP_Oracle {
public:
/*
FIXME: the const qualifiers on expressions may raise CLANG
compatibility issues. It may be necessary to omit them.
*/
/*! \brief
Asks the external analyzer for an interval that correctly
approximates the floating point entity referenced by \p dim.
Result is stored into \p result.
\return <CODE>true</CODE> if the analyzer was able to find a correct
approximation, <CODE>false</CODE> otherwise.
*/
virtual bool get_interval(dimension_type dim, FP_Interval_Type& result) const
= 0;
/*! \brief
Asks the external analyzer for an interval that correctly
approximates the value of floating point constant \p expr.
Result is stored into \p result.
\return <CODE>true</CODE> if the analyzer was able to find a correct
approximation, <CODE>false</CODE> otherwise.
*/
virtual bool get_fp_constant_value(
const Floating_Point_Constant<Target>& expr,
FP_Interval_Type& result) const = 0;
/*! \brief
Asks the external analyzer for an interval that correctly approximates
the value of \p expr, which must be of integer type.
Result is stored into \p result.
\return <CODE>true</CODE> if the analyzer was able to find a correct
approximation, <CODE>false</CODE> otherwise.
*/
virtual bool get_integer_expr_value(const Concrete_Expression<Target>& expr,
FP_Interval_Type& result) const = 0;
/*! \brief
Asks the external analyzer for the possible space dimensions that
are associated to the approximable reference \p expr.
Result is stored into \p result.
\return <CODE>true</CODE> if the analyzer was able to return
the (possibly empty!) set, <CODE>false</CODE> otherwise.
The resulting set MUST NOT contain <CODE>not_a_dimension()</CODE>.
*/
virtual bool get_associated_dimensions(
const Approximable_Reference<Target>& expr,
std::set<dimension_type>& result) const = 0;
};
/* FIXME: some of the following documentation should probably be
under PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS */
/*! \brief \relates Float
Returns <CODE>true</CODE> if and only if there is some floating point
number that is representable by \p f2 but not by \p f1.
*/
bool is_less_precise_than(Floating_Point_Format f1, Floating_Point_Format f2);
/*! \brief \relates Float
Computes the absolute error of floating point computations.
\par Template type parameters
- The class template parameter \p FP_Interval_Type represents the type
of the intervals used in the abstract domain. The interval bounds
should have a floating point type.
\param analyzed_format The floating point format used by the analyzed
program.
\return The interval \f$[-\omega, \omega]\f$ where \f$\omega\f$ is the
smallest non-zero positive number in the less precise floating point
format between the analyzer format and the analyzed format.
*/
template <typename FP_Interval_Type>
const FP_Interval_Type&
compute_absolute_error(Floating_Point_Format analyzed_format);
/*! \brief \relates Linear_Form
Discards all linear forms containing variable \p var from the
linear form abstract store \p lf_store.
*/
template <typename FP_Interval_Type>
void
discard_occurrences(std::map<dimension_type,
Linear_Form<FP_Interval_Type> >& lf_store,
Variable var);
/*! \brief \relates Linear_Form
Assigns the linear form \p lf to \p var in the linear form abstract
store \p lf_store, then discards all occurrences of \p var from it.
*/
template <typename FP_Interval_Type>
void
affine_form_image(std::map<dimension_type,
Linear_Form<FP_Interval_Type> >& lf_store,
Variable var,
const Linear_Form<FP_Interval_Type>& lf);
/*! \brief \relates Linear_Form
Discards from \p ls1 all linear forms but those that are associated
to the same variable in \p ls2.
*/
template <typename FP_Interval_Type>
void
upper_bound_assign(std::map<dimension_type,
Linear_Form<FP_Interval_Type> >& ls1,
const std::map<dimension_type,
Linear_Form<FP_Interval_Type> >& ls2);
} // namespace Parma_Polyhedra_Library
#include "Float.inlines.hh"
#include "Float.templates.hh"
#endif // !defined(PPL_Float_defs_hh)
|