Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add IEEE 754 TiesToAway rounding mode #8515

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions jbmc/src/java_bytecode/assignments_from_json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -358,13 +358,13 @@ assign_primitive_from_json(const exprt &expr, const jsont &json)
}
else if(expr.type() == java_double_type())
{
ieee_floatt ieee_float(to_floatbv_type(expr.type()));
ieee_float_valuet ieee_float(to_floatbv_type(expr.type()));
ieee_float.from_double(std::stod(json.value));
result.add(code_frontend_assignt{expr, ieee_float.to_expr()});
}
else if(expr.type() == java_float_type())
{
ieee_floatt ieee_float(to_floatbv_type(expr.type()));
ieee_float_valuet ieee_float(to_floatbv_type(expr.type()));
ieee_float.from_float(std::stof(json.value));
result.add(code_frontend_assignt{expr, ieee_float.to_expr()});
}
Expand Down
2 changes: 1 addition & 1 deletion jbmc/src/java_bytecode/expr2java.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ std::string expr2javat::convert_constant(
(src.type()==java_double_type()))
{
// This converts NaNs to the canonical NaN
const ieee_floatt ieee_repr(to_constant_expr(src));
const ieee_float_valuet ieee_repr(to_constant_expr(src));
if(ieee_repr.is_double())
return floating_point_to_java_string(ieee_repr.to_double());
return floating_point_to_java_string(ieee_repr.to_float());
Expand Down
11 changes: 7 additions & 4 deletions jbmc/src/java_bytecode/java_bytecode_convert_method.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2181,16 +2181,19 @@
is_float ? ieee_float_spect::single_precision()
: ieee_float_spect::double_precision());

ieee_floatt value(spec);
if(arg0.type().id() != ID_floatbv)
{
// conversion from integer to float may need rounding
auto rm = ieee_floatt::rounding_modet::ROUND_TO_EVEN;
const mp_integer number = numeric_cast_v<mp_integer>(arg0);
ieee_floatt value(spec, rm);
value.from_integer(number);
results[0] = value.to_expr();
}
else
value.from_expr(arg0);

