From 61161132b63d641657df3f099511e2fa5062d0d1 Mon Sep 17 00:00:00 2001 From: mihael Date: Fri, 27 Mar 2026 22:45:56 +0100 Subject: [PATCH] `compiler_rt`: Dissolve `math_utils.zig` into `long_double.zig` & `trig.zig` The closest namespace the pi/4 constant could belong to is `trig.zig` since it's used across trig function implementations. On the other hand, chucking `long double` bit slicing functions into `trig.zig` seems a little more awkward, so they're put into their own namespace. --- lib/compiler_rt/cos.zig | 6 +++--- .../{math_utils.zig => long_double.zig} | 12 ++++++------ lib/compiler_rt/rem_pio2l.zig | 16 ++++++++-------- lib/compiler_rt/sin.zig | 6 +++--- lib/compiler_rt/sincos.zig | 6 +++--- lib/compiler_rt/tan.zig | 6 +++--- lib/compiler_rt/trig.zig | 3 +++ 7 files changed, 29 insertions(+), 26 deletions(-) rename lib/compiler_rt/{math_utils.zig => long_double.zig} (68%) diff --git a/lib/compiler_rt/cos.zig b/lib/compiler_rt/cos.zig index 3c4bc4adb43e05584c08d0842217249967c3d75a..582de530f5186b9d435081ad117ed6cf2d7e7f40 100644 --- a/lib/compiler_rt/cos.zig +++ b/lib/compiler_rt/cos.zig @@ -17,7 +17,7 @@ const trig = @import("trig.zig"); const rem_pio2 = @import("rem_pio2.zig").rem_pio2; const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f; const rem_pio2l = @import("rem_pio2l.zig").rem_pio2l; -const utils = @import("math_utils.zig"); +const ld = @import("long_double.zig"); comptime { symbol(&__cosh, "__cosh"); @@ -124,12 +124,12 @@ pub fn cos(x: f64) callconv(.c) f64 { } fn coslGeneric(comptime T: type, x: T) T { - const se = utils.ldSignExponent(x) & 0x7fff; + const se = ld.signExponent(x) & 0x7fff; if (se == 0x7fff) { return x - x; } - if (@abs(x) < utils.pi_4) { + if (@abs(x) < trig.pi_4) { if (se < 0x3fff - math.floatMantissaBits(T)) { // raise inexact if x!=0 return 1.0 + x; diff --git a/lib/compiler_rt/math_utils.zig b/lib/compiler_rt/long_double.zig similarity index 68% rename from lib/compiler_rt/math_utils.zig rename to lib/compiler_rt/long_double.zig index 70e6a4b3b71b252db9699ead62909d65cc688c55..8c018b529fe90c4815f575c5b3c0bf447c1d04b2 100644 --- a/lib/compiler_rt/math_utils.zig +++ b/lib/compiler_rt/long_double.zig @@ -1,11 +1,11 @@ +//! Utilities for dealing with the `long double` type (`f80` or `f128`) + const std = @import("std"); pub const U80 = std.meta.Int(.unsigned, 80); -/// pi divided by 4 -pub const pi_4 = 0.78539816339744830962; /// Returns the sign + exponent bits of a `long double` -pub fn ldSignExponent(x: anytype) u16 { +pub fn signExponent(x: anytype) u16 { const T = @TypeOf(x); switch (T) { f80 => { @@ -16,12 +16,12 @@ pub fn ldSignExponent(x: anytype) u16 { const bits: u128 = @bitCast(x); return @intCast(bits >> 112); }, - else => @compileError("`ldSignExponent` supports only `f80` and `f128`, got: " ++ @typeName(T)), + else => @compileError("`signExponent` supports only `f80` and `f128`, got: " ++ @typeName(T)), } } /// Takes the top 16 bits of a `long double`'s mantissa -pub fn ldMantissaTop(x: anytype) u16 { +pub fn mantissaTop(x: anytype) u16 { const T = @TypeOf(x); switch (T) { f80 => { @@ -32,6 +32,6 @@ pub fn ldMantissaTop(x: anytype) u16 { const bits: u128 = @bitCast(x); return @intCast((bits >> 96) & 0xFFFF); }, - else => @compileError("`ldMantissaTop` supports only `f80` and `f128`, got: " ++ @typeName(T)), + else => @compileError("`mantissaTop` supports only `f80` and `f128`, got: " ++ @typeName(T)), } } diff --git a/lib/compiler_rt/rem_pio2l.zig b/lib/compiler_rt/rem_pio2l.zig index 1ca9d170bcdcbbfbc065f23367581d9afc63e980..fe878f116d91204b000f6fba1d2e5280b15723da 100644 --- a/lib/compiler_rt/rem_pio2l.zig +++ b/lib/compiler_rt/rem_pio2l.zig @@ -6,7 +6,7 @@ const std = @import("std"); const math = std.math; -const utils = @import("math_utils.zig"); +const ld = @import("long_double.zig"); const rem_pio2_large = @import("rem_pio2_large.zig").rem_pio2_large; pub fn rem_pio2l(comptime T: type, x: T, y: *[2]T) i32 { @@ -34,8 +34,8 @@ pub fn rem_pio2l(comptime T: type, x: T, y: *[2]T) i32 { const pio2_3: f64 = 6.36831716351370313614e-25; // 0x18a2e037074000.0p-133 fn small(x_val: T) bool { - const se = utils.ldSignExponent(x_val); - const top = utils.ldMantissaTop(x_val); + const se = ld.signExponent(x_val); + const top = ld.mantissaTop(x_val); const lhs = (@as(u32, se & 0x7fff) << 16) | top; const rhs: u32 = ((0x3fff + 25) << 16) | 0x921f >> 1 | 0x8000; return lhs < rhs; @@ -62,8 +62,8 @@ pub fn rem_pio2l(comptime T: type, x: T, y: *[2]T) i32 { const pio2_3t: T = -2.5650587247459238361625433492959285e-65; fn small(x_val: T) bool { - const se = utils.ldSignExponent(x_val); - const top = utils.ldMantissaTop(x_val); + const se = ld.signExponent(x_val); + const top = ld.mantissaTop(x_val); const lhs = (@as(u32, se & 0x7fff) << 16) | top; const rhs: u32 = ((0x3fff + 45) << 16) | 0x921f; return lhs < rhs; @@ -77,7 +77,7 @@ pub fn rem_pio2l(comptime T: type, x: T, y: *[2]T) i32 { else => @compileError("rem_pio2l supports only f80 and f128, got: " ++ @typeName(T)), }; - const x_se = utils.ldSignExponent(x); + const x_se = ld.signExponent(x); const ex: i32 = @intCast(x_se & 0x7fff); if (impl.small(x)) { @@ -105,14 +105,14 @@ pub fn rem_pio2l(comptime T: type, x: T, y: *[2]T) i32 { y[0] = r - w; - const ey: i32 = @intCast(utils.ldSignExponent(y[0]) & 0x7fff); + const ey: i32 = @intCast(ld.signExponent(y[0]) & 0x7fff); if (ex - ey > impl.round1) { var t = r; w = fn_ * impl.pio2_2; r = t - w; w = fn_ * impl.pio2_2t - ((t - r) - w); y[0] = r - w; - const ey2: i32 = @intCast(utils.ldSignExponent(y[0]) & 0x7fff); + const ey2: i32 = @intCast(ld.signExponent(y[0]) & 0x7fff); if (ex - ey2 > impl.round2) { t = r; w = fn_ * impl.pio2_3; diff --git a/lib/compiler_rt/sin.zig b/lib/compiler_rt/sin.zig index ca8c9943bfcad2d047d2dea27f4d9dba8a17243b..0cff43997e06e31606cd0be4ffb66d3cb36203a2 100644 --- a/lib/compiler_rt/sin.zig +++ b/lib/compiler_rt/sin.zig @@ -17,7 +17,7 @@ const trig = @import("trig.zig"); const rem_pio2 = @import("rem_pio2.zig").rem_pio2; const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f; const rem_pio2l = @import("rem_pio2l.zig").rem_pio2l; -const utils = @import("math_utils.zig"); +const ld = @import("long_double.zig"); comptime { symbol(&__sinh, "__sinh"); @@ -134,12 +134,12 @@ pub fn sin(x: f64) callconv(.c) f64 { } fn sinlGeneric(comptime T: type, x: T) T { - const se = utils.ldSignExponent(x) & 0x7fff; + const se = ld.signExponent(x) & 0x7fff; if (se == 0x7fff) { return x - x; } - if (@abs(x) < utils.pi_4) { + if (@abs(x) < trig.pi_4) { if (se < 0x3fff - (math.floatMantissaBits(T) / 2)) { // raise inexact if x!=0 and underflow if subnormal if (compiler_rt.want_float_exceptions) { diff --git a/lib/compiler_rt/sincos.zig b/lib/compiler_rt/sincos.zig index bc43525fbe73143978bbb172aa1b7408d3fa6470..1616cc5556459503d5ac6fd9eeab045a9ba52c07 100644 --- a/lib/compiler_rt/sincos.zig +++ b/lib/compiler_rt/sincos.zig @@ -9,7 +9,7 @@ const trig = @import("trig.zig"); const rem_pio2 = @import("rem_pio2.zig").rem_pio2; const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f; const rem_pio2l = @import("rem_pio2l.zig").rem_pio2l; -const utils = @import("math_utils.zig"); +const ld = @import("long_double.zig"); const compiler_rt = @import("../compiler_rt.zig"); const symbol = compiler_rt.symbol; @@ -197,7 +197,7 @@ fn sincoslGeneric(comptime T: type, x: T, r_sin: *T, r_cos: *T) void { @compileError("`sincoslGeneric` implemented only for `f80` and `f128`, got: " ++ @typeName(T)); } - const se = utils.ldSignExponent(x) & 0x7fff; + const se = ld.signExponent(x) & 0x7fff; if (se == 0x7fff) { const result = x - x; r_sin.* = result; @@ -205,7 +205,7 @@ fn sincoslGeneric(comptime T: type, x: T, r_sin: *T, r_cos: *T) void { return; } - if (@abs(x) < utils.pi_4) { + if (@abs(x) < trig.pi_4) { if (se < 0x3fff - math.floatMantissaBits(T)) { // raise underflow if subnormal if (compiler_rt.want_float_exceptions and se == 0) { diff --git a/lib/compiler_rt/tan.zig b/lib/compiler_rt/tan.zig index 746982a0d6ac7657bcaffd000e92063c18d5b270..1f925e3e8c6c6abac73d65d33f39ff2680377b03 100644 --- a/lib/compiler_rt/tan.zig +++ b/lib/compiler_rt/tan.zig @@ -17,7 +17,7 @@ const kernel = @import("trig.zig"); const rem_pio2 = @import("rem_pio2.zig").rem_pio2; const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f; const rem_pio2l = @import("rem_pio2l.zig").rem_pio2l; -const utils = @import("math_utils.zig"); +const ld = @import("long_double.zig"); const arch = builtin.cpu.arch; const compiler_rt = @import("../compiler_rt.zig"); @@ -125,12 +125,12 @@ fn tanlGeneric(comptime T: type, x: T) T { @compileError("`tanlGeneric` implemented only for `f80` and `f128`, got: " ++ T); } - const se = utils.ldSignExponent(x) & 0x7fff; + const se = ld.signExponent(x) & 0x7fff; if (se == 0x7fff) { return x - x; } - if (@abs(x) < utils.pi_4) { + if (@abs(x) < kernel.pi_4) { if (se < 0x3fff - math.floatMantissaBits(T) / 2) { if (compiler_rt.want_float_exceptions) { mem.doNotOptimizeAway(if (se == 0) x * 0x1p-120 else x + 0x1p120); diff --git a/lib/compiler_rt/trig.zig b/lib/compiler_rt/trig.zig index 8a20f2c2ac03c452d0202f825b25471c8f158bab..e68089baeab1b6a9ff4cb818e81db5ca7e14952a 100644 --- a/lib/compiler_rt/trig.zig +++ b/lib/compiler_rt/trig.zig @@ -11,6 +11,9 @@ // https://git.musl-libc.org/cgit/musl/tree/src/math/__cosl.c // https://git.musl-libc.org/cgit/musl/tree/src/math/__tanl.c +/// pi divided by 4 +pub const pi_4 = 0.78539816339744830962; + /// kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164 /// Input x is assumed to be bounded by ~pi/4 in magnitude. /// Input y is the tail of x. -- 2.54.0