zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit eb6a8e6a3bba061c4a7fb18f53976e1fb683c3d4 (tree)
parent 4eca75c53b4679e7e31df1505d22a5b618a2d797
Author: Ben Noordhuis <info@bnoordhuis.nl>
Date:   Wed, 20 Jun 2018 21:51:18 +0200

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

Diffstat:
Msrc/ir.cpp | 12+++++++++---
Mtest/cases/math.zig | 14++++++++++++++
2 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/src/ir.cpp b/src/ir.cpp @@ -7710,6 +7710,14 @@ static void float_rem(ConstExprValue *out_val, ConstExprValue *op1, ConstExprVal } } +// c = a - b * trunc(a / b) +static void zig_f128M_mod(const float128_t* a, const float128_t* b, float128_t* c) { + f128M_div(a, b, c); + f128M_roundToInt(c, softfloat_round_min, true, c); + f128M_mul(b, c, c); + f128M_sub(a, c, c); +} + static void float_mod(ConstExprValue *out_val, ConstExprValue *op1, ConstExprValue *op2) { assert(op1->type == op2->type); out_val->type = op1->type; @@ -7724,9 +7732,7 @@ static void float_mod(ConstExprValue *out_val, ConstExprValue *op1, ConstExprVal out_val->data.x_f64 = fmod(fmod(op1->data.x_f64, op2->data.x_f64) + op2->data.x_f64, op2->data.x_f64); return; case 128: - f128M_rem(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128); - f128M_add(&out_val->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128); - f128M_rem(&out_val->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128); + zig_f128M_mod(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128); return; default: zig_unreachable(); diff --git a/test/cases/math.zig b/test/cases/math.zig @@ -434,6 +434,20 @@ test "comptime float rem int" { } } +test "remainder division" { + comptime remdiv(f32); + comptime remdiv(f64); + comptime remdiv(f128); + remdiv(f32); + remdiv(f64); + remdiv(f128); +} + +fn remdiv(comptime T: type) void { + assert(T(1) == T(1) % T(2)); + assert(T(1) == T(7) % T(3)); +} + test "@sqrt" { testSqrt(f64, 12.0); comptime testSqrt(f64, 12.0);