Skip to content

Commit 49c66f4

Browse files
committed
Cleanup fmod vs IEEE remainder
1. Add tests for both the C and Java front-end. 2. Make sure we support both variants of the modulus operator on floating-point values in the back-ends: the SMT back-end only supported remainder (and only for FPA mode), the propositional back-end did not distinguish between fmod and IEEE remainder.
1 parent 45fa2ca commit 49c66f4

File tree

31 files changed

+209
-176
lines changed

31 files changed

+209
-176
lines changed
884 Bytes
Binary file not shown.
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
class farith2
2+
{
3+
public static void main(String[] args)
4+
{
5+
// examples from
6+
// https://stackoverflow.com/questions/2947044/how-do-i-use-modulus-for-float-double
7+
// and
8+
// https://stackoverflow.com/questions/25734144/difference-between-c-functions-remainder-and-fmod
9+
double d1 = 0.5 % 0.3;
10+
assert d1 == 0.2;
11+
double d2 = (-0.5) % 0.3;
12+
assert d2 == -0.2;
13+
double x = 7.5, y = 2.1;
14+
double xModY = x % y;
15+
assert xModY > 1.19 && xModY < 1.21;
16+
}
17+
}

regression/cbmc-library/__sort_of_CPROVER_remainder-01/test.desc renamed to jbmc/regression/jbmc/farith2/test.desc

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
KNOWNBUG
2-
main.c
3-
--pointer-check --bounds-check
1+
CORE
2+
farith2
3+
44
^EXIT=0$
55
^SIGNAL=0$
66
^VERIFICATION SUCCESSFUL$

regression/cbmc-library/__sort_of_CPROVER_remainder-01/main.c

-9
This file was deleted.

regression/cbmc-library/__sort_of_CPROVER_remainderf-01/main.c

-9
This file was deleted.

regression/cbmc-library/__sort_of_CPROVER_remainderf-01/test.desc

-8
This file was deleted.

regression/cbmc-library/__sort_of_CPROVER_remainderl-01/main.c

-9
This file was deleted.

regression/cbmc-library/__sort_of_CPROVER_remainderl-01/test.desc

-8
This file was deleted.

regression/cbmc-library/fmod-01/main.c

+11-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,15 @@
33

44
int main()
55
{
6-
fmod();
7-
assert(0);
8-
return 0;
6+
// examples from
7+
// https://stackoverflow.com/questions/2947044/how-do-i-use-modulus-for-float-double
8+
// and
9+
// https://stackoverflow.com/questions/25734144/difference-between-c-functions-remainder-and-fmod
10+
double d1 = fmod(0.5, 0.3);
11+
assert(d1 == 0.2);
12+
double d2 = fmod(-0.5, 0.3);
13+
assert(d2 == -0.2);
14+
double x = 7.5, y = 2.1;
15+
double xModY = fmod(x, y);
16+
assert(xModY > 1.19 && xModY < 1.21);
917
}

regression/cbmc-library/fmod-01/test.desc

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
KNOWNBUG
1+
CORE
22
main.c
3-
--pointer-check --bounds-check
3+
--float-overflow-check --nan-check
44
^EXIT=0$
55
^SIGNAL=0$
66
^VERIFICATION SUCCESSFUL$

regression/cbmc-library/fmodf-01/main.c

+11-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,15 @@
33

44
int main()
55
{
6-
fmodf();
7-
assert(0);
8-
return 0;
6+
// examples from
7+
// https://stackoverflow.com/questions/2947044/how-do-i-use-modulus-for-float-double
8+
// and
9+
// https://stackoverflow.com/questions/25734144/difference-between-c-functions-remainder-and-fmod
10+
float d1 = fmodf(0.5f, 0.3f);
11+
assert(d1 > 0.19f && d1 < 0.21f);
12+
float d2 = fmodf(-0.5f, 0.3f);
13+
assert(d2 > -0.21f && d2 < -0.19f);
14+
float x = 7.5f, y = 2.1f;
15+
float xModY = fmodf(x, y);
16+
assert(xModY > 1.19f && xModY < 1.21f);
917
}

