Skip to content

Commit f59ad70

Browse files
committed
Introduce floatbv_round_to_integral_exprt
This adds a new expression, floatbv_round_to_integral, which rounds an IEEE 754 floating-point number given as bit-vector to the nearest integer, considering the explicitly given rounding mode.
1 parent 1102fa1 commit f59ad70

File tree

25 files changed

+604
-332
lines changed

25 files changed

+604
-332
lines changed

regression/cbmc-library/__sort_of_CPROVER_round_to_integral-01/main.c

-9
This file was deleted.

regression/cbmc-library/__sort_of_CPROVER_round_to_integral-01/test.desc

-8
This file was deleted.

regression/cbmc-library/__sort_of_CPROVER_round_to_integralf-01/main.c

-9
This file was deleted.

regression/cbmc-library/__sort_of_CPROVER_round_to_integralf-01/test.desc

-8
This file was deleted.

regression/cbmc-library/__sort_of_CPROVER_round_to_integrall-01/main.c

-9
This file was deleted.

regression/cbmc-library/__sort_of_CPROVER_round_to_integrall-01/test.desc

-8
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
(set-logic FP)
2+
3+
(assert (not (and
4+
5+
; round up
6+
(= (fp.roundToIntegral roundTowardPositive (_ NaN 11 53)) (_ NaN 11 53))
7+
(= (fp.roundToIntegral roundTowardPositive (_ +oo 11 53)) (_ +oo 11 53))
8+
(= (fp.roundToIntegral roundTowardPositive (_ -oo 11 53)) (_ -oo 11 53))
9+
REQUIRE(ieee_floatt::from_double(up, 1).round_to_integral() == 1);
10+
REQUIRE(ieee_floatt::from_double(up, 0.1).round_to_integral() == 1);
11+
REQUIRE(ieee_floatt::from_double(up, -0.1).round_to_integral() == -0.0);
12+
REQUIRE(ieee_floatt::from_double(up, 10.1).round_to_integral() == 11);
13+
REQUIRE(ieee_floatt::from_double(up, -10.1).round_to_integral() == -10);
14+
REQUIRE(ieee_floatt::from_double(up, dmax).round_to_integral() == dmax);
15+
16+
; round down
17+
(= (fp.roundToIntegral roundTowardNegative (_ NaN 11 53)) (_ NaN 11 53))
18+
(= (fp.roundToIntegral roundTowardNegative (_ +oo 11 53)) (_ +oo 11 53))
19+
(= (fp.roundToIntegral roundTowardNegative (_ -oo 11 53)) (_ -oo 11 53))
20+
REQUIRE(ieee_floatt::from_double(down, 0).round_to_integral() == 0);
21+
REQUIRE(ieee_floatt::from_double(down, -0.0).round_to_integral() == -0.0);
22+
REQUIRE(ieee_floatt::from_double(down, 1).round_to_integral() == 1);
23+
REQUIRE(ieee_floatt::from_double(down, 0.1).round_to_integral() == 0);
24+
REQUIRE(ieee_floatt::from_double(down, -0.1).round_to_integral() == -1);
25+
REQUIRE(ieee_floatt::from_double(down, 10.1).round_to_integral() == 10);
26+
REQUIRE(ieee_floatt::from_double(down, -10.1).round_to_integral() == -11);
27+
REQUIRE(ieee_floatt::from_double(down, 0x1.0p+52).round_to_integral() == 0x1.0p+52);
28+
REQUIRE(ieee_floatt::from_double(down, dmax).round_to_integral() == dmax);
29+
30+
; round to nearest ties to even
31+
(= (fp.roundToIntegral roundNearestTiesToEven (_ NaN 11 53)) (_ NaN 11 53))
32+
(= (fp.roundToIntegral roundNearestTiesToEven (_ +oo 11 53)) (_ +oo 11 53))
33+
(= (fp.roundToIntegral roundNearestTiesToEven (_ -oo 11 53)) (_ -oo 11 53))
34+
REQUIRE(ieee_floatt::from_double(even, 0).round_to_integral() == 0);
35+
REQUIRE(ieee_floatt::from_double(even, -0.0).round_to_integral() == -0.0);
36+
REQUIRE(ieee_floatt::from_double(even, 1).round_to_integral() == 1);
37+
REQUIRE(ieee_floatt::from_double(even, 0.1).round_to_integral() == 0);
38+
REQUIRE(ieee_floatt::from_double(even, -0.1).round_to_integral() == -0.0);
39+
REQUIRE(ieee_floatt::from_double(even, 10.1).round_to_integral() == 10);
40+
REQUIRE(ieee_floatt::from_double(even, -10.1).round_to_integral() == -10);
41+
REQUIRE(ieee_floatt::from_double(even, 0x1.0p+52).round_to_integral() == 0x1.0p+52);
42+
REQUIRE(ieee_floatt::from_double(even, dmax).round_to_integral() == dmax);
43+
44+
; round to zero
45+
(= (fp.roundToIntegral roundTowardZero (_ NaN 11 53)) (_ NaN 11 53))
46+
(= (fp.roundToIntegral roundTowardZero (_ +oo 11 53)) (_ +oo 11 53))
47+
(= (fp.roundToIntegral roundTowardZero (_ -oo 11 53)) (_ -oo 11 53))
48+
REQUIRE(ieee_floatt::from_double(zero, 0).round_to_integral() == 0);
49+
REQUIRE(ieee_floatt::from_double(zero, -0.0).round_to_integral() == -0.0);
50+
REQUIRE(ieee_floatt::from_double(zero, 1).round_to_integral() == 1);
51+
REQUIRE(ieee_floatt::from_double(zero, 0.1).round_to_integral() == 0);
52+
REQUIRE(ieee_floatt::from_double(zero, -0.1).round_to_integral() == -0.0);
53+
REQUIRE(ieee_floatt::from_double(zero, 10.1).round_to_integral() == 10);
54+
REQUIRE(ieee_floatt::from_double(zero, -10.1).round_to_integral() == -10);
55+
REQUIRE(ieee_floatt::from_double(zero, 0x1.0p+52).round_to_integral() == 0x1.0p+52);
56+
REQUIRE(ieee_floatt::from_double(zero, dmax).round_to_integral() == dmax);
57+
)))
58+
59+
; should be unsat
60+
(check-sat)

