Skip to content

Commit a038d0c

Browse files
committed
introduce __CROVER_fmod functions
This will allow us to map the fmod family of library functions to appropriate backend operators.
1 parent 9a04436 commit a038d0c

File tree

12 files changed

+96
-18
lines changed

12 files changed

+96
-18
lines changed

src/ansi-c/c_typecheck_expr.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2567,6 +2567,30 @@ exprt c_typecheck_baset::do_special_functions(
25672567

25682568
return std::move(abs_expr);
25692569
}
2570+
else if(
2571+
identifier == CPROVER_PREFIX "fmod" ||
2572+
identifier == CPROVER_PREFIX "fmodf" ||
2573+
identifier == CPROVER_PREFIX "fmodl")
2574+
{
2575+
if(expr.arguments().size() != 2)
2576+
{
2577+
error().source_location = f_op.source_location();
2578+
error() << "fmod-functions expect two operands" << eom;
2579+
throw 0;
2580+
}
2581+
2582+
typecheck_function_call_arguments(expr);
2583+
2584+
// Note that the semantics differ from the
2585+
// "floating point remainder" operation as defined by IEEE.
2586+
// Note that these do not take a rounding mode.
2587+
binary_exprt fmod_expr(
2588+
expr.arguments()[0], ID_floatbv_mod, expr.arguments()[1]);
2589+
2590+
fmod_expr.add_source_location() = source_location;
2591+
2592+
return std::move(fmod_expr);
2593+
}
25702594
else if(identifier==CPROVER_PREFIX "allocate")
25712595
{
25722596
if(expr.arguments().size()!=2)

src/ansi-c/cprover_builtin_headers.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,11 @@ double __CPROVER_fabs(double x);
8686
long double __CPROVER_fabsl(long double x);
8787
float __CPROVER_fabsf(float x);
8888

89+
// modulo and remainder
90+
double __CPROVER_fmod(double, double);
91+
float __CPROVER_fmodf(float, float);
92+
long double __CPROVER_fmodl(long double, long double);
93+
8994
// arrays
9095
__CPROVER_bool __CPROVER_array_equal(const void *array1, const void *array2);
9196
// overwrite all of *dest (possibly using nondet values), even

src/ansi-c/library/cprover.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,11 @@ double __CPROVER_fabs(double);
117117
long double __CPROVER_fabsl(long double);
118118
float __CPROVER_fabsf(float);
119119

120+
// modulo and remainder
121+
double __CPROVER_fmod(double, double);
122+
float __CPROVER_fmodf(float, float);
123+
long double __CPROVER_fmodl(long double, long double);
124+
120125
// arrays
121126
//__CPROVER_bool __CPROVER_array_equal(const void *array1, const void *array2);
122127
void __CPROVER_array_copy(const void *dest, const void *src);

src/ansi-c/library/math.c

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2140,10 +2140,10 @@ long double __sort_of_CPROVER_remainderl (int rounding_mode, long double x, long
21402140
#define __CPROVER_FENV_H_INCLUDED
21412141
#endif
21422142

2143-
double __sort_of_CPROVER_remainder (int rounding_mode, double x, double y);
2144-
2145-
double fmod(double x, double y) { return __sort_of_CPROVER_remainder(FE_TOWARDZERO, x, y); }
2146-
2143+
double fmod(double x, double y)
2144+
{
2145+
return __CPROVER_fmod(x, y);
2146+
}
21472147

21482148
/* FUNCTION: fmodf */
21492149

@@ -2157,10 +2157,10 @@ double fmod(double x, double y) { return __sort_of_CPROVER_remainder(FE_TOWARDZE
21572157
#define __CPROVER_FENV_H_INCLUDED
21582158
#endif
21592159

2160-
float __sort_of_CPROVER_remainderf (int rounding_mode, float x, float y);
2161-
2162-
float fmodf(float x, float y) { return __sort_of_CPROVER_remainderf(FE_TOWARDZERO, x, y); }
2163-
2160+
float fmodf(float x, float y)
2161+
{
2162+
return __CPROVER_fmodf(x, y);
2163+
}
21642164

21652165
/* FUNCTION: fmodl */
21662166

@@ -2174,11 +2174,10 @@ float fmodf(float x, float y) { return __sort_of_CPROVER_remainderf(FE_TOWARDZER
21742174
#define __CPROVER_FENV_H_INCLUDED
21752175
#endif
21762176

2177-
long double __sort_of_CPROVER_remainderl (int rounding_mode, long double x, long double y);
2178-
2179-
long double fmodl(long double x, long double y) { return __sort_of_CPROVER_remainderl(FE_TOWARDZERO, x, y); }
2180-
2181-
2177+
long double fmodl(long double x, long double y)
2178+
{
2179+
return __CPROVER_fmodl(x, y);
2180+
}
21822181

21832182
/* ISO 9899:2011
21842183
*

src/solvers/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ SRC = $(BOOLEFORCE_SRC) \
102102
flattening/boolbv_equality.cpp \
103103
flattening/boolbv_extractbit.cpp \
104104
flattening/boolbv_extractbits.cpp \
105+
flattening/boolbv_floatbv_mod_rem.cpp \
105106
flattening/boolbv_floatbv_op.cpp \
106107
flattening/boolbv_get.cpp \
107108
flattening/boolbv_ieee_float_rel.cpp \

src/solvers/flattening/boolbv.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,12 +132,14 @@ bvt boolbvt::convert_bitvector(const exprt &expr)
132132
else if(expr.id()==ID_shl || expr.id()==ID_ashr || expr.id()==ID_lshr ||
133133
expr.id()==ID_rol || expr.id()==ID_ror)
134134
return convert_shift(to_shift_expr(expr));
135-
else if(expr.id()==ID_floatbv_plus || expr.id()==ID_floatbv_minus ||
136-
expr.id()==ID_floatbv_mult || expr.id()==ID_floatbv_div ||
137-
expr.id()==ID_floatbv_rem)
135+
else if(
136+
expr.id() == ID_floatbv_plus || expr.id() == ID_floatbv_minus ||
137+
expr.id() == ID_floatbv_mult || expr.id() == ID_floatbv_div)
138138
{
139139
return convert_floatbv_op(to_ieee_float_op_expr(expr));
140140
}
141+
else if(expr.id() == ID_floatbv_mod)
142+
return convert_floatbv_mod_rem(to_binary_expr(expr));
141143
else if(expr.id()==ID_floatbv_typecast)
142144
return convert_floatbv_typecast(to_floatbv_typecast_expr(expr));
143145
else if(expr.id()==ID_concatenation)

src/solvers/flattening/boolbv.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ class boolbvt:public arrayst
168168
virtual bvt convert_div(const div_exprt &expr);
169169
virtual bvt convert_mod(const mod_exprt &expr);
170170
virtual bvt convert_floatbv_op(const ieee_float_op_exprt &);
171+
virtual bvt convert_floatbv_mod_rem(const binary_exprt &);
171172
virtual bvt convert_floatbv_typecast(const floatbv_typecast_exprt &expr);
172173
virtual bvt convert_member(const member_exprt &expr);
173174
virtual bvt convert_with(const with_exprt &expr);
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*******************************************************************\
2+
3+
Module:
4+
5+
Author: Daniel Kroening, kroening@kroening.com
6+
7+
\*******************************************************************/
8+
9+
#include "boolbv.h"
10+
11+
#include <util/bitvector_types.h>
12+
13+
#include <solvers/floatbv/float_utils.h>
14+
15+
bvt boolbvt::convert_floatbv_mod_rem(const binary_exprt &expr)
16+
{
17+
// Note that the expressions do not have rounding modes
18+
// but float_utils requires one.
19+
20+
float_utilst float_utils(prop);
21+
22+
auto rm = bv_utils.build_constant(ieee_floatt::ROUND_TO_EVEN, 32);
23+
float_utils.set_rounding_mode(rm);
24+
25+
float_utils.spec = ieee_float_spect(to_floatbv_type(expr.type()));
26+
27+
bvt lhs_as_bv = convert_bv(expr.lhs());
28+
bvt rhs_as_bv = convert_bv(expr.rhs());
29+
30+
// float_utilst::rem implements lhs-(lhs/rhs)*rhs, which matches
31+
// neither fmod() nor IEEE
32+
return float_utils.rem(lhs_as_bv, rhs_as_bv);
33+
}

src/solvers/flattening/boolbv_floatbv_op.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,6 @@ bvt boolbvt::convert_floatbv_op(const ieee_float_op_exprt &expr)
111111
return float_utils.mul(lhs_as_bv, rhs_as_bv);
112112
else if(expr.id()==ID_floatbv_div)
113113
return float_utils.div(lhs_as_bv, rhs_as_bv);
114-
else if(expr.id()==ID_floatbv_rem)
115-
return float_utils.rem(lhs_as_bv, rhs_as_bv);
116114
else
117115
UNREACHABLE;
118116
}

src/util/ieee_float.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Author: Daniel Kroening, kroening@kroening.com
1212

1313
#include "arith_tools.h"
1414
#include "bitvector_types.h"
15+
#include "c_types.h"
1516
#include "invariant.h"
1617
#include "std_expr.h"
1718

@@ -55,6 +56,11 @@ void ieee_float_spect::from_type(const floatbv_typet &type)
5556
e=e-1; // no hidden bit
5657
}
5758

59+
constant_exprt ieee_floatt::rounding_mode_expr(rounding_modet rm)
60+
{
61+
return ::from_integer(static_cast<int>(rm), unsigned_int_type());
62+
}
63+
5864
void ieee_floatt::print(std::ostream &out) const
5965
{
6066
out << to_ansi_c_string();

0 commit comments

Comments
 (0)