regression/cbmc-library/fmodf-01/test.desc

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
KNOWNBUG
1+
CORE
22
main.c
3-
--pointer-check --bounds-check
3+
--float-overflow-check --nan-check
44
^EXIT=0$
55
^SIGNAL=0$
66
^VERIFICATION SUCCESSFUL$

regression/cbmc-library/fmodl-01/main.c

+11-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,15 @@
33

44
int main()
55
{
6-
fmodl();
7-
assert(0);
8-
return 0;
6+
// examples from
7+
// https://stackoverflow.com/questions/2947044/how-do-i-use-modulus-for-float-double
8+
// and
9+
// https://stackoverflow.com/questions/25734144/difference-between-c-functions-remainder-and-fmod
10+
long double d1 = fmodl(0.5l, 0.3l);
11+
assert(d1 == 0.2l);
12+
long double d2 = fmodl(-0.5l, 0.3l);
13+
assert(d2 == -0.2l);
14+
long double x = 7.5l, y = 2.1l;
15+
long double xModY = fmodl(x, y);
16+
assert(xModY > 1.19l && xModY < 1.21l);
917
}

regression/cbmc-library/fmodl-01/test.desc

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
KNOWNBUG
1+
CORE
22
main.c
3-
--pointer-check --bounds-check
3+
--float-overflow-check --nan-check
44
^EXIT=0$
55
^SIGNAL=0$
66
^VERIFICATION SUCCESSFUL$

regression/cbmc-library/remainder-01/main.c

+5-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33

44
int main()
55
{
6-
remainder();
7-
assert(0);
8-
return 0;
6+
// example from
7+
// https://stackoverflow.com/questions/25734144/difference-between-c-functions-remainder-and-fmod
8+
double x = 7.5, y = 2.1;
9+
double xModY = remainder(x, y);
10+
assert(xModY > -0.91 && xModY < -0.89);
911
}

regression/cbmc-library/remainder-01/test.desc

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
KNOWNBUG
1+
CORE
22
main.c
3-
--pointer-check --bounds-check
3+
--float-overflow-check --nan-check
44
^EXIT=0$
55
^SIGNAL=0$
66
^VERIFICATION SUCCESSFUL$

regression/cbmc-library/remainderf-01/main.c

+5-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33

44
int main()
55
{
6-
remainderf();
7-
assert(0);
8-
return 0;
6+
// example from
7+
// https://stackoverflow.com/questions/25734144/difference-between-c-functions-remainder-and-fmod
8+
float x = 7.5f, y = 2.1f;
9+
float xModY = remainderf(x, y);
10+
assert(xModY > -0.91f && xModY < -0.89f);
911
}

regression/cbmc-library/remainderf-01/test.desc

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
KNOWNBUG
1+
CORE
22
main.c
3-
--pointer-check --bounds-check
3+
--float-overflow-check --nan-check
44
^EXIT=0$
55
^SIGNAL=0$
66
^VERIFICATION SUCCESSFUL$

regression/cbmc-library/remainderl-01/main.c

+5-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33

44
int main()
55
{
6-
remainderl();
7-
assert(0);
8-
return 0;
6+
// example from
7+
// https://stackoverflow.com/questions/25734144/difference-between-c-functions-remainder-and-fmod
8+
long double x = 7.5l, y = 2.1l;
9+
long double xModY = remainderl(x, y);
10+
assert(xModY > -0.91l && xModY < -0.89l);
911
}

regression/cbmc-library/remainderl-01/test.desc

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
KNOWNBUG
1+
CORE
22
main.c
3-
--pointer-check --bounds-check
3+
--float-overflow-check --nan-check
44
^EXIT=0$
55
^SIGNAL=0$
66
^VERIFICATION SUCCESSFUL$

