diff options
| author | Andrew Kelley <superjoe30@gmail.com> | 2017-06-19 14:36:33 -0400 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2017-06-19 14:36:33 -0400 |
| commit | c9fc8bd802f5ed52c4cc78b93f18fc5dc9b6bb7f (patch) | |
| tree | 8ddb992d7c1b4ede1b6a99e32fad16c1a476e0c1 /std/math/fmod.zig | |
| parent | 799c69910172a7248ab9db366e6e3a6556e7d626 (diff) | |
| download | zig-c9fc8bd802f5ed52c4cc78b93f18fc5dc9b6bb7f.tar.gz zig-c9fc8bd802f5ed52c4cc78b93f18fc5dc9b6bb7f.zip | |
workaround for llvm bug
See #393 for details
Diffstat (limited to 'std/math/fmod.zig')
| -rw-r--r-- | std/math/fmod.zig | 190 |
1 files changed, 0 insertions, 190 deletions
diff --git a/std/math/fmod.zig b/std/math/fmod.zig deleted file mode 100644 index 8cc9586bc0..0000000000 --- a/std/math/fmod.zig +++ /dev/null @@ -1,190 +0,0 @@ -const math = @import("index.zig"); -const assert = @import("../debug.zig").assert; - -pub fn fmod(comptime T: type, x: T, y: T) -> T { - switch (T) { - f32 => @inlineCall(fmod32, x, y), - f64 => @inlineCall(fmod64, x, y), - else => @compileError("fmod not implemented for " ++ @typeName(T)), - } -} - -fn fmod32(x: f32, y: f32) -> f32 { - var ux = @bitCast(u32, x); - var uy = @bitCast(u32, y); - var ex = i32(ux >> 23) & 0xFF; - var ey = i32(ux >> 23) & 0xFF; - const sx = ux & 0x80000000; - - if (uy << 1 == 0 or math.isNan(y) or ex == 0xFF) { - return (x * y) / (x * y); - } - if (ux << 1 <= uy << 1) { - if (ux << 1 == uy << 1) { - return 0 * x; - } else { - return x; - } - } - - // normalize x and y - if (ex == 0) { - var i = ux << 9; - while (i >> 31 == 0) : (i <<= 1) { - ex -= 1; - } - ux <<= u32(-ex + 1); - } else { - ux &= @maxValue(u32) >> 9; - ux |= 1 << 23; - } - - if (ey == 0) { - var i = uy << 9; - while (i >> 31 == 0) : (i <<= 1) { - ey -= 1; - } - uy <<= u32(-ey + 1); - } else { - uy &= @maxValue(u32) >> 9; - uy |= 1 << 23; - } - - // x mod y - while (ex > ey) : (ex -= 1) { - const i = ux - uy; - if (i >> 31 == 0) { - if (i == 0) { - return 0 * x; - } - ux = i; - } - ux <<= 1; - } - { - const i = ux - uy; - if (i >> 31 == 0) { - if (i == 0) { - return 0 * x; - } - ux = i; - } - } - - while (ux >> 23 == 0) : (ux <<= 1) { - ex -= 1; - } - - // scale result up - if (ex > 0) { - ux -= 1 << 23; - ux |= u32(ex) << 23; - } else { - ux >>= u32(-ex + 1); - } - - ux |= sx; - @bitCast(f32, ux) -} - -fn fmod64(x: f64, y: f64) -> f64 { - var ux = @bitCast(u64, x); - var uy = @bitCast(u64, y); - var ex = i32(ux >> 52) & 0x7FF; - var ey = i32(ux >> 52) & 0x7FF; - const sx = ux >> 63; - - if (uy << 1 == 0 or math.isNan(y) or ex == 0x7FF) { - return (x * y) / (x * y); - } - if (ux << 1 <= uy << 1) { - if (ux << 1 == uy << 1) { - return 0 * x; - } else { - return x; - } - } - - // normalize x and y - if (ex == 0) { - var i = ux << 12; - while (i >> 63 == 0) : (i <<= 1) { - ex -= 1; - } - ux <<= u64(-ex + 1); - } else { - ux &= @maxValue(u64) >> 12; - ux |= 1 << 52; - } - - if (ey == 0) { - var i = uy << 12; - while (i >> 63 == 0) : (i <<= 1) { - ey -= 1; - } - uy <<= u64(-ey + 1); - } else { - uy &= @maxValue(u64) >> 12; - uy |= 1 << 52; - } - - // x mod y - while (ex > ey) : (ex -= 1) { - const i = ux - uy; - if (i >> 63 == 0) { - if (i == 0) { - return 0 * x; - } - ux = i; - } - ux <<= 1; - } - { - const i = ux - uy; - if (i >> 63 == 0) { - if (i == 0) { - return 0 * x; - } - ux = i; - } - } - - while (ux >> 52 == 0) : (ux <<= 1) { - ex -= 1; - } - - // scale result up - if (ex > 0) { - ux -= 1 << 52; - ux |= u64(ex) << 52; - } else { - ux >>= u64(-ex + 1); - } - - ux |= sx << 63; - @bitCast(f64, ux) -} - -// duplicate symbol clash with `fmod` test name -test "fmod_" { - assert(fmod(f32, 1.3, 2.5) == fmod32(1.3, 2.5)); - assert(fmod(f64, 1.3, 2.5) == fmod64(1.3, 2.5)); -} - -test "fmod32" { - const epsilon = 0.000001; - - assert(math.approxEq(f32, fmod32(5.2, 2.0), 1.2, epsilon)); - assert(math.approxEq(f32, fmod32(18.5, 4.2), 1.7, epsilon)); - assert(math.approxEq(f32, fmod32(23, 48.34), 23.0, epsilon)); - assert(math.approxEq(f32, fmod32(123.340890, 2398.2314), 123.340889, epsilon)); -} - -test "fmod64" { - const epsilon = 0.000001; - - assert(math.approxEq(f64, fmod64(5.2, 2.0), 1.2, epsilon)); - assert(math.approxEq(f64, fmod64(18.5, 4.2), 1.7, epsilon)); - assert(math.approxEq(f64, fmod64(23, 48.34), 23.0, epsilon)); - assert(math.approxEq(f64, fmod64(123.340890, 2398.2314), 123.340889, epsilon)); -} |
