diff options
| author | Marc Tiehuis <marctiehuis@gmail.com> | 2017-06-16 20:26:10 +1200 |
|---|---|---|
| committer | Marc Tiehuis <marctiehuis@gmail.com> | 2017-06-16 20:32:31 +1200 |
| commit | 4c16f9a3c35b23b9917f2a27b91ba8cd20e6fd82 (patch) | |
| tree | 778f0f06734f7dc17e9269ee1cf5b513f7b504c0 /std/math/ceil.zig | |
| parent | 865b53f2860405a718262abf9a794d2bf9529dbc (diff) | |
| download | zig-4c16f9a3c35b23b9917f2a27b91ba8cd20e6fd82.tar.gz zig-4c16f9a3c35b23b9917f2a27b91ba8cd20e6fd82.zip | |
Add math library
This covers the majority of the functions as covered by the C99
specification for a math library.
Code is adapted primarily from musl libc, with the pow and standard
trigonometric functions adapted from the Go stdlib.
Changes:
- Remove assert expose in index and import as needed.
- Add float log function and merge with existing base 2 integer
implementation.
See https://github.com/tiehuis/zig-fmath.
See #374.
Diffstat (limited to 'std/math/ceil.zig')
| -rw-r--r-- | std/math/ceil.zig | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/std/math/ceil.zig b/std/math/ceil.zig new file mode 100644 index 0000000000..f80e493f1f --- /dev/null +++ b/std/math/ceil.zig @@ -0,0 +1,89 @@ +const builtin = @import("builtin"); +const math = @import("index.zig"); +const assert = @import("../debug.zig").assert; + +pub fn ceil(x: var) -> @typeOf(x) { + const T = @typeOf(x); + switch (T) { + f32 => @inlineCall(ceil32, x), + f64 => @inlineCall(ceil64, x), + else => @compileError("ceil not implemented for " ++ @typeName(T)), + } +} + +fn ceil32(x: f32) -> f32 { + var u = @bitCast(u32, x); + var e = i32((u >> 23) & 0xFF) - 0x7F; + var m: u32 = undefined; + + if (e >= 23) { + return x; + } + else if (e >= 0) { + m = 0x007FFFFF >> u32(e); + if (u & m == 0) { + return x; + } + math.forceEval(x + 0x1.0p120); + if (u >> 31 == 0) { + u += m; + } + u &= ~m; + @bitCast(f32, u) + } else { + math.forceEval(x + 0x1.0p120); + if (u >> 31 != 0) { + return -0.0; + } else { + 1.0 + } + } +} + +fn ceil64(x: f64) -> f64 { + const u = @bitCast(u64, x); + const e = (u >> 52) & 0x7FF; + var y: f64 = undefined; + + if (e >= 0x3FF+52 or x == 0) { + return x; + } + + if (u >> 63 != 0) { + @setFloatMode(this, builtin.FloatMode.Strict); + y = x - math.f64_toint + math.f64_toint - x; + } else { + @setFloatMode(this, builtin.FloatMode.Strict); + y = x + math.f64_toint - math.f64_toint - x; + } + + if (e <= 0x3FF-1) { + math.forceEval(y); + if (u >> 63 != 0) { + return -0.0; // Compiler requires return. + } else { + 1.0 + } + } else if (y < 0) { + x + y + 1 + } else { + x + y + } +} + +test "ceil" { + assert(ceil(f32(0.0)) == ceil32(0.0)); + assert(ceil(f64(0.0)) == ceil64(0.0)); +} + +test "ceil32" { + assert(ceil32(1.3) == 2.0); + assert(ceil32(-1.3) == -1.0); + assert(ceil32(0.2) == 1.0); +} + +test "ceil64" { + assert(ceil64(1.3) == 2.0); + assert(ceil64(-1.3) == -1.0); + assert(ceil64(0.2) == 1.0); +} |