src/ansi-c/expr2c.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -4091,6 +4091,7 @@ optionalt<std::string> expr2ct::convert_function(const exprt &src)
40914091
{ID_separate, "SEPARATE"},
40924092
{ID_floatbv_div, "FLOAT/"},
40934093
{ID_floatbv_minus, "FLOAT-"},
4094+
{ID_floatbv_mod, "fmod"},
40944095
{ID_floatbv_mult, "FLOAT*"},
40954096
{ID_floatbv_plus, "FLOAT+"},
40964097
{ID_floatbv_rem, "FLOAT%"},

src/ansi-c/library/math.c

+12-83
Original file line numberDiff line numberDiff line change
@@ -2186,60 +2186,6 @@ long double __sort_of_CPROVER_round_to_integrall (int rounding_mode, long double
21862186
return (x - *iptr);
21872187
}
21882188

2189-
2190-
2191-
/* FUNCTION: __sort_of_CPROVER_remainder */
2192-
// TODO : Should be a real __CPROVER function to convert to SMT-LIB
2193-
double __sort_of_CPROVER_round_to_integral (int rounding_mode, double d);
2194-
2195-
double __sort_of_CPROVER_remainder (int rounding_mode, double x, double y)
2196-
{
2197-
if (x == 0.0 || __CPROVER_isinfd(y))
2198-
return x;
2199-
2200-
// Extended precision helps... a bit...
2201-
long double div = x/y;
2202-
long double n = __sort_of_CPROVER_round_to_integral(rounding_mode,div);
2203-
long double res = (-y * n) + x; // TODO : FMA would be an improvement
2204-
return res;
2205-
}
2206-
2207-
/* FUNCTION: __sort_of_CPROVER_remainderf */
2208-
// TODO : Should be a real __CPROVER function to convert to SMT-LIB
2209-
2210-
float __sort_of_CPROVER_round_to_integralf (int rounding_mode, float d);
2211-
2212-
float __sort_of_CPROVER_remainderf (int rounding_mode, float x, float y)
2213-
{
2214-
if (x == 0.0f || __CPROVER_isinff(y))
2215-
return x;
2216-
2217-
// Extended precision helps... a bit...
2218-
long double div = x/y;
2219-
long double n = __sort_of_CPROVER_round_to_integral(rounding_mode,div);
2220-
long double res = (-y * n) + x; // TODO : FMA would be an improvement
2221-
return res;
2222-
}
2223-
2224-
/* FUNCTION: __sort_of_CPROVER_remainderl */
2225-
// TODO : Should be a real __CPROVER function to convert to SMT-LIB
2226-
2227-
long double __sort_of_CPROVER_round_to_integrall (int rounding_mode, long double d);
2228-
2229-
long double __sort_of_CPROVER_remainderl (int rounding_mode, long double x, long double y)
2230-
{
2231-
if (x == 0.0 || __CPROVER_isinfld(y))
2232-
return x;
2233-
2234-
// Extended precision helps... a bit...
2235-
long double div = x/y;
2236-
long double n = __sort_of_CPROVER_round_to_integral(rounding_mode,div);
2237-
long double res = (-y * n) + x; // TODO : FMA would be an improvement
2238-
return res;
2239-
}
2240-
2241-
2242-
22432189
/* ISO 9899:2011
22442190
*
22452191
* The fmod functions return the value x - ny, for some
@@ -2320,15 +2266,10 @@ long double fmodl(long double x, long double y)
23202266
#define __CPROVER_MATH_H_INCLUDED
23212267
#endif
23222268

2323-
#ifndef __CPROVER_FENV_H_INCLUDED
2324-
#include <fenv.h>
2325-
#define __CPROVER_FENV_H_INCLUDED
2326-
#endif
2327-
2328-
double __sort_of_CPROVER_remainder (int rounding_mode, double x, double y);
2329-
2330-
double remainder(double x, double y) { return __sort_of_CPROVER_remainder(FE_TONEAREST, x, y); }
2331-
2269+
double remainder(double x, double y)
2270+
{
2271+
return __CPROVER_remainder(x, y);
2272+
}
23322273

23332274
/* FUNCTION: remainderf */
23342275