src/ansi-c/c_typecheck_expr.cpp

+18
Original file line numberDiff line numberDiff line change
@@ -3237,6 +3237,24 @@ exprt c_typecheck_baset::do_special_functions(
32373237

32383238
return std::move(infl_expr);
32393239
}
3240+
else if(
3241+
identifier == CPROVER_PREFIX "round_to_integralf" ||
3242+
identifier == CPROVER_PREFIX "round_to_integrald" ||
3243+
identifier == CPROVER_PREFIX "round_to_integralld")
3244+
{
3245+
if(expr.arguments().size() != 2)
3246+
{
3247+
error().source_location = f_op.source_location();
3248+
error() << identifier << " expects two arguments" << eom;
3249+
throw 0;
3250+
}
3251+
3252+
auto round_to_integral_expr =
3253+
floatbv_round_to_integral_exprt{expr.arguments()[0], expr.arguments()[1]};
3254+
round_to_integral_expr.add_source_location() = source_location;
3255+
3256+
return std::move(round_to_integral_expr);
3257+
}
32403258
else if(
32413259
identifier == CPROVER_PREFIX "abs" || identifier == CPROVER_PREFIX "labs" ||
32423260
identifier == CPROVER_PREFIX "llabs" ||

src/ansi-c/cprover_builtin_headers.h

+3
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ int __CPROVER_islessgreaterf(float f, float g);
9393
int __CPROVER_islessgreaterd(double f, double g);
9494
int __CPROVER_isunorderedf(float f, float g);
9595
int __CPROVER_isunorderedd(double f, double g);
96+
float __CPROVER_round_to_integralf(float, int);
97+
double __CPROVER_round_to_integrald(double, int);
98+
long double __CPROVER_round_to_integralld(long double, int);
9699

97100
// absolute value
98101
int __CPROVER_abs(int x);

0 commit comments

Comments
 (0)