Skip to content

Commit

Permalink
Try all rounding modes when domain is unknown
Browse files Browse the repository at this point in the history
For rounding modes in constant propagator domain
  • Loading branch information
hannes-steffenhagen-diffblue committed Apr 18, 2018
1 parent d236828 commit d737d60
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include <fenv.h>
#include <stdio.h>
#include <assert.h>

int nondet_rounding_mode(void);

int main(void)
{
// slightly bigger than 0.1
float f = 1.0f / 10.0f;

// now we don't know what rounding mode we're in
__CPROVER_rounding_mode = nondet_rounding_mode();
// depending on rounding mode 1.0f/10.0f could
// be greater or smaller than 0.1

// definitely not smaller than -0.1
assert((1.0f / 10.0f) - f < -0.1f);
// might be smaller than 0
assert((1.0f / 10.0f) - f < 0.0f);
// definitely smaller or equal to 0
assert((1.0f / 10.0f) - f <= 0.0f);
// might be greater or equal to 0
assert((1.0f / 10.0f) - f >= 0.0f);
// definitely not greater than 0
assert((1.0f / 10.0f) - f > 0.0f);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
CORE
main.c
--constants --verify
^EXIT=0$
^SIGNAL=0$
\[main.assertion.1\] file main.c line 18 function main, assertion \(1.0f / 10.0f\) - f < -0.1f: Failure \(if reachable\)
\[main.assertion.2\] file main.c line 20 function main, assertion \(1.0f / 10.0f\) - f < 0.0f: Unknown
\[main.assertion.3\] file main.c line 22 function main, assertion \(1.0f / 10.0f\) - f <= 0.0f: Success
\[main.assertion.4\] file main.c line 24 function main, assertion \(1.0f / 10.0f\) - f >= 0.0f: Unknown
\[main.assertion.5\] file main.c line 26 function main, assertion \(1.0f / 10.0f\) - f > 0.0f: Failure \(if reachable\)

--
^warning: ignoring
41 changes: 41 additions & 0 deletions src/analyses/constant_propagator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ Author: Peter Schrammel

#include <langapi/language_util.h>
#include <goto-programs/adjust_float_expressions.h>
#include <util/ieee_float.h>

#include <algorithm>
#include <array>

void constant_propagator_domaint::assign_rec(
valuest &values,
Expand Down Expand Up @@ -509,7 +513,44 @@ bool constant_propagator_domaint::try_evaluate(
exprt &expr,
const namespacet &ns) const
{
const irep_idt ID_rounding_mode = CPROVER_PREFIX "rounding_mode";
adjust_float_expressions(expr, ns);

// if the current rounding mode is top we can
// still get a non-top result by trying all rounding
// modes and checking if the results are all the same
if(!values.is_constant(symbol_exprt(ID_rounding_mode)))
{
// NOLINTNEXTLINE(whitespace/braces)
auto rounding_modes = std::array<ieee_floatt::rounding_modet, 4>{
ieee_floatt::ROUND_TO_EVEN,
ieee_floatt::ROUND_TO_ZERO,
ieee_floatt::ROUND_TO_MINUS_INF,
ieee_floatt::ROUND_TO_PLUS_INF};
// instead of 4, we could write rounding_modes.size() here
// if we dropped Visual Studio 2013 support (no constexpr)
std::array<exprt, 4> possible_results;
for(std::size_t i = 0; i < possible_results.size(); ++i)
{
constant_propagator_domaint child(*this);
child.values.set_to(
ID_rounding_mode, from_integer(rounding_modes[i], integer_typet()));
possible_results[i] = expr;
if(child.try_evaluate(possible_results[i], ns))
{
return true;
}
}
for(auto const &possible_result : possible_results)
{
if(possible_result != possible_results.front())
{
return true;
}
}
expr = possible_results.front();
return false;
}
bool did_not_change_anything = values.replace_const.replace(expr);
did_not_change_anything &= simplify(expr, ns);
return did_not_change_anything;
Expand Down

0 comments on commit d737d60

Please sign in to comment.