ceil.zig (5139B) - Raw
1 //! Ported from musl, which is MIT licensed. 2 //! https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT 3 //! 4 //! https://git.musl-libc.org/cgit/musl/tree/src/math/ceilf.c 5 //! https://git.musl-libc.org/cgit/musl/tree/src/math/ceil.c 6 7 const std = @import("std"); 8 const builtin = @import("builtin"); 9 const arch = builtin.cpu.arch; 10 const math = std.math; 11 const mem = std.mem; 12 const expect = std.testing.expect; 13 const common = @import("common.zig"); 14 15 pub const panic = common.panic; 16 17 comptime { 18 @export(&__ceilh, .{ .name = "__ceilh", .linkage = common.linkage, .visibility = common.visibility }); 19 @export(&ceilf, .{ .name = "ceilf", .linkage = common.linkage, .visibility = common.visibility }); 20 @export(&ceil, .{ .name = "ceil", .linkage = common.linkage, .visibility = common.visibility }); 21 @export(&__ceilx, .{ .name = "__ceilx", .linkage = common.linkage, .visibility = common.visibility }); 22 if (common.want_ppc_abi) { 23 @export(&ceilq, .{ .name = "ceilf128", .linkage = common.linkage, .visibility = common.visibility }); 24 } 25 @export(&ceilq, .{ .name = "ceilq", .linkage = common.linkage, .visibility = common.visibility }); 26 @export(&ceill, .{ .name = "ceill", .linkage = common.linkage, .visibility = common.visibility }); 27 } 28 29 pub fn __ceilh(x: f16) callconv(.c) f16 { 30 // TODO: more efficient implementation 31 return @floatCast(ceilf(x)); 32 } 33 34 pub fn ceilf(x: f32) callconv(.c) f32 { 35 var u: u32 = @bitCast(x); 36 const e = @as(i32, @intCast((u >> 23) & 0xFF)) - 0x7F; 37 var m: u32 = undefined; 38 39 // TODO: Shouldn't need this explicit check. 40 if (x == 0.0) { 41 return x; 42 } 43 44 if (e >= 23) { 45 return x; 46 } else if (e >= 0) { 47 m = @as(u32, 0x007FFFFF) >> @intCast(e); 48 if (u & m == 0) { 49 return x; 50 } 51 if (common.want_float_exceptions) mem.doNotOptimizeAway(x + 0x1.0p120); 52 if (u >> 31 == 0) { 53 u += m; 54 } 55 u &= ~m; 56 return @bitCast(u); 57 } else { 58 if (common.want_float_exceptions) mem.doNotOptimizeAway(x + 0x1.0p120); 59 if (u >> 31 != 0) { 60 return -0.0; 61 } else { 62 return 1.0; 63 } 64 } 65 } 66 67 pub fn ceil(x: f64) callconv(.c) f64 { 68 const f64_toint = 1.0 / math.floatEps(f64); 69 70 const u: u64 = @bitCast(x); 71 const e = (u >> 52) & 0x7FF; 72 var y: f64 = undefined; 73 74 if (e >= 0x3FF + 52 or x == 0) { 75 return x; 76 } 77 78 if (u >> 63 != 0) { 79 y = x - f64_toint + f64_toint - x; 80 } else { 81 y = x + f64_toint - f64_toint - x; 82 } 83 84 if (e <= 0x3FF - 1) { 85 if (common.want_float_exceptions) mem.doNotOptimizeAway(y); 86 if (u >> 63 != 0) { 87 return -0.0; 88 } else { 89 return 1.0; 90 } 91 } else if (y < 0) { 92 return x + y + 1; 93 } else { 94 return x + y; 95 } 96 } 97 98 pub fn __ceilx(x: f80) callconv(.c) f80 { 99 // TODO: more efficient implementation 100 return @floatCast(ceilq(x)); 101 } 102 103 pub fn ceilq(x: f128) callconv(.c) f128 { 104 const f128_toint = 1.0 / math.floatEps(f128); 105 106 const u: u128 = @bitCast(x); 107 const e = (u >> 112) & 0x7FFF; 108 var y: f128 = undefined; 109 110 if (e >= 0x3FFF + 112 or x == 0) return x; 111 112 if (u >> 127 != 0) { 113 y = x - f128_toint + f128_toint - x; 114 } else { 115 y = x + f128_toint - f128_toint - x; 116 } 117 118 if (e <= 0x3FFF - 1) { 119 if (common.want_float_exceptions) mem.doNotOptimizeAway(y); 120 if (u >> 127 != 0) { 121 return -0.0; 122 } else { 123 return 1.0; 124 } 125 } else if (y < 0) { 126 return x + y + 1; 127 } else { 128 return x + y; 129 } 130 } 131 132 pub fn ceill(x: c_longdouble) callconv(.c) c_longdouble { 133 switch (@typeInfo(c_longdouble).float.bits) { 134 16 => return __ceilh(x), 135 32 => return ceilf(x), 136 64 => return ceil(x), 137 80 => return __ceilx(x), 138 128 => return ceilq(x), 139 else => @compileError("unreachable"), 140 } 141 } 142 143 test "ceil32" { 144 try expect(ceilf(1.3) == 2.0); 145 try expect(ceilf(-1.3) == -1.0); 146 try expect(ceilf(0.2) == 1.0); 147 } 148 149 test "ceil64" { 150 try expect(ceil(1.3) == 2.0); 151 try expect(ceil(-1.3) == -1.0); 152 try expect(ceil(0.2) == 1.0); 153 } 154 155 test "ceil128" { 156 try expect(ceilq(1.3) == 2.0); 157 try expect(ceilq(-1.3) == -1.0); 158 try expect(ceilq(0.2) == 1.0); 159 } 160 161 test "ceil32.special" { 162 try expect(ceilf(0.0) == 0.0); 163 try expect(ceilf(-0.0) == -0.0); 164 try expect(math.isPositiveInf(ceilf(math.inf(f32)))); 165 try expect(math.isNegativeInf(ceilf(-math.inf(f32)))); 166 try expect(math.isNan(ceilf(math.nan(f32)))); 167 } 168 169 test "ceil64.special" { 170 try expect(ceil(0.0) == 0.0); 171 try expect(ceil(-0.0) == -0.0); 172 try expect(math.isPositiveInf(ceil(math.inf(f64)))); 173 try expect(math.isNegativeInf(ceil(-math.inf(f64)))); 174 try expect(math.isNan(ceil(math.nan(f64)))); 175 } 176 177 test "ceil128.special" { 178 try expect(ceilq(0.0) == 0.0); 179 try expect(ceilq(-0.0) == -0.0); 180 try expect(math.isPositiveInf(ceilq(math.inf(f128)))); 181 try expect(math.isNegativeInf(ceilq(-math.inf(f128)))); 182 try expect(math.isNan(ceilq(math.nan(f128)))); 183 }