const math = @import("index.zig"); const assert = @import("../debug.zig").assert; pub fn scalbn(x: var, n: i32) -> @typeOf(x) { const T = @typeOf(x); switch (T) { f32 => @inlineCall(scalbn32, x, n), f64 => @inlineCall(scalbn64, x, n), else => @compileError("scalbn not implemented for " ++ @typeName(T)), } } fn scalbn32(x: f32, n_: i32) -> f32 { var y = x; var n = n_; if (n > 127) { y *= 0x1.0p127; n -= 127; if (n > 1023) { y *= 0x1.0p127; n -= 127; if (n > 127) { n = 127; } } } else if (n < -126) { y *= 0x1.0p-126 * 0x1.0p24; n += 126 - 24; if (n < -126) { y *= 0x1.0p-126 * 0x1.0p24; n += 126 - 24; if (n < -126) { n = -126; } } } const u = u32(n +% 0x7F) << 23; y * @bitCast(f32, u) } fn scalbn64(x: f64, n_: i32) -> f64 { var y = x; var n = n_; if (n > 1023) { y *= 0x1.0p1022 * 2.0; n -= 1023; if (n > 1023) { y *= 0x1.0p1022 * 2.0; n -= 1023; if (n > 1023) { n = 1023; } } } else if (n < -1022) { y *= 0x1.0p-1022 * 0x1.0p53; n += 1022 - 53; if (n < -1022) { y *= 0x1.0p-1022 * 0x1.0p53; n += 1022 - 53; if (n < -1022) { n = -1022; } } } const u = u64(n +% 0x3FF) << 52; y * @bitCast(f64, u) } test "math.scalbn" { assert(scalbn(f32(1.5), 4) == scalbn32(1.5, 4)); assert(scalbn(f64(1.5), 4) == scalbn64(1.5, 4)); } test "math.scalbn32" { assert(scalbn32(1.5, 4) == 24.0); } test "math.scalbn64" { assert(scalbn64(1.5, 4) == 24.0); }