authorgravatar for info@bnoordhuis.nlBen Noordhuis <info@bnoordhuis.nl> 2018-06-20 21:51:18+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-06-20 17:37:38-04:00
logeb6a8e6a3bba061c4a7fb18f53976e1fb683c3d4
tree137d90a657f1b6fe178f4eba4436c7ebfa2638b0
parent4eca75c53b4679e7e31df1505d22a5b618a2d797

fix f128 remainder division bug

The modulo operation computed rem(b+rem(a,b), b) which produces -1 for a=1 and b=2. Switch to a - b * trunc(a/b) which produces the expected result, 1. closes #1137

2 files changed, 23 insertions(+), 3 deletions(-)

src/ir.cpp+9-3
......@@ -7710,6 +7710,14 @@ static void float_rem(ConstExprValue *out_val, ConstExprValue *op1, ConstExprVal
77107710 }
77117711}
77127712
7713// c = a - b * trunc(a / b)
7714static void zig_f128M_mod(const float128_t* a, const float128_t* b, float128_t* c) {
7715 f128M_div(a, b, c);
7716 f128M_roundToInt(c, softfloat_round_min, true, c);
7717 f128M_mul(b, c, c);
7718 f128M_sub(a, c, c);
7719}
7720
77137721static void float_mod(ConstExprValue *out_val, ConstExprValue *op1, ConstExprValue *op2) {
77147722 assert(op1->type == op2->type);
77157723 out_val->type = op1->type;
......@@ -7724,9 +7732,7 @@ static void float_mod(ConstExprValue *out_val, ConstExprValue *op1, ConstExprVal
77247732 out_val->data.x_f64 = fmod(fmod(op1->data.x_f64, op2->data.x_f64) + op2->data.x_f64, op2->data.x_f64);
77257733 return;
77267734 case 128:
7727 f128M_rem(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128);
7728 f128M_add(&out_val->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128);
7729 f128M_rem(&out_val->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128);
7735 zig_f128M_mod(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128);
77307736 return;
77317737 default:
77327738 zig_unreachable();
test/cases/math.zig+14
......@@ -434,6 +434,20 @@ test "comptime float rem int" {
434434 }
435435}
436436
437test "remainder division" {
438 comptime remdiv(f32);
439 comptime remdiv(f64);
440 comptime remdiv(f128);
441 remdiv(f32);
442 remdiv(f64);
443 remdiv(f128);
444}
445
446fn remdiv(comptime T: type) void {
447 assert(T(1) == T(1) % T(2));
448 assert(T(1) == T(7) % T(3));
449}
450
437451test "@sqrt" {
438452 testSqrt(f64, 12.0);
439453 comptime testSqrt(f64, 12.0);