| author | |
| committer | |
| log | 61161132b63d641657df3f099511e2fa5062d0d1 |
| tree | 61053d284233594caffbc28c3aa9621d1b82ea64 |
| parent | f6ac1a6e05cbd46f646cf09e036921ca282694cf |
| signature |
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.8 files changed, 60 insertions(+), 57 deletions(-)
lib/compiler_rt/cos.zig+3-3| ... | @@ -17,7 +17,7 @@ const trig = @import("trig.zig"); | ... | @@ -17,7 +17,7 @@ const trig = @import("trig.zig"); |
| 17 | const rem_pio2 = @import("rem_pio2.zig").rem_pio2; | 17 | const rem_pio2 = @import("rem_pio2.zig").rem_pio2; |
| 18 | const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f; | 18 | const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f; |
| 19 | const rem_pio2l = @import("rem_pio2l.zig").rem_pio2l; | 19 | const rem_pio2l = @import("rem_pio2l.zig").rem_pio2l; |
| 20 | const utils = @import("math_utils.zig"); | 20 | const ld = @import("long_double.zig"); |
| 21 | 21 | ||
| 22 | comptime { | 22 | comptime { |
| 23 | symbol(&__cosh, "__cosh"); | 23 | symbol(&__cosh, "__cosh"); |
| ... | @@ -124,12 +124,12 @@ pub fn cos(x: f64) callconv(.c) f64 { | ... | @@ -124,12 +124,12 @@ pub fn cos(x: f64) callconv(.c) f64 { |
| 124 | } | 124 | } |
| 125 | 125 | ||
| 126 | fn coslGeneric(comptime T: type, x: T) T { | 126 | fn coslGeneric(comptime T: type, x: T) T { |
| 127 | const se = utils.ldSignExponent(x) & 0x7fff; | 127 | const se = ld.signExponent(x) & 0x7fff; |
| 128 | if (se == 0x7fff) { | 128 | if (se == 0x7fff) { |
| 129 | return x - x; | 129 | return x - x; |
| 130 | } | 130 | } |
| 131 | 131 | ||
| 132 | if (@abs(x) < utils.pi_4) { | 132 | if (@abs(x) < trig.pi_4) { |
| 133 | if (se < 0x3fff - math.floatMantissaBits(T)) { | 133 | if (se < 0x3fff - math.floatMantissaBits(T)) { |
| 134 | // raise inexact if x!=0 | 134 | // raise inexact if x!=0 |
| 135 | return 1.0 + x; | 135 | return 1.0 + x; |
lib/compiler_rt/long_double.zig created+37| ... | @@ -0,0 +1,37 @@ | ||
| 1 | //! Utilities for dealing with the `long double` type (`f80` or `f128`) | ||
| 2 | |||
| 3 | const std = @import("std"); | ||
| 4 | |||
| 5 | pub const U80 = std.meta.Int(.unsigned, 80); | ||
| 6 | |||
| 7 | /// Returns the sign + exponent bits of a `long double` | ||
| 8 | pub fn signExponent(x: anytype) u16 { | ||
| 9 | const T = @TypeOf(x); | ||
| 10 | switch (T) { | ||
| 11 | f80 => { | ||
| 12 | const bits: U80 = @bitCast(x); | ||
| 13 | return @intCast(bits >> 64); | ||
| 14 | }, | ||
| 15 | f128 => { | ||
| 16 | const bits: u128 = @bitCast(x); | ||
| 17 | return @intCast(bits >> 112); | ||
| 18 | }, | ||
| 19 | else => @compileError("`signExponent` supports only `f80` and `f128`, got: " ++ @typeName(T)), | ||
| 20 | } | ||
| 21 | } | ||
| 22 | |||
| 23 | /// Takes the top 16 bits of a `long double`'s mantissa | ||
| 24 | pub fn mantissaTop(x: anytype) u16 { | ||
| 25 | const T = @TypeOf(x); | ||
| 26 | switch (T) { | ||
| 27 | f80 => { | ||
| 28 | const bits: U80 = @bitCast(x); | ||
| 29 | return @intCast((bits >> 48) & 0xFFFF); | ||
| 30 | }, | ||
| 31 | f128 => { | ||
| 32 | const bits: u128 = @bitCast(x); | ||
| 33 | return @intCast((bits >> 96) & 0xFFFF); | ||
| 34 | }, | ||
| 35 | else => @compileError("`mantissaTop` supports only `f80` and `f128`, got: " ++ @typeName(T)), | ||
| 36 | } | ||
| 37 | } | ||
lib/compiler_rt/math_utils.zig deleted-37| ... | @@ -1,37 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub const U80 = std.meta.Int(.unsigned, 80); | ||
| 4 | /// pi divided by 4 | ||
| 5 | pub const pi_4 = 0.78539816339744830962; | ||
| 6 | |||
| 7 | /// Returns the sign + exponent bits of a `long double` | ||
| 8 | pub fn ldSignExponent(x: anytype) u16 { | ||
| 9 | const T = @TypeOf(x); | ||
| 10 | switch (T) { | ||
| 11 | f80 => { | ||
| 12 | const bits: U80 = @bitCast(x); | ||
| 13 | return @intCast(bits >> 64); | ||
| 14 | }, | ||
| 15 | f128 => { | ||
| 16 | const bits: u128 = @bitCast(x); | ||
| 17 | return @intCast(bits >> 112); | ||
| 18 | }, | ||
| 19 | else => @compileError("`ldSignExponent` supports only `f80` and `f128`, got: " ++ @typeName(T)), | ||
| 20 | } | ||
| 21 | } | ||
| 22 | |||
| 23 | /// Takes the top 16 bits of a `long double`'s mantissa | ||
| 24 | pub fn ldMantissaTop(x: anytype) u16 { | ||
| 25 | const T = @TypeOf(x); | ||
| 26 | switch (T) { | ||
| 27 | f80 => { | ||
| 28 | const bits: U80 = @bitCast(x); | ||
| 29 | return @intCast((bits >> 48) & 0xFFFF); | ||
| 30 | }, | ||
| 31 | f128 => { | ||
| 32 | const bits: u128 = @bitCast(x); | ||
| 33 | return @intCast((bits >> 96) & 0xFFFF); | ||
| 34 | }, | ||
| 35 | else => @compileError("`ldMantissaTop` supports only `f80` and `f128`, got: " ++ @typeName(T)), | ||
| 36 | } | ||
| 37 | } | ||
lib/compiler_rt/rem_pio2l.zig+8-8| ... | @@ -6,7 +6,7 @@ | ... | @@ -6,7 +6,7 @@ |
| 6 | const std = @import("std"); | 6 | const std = @import("std"); |
| 7 | const math = std.math; | 7 | const math = std.math; |
| 8 | 8 | ||
| 9 | const utils = @import("math_utils.zig"); | 9 | const ld = @import("long_double.zig"); |
| 10 | const rem_pio2_large = @import("rem_pio2_large.zig").rem_pio2_large; | 10 | const rem_pio2_large = @import("rem_pio2_large.zig").rem_pio2_large; |
| 11 | 11 | ||
| 12 | pub fn rem_pio2l(comptime T: type, x: T, y: *[2]T) i32 { | 12 | 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 { | ... | @@ -34,8 +34,8 @@ pub fn rem_pio2l(comptime T: type, x: T, y: *[2]T) i32 { |
| 34 | const pio2_3: f64 = 6.36831716351370313614e-25; // 0x18a2e037074000.0p-133 | 34 | const pio2_3: f64 = 6.36831716351370313614e-25; // 0x18a2e037074000.0p-133 |
| 35 | 35 | ||
| 36 | fn small(x_val: T) bool { | 36 | fn small(x_val: T) bool { |
| 37 | const se = utils.ldSignExponent(x_val); | 37 | const se = ld.signExponent(x_val); |
| 38 | const top = utils.ldMantissaTop(x_val); | 38 | const top = ld.mantissaTop(x_val); |
| 39 | const lhs = (@as(u32, se & 0x7fff) << 16) | top; | 39 | const lhs = (@as(u32, se & 0x7fff) << 16) | top; |
| 40 | const rhs: u32 = ((0x3fff + 25) << 16) | 0x921f >> 1 | 0x8000; | 40 | const rhs: u32 = ((0x3fff + 25) << 16) | 0x921f >> 1 | 0x8000; |
| 41 | return lhs < rhs; | 41 | return lhs < rhs; |
| ... | @@ -62,8 +62,8 @@ pub fn rem_pio2l(comptime T: type, x: T, y: *[2]T) i32 { | ... | @@ -62,8 +62,8 @@ pub fn rem_pio2l(comptime T: type, x: T, y: *[2]T) i32 { |
| 62 | const pio2_3t: T = -2.5650587247459238361625433492959285e-65; | 62 | const pio2_3t: T = -2.5650587247459238361625433492959285e-65; |
| 63 | 63 | ||
| 64 | fn small(x_val: T) bool { | 64 | fn small(x_val: T) bool { |
| 65 | const se = utils.ldSignExponent(x_val); | 65 | const se = ld.signExponent(x_val); |
| 66 | const top = utils.ldMantissaTop(x_val); | 66 | const top = ld.mantissaTop(x_val); |
| 67 | const lhs = (@as(u32, se & 0x7fff) << 16) | top; | 67 | const lhs = (@as(u32, se & 0x7fff) << 16) | top; |
| 68 | const rhs: u32 = ((0x3fff + 45) << 16) | 0x921f; | 68 | const rhs: u32 = ((0x3fff + 45) << 16) | 0x921f; |
| 69 | return lhs < rhs; | 69 | return lhs < rhs; |
| ... | @@ -77,7 +77,7 @@ pub fn rem_pio2l(comptime T: type, x: T, y: *[2]T) i32 { | ... | @@ -77,7 +77,7 @@ pub fn rem_pio2l(comptime T: type, x: T, y: *[2]T) i32 { |
| 77 | else => @compileError("rem_pio2l supports only f80 and f128, got: " ++ @typeName(T)), | 77 | else => @compileError("rem_pio2l supports only f80 and f128, got: " ++ @typeName(T)), |
| 78 | }; | 78 | }; |
| 79 | 79 | ||
| 80 | const x_se = utils.ldSignExponent(x); | 80 | const x_se = ld.signExponent(x); |
| 81 | const ex: i32 = @intCast(x_se & 0x7fff); | 81 | const ex: i32 = @intCast(x_se & 0x7fff); |
| 82 | 82 | ||
| 83 | if (impl.small(x)) { | 83 | if (impl.small(x)) { |
| ... | @@ -105,14 +105,14 @@ pub fn rem_pio2l(comptime T: type, x: T, y: *[2]T) i32 { | ... | @@ -105,14 +105,14 @@ pub fn rem_pio2l(comptime T: type, x: T, y: *[2]T) i32 { |
| 105 | 105 | ||
| 106 | y[0] = r - w; | 106 | y[0] = r - w; |
| 107 | 107 | ||
| 108 | const ey: i32 = @intCast(utils.ldSignExponent(y[0]) & 0x7fff); | 108 | const ey: i32 = @intCast(ld.signExponent(y[0]) & 0x7fff); |
| 109 | if (ex - ey > impl.round1) { | 109 | if (ex - ey > impl.round1) { |
| 110 | var t = r; | 110 | var t = r; |
| 111 | w = fn_ * impl.pio2_2; | 111 | w = fn_ * impl.pio2_2; |
| 112 | r = t - w; | 112 | r = t - w; |
| 113 | w = fn_ * impl.pio2_2t - ((t - r) - w); | 113 | w = fn_ * impl.pio2_2t - ((t - r) - w); |
| 114 | y[0] = r - w; | 114 | y[0] = r - w; |
| 115 | const ey2: i32 = @intCast(utils.ldSignExponent(y[0]) & 0x7fff); | 115 | const ey2: i32 = @intCast(ld.signExponent(y[0]) & 0x7fff); |
| 116 | if (ex - ey2 > impl.round2) { | 116 | if (ex - ey2 > impl.round2) { |
| 117 | t = r; | 117 | t = r; |
| 118 | w = fn_ * impl.pio2_3; | 118 | w = fn_ * impl.pio2_3; |
lib/compiler_rt/sin.zig+3-3| ... | @@ -17,7 +17,7 @@ const trig = @import("trig.zig"); | ... | @@ -17,7 +17,7 @@ const trig = @import("trig.zig"); |
| 17 | const rem_pio2 = @import("rem_pio2.zig").rem_pio2; | 17 | const rem_pio2 = @import("rem_pio2.zig").rem_pio2; |
| 18 | const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f; | 18 | const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f; |
| 19 | const rem_pio2l = @import("rem_pio2l.zig").rem_pio2l; | 19 | const rem_pio2l = @import("rem_pio2l.zig").rem_pio2l; |
| 20 | const utils = @import("math_utils.zig"); | 20 | const ld = @import("long_double.zig"); |
| 21 | 21 | ||
| 22 | comptime { | 22 | comptime { |
| 23 | symbol(&__sinh, "__sinh"); | 23 | symbol(&__sinh, "__sinh"); |
| ... | @@ -134,12 +134,12 @@ pub fn sin(x: f64) callconv(.c) f64 { | ... | @@ -134,12 +134,12 @@ pub fn sin(x: f64) callconv(.c) f64 { |
| 134 | } | 134 | } |
| 135 | 135 | ||
| 136 | fn sinlGeneric(comptime T: type, x: T) T { | 136 | fn sinlGeneric(comptime T: type, x: T) T { |
| 137 | const se = utils.ldSignExponent(x) & 0x7fff; | 137 | const se = ld.signExponent(x) & 0x7fff; |
| 138 | if (se == 0x7fff) { | 138 | if (se == 0x7fff) { |
| 139 | return x - x; | 139 | return x - x; |
| 140 | } | 140 | } |
| 141 | 141 | ||
| 142 | if (@abs(x) < utils.pi_4) { | 142 | if (@abs(x) < trig.pi_4) { |
| 143 | if (se < 0x3fff - (math.floatMantissaBits(T) / 2)) { | 143 | if (se < 0x3fff - (math.floatMantissaBits(T) / 2)) { |
| 144 | // raise inexact if x!=0 and underflow if subnormal | 144 | // raise inexact if x!=0 and underflow if subnormal |
| 145 | if (compiler_rt.want_float_exceptions) { | 145 | if (compiler_rt.want_float_exceptions) { |
lib/compiler_rt/sincos.zig+3-3| ... | @@ -9,7 +9,7 @@ const trig = @import("trig.zig"); | ... | @@ -9,7 +9,7 @@ const trig = @import("trig.zig"); |
| 9 | const rem_pio2 = @import("rem_pio2.zig").rem_pio2; | 9 | const rem_pio2 = @import("rem_pio2.zig").rem_pio2; |
| 10 | const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f; | 10 | const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f; |
| 11 | const rem_pio2l = @import("rem_pio2l.zig").rem_pio2l; | 11 | const rem_pio2l = @import("rem_pio2l.zig").rem_pio2l; |
| 12 | const utils = @import("math_utils.zig"); | 12 | const ld = @import("long_double.zig"); |
| 13 | const compiler_rt = @import("../compiler_rt.zig"); | 13 | const compiler_rt = @import("../compiler_rt.zig"); |
| 14 | const symbol = compiler_rt.symbol; | 14 | const symbol = compiler_rt.symbol; |
| 15 | 15 | ||
| ... | @@ -197,7 +197,7 @@ fn sincoslGeneric(comptime T: type, x: T, r_sin: *T, r_cos: *T) void { | ... | @@ -197,7 +197,7 @@ fn sincoslGeneric(comptime T: type, x: T, r_sin: *T, r_cos: *T) void { |
| 197 | @compileError("`sincoslGeneric` implemented only for `f80` and `f128`, got: " ++ @typeName(T)); | 197 | @compileError("`sincoslGeneric` implemented only for `f80` and `f128`, got: " ++ @typeName(T)); |
| 198 | } | 198 | } |
| 199 | 199 | ||
| 200 | const se = utils.ldSignExponent(x) & 0x7fff; | 200 | const se = ld.signExponent(x) & 0x7fff; |
| 201 | if (se == 0x7fff) { | 201 | if (se == 0x7fff) { |
| 202 | const result = x - x; | 202 | const result = x - x; |
| 203 | r_sin.* = result; | 203 | r_sin.* = result; |
| ... | @@ -205,7 +205,7 @@ fn sincoslGeneric(comptime T: type, x: T, r_sin: *T, r_cos: *T) void { | ... | @@ -205,7 +205,7 @@ fn sincoslGeneric(comptime T: type, x: T, r_sin: *T, r_cos: *T) void { |
| 205 | return; | 205 | return; |
| 206 | } | 206 | } |
| 207 | 207 | ||
| 208 | if (@abs(x) < utils.pi_4) { | 208 | if (@abs(x) < trig.pi_4) { |
| 209 | if (se < 0x3fff - math.floatMantissaBits(T)) { | 209 | if (se < 0x3fff - math.floatMantissaBits(T)) { |
| 210 | // raise underflow if subnormal | 210 | // raise underflow if subnormal |
| 211 | if (compiler_rt.want_float_exceptions and se == 0) { | 211 | if (compiler_rt.want_float_exceptions and se == 0) { |
lib/compiler_rt/tan.zig+3-3| ... | @@ -17,7 +17,7 @@ const kernel = @import("trig.zig"); | ... | @@ -17,7 +17,7 @@ const kernel = @import("trig.zig"); |
| 17 | const rem_pio2 = @import("rem_pio2.zig").rem_pio2; | 17 | const rem_pio2 = @import("rem_pio2.zig").rem_pio2; |
| 18 | const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f; | 18 | const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f; |
| 19 | const rem_pio2l = @import("rem_pio2l.zig").rem_pio2l; | 19 | const rem_pio2l = @import("rem_pio2l.zig").rem_pio2l; |
| 20 | const utils = @import("math_utils.zig"); | 20 | const ld = @import("long_double.zig"); |
| 21 | 21 | ||
| 22 | const arch = builtin.cpu.arch; | 22 | const arch = builtin.cpu.arch; |
| 23 | const compiler_rt = @import("../compiler_rt.zig"); | 23 | const compiler_rt = @import("../compiler_rt.zig"); |
| ... | @@ -125,12 +125,12 @@ fn tanlGeneric(comptime T: type, x: T) T { | ... | @@ -125,12 +125,12 @@ fn tanlGeneric(comptime T: type, x: T) T { |
| 125 | @compileError("`tanlGeneric` implemented only for `f80` and `f128`, got: " ++ T); | 125 | @compileError("`tanlGeneric` implemented only for `f80` and `f128`, got: " ++ T); |
| 126 | } | 126 | } |
| 127 | 127 | ||
| 128 | const se = utils.ldSignExponent(x) & 0x7fff; | 128 | const se = ld.signExponent(x) & 0x7fff; |
| 129 | if (se == 0x7fff) { | 129 | if (se == 0x7fff) { |
| 130 | return x - x; | 130 | return x - x; |
| 131 | } | 131 | } |
| 132 | 132 | ||
| 133 | if (@abs(x) < utils.pi_4) { | 133 | if (@abs(x) < kernel.pi_4) { |
| 134 | if (se < 0x3fff - math.floatMantissaBits(T) / 2) { | 134 | if (se < 0x3fff - math.floatMantissaBits(T) / 2) { |
| 135 | if (compiler_rt.want_float_exceptions) { | 135 | if (compiler_rt.want_float_exceptions) { |
| 136 | mem.doNotOptimizeAway(if (se == 0) x * 0x1p-120 else x + 0x1p120); | 136 | mem.doNotOptimizeAway(if (se == 0) x * 0x1p-120 else x + 0x1p120); |
lib/compiler_rt/trig.zig+3| ... | @@ -11,6 +11,9 @@ | ... | @@ -11,6 +11,9 @@ |
| 11 | // https://git.musl-libc.org/cgit/musl/tree/src/math/__cosl.c | 11 | // https://git.musl-libc.org/cgit/musl/tree/src/math/__cosl.c |
| 12 | // https://git.musl-libc.org/cgit/musl/tree/src/math/__tanl.c | 12 | // https://git.musl-libc.org/cgit/musl/tree/src/math/__tanl.c |
| 13 | 13 | ||
| 14 | /// pi divided by 4 | ||
| 15 | pub const pi_4 = 0.78539816339744830962; | ||
| 16 | |||
| 14 | /// kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164 | 17 | /// kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164 |
| 15 | /// Input x is assumed to be bounded by ~pi/4 in magnitude. | 18 | /// Input x is assumed to be bounded by ~pi/4 in magnitude. |
| 16 | /// Input y is the tail of x. | 19 | /// Input y is the tail of x. |