Skip to content

Commit 066829c

Browse files
author
martin
committed
Fix a bug in the bitwise encoding of float to int casting.
This affects cases when a floating-point number is cast to an integer which is longer than the significand of the float and the exponent is greater than the length of the significand. This includes float -> (u)int32_t and double -> (u)int64_t. These were incorrectly converted to 0.
1 parent 3d9eba2 commit 066829c

File tree

7 files changed

+91
-7
lines changed

7 files changed

+91
-7
lines changed

regression/cbmc/Float-to-int1/main.c

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#include <assert.h>
2+
3+
double nondet_double();
4+
5+
int main(void)
6+
{
7+
double d = nondet_double();
8+
9+
__CPROVER_assume(d < 0x1.0p+63 && d > 0x1.0p+53);
10+
11+
long long int i = d;
12+
double d1 = i;
13+
14+
assert(d1 != 0x0);
15+
16+
return 0;
17+
}
18+
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
--floatbv
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring

regression/cbmc/Float-to-int2/main.c

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#include <assert.h>
2+
3+
int nondet_int();
4+
double nondet_double();
5+
6+
int main(void)
7+
{
8+
int i = nondet_int();
9+
double di = (double)i;
10+
int j = (int)di;
11+
12+
assert(i == j);
13+
14+
return 0;
15+
}
16+
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
--floatbv
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring

regression/cbmc/Float-to-int3/main.c

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#include <assert.h>
2+
#include <stdint.h>
3+
4+
int64_t nondet_int64_t();
5+
double nondet_double();
6+
7+
int main(void)
8+
{
9+
int64_t i = nondet_int64_t();
10+
11+
__CPROVER_assume((i & (int64_t)0x7FF) == (int64_t)0);
12+
13+
double di = (double)i;
14+
int64_t j = (int64_t)di;
15+
16+
assert(i == j);
17+
18+
return 0;
19+
}
20+
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
--floatbv
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring

src/solvers/floatbv/float_utils.cpp

+13-7
Original file line numberDiff line numberDiff line change
@@ -159,10 +159,21 @@ bvt float_utilst::to_integer(
159159
// The following is the usual case in ANSI-C, and we optimize for that.
160160
if(rounding_mode_bits.round_to_zero.is_true())
161161
{
162+
bvt fraction=unpacked.fraction;
163+
164+
if(dest_width>fraction.size())
165+
{
166+
bvt lsb_extension=bv_utils.build_constant(0U, dest_width-fraction.size());
167+
fraction.insert(fraction.begin(),
168+
lsb_extension.begin(),
169+
lsb_extension.end());
170+
}
171+
162172
// if the exponent is positive, shift right
163-
bvt offset=bv_utils.build_constant(spec.f, unpacked.exponent.size());
173+
bvt offset=bv_utils.build_constant(fraction.size()-1,
174+
unpacked.exponent.size());
164175
bvt distance=bv_utils.sub(offset, unpacked.exponent);
165-
bvt shift_result=bv_utils.shift(unpacked.fraction, bv_utilst::LRIGHT, distance);
176+
bvt shift_result=bv_utils.shift(fraction, bv_utilst::LRIGHT, distance);
166177

167178
// if the exponent is negative, we have zero anyways
168179
bvt result=shift_result;
@@ -176,11 +187,6 @@ bvt float_utilst::to_integer(
176187
{
177188
result.resize(dest_width);
178189
}
179-
else if(result.size()<dest_width)
180-
{
181-
// zero extend
182-
result=bv_utils.zero_extension(result, dest_width);
183-
}
184190

185191
assert(result.size()==dest_width);
186192

0 commit comments

Comments
 (0)