@@ -2337,15 +2278,10 @@ double remainder(double x, double y) { return __sort_of_CPROVER_remainder(FE_TON
23372278
#define __CPROVER_MATH_H_INCLUDED
23382279
#endif
23392280

2340-
#ifndef __CPROVER_FENV_H_INCLUDED
2341-
#include <fenv.h>
2342-
#define __CPROVER_FENV_H_INCLUDED
2343-
#endif
2344-
2345-
float __sort_of_CPROVER_remainderf (int rounding_mode, float x, float y);
2346-
2347-
float remainderf(float x, float y) { return __sort_of_CPROVER_remainderf(FE_TONEAREST, x, y); }
2348-
2281+
float remainderf(float x, float y)
2282+
{
2283+
return __CPROVER_remainderf(x, y);
2284+
}
23492285

23502286
/* FUNCTION: remainderl */
23512287

@@ -2354,17 +2290,10 @@ float remainderf(float x, float y) { return __sort_of_CPROVER_remainderf(FE_TONE
23542290
#define __CPROVER_MATH_H_INCLUDED
23552291
#endif
23562292

2357-
#ifndef __CPROVER_FENV_H_INCLUDED
2358-
#include <fenv.h>
2359-
#define __CPROVER_FENV_H_INCLUDED
2360-
#endif
2361-
2362-
long double __sort_of_CPROVER_remainderl (int rounding_mode, long double x, long double y);
2363-
2364-
long double remainderl(long double x, long double y) { return __sort_of_CPROVER_remainderl(FE_TONEAREST, x, y); }
2365-
2366-
2367-
2293+
long double remainderl(long double x, long double y)
2294+
{
2295+
return __CPROVER_remainderl(x, y);
2296+
}
23682297

23692298
/* ISO 9899:2011
23702299
* The copysign functions produce a value with the magnitude of x and

src/goto-programs/adjust_float_expressions.cpp

+5-7
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,11 @@ irep_idt rounding_mode_identifier()
3131
/// yet.
3232
static bool have_to_adjust_float_expressions(const exprt &expr)
3333
{
34-
if(expr.id()==ID_floatbv_plus ||
35-
expr.id()==ID_floatbv_minus ||
36-
expr.id()==ID_floatbv_mult ||
37-
expr.id()==ID_floatbv_div ||
38-
expr.id()==ID_floatbv_div ||
39-
expr.id()==ID_floatbv_rem ||
40-
expr.id()==ID_floatbv_typecast)
34+
if(
35+
expr.id() == ID_floatbv_plus || expr.id() == ID_floatbv_minus ||
36+
expr.id() == ID_floatbv_mult || expr.id() == ID_floatbv_div ||
37+
expr.id() == ID_floatbv_mod || expr.id() == ID_floatbv_rem ||
38+
expr.id() == ID_floatbv_typecast)
4139
return false;
4240

4341
const typet &type = expr.type();

src/solvers/flattening/boolbv_floatbv_mod_rem.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ bvt boolbvt::convert_floatbv_mod_rem(const binary_exprt &expr)
1919

2020
float_utilst float_utils(prop);
2121

22-
auto rm = bv_utils.build_constant(ieee_floatt::ROUND_TO_EVEN, 32);
22+
auto rm = bv_utils.build_constant(
23+
expr.id() == ID_floatbv_rem ? ieee_floatt::ROUND_TO_EVEN
24+
: ieee_floatt::ROUND_TO_ZERO,
25+
32);
2326
float_utils.set_rounding_mode(rm);
2427

2528
float_utils.spec = ieee_float_spect(to_floatbv_type(expr.type()));

0 commit comments

Comments
 (0)