Skip to content

Commit

Permalink
ieee_floatt: introduce NOT_SET rounding mode
Browse files Browse the repository at this point in the history
This adds a new rounding mode to ieee_floatt, NOT_SET, which is the default
when constructing the object without rounding mode.

Operations that require a rounding mode fail when the rounding mode is NOT_SET.
  • Loading branch information
kroening committed Dec 22, 2024
1 parent c4aaafd commit 0409105
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 27 deletions.
2 changes: 1 addition & 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,7 @@ exprt convert_float_literal(const std::string &src)
// but these aren't handled anywhere
}

ieee_floatt a(type);
ieee_floatt a(type, ieee_floatt::rounding_modet::ROUND_TO_EVEN);

if(parsed_float.exponent_base==10)
a.from_base10(parsed_float.significand, parsed_float.exponent);
Expand Down
3 changes: 3 additions & 0 deletions src/solvers/floatbv/float_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ class float_utilst

switch(mode)
{
case ieee_floatt::NOT_SET:
PRECONDITION(false);

case ieee_floatt::ROUND_TO_EVEN:
round_to_even=const_literal(true);
break;
Expand Down
16 changes: 16 additions & 0 deletions src/util/ieee_float.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,8 @@ void ieee_floatt::build(
const mp_integer &_fraction,
const mp_integer &_exponent)
{
PRECONDITION(rounding_mode != rounding_modet::NOT_SET);

sign_flag=_fraction<0;
fraction=_fraction;
if(sign_flag)
Expand All @@ -488,6 +490,8 @@ void ieee_floatt::from_base10(
const mp_integer &_fraction,
const mp_integer &_exponent)
{
PRECONDITION(rounding_mode != rounding_modet::NOT_SET);

NaN_flag=infinity_flag=false;
sign_flag=_fraction<0;
fraction=_fraction;
Expand Down Expand Up @@ -584,6 +588,9 @@ void ieee_floatt::align()
// we need to consider the rounding mode here
switch(rounding_mode)
{
case NOT_SET:
PRECONDITION(false);

case UNKNOWN:
case NONDETERMINISTIC:
case ROUND_TO_EVEN:
Expand Down Expand Up @@ -660,6 +667,9 @@ void ieee_floatt::divide_and_round(
{
switch(rounding_mode)
{
case NOT_SET:
PRECONDITION(false);

case ROUND_TO_EVEN:
{
mp_integer divisor_middle = divisor / 2;
Expand Down Expand Up @@ -708,6 +718,7 @@ constant_exprt ieee_floatt::to_expr() const
ieee_floatt &ieee_floatt::operator/=(const ieee_floatt &other)
{
PRECONDITION(other.spec.f == spec.f);
PRECONDITION(rounding_mode != rounding_modet::NOT_SET);

// NaN/x = NaN
if(NaN_flag)
Expand Down Expand Up @@ -782,6 +793,7 @@ ieee_floatt &ieee_floatt::operator/=(const ieee_floatt &other)
ieee_floatt &ieee_floatt::operator*=(const ieee_floatt &other)
{
PRECONDITION(other.spec.f == spec.f);
PRECONDITION(rounding_mode != rounding_modet::NOT_SET);

if(other.NaN_flag)
make_NaN();
Expand Down Expand Up @@ -818,6 +830,8 @@ ieee_floatt &ieee_floatt::operator*=(const ieee_floatt &other)
ieee_floatt &ieee_floatt::operator+=(const ieee_floatt &other)
{
PRECONDITION(other.spec == spec);
PRECONDITION(rounding_mode != rounding_modet::NOT_SET);

ieee_floatt _other=other;

if(other.NaN_flag)
Expand Down Expand Up @@ -1058,6 +1072,8 @@ bool ieee_floatt::ieee_not_equal(const ieee_floatt &other) const

void ieee_floatt::change_spec(const ieee_float_spect &dest_spec)
{
PRECONDITION(rounding_mode != rounding_modet::NOT_SET);

mp_integer _exponent=exponent-spec.f;
mp_integer _fraction=fraction;

Expand Down
72 changes: 50 additions & 22 deletions src/util/ieee_float.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,22 +121,29 @@ class ieee_floatt
// what is recommended in C11 5.2.4.2.2
enum rounding_modet
{
ROUND_TO_EVEN=0, ROUND_TO_MINUS_INF=1,
ROUND_TO_PLUS_INF=2, ROUND_TO_ZERO=3,
UNKNOWN, NONDETERMINISTIC
ROUND_TO_EVEN = 0,
ROUND_TO_MINUS_INF = 1,
ROUND_TO_PLUS_INF = 2,
ROUND_TO_ZERO = 3,
UNKNOWN,
NONDETERMINISTIC,
NOT_SET
};

// A helper to turn a rounding mode into a constant bitvector expression
static constant_exprt rounding_mode_expr(rounding_modet);

rounding_modet rounding_mode;
rounding_modet rounding_mode = rounding_modet::NOT_SET;

ieee_float_spect spec;

explicit ieee_floatt(const ieee_float_spect &_spec):
rounding_mode(ROUND_TO_EVEN),
spec(_spec), sign_flag(false), exponent(0), fraction(0),
NaN_flag(false), infinity_flag(false)
explicit ieee_floatt(const ieee_float_spect &_spec)
: spec(_spec),
sign_flag(false),
exponent(0),
fraction(0),
NaN_flag(false),
infinity_flag(false)
{
}

Expand All @@ -151,26 +158,47 @@ class ieee_floatt
{
}

explicit ieee_floatt(const floatbv_typet &type):
rounding_mode(ROUND_TO_EVEN),
spec(ieee_float_spect(type)),
sign_flag(false),
exponent(0),
fraction(0),
NaN_flag(false),
infinity_flag(false)
explicit ieee_floatt(const floatbv_typet &type)
: spec(ieee_float_spect(type)),
sign_flag(false),
exponent(0),
fraction(0),
NaN_flag(false),
infinity_flag(false)
{
}

ieee_floatt():
rounding_mode(ROUND_TO_EVEN),
sign_flag(false), exponent(0), fraction(0),
NaN_flag(false), infinity_flag(false)
explicit ieee_floatt(
const floatbv_typet &type,
rounding_modet __rounding_mode)
: rounding_mode(__rounding_mode),
spec(ieee_float_spect(type)),
sign_flag(false),
exponent(0),
fraction(0),
NaN_flag(false),
infinity_flag(false)
{
}

explicit ieee_floatt(const constant_exprt &expr):
rounding_mode(ROUND_TO_EVEN)
ieee_floatt()
: sign_flag(false),
exponent(0),
fraction(0),
NaN_flag(false),
infinity_flag(false)
{
}

explicit ieee_floatt(const constant_exprt &expr)
{
from_expr(expr);
}

explicit ieee_floatt(
const constant_exprt &expr,
rounding_modet __rounding_mode)
: rounding_mode(__rounding_mode)
{
from_expr(expr);
}
Expand Down
11 changes: 8 additions & 3 deletions src/util/simplify_expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ simplify_exprt::resultt<> simplify_exprt::simplify_abs(const abs_exprt &expr)

if(type.id()==ID_floatbv)
{
// Does not need rounding
ieee_floatt value(to_constant_expr(to_unary_expr(expr).op()));
value.set_sign(false);
return value.to_expr();
Expand Down Expand Up @@ -104,6 +105,7 @@ simplify_exprt::resultt<> simplify_exprt::simplify_sign(const sign_exprt &expr)

if(type.id()==ID_floatbv)
{
// Does not need rounding
ieee_floatt value(to_constant_expr(expr.op()));
return make_boolean_expr(value.get_sign());
}
Expand Down Expand Up @@ -1179,7 +1181,7 @@ simplify_exprt::simplify_typecast(const typecast_exprt &expr)
const floatbv_typet &f_expr_type=
to_floatbv_type(expr_type);

ieee_floatt f(f_expr_type);
ieee_floatt f(f_expr_type, ieee_floatt::rounding_modet::ROUND_TO_EVEN);
f.from_integer(int_value);

return f.to_expr();
Expand Down Expand Up @@ -1215,7 +1217,9 @@ simplify_exprt::simplify_typecast(const typecast_exprt &expr)
}
else if(op_type_id==ID_floatbv)
{
ieee_floatt f(to_constant_expr(expr.op()));
ieee_floatt f{
to_constant_expr(expr.op()),
ieee_floatt::rounding_modet::ROUND_TO_EVEN};

if(expr_type_id==ID_unsignedbv ||
expr_type_id==ID_signedbv)
Expand All @@ -1233,7 +1237,7 @@ simplify_exprt::simplify_typecast(const typecast_exprt &expr)
{
fixedbvt fixedbv;
fixedbv.spec=fixedbv_spect(to_fixedbv_type(expr_type));
ieee_floatt factor(f.spec);
ieee_floatt factor(f.spec, ieee_floatt::rounding_modet::ROUND_TO_EVEN);
factor.from_integer(power(2, fixedbv.spec.get_fraction_bits()));
f*=factor;
fixedbv.set_value(f.to_integer());
Expand Down Expand Up @@ -1267,6 +1271,7 @@ simplify_exprt::simplify_typecast(const typecast_exprt &expr)
{
const auto width = to_bv_type(op_type).get_width();
const auto int_value = bvrep2integer(value, width, false);
// Does not need rounding.
ieee_floatt ieee_float{to_floatbv_type(expr_type)};
ieee_float.unpack(int_value);
return ieee_float.to_expr();
Expand Down
3 changes: 2 additions & 1 deletion src/util/simplify_expr_int.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1889,7 +1889,8 @@ simplify_exprt::resultt<> simplify_exprt::simplify_inequality_rhs_is_constant(
expr.op0().id() == ID_typecast && expr.op0().type().id() == ID_floatbv &&
to_typecast_expr(expr.op0()).op().type().id() == ID_floatbv)
{
ieee_floatt const_val(to_constant_expr(expr.op1()));
ieee_floatt const_val{
to_constant_expr(expr.op1()), ieee_floatt::rounding_modet::ROUND_TO_EVEN};
ieee_floatt const_val_converted=const_val;
const_val_converted.change_spec(ieee_float_spect(
to_floatbv_type(to_typecast_expr(expr.op0()).op().type())));
Expand Down

0 comments on commit 0409105

Please sign in to comment.