results[0] = value.to_expr();
{
results[0] = ieee_float_valuet{arg0}.to_expr();

Check warning on line 2195 in jbmc/src/java_bytecode/java_bytecode_convert_method.cpp

View check run for this annotation

Codecov / codecov/patch

jbmc/src/java_bytecode/java_bytecode_convert_method.cpp#L2195

Added line #L2195 was not covered by tests
}
}
else
{
Expand Down
4 changes: 2 additions & 2 deletions jbmc/src/java_bytecode/java_bytecode_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -782,7 +782,7 @@ void java_bytecode_parsert::rconstant_pool()

case CONSTANT_Float:
{
ieee_floatt value(ieee_float_spect::single_precision());
ieee_float_valuet value(ieee_float_spect::single_precision());
value.unpack(entry.number);
entry.expr = value.to_expr();
}
Expand All @@ -794,7 +794,7 @@ void java_bytecode_parsert::rconstant_pool()

case CONSTANT_Double:
{
ieee_floatt value(ieee_float_spect::double_precision());
ieee_float_valuet value(ieee_float_spect::double_precision());
value.unpack(entry.number);
entry.expr = value.to_expr();
}
Expand Down
9 changes: 5 additions & 4 deletions jbmc/src/java_bytecode/java_string_library_preprocess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -938,7 +938,7 @@ code_blockt java_string_library_preprocesst::make_float_to_string_code(

// Expression representing 0.0
const ieee_float_spect float_spec{to_floatbv_type(params[0].type())};
ieee_floatt zero_float(float_spec);
ieee_float_valuet zero_float(float_spec);
zero_float.from_float(0.0);
const constant_exprt zero = zero_float.to_expr();

Expand Down Expand Up @@ -996,16 +996,17 @@ code_blockt java_string_library_preprocesst::make_float_to_string_code(
string_expr_list.push_back(zero_string);

// Case of -0.0
ieee_floatt minus_zero_float(float_spec);
ieee_float_valuet minus_zero_float(float_spec);
minus_zero_float.from_float(-0.0f);
condition_list.push_back(equal_exprt(arg, minus_zero_float.to_expr()));
const refined_string_exprt minus_zero_string =
string_literal_to_string_expr("-0.0", loc, symbol_table, code);
string_expr_list.push_back(minus_zero_string);

// Case of simple notation
ieee_floatt bound_inf_float(float_spec);
ieee_floatt bound_sup_float(float_spec);
auto rm = ieee_floatt::rounding_modet::ROUND_TO_EVEN;
ieee_floatt bound_inf_float(float_spec, rm);
ieee_floatt bound_sup_float(float_spec, rm);
bound_inf_float.from_float(1e-3f);
bound_sup_float.from_float(1e7f);
bound_inf_float.change_spec(float_spec);
Expand Down
4 changes: 2 additions & 2 deletions src/analyses/interval_domain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@
}
else if(is_float(lhs.type()) && is_float(rhs.type()))
{
ieee_floatt tmp(to_constant_expr(rhs));
ieee_float_valuet tmp(to_constant_expr(rhs));

Check warning on line 291 in src/analyses/interval_domain.cpp

View check run for this annotation

Codecov / codecov/patch

src/analyses/interval_domain.cpp#L291

Added line #L291 was not covered by tests
if(id==ID_lt)
tmp.decrement();
ieee_float_intervalt &fi=float_map[lhs_identifier];
Expand All @@ -313,7 +313,7 @@
}
else if(is_float(lhs.type()) && is_float(rhs.type()))
{
ieee_floatt tmp(to_constant_expr(lhs));
ieee_float_valuet tmp(to_constant_expr(lhs));

Check warning on line 316 in src/analyses/interval_domain.cpp

View check run for this annotation

Codecov / codecov/patch

src/analyses/interval_domain.cpp#L316

Added line #L316 was not covered by tests
if(id==ID_lt)
tmp.increment();
ieee_float_intervalt &fi=float_map[rhs_identifier];
Expand Down
2 changes: 1 addition & 1 deletion src/analyses/interval_domain.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Author: Daniel Kroening, [email protected]

#include "ai_domain.h"

typedef interval_templatet<ieee_floatt> ieee_float_intervalt;
typedef interval_templatet<ieee_float_valuet> ieee_float_intervalt;

class interval_domaint:public ai_domain_baset
{
Expand Down
2 changes: 1 addition & 1 deletion src/ansi-c/expr2c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1912,7 +1912,7 @@ std::string expr2ct::convert_constant(
}
else if(type.id()==ID_floatbv)
{
dest=ieee_floatt(to_constant_expr(src)).to_ansi_c_string();
dest = ieee_float_valuet(to_constant_expr(src)).to_ansi_c_string();

if(!dest.empty() && isdigit(dest[dest.size() - 1]))
{
Expand Down
18 changes: 10 additions & 8 deletions src/ansi-c/goto-conversion/goto_check_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -761,12 +761,13 @@
else if(old_type.id() == ID_floatbv) // float -> signed
{
// Note that the fractional part is truncated!
ieee_floatt upper(to_floatbv_type(old_type));
auto rm = ieee_floatt::rounding_modet::ROUND_TO_EVEN;
ieee_floatt upper(to_floatbv_type(old_type), rm);

Check warning on line 765 in src/ansi-c/goto-conversion/goto_check_c.cpp

View check run for this annotation

Codecov / codecov/patch

src/ansi-c/goto-conversion/goto_check_c.cpp#L764-L765

Added lines #L764 - L765 were not covered by tests
upper.from_integer(power(2, new_width - 1));
const binary_relation_exprt no_overflow_upper(
op, ID_lt, upper.to_expr());

ieee_floatt lower(to_floatbv_type(old_type));
ieee_floatt lower(to_floatbv_type(old_type), rm);

Check warning on line 770 in src/ansi-c/goto-conversion/goto_check_c.cpp

View check run for this annotation

Codecov / codecov/patch

src/ansi-c/goto-conversion/goto_check_c.cpp#L770

Added line #L770 was not covered by tests
lower.from_integer(-power(2, new_width - 1) - 1);
const binary_relation_exprt no_overflow_lower(
op, ID_gt, lower.to_expr());
Expand Down Expand Up @@ -844,12 +845,13 @@
else if(old_type.id() == ID_floatbv) // float -> unsigned
{
// Note that the fractional part is truncated!
ieee_floatt upper(to_floatbv_type(old_type));
auto rm = ieee_floatt::rounding_modet::ROUND_TO_EVEN;
ieee_floatt upper(to_floatbv_type(old_type), rm);

Check warning on line 849 in src/ansi-c/goto-conversion/goto_check_c.cpp

View check run for this annotation

Codecov / codecov/patch

src/ansi-c/goto-conversion/goto_check_c.cpp#L848-L849

Added lines #L848 - L849 were not covered by tests
upper.from_integer(power(2, new_width));
const binary_relation_exprt no_overflow_upper(
op, ID_lt, upper.to_expr());

ieee_floatt lower(to_floatbv_type(old_type));
ieee_floatt lower(to_floatbv_type(old_type), rm);

Check warning on line 854 in src/ansi-c/goto-conversion/goto_check_c.cpp

View check run for this annotation

Codecov / codecov/patch

src/ansi-c/goto-conversion/goto_check_c.cpp#L854

Added line #L854 was not covered by tests
lower.from_integer(-1);
const binary_relation_exprt no_overflow_lower(
op, ID_gt, lower.to_expr());
Expand Down Expand Up @@ -1295,8 +1297,8 @@
// -inf + +inf = NaN and +inf + -inf = NaN,
// i.e., signs differ
ieee_float_spect spec = ieee_float_spect(to_floatbv_type(plus_expr.type()));
exprt plus_inf = ieee_floatt::plus_infinity(spec).to_expr();
exprt minus_inf = ieee_floatt::minus_infinity(spec).to_expr();
exprt plus_inf = ieee_float_valuet::plus_infinity(spec).to_expr();
exprt minus_inf = ieee_float_valuet::minus_infinity(spec).to_expr();

isnan = or_exprt(
and_exprt(
Expand All @@ -1315,8 +1317,8 @@

ieee_float_spect spec =
ieee_float_spect(to_floatbv_type(minus_expr.type()));
exprt plus_inf = ieee_floatt::plus_infinity(spec).to_expr();
exprt minus_inf = ieee_floatt::minus_infinity(spec).to_expr();
exprt plus_inf = ieee_float_valuet::plus_infinity(spec).to_expr();
exprt minus_inf = ieee_float_valuet::minus_infinity(spec).to_expr();

isnan = or_exprt(
and_exprt(
Expand Down
4 changes: 3 additions & 1 deletion src/ansi-c/literals/convert_float_literal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,9 @@
// but these aren't handled anywhere
}

ieee_floatt a(type);
// This may require rounding.

Check warning on line 74 in src/ansi-c/literals/convert_float_literal.cpp

View check run for this annotation

Codecov / codecov/patch

src/ansi-c/literals/convert_float_literal.cpp#L74

Added line #L74 was not covered by tests
auto rm = ieee_floatt::rounding_modet::ROUND_TO_EVEN;
ieee_floatt a(type, rm);

if(parsed_float.exponent_base==10)
a.from_base10(parsed_float.significand, parsed_float.exponent);
Expand Down
2 changes: 1 addition & 1 deletion src/goto-instrument/goto_program2code.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1923,7 +1923,7 @@ void goto_program2codet::cleanup_expr(exprt &expr, bool no_typecast)
{
if(expr.type().id()==ID_floatbv)
{
const ieee_floatt f(to_constant_expr(expr));
const ieee_float_valuet f(to_constant_expr(expr));
if(f.is_NaN() || f.is_infinity())
system_headers.insert("math.h");
}
Expand Down
2 changes: 1 addition & 1 deletion src/goto-programs/interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,7 @@
}
else if(type.id() == ID_floatbv)
{
ieee_floatt f(to_floatbv_type(type));
ieee_float_valuet f(to_floatbv_type(type));

Check warning on line 579 in src/goto-programs/interpreter.cpp

View check run for this annotation

Codecov / codecov/patch

src/goto-programs/interpreter.cpp#L579

Added line #L579 was not covered by tests
f.unpack(rhs[numeric_cast_v<std::size_t>(offset)]);
return f.to_expr();
}
Expand Down
7 changes: 4 additions & 3 deletions src/goto-programs/interpreter_evaluate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@
}
else if(expr.type().id()==ID_floatbv)
{
ieee_floatt f;
ieee_float_valuet f;

Check warning on line 367 in src/goto-programs/interpreter_evaluate.cpp

View check run for this annotation

Codecov / codecov/patch

src/goto-programs/interpreter_evaluate.cpp#L367

Added line #L367 was not covered by tests
f.from_expr(to_constant_expr(expr));
return {f.pack()};
}
Expand Down Expand Up @@ -731,8 +731,9 @@
}
else if(expr.type().id()==ID_floatbv)
{
ieee_floatt f1(to_floatbv_type(expr.type()));
ieee_floatt f2(to_floatbv_type(op.type()));
auto rm = ieee_floatt::rounding_modet::ROUND_TO_EVEN;
ieee_floatt f1(to_floatbv_type(expr.type()), rm);
ieee_floatt f2(to_floatbv_type(op.type()), rm);

Check warning on line 736 in src/goto-programs/interpreter_evaluate.cpp

View check run for this annotation

Codecov / codecov/patch

src/goto-programs/interpreter_evaluate.cpp#L734-L736

Added lines #L734 - L736 were not covered by tests
f1.unpack(result);
f2.unpack(tmp.front());
f1*=f2;
Expand Down
2 changes: 1 addition & 1 deletion src/goto-programs/json_expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ json_objectt json(const exprt &expr, const namespacet &ns, const irep_idt &mode)
json_numbert(std::to_string(to_bitvector_type(type).get_width()));
result["binary"] = json_stringt(binary(constant_expr));
result["data"] =
json_stringt(ieee_floatt(constant_expr).to_ansi_c_string());
json_stringt(ieee_float_valuet(constant_expr).to_ansi_c_string());
}
else if(type.id() == ID_pointer)
{
Expand Down
2 changes: 1 addition & 1 deletion src/goto-programs/xml_expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ xmlt xml(const exprt &expr, const namespacet &ns)
result.set_attribute("width", width);
result.set_attribute(
"binary", integer2binary(bvrep2integer(value, width, false), width));
result.data = ieee_floatt(constant_expr).to_ansi_c_string();
result.data = ieee_float_valuet(constant_expr).to_ansi_c_string();
}
else if(type.id() == ID_pointer)
{
Expand Down
13 changes: 11 additions & 2 deletions src/solvers/floatbv/float_bv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@

constant_exprt mask(integer2bvrep(v, width), src.type());

ieee_floatt z(type);
ieee_float_valuet z(type);
z.make_zero();

return equal_exprt(bitand_exprt(src, mask), z.to_expr());
Expand Down Expand Up @@ -282,11 +282,14 @@
exprt round_to_minus_inf_const=
from_integer(ieee_floatt::ROUND_TO_MINUS_INF, rm.type());
exprt round_to_zero_const=from_integer(ieee_floatt::ROUND_TO_ZERO, rm.type());
exprt round_to_away_const =
from_integer(ieee_floatt::ROUND_TO_AWAY, rm.type());

round_to_even=equal_exprt(rm, round_to_even_const);
round_to_plus_inf=equal_exprt(rm, round_to_plus_inf_const);
round_to_minus_inf=equal_exprt(rm, round_to_minus_inf_const);
round_to_zero=equal_exprt(rm, round_to_zero_const);
round_to_away = equal_exprt(rm, round_to_away_const);
}

exprt float_bvt::sign_bit(const exprt &op)
Expand Down Expand Up @@ -1166,12 +1169,18 @@
// round to zero
false_exprt round_to_zero;

// round to away

Check warning on line 1172 in src/solvers/floatbv/float_bv.cpp

View check run for this annotation

Codecov / codecov/patch

src/solvers/floatbv/float_bv.cpp#L1172

Added line #L1172 was not covered by tests
const auto round_to_away = or_exprt(rounding_bit, sticky_bit);

Check warning on line 1174 in src/solvers/floatbv/float_bv.cpp

View check run for this annotation

Codecov / codecov/patch

src/solvers/floatbv/float_bv.cpp#L1174

Added line #L1174 was not covered by tests
// now select appropriate one
// clang-format off
return if_exprt(rounding_mode_bits.round_to_even, round_to_even,
if_exprt(rounding_mode_bits.round_to_plus_inf, round_to_plus_inf,
if_exprt(rounding_mode_bits.round_to_minus_inf, round_to_minus_inf,
if_exprt(rounding_mode_bits.round_to_zero, round_to_zero,
false_exprt())))); // otherwise zero
if_exprt(rounding_mode_bits.round_to_away, round_to_away,
false_exprt()))))); // otherwise zero
// clang-format off

Check warning on line 1183 in src/solvers/floatbv/float_bv.cpp

View check run for this annotation

Codecov / codecov/patch

src/solvers/floatbv/float_bv.cpp#L1183

Added line #L1183 was not covered by tests
}

void float_bvt::round_fraction(
Expand Down
1 change: 1 addition & 0 deletions src/solvers/floatbv/float_bv.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ class float_bvt
exprt round_to_zero;
exprt round_to_plus_inf;
exprt round_to_minus_inf;
exprt round_to_away;

void get(const exprt &rm);
explicit rounding_mode_bitst(const exprt &rm) { get(rm); }
Expand Down
17 changes: 13 additions & 4 deletions src/solvers/floatbv/float_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,14 @@
bv_utils.build_constant(ieee_floatt::ROUND_TO_MINUS_INF, src.size());
bvt round_to_zero=
bv_utils.build_constant(ieee_floatt::ROUND_TO_ZERO, src.size());
bvt round_to_away =
bv_utils.build_constant(ieee_floatt::ROUND_TO_AWAY, src.size());

rounding_mode_bits.round_to_even=bv_utils.equal(src, round_to_even);
rounding_mode_bits.round_to_plus_inf=bv_utils.equal(src, round_to_plus_inf);
rounding_mode_bits.round_to_minus_inf=bv_utils.equal(src, round_to_minus_inf);
rounding_mode_bits.round_to_zero=bv_utils.equal(src, round_to_zero);
rounding_mode_bits.round_to_away = bv_utils.equal(src, round_to_away);
}

bvt float_utilst::from_signed_integer(const bvt &src)
Expand Down Expand Up @@ -136,7 +139,7 @@
return result;
}

bvt float_utilst::build_constant(const ieee_floatt &src)
bvt float_utilst::build_constant(const ieee_float_valuet &src)
{
unbiased_floatt result;

Expand Down Expand Up @@ -990,12 +993,18 @@
literalt round_to_zero=
const_literal(false);

// round to away
literalt round_to_away = prop.lor(rounding_least, sticky_bit);

Check warning on line 998 in src/solvers/floatbv/float_utils.cpp

View check run for this annotation

Codecov / codecov/patch

src/solvers/floatbv/float_utils.cpp#L998

Added line #L998 was not covered by tests
// now select appropriate one
// clang-format off
return prop.lselect(rounding_mode_bits.round_to_even, round_to_even,
prop.lselect(rounding_mode_bits.round_to_plus_inf, round_to_plus_inf,
prop.lselect(rounding_mode_bits.round_to_minus_inf, round_to_minus_inf,
prop.lselect(rounding_mode_bits.round_to_zero, round_to_zero,
prop.new_variable())))); // otherwise non-det
prop.lselect(rounding_mode_bits.round_to_away, round_to_away,
prop.new_variable()))))); // otherwise non-det
// clang-format on
}

void float_utilst::round_fraction(unbiased_floatt &result)
Expand Down Expand Up @@ -1268,14 +1277,14 @@
return result;
}

ieee_floatt float_utilst::get(const bvt &src) const
ieee_float_valuet float_utilst::get(const bvt &src) const
{
mp_integer int_value=0;

for(std::size_t i=0; i<src.size(); i++)
int_value+=power(2, i)*prop.l_get(src[i]).is_true();

ieee_floatt result;
ieee_float_valuet result;
result.spec=spec;
result.unpack(int_value);

Expand Down
Loading
Loading