Skip to content

Commit da59085

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 cee5157 commit da59085

File tree

4 files changed

+197
-135
lines changed

4 files changed

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

0 commit comments

Comments
 (0)