╭ round.zig ────────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭ find file ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ ╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │ │ │http│ ssh │ │ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
.. aarch64_outline_atomics.zig absv.zig absvdi2.zig absvdi2_test.zig absvsi2.zig absvsi2_test.zig absvti2.zig absvti2_test.zig addf3.zig addf3_test.zig addvdi3.zig addvsi3.zig arm.zig atomics.zig aulldiv.zig aullrem.zig bitreverse.zig bitreversedi2_test.zig bitreversesi2_test.zig bitreverseti2_test.zig bswap.zig bswapdi2_test.zig bswapsi2_test.zig bswapti2_test.zig clear_cache.zig clzdi2_test.zig clzsi2_test.zig clzti2_test.zig cmp.zig cmpdi2_test.zig cmpsi2_test.zig cmpti2_test.zig comparedf2_test.zig comparef.zig comparesf2_test.zig cos.zig count0bits.zig ctzdi2_test.zig ctzsi2_test.zig ctzti2_test.zig divc3.zig divc3_test.zig divdf3.zig divdf3_test.zig divmodei4.zig divsf3.zig divsf3_test.zig divtf3.zig divtf3_test.zig divti3_test.zig divxf3.zig divxf3_test.zig emutls.zig exp.zig exp2.zig exp_f128.zig extendf.zig extendf_test.zig fabs.zig ffsdi2_test.zig ffssi2_test.zig ffsti2_test.zig float_from_int.zig float_from_int_test.zig floor_ceil.zig fma.zig fmax.zig fmin.zig fmod.zig fmodq_test.zig fmodx_test.zig hexagon.zig int.zig int_from_float.zig int_from_float_test.zig limb64.zig log.zig log10.zig log2.zig log_f128.zig memcpy.zig memmove.zig modti3_test.zig mulXi3.zig mulXi3_test.zig mulc3.zig mulc3_test.zig mulf3.zig mulf3_test.zig mulo.zig mulodi4_test.zig mulosi4_test.zig muloti4_test.zig mulvsi3.zig negdi2_test.zig negsi2_test.zig negti2_test.zig negv.zig negvdi2_test.zig negvsi2_test.zig negvti2_test.zig os_version_check.zig parity.zig paritydi2_test.zig paritysi2_test.zig parityti2_test.zig popcount.zig popcountdi2_test.zig popcountsi2_test.zig popcountti2_test.zig powiXf2.zig powiXf2_test.zig rem_pio2.zig rem_pio2_large.zig rem_pio2f.zig rem_pio2l.zig ╭─────────────────────────────────╮ │round.zig │ ╰─────────────────────────────────╯ shift.zig shift_test.zig sin.zig sincos.zig sqrt.zig ssp.zig stack_probe.zig subvdi3.zig subvsi3.zig tan.zig trig.zig trunc.zig truncf.zig truncf_test.zig ucmpdi2_test.zig ucmpsi2_test.zig ucmpti2_test.zig udivmod.zig udivmoddi4_test.zig udivmodei4.zig udivmodsi4_test.zig udivmodti4_test.zig
1 //! Ported from musl, which is licensed under the MIT license: 2 //! https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT 3 //! 4 //! https://git.musl-libc.org/cgit/musl/tree/src/math/roundf.c 5 //! https://git.musl-libc.org/cgit/musl/tree/src/math/round.c 6 7 const std = @import("std"); 8 const builtin = @import("builtin"); 9 const math = std.math; 10 const mem = std.mem; 11 const expect = std.testing.expect; 12 const arch = builtin.cpu.arch; 13 const compiler_rt = @import("../compiler_rt.zig"); 14 const symbol = compiler_rt.symbol; 15 16 comptime { 17 symbol(&__roundh, "__roundh"); 18 symbol(&roundf, "roundf"); 19 symbol(&round, "round"); 20 symbol(&__roundx, "__roundx"); 21 symbol(&roundq, "roundf128"); 22 symbol(&roundl, "roundl"); 23 } 24 25 fn __roundh(x: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { 26 return compiler_rt.f16.toAbi(round_f16(compiler_rt.f16.fromAbi(x))); 27 } 28 pub fn round_f16(x: f16) f16 { 29 // TODO: more efficient implementation 30 return @floatCast(round_f32(x)); 31 } 32 33 fn roundf(x: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { 34 return compiler_rt.f32.toAbi(round_f32(compiler_rt.f32.fromAbi(x))); 35 } 36 pub fn round_f32(x_: f32) f32 { 37 const f32_toint = 1.0 / math.floatEps(f32); 38 39 var x = x_; 40 const u: u32 = @bitCast(x); 41 const e = (u >> 23) & 0xFF; 42 var y: f32 = undefined; 43 44 if (e >= 0x7F + 23) { 45 return x; 46 } 47 if (u >> 31 != 0) { 48 x = -x; 49 } 50 if (e < 0x7F - 1) { 51 if (compiler_rt.want_float_exceptions) mem.doNotOptimizeAway(x + f32_toint); 52 return 0 * @as(f32, @bitCast(u)); 53 } 54 55 y = x + f32_toint - f32_toint - x; 56 if (y > 0.5) { 57 y = y + x - 1; 58 } else if (y <= -0.5) { 59 y = y + x + 1; 60 } else { 61 y = y + x; 62 } 63 64 if (u >> 31 != 0) { 65 return -y; 66 } else { 67 return y; 68 } 69 } 70 71 fn round(x: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { 72 return compiler_rt.f64.toAbi(round_f64(compiler_rt.f64.fromAbi(x))); 73 } 74 pub fn round_f64(x_: f64) f64 { 75 const f64_toint = 1.0 / math.floatEps(f64); 76 77 var x = x_; 78 const u: u64 = @bitCast(x); 79 const e = (u >> 52) & 0x7FF; 80 var y: f64 = undefined; 81 82 if (e >= 0x3FF + 52) { 83 return x; 84 } 85 if (u >> 63 != 0) { 86 x = -x; 87 } 88 if (e < 0x3ff - 1) { 89 if (compiler_rt.want_float_exceptions) mem.doNotOptimizeAway(x + f64_toint); 90 return 0 * @as(f64, @bitCast(u)); 91 } 92 93 y = x + f64_toint - f64_toint - x; 94 if (y > 0.5) { 95 y = y + x - 1; 96 } else if (y <= -0.5) { 97 y = y + x + 1; 98 } else { 99 y = y + x; 100 } 101 102 if (u >> 63 != 0) { 103 return -y; 104 } else { 105 return y; 106 } 107 } 108 109 fn __roundx(x: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { 110 return compiler_rt.f80.toAbi(round_f80(compiler_rt.f80.fromAbi(x))); 111 } 112 pub fn round_f80(x: f80) f80 { 113 // TODO: more efficient implementation 114 return @floatCast(round_f128(x)); 115 } 116 117 fn roundq(x: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { 118 return compiler_rt.f128.toAbi(round_f128(compiler_rt.f128.fromAbi(x))); 119 } 120 pub fn round_f128(x_: f128) f128 { 121 const f128_toint = 1.0 / math.floatEps(f128); 122 123 var x = x_; 124 const u: u128 = @bitCast(x); 125 const e = (u >> 112) & 0x7FFF; 126 var y: f128 = undefined; 127 128 if (e >= 0x3FFF + 112) { 129 return x; 130 } 131 if (u >> 127 != 0) { 132 x = -x; 133 } 134 if (e < 0x3FFF - 1) { 135 if (compiler_rt.want_float_exceptions) mem.doNotOptimizeAway(x + f128_toint); 136 return 0 * @as(f128, @bitCast(u)); 137 } 138 139 y = x + f128_toint - f128_toint - x; 140 if (y > 0.5) { 141 y = y + x - 1; 142 } else if (y <= -0.5) { 143 y = y + x + 1; 144 } else { 145 y = y + x; 146 } 147 148 if (u >> 127 != 0) { 149 return -y; 150 } else { 151 return y; 152 } 153 } 154 155 pub fn roundl(x: c_longdouble) callconv(.c) c_longdouble { 156 switch (@typeInfo(c_longdouble).float.bits) { 157 64 => return round_f64(x), 158 80 => return round_f80(x), 159 128 => return round_f128(x), 160 else => comptime unreachable, 161 } 162 } 163 164 test round_f16 { 165 try expect(round_f16(1.3) == 1.0); 166 try expect(round_f16(-1.3) == -1.0); 167 try expect(round_f16(1.8) == 2.0); 168 try expect(round_f16(-1.8) == -2.0); 169 try expect(math.isPositiveZero(round_f16(0.2))); 170 try expect(math.isNegativeZero(round_f16(-0.2))); 171 try expect(math.isPositiveZero(round_f16(0.0))); 172 try expect(math.isNegativeZero(round_f16(-0.0))); 173 try expect(math.isPositiveInf(round_f16(math.inf(f32)))); 174 try expect(math.isNegativeInf(round_f16(-math.inf(f32)))); 175 try expect(math.isNan(round_f16(math.nan(f32)))); 176 } 177 178 test round_f32 { 179 try expect(round_f32(1.3) == 1.0); 180 try expect(round_f32(-1.3) == -1.0); 181 try expect(round_f32(1.8) == 2.0); 182 try expect(round_f32(-1.8) == -2.0); 183 try expect(math.isPositiveZero(round_f32(0.2))); 184 try expect(math.isNegativeZero(round_f32(-0.2))); 185 try expect(math.isPositiveZero(round_f32(0.0))); 186 try expect(math.isNegativeZero(round_f32(-0.0))); 187 try expect(math.isPositiveInf(round_f32(math.inf(f32)))); 188 try expect(math.isNegativeInf(round_f32(-math.inf(f32)))); 189 try expect(math.isNan(round_f32(math.nan(f32)))); 190 } 191 192 test round_f64 { 193 try expect(round_f64(1.3) == 1.0); 194 try expect(round_f64(-1.3) == -1.0); 195 try expect(round_f64(1.8) == 2.0); 196 try expect(round_f64(-1.8) == -2.0); 197 try expect(math.isPositiveZero(round_f64(0.2))); 198 try expect(math.isNegativeZero(round_f64(-0.2))); 199 try expect(math.isPositiveZero(round_f64(0.0))); 200 try expect(math.isNegativeZero(round_f64(-0.0))); 201 try expect(math.isPositiveInf(round_f64(math.inf(f64)))); 202 try expect(math.isNegativeInf(round_f64(-math.inf(f64)))); 203 try expect(math.isNan(round_f64(math.nan(f64)))); 204 } 205 206 test round_f80 { 207 try expect(round_f80(1.3) == 1.0); 208 try expect(round_f80(-1.3) == -1.0); 209 try expect(round_f80(1.8) == 2.0); 210 try expect(round_f80(-1.8) == -2.0); 211 try expect(math.isPositiveZero(round_f80(0.2))); 212 try expect(math.isNegativeZero(round_f80(-0.2))); 213 try expect(math.isPositiveZero(round_f80(0.0))); 214 try expect(math.isNegativeZero(round_f80(-0.0))); 215 try expect(math.isPositiveInf(round_f80(math.inf(f64)))); 216 try expect(math.isNegativeInf(round_f80(-math.inf(f64)))); 217 try expect(math.isNan(round_f80(math.nan(f64)))); 218 } 219 220 test round_f128 { 221 try expect(round_f128(1.3) == 1.0); 222 try expect(round_f128(-1.3) == -1.0); 223 try expect(round_f128(1.8) == 2.0); 224 try expect(round_f128(-1.8) == -2.0); 225 try expect(math.isPositiveZero(round_f128(0.2))); 226 try expect(math.isNegativeZero(round_f128(-0.2))); 227 try expect(math.isPositiveZero(round_f128(0.0))); 228 try expect(math.isNegativeZero(round_f128(-0.0))); 229 try expect(math.isPositiveInf(round_f128(math.inf(f128)))); 230 try expect(math.isNegativeInf(round_f128(-math.inf(f128)))); 231 try expect(math.isNan(round_f128(math.nan(f128)))); 232 } 233