Skip to content

Commit 6a87849

Browse files
committed
Transform float_utils unit test to use CATCH and enable it
It now tests both the approximating and non-approximating version of float_utilst.
1 parent 855d0c1 commit 6a87849

File tree

5 files changed

+209
-135
lines changed

5 files changed

+209
-135
lines changed

unit/CMakeLists.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ list(REMOVE_ITEM sources
77
${CMAKE_CURRENT_SOURCE_DIR}/miniBDD.cpp
88

99
# Don't build
10-
${CMAKE_CURRENT_SOURCE_DIR}/sharing_map.cpp
1110
${CMAKE_CURRENT_SOURCE_DIR}/elf_reader.cpp
1211
${CMAKE_CURRENT_SOURCE_DIR}/smt2_parser.cpp
1312
${CMAKE_CURRENT_SOURCE_DIR}/json.cpp
@@ -16,7 +15,6 @@ list(REMOVE_ITEM sources
1615
${CMAKE_CURRENT_SOURCE_DIR}/unicode.cpp
1716
${CMAKE_CURRENT_SOURCE_DIR}/wp.cpp
1817
${CMAKE_CURRENT_SOURCE_DIR}/cpp_scanner.cpp
19-
${CMAKE_CURRENT_SOURCE_DIR}/float_utils.cpp
2018
${CMAKE_CURRENT_SOURCE_DIR}/ieee_float.cpp
2119

2220
# Will be built into a separate library and linked

unit/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ SRC += unit_tests.cpp \
1616
analyses/does_remove_const/is_type_at_least_as_const_as.cpp \
1717
goto-programs/goto_trace_output.cpp \
1818
path_strategies.cpp \
19+
solvers/floatbv/float_utils.cpp \
1920
solvers/refinement/array_pool/array_pool.cpp \
2021
solvers/refinement/string_constraint_generator_valueof/calculate_max_string_length.cpp \
2122
solvers/refinement/string_constraint_generator_valueof/get_numeric_value_from_character.cpp \

unit/float_utils.cpp

Lines changed: 0 additions & 133 deletions
This file was deleted.

unit/solvers/floatbv/float_utils.cpp

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
/*******************************************************************\
2+
3+
Module: Unit tests for float utils and approximation
4+
5+
Author: Daniel Kroening
6+
7+
\*******************************************************************/
8+
9+
#include <testing-utils/catch.hpp>
10+
11+
// for debug output in case of failure
12+
#include <iostream>
13+
#include <cstdlib>
14+
15+
#include <solvers/floatbv/float_approximation.h>
16+
#include <solvers/floatbv/float_utils.h>
17+
#include <solvers/sat/satcheck.h>
18+
19+
float random_float()
20+
{
21+
union
22+
{
23+
float f;
24+
unsigned int i;
25+
} u;
26+
27+
u.i = static_cast<unsigned>(random());
28+
u.i = (u.i << 16) ^ static_cast<unsigned>(random());
29+
30+
return u.f;
31+
}
32+
33+
bool eq(const ieee_floatt &a, const ieee_floatt &b)
34+
{
35+
return (a.is_NaN() && b.is_NaN()) ||
36+
(a.is_infinity() && b.is_infinity() && a.get_sign() == b.get_sign()) ||
37+
a == b;
38+
}
39+
40+
std::string to_str(const bvt &bv)
41+
{
42+
std::string result;
43+
for(unsigned i=0; i<bv.size(); i++)
44+
{
45+
char ch;
46+
if(bv[i]==const_literal(true))
47+
ch='1';
48+
else if(bv[i]==const_literal(false))
49+
ch='0';
50+
else
51+
ch='?';
52+
result=ch+result;
53+
}
54+
return result;
55+
}
56+
57+
typedef enum { PLUS=0, MINUS=1, MULT=2, DIV=3 } binopt;
58+
const char *binopsyms[]={ " + ", " - ", " * ", " / " };
59+
60+
float set_values(
61+
float_utilst &float_utils,
62+
float &f1,
63+
float &f2,
64+
ieee_floatt &i1,
65+
ieee_floatt &i2)
66+
{
67+
f1 = random_float();
68+
f2 = random_float();
69+
i1.from_float(f1);
70+
i2.from_float(f2);
71+
float_utils.spec = i1.spec;
72+
73+
return f1;
74+
}
75+
76+
bvt compute(
77+
unsigned i,
78+
float_utilst &float_utils,
79+
const float &f2,
80+
float &f3,
81+
const ieee_floatt &i1,
82+
const ieee_floatt &i2)
83+
{
84+
const bvt b1 = float_utils.build_constant(i1);
85+
const bvt b2 = float_utils.build_constant(i2);
86+
87+
const auto op = i % 3;
88+
89+
switch(op)
90+
{
91+
case PLUS:
92+
f3 += f2;
93+
return float_utils.add(b1, b2);
94+
95+
case MINUS:
96+
f3 -= f2;
97+
return float_utils.sub(b1, b2);
98+
99+
case MULT:
100+
f3 *= f2;
101+
return float_utils.mul(b1, b2);
102+
103+
case DIV:
104+
f3 /= f2;
105+
return float_utils.div(b1, b2);
106+
}
107+
108+
return bvt();
109+
}
110+
111+
void print(
112+
unsigned i,
113+
const ieee_floatt &i1,
114+
const ieee_floatt &i2,
115+
const ieee_floatt &i3,
116+
const ieee_floatt &fres,
117+
const float &f1,
118+
const float &f2,
119+
const float &f3)
120+
{
121+
const unsigned op = i % 3;
122+
const char *opsym = binopsyms[op];
123+
124+
std::cout << i1 << opsym << i2 << " != " << fres << '\n';
125+
std::cout << f1 << opsym << f2 << " == " << f3 << '\n';
126+
std::cout << integer2binary(i1.get_exponent(), i1.spec.e) << " "
127+
<< integer2binary(i1.get_fraction(), i1.spec.f + 1) << opsym
128+
<< integer2binary(i2.get_exponent(), i1.spec.e) << " "
129+
<< integer2binary(i2.get_fraction(), i1.spec.f + 1) << " != "
130+
<< integer2binary(fres.get_exponent(), i1.spec.e) << " "
131+
<< integer2binary(fres.get_fraction(), i1.spec.f + 1) << '\n';
132+
std::cout << integer2binary(i1.get_exponent(), i1.spec.e) << " "
133+
<< integer2binary(i1.get_fraction(), i1.spec.f + 1) << opsym
134+
<< integer2binary(i2.get_exponent(), i1.spec.e) << " "
135+
<< integer2binary(i2.get_fraction(), i1.spec.f + 1) << " == "
136+
<< integer2binary(i3.get_exponent(), i1.spec.e) << " "
137+
<< integer2binary(i3.get_fraction(), i1.spec.f + 1) << '\n';
138+
}
139+
140+
SCENARIO("float_utils", "[core][solvers][floatbv][float_utils]")
141+
{
142+
ieee_floatt i1, i2, i3;
143+
float f1, f2, f3;
144+
145+
for(unsigned i = 0; i < 200; i++)
146+
{
147+
satcheckt satcheck;
148+
float_utilst float_utils(satcheck);
149+
150+
GIVEN("Two random floating point numbers")
151+
{
152+
f3 = set_values(float_utils, f1, f2, i1, i2);
153+
bvt res = compute(i, float_utils, f2, f3, i1, i2);
154+
155+
THEN("Machine execution yields the same result as symbolic computation")
156+
{
157+
i3.from_float(f3);
158+
159+
const satcheckt::resultt result = satcheck.prop_solve();
160+
REQUIRE(result == satcheckt::resultt::P_SATISFIABLE);
161+
162+
const ieee_floatt fres = float_utils.get(res);
163+
164+
if(!eq(fres, i3))
165+
print(i, i1, i2, i3, fres, f1, f2, f3);
166+
167+
REQUIRE(eq(fres, i3));
168+
}
169+
}
170+
}
171+
}
172+
173+
SCENARIO("float_approximation", "[core][solvers][floatbv][float_approximation]")
174+
{
175+
ieee_floatt i1, i2, i3;
176+
float f1, f2, f3;
177+
178+
for(unsigned i = 0; i < 200; i++)
179+
{
180+
satcheckt satcheck;
181+
float_approximationt float_utils(satcheck);
182+
183+
GIVEN("Two random floating point numbers")
184+
{
185+
f3 = set_values(float_utils, f1, f2, i1, i2);
186+
bvt res = compute(i, float_utils, f2, f3, i1, i2);
187+
188+
THEN("Machine execution yields the same result as symbolic computation")
189+
{
190+
i3.from_float(f3);
191+
192+
const satcheckt::resultt result = satcheck.prop_solve();
193+
REQUIRE(result == satcheckt::resultt::P_SATISFIABLE);
194+
195+
const ieee_floatt fres = float_utils.get(res);
196+
197+
if(!eq(fres, i3))
198+
print(i, i1, i2, i3, fres, f1, f2, f3);
199+
200+
REQUIRE(eq(fres, i3));
201+
}
202+
}
203+
}
204+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
solvers/floatbv
2+
solvers/sat
3+
testing-utils
4+
util

0 commit comments

Comments
 (0)