From 9ce421365e501ed6416b81d27bc1eb78a53f3a2c Mon Sep 17 00:00:00 2001 From: James Cox-Morton Date: Fri, 23 May 2025 13:06:42 +0100 Subject: [PATCH 1/6] Add the ldexp family of functions, proxy to std.math.ldexp Addresses https://github.com/ziglang/zig/issues/23358 --- lib/compiler_rt.zig | 1 + lib/compiler_rt/ldexp.zig | 70 ++++++++++++++++++++++++++++++++++ test/link/build.zig.zon | 3 ++ test/link/wasm/ldexp/build.zig | 34 +++++++++++++++++ test/link/wasm/ldexp/lib.zig | 16 ++++++++ 5 files changed, 124 insertions(+) create mode 100644 lib/compiler_rt/ldexp.zig create mode 100644 test/link/wasm/ldexp/build.zig create mode 100644 test/link/wasm/ldexp/lib.zig diff --git a/lib/compiler_rt.zig b/lib/compiler_rt.zig index e17dea2b4c08..caf5dd94e53a 100644 --- a/lib/compiler_rt.zig +++ b/lib/compiler_rt.zig @@ -224,6 +224,7 @@ comptime { _ = @import("compiler_rt/fmax.zig"); _ = @import("compiler_rt/fmin.zig"); _ = @import("compiler_rt/fmod.zig"); + _ = @import("compiler_rt/ldexp.zig"); _ = @import("compiler_rt/log.zig"); _ = @import("compiler_rt/log10.zig"); _ = @import("compiler_rt/log2.zig"); diff --git a/lib/compiler_rt/ldexp.zig b/lib/compiler_rt/ldexp.zig new file mode 100644 index 000000000000..25a2ad0796b5 --- /dev/null +++ b/lib/compiler_rt/ldexp.zig @@ -0,0 +1,70 @@ +const std = @import("std"); +const expect = std.testing.expect; +const math = std.math; +const common = @import("common.zig"); + +comptime { + @export(&ldexp, .{ .name = "ldexp", .linkage = common.linkage, .visibility = common.visibility }); + @export(&ldexpf, .{ .name = "ldexpf", .linkage = common.linkage, .visibility = common.visibility }); + @export(&ldexpl, .{ .name = "ldexpl", .linkage = common.linkage, .visibility = common.visibility }); +} + +pub fn ldexp(x: f64, n: i32) callconv(.c) f64 { + return math.ldexp(x, n); +} + +test "ldexp" { + // Ported from libc-test + // https://repo.or.cz/libc-test.git/blob/HEAD:/src/math/sanity/ldexp.h + try expect(ldexp(-0x1.02239f3c6a8f1p+3, -2) == -0x1.02239f3c6a8f1p+1); +} + +test "ldexp.special" { + // Ported from libc-test + // https://repo.or.cz/libc-test.git/blob/HEAD:/src/math/special/ldexp.h + try expect(math.isNan(ldexp(math.nan(f64), 0))); + try expect(math.isPositiveInf(ldexp(math.inf(f64), 0))); +} + +pub fn ldexpf(x: f32, n: i32) callconv(.c) f32 { + return math.ldexp(x, n); +} + +test "ldexpf" { + // Ported from libc-test + // https://repo.or.cz/libc-test.git/blob/HEAD:/src/math/sanity/ldexpf.h + try expect(ldexpf(-0x1.0223ap+3, -2) == -0x1.0223ap+1); +} + +test "ldexpf.special" { + // Ported from libc-test + // https://repo.or.cz/libc-test.git/blob/HEAD:/src/math/special/ldexpf.h + try expect(math.isNan(ldexpf(math.nan(f32), 0))); + try expect(math.isPositiveInf(ldexpf(math.inf(f32), 0))); +} + +pub fn ldexpl(x: c_longdouble, n: i32) callconv(.c) c_longdouble { + switch (@typeInfo(c_longdouble).float.bits) { + 16 => return math.ldexp(@as(f16, x), n), + 32 => return math.ldexp(@as(f32, x), n), + 64 => return math.ldexp(@as(f64, x), n), + 80 => return math.ldexp(@as(f80, x), n), + 128 => return math.ldexp(@as(f128, x), n), + else => @compileError("unreachable"), + } +} + +test "ldexpl" { + // Ported from libc-test + // https://repo.or.cz/libc-test.git/blob/HEAD:/src/math/sanity/ldexpl.h + const x: c_longdouble = -0x1.02239f3c6a8f13dep+3; + const expected: c_longdouble = -0x1.02239f3c6a8f13dep+1; + try expect(ldexpl(x, -2) == expected); +} + +test "ldexpl.special" { + // Ported from libc-test + // https://repo.or.cz/libc-test.git/blob/HEAD:/src/math/special/ldexpl.h + try expect(math.isNan(ldexpl(math.nan(c_longdouble), 0))); + try expect(math.isPositiveInf(ldexpl(math.inf(c_longdouble), 0))); +} diff --git a/test/link/build.zig.zon b/test/link/build.zig.zon index 16bba08c4e01..ce6fc84b4b10 100644 --- a/test/link/build.zig.zon +++ b/test/link/build.zig.zon @@ -54,6 +54,9 @@ .wasm_type = .{ .path = "wasm/type", }, + .wasm_ldexp = .{ + .path = "wasm/ldexp", + }, }, .paths = .{ "build.zig", diff --git a/test/link/wasm/ldexp/build.zig b/test/link/wasm/ldexp/build.zig new file mode 100644 index 000000000000..a8152e03a17f --- /dev/null +++ b/test/link/wasm/ldexp/build.zig @@ -0,0 +1,34 @@ +const std = @import("std"); + +pub fn build(b: *std.Build) void { + const test_step = b.step("test", "Test it"); + b.default_step = test_step; + + // Ensure ldexp symbols are available in Release modes + // Regression test for https://github.com/ziglang/zig/issues/23358 + add(b, test_step, .ReleaseSafe); + add(b, test_step, .ReleaseFast); + add(b, test_step, .ReleaseSmall); + // Also verify Debug still works + add(b, test_step, .Debug); +} + +fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void { + const exe = b.addExecutable(.{ + .name = "ldexp_test", + .root_module = b.createModule(.{ + .root_source_file = b.path("lib.zig"), + .target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }), + .optimize = optimize, + }), + }); + + exe.entry = .disabled; + exe.rdynamic = true; + + exe.root_module.export_symbol_names = &.{ "use_double", "use_float", "use_long" }; + + b.installArtifact(exe); + + test_step.dependOn(&exe.step); +} diff --git a/test/link/wasm/ldexp/lib.zig b/test/link/wasm/ldexp/lib.zig new file mode 100644 index 000000000000..87f604b1d72c --- /dev/null +++ b/test/link/wasm/ldexp/lib.zig @@ -0,0 +1,16 @@ +// Test that LLVM's exp2 optimization requiring ldexp symbols works correctly. +// In Release modes, LLVM's LibCallSimplifier converts exp2 calls to ldexp +// when the input is an integer converted to float. +// See https://github.com/ziglang/zig/issues/23358 + +export fn use_double(f: i32) f64 { + return @exp2(@as(f64, @floatFromInt(f))); +} + +export fn use_float(f: i32) f32 { + return @exp2(@as(f32, @floatFromInt(f))); +} + +export fn use_long(f: i32) f128 { + return @exp2(@as(f128, @floatFromInt(f))); +} From 210177a9025b28b9fc1f455efc9ed4a25a58b4f1 Mon Sep 17 00:00:00 2001 From: James Cox-Morton Date: Mon, 2 Jun 2025 22:04:06 +0100 Subject: [PATCH 2/6] Add scalbn compiler_rt implementation which aliases ldexp --- lib/compiler_rt.zig | 1 + lib/compiler_rt/scalbn.zig | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 lib/compiler_rt/scalbn.zig diff --git a/lib/compiler_rt.zig b/lib/compiler_rt.zig index caf5dd94e53a..6f14862ec1ed 100644 --- a/lib/compiler_rt.zig +++ b/lib/compiler_rt.zig @@ -225,6 +225,7 @@ comptime { _ = @import("compiler_rt/fmin.zig"); _ = @import("compiler_rt/fmod.zig"); _ = @import("compiler_rt/ldexp.zig"); + _ = @import("compiler_rt/scalbn.zig"); _ = @import("compiler_rt/log.zig"); _ = @import("compiler_rt/log10.zig"); _ = @import("compiler_rt/log2.zig"); diff --git a/lib/compiler_rt/scalbn.zig b/lib/compiler_rt/scalbn.zig new file mode 100644 index 000000000000..8841b429df88 --- /dev/null +++ b/lib/compiler_rt/scalbn.zig @@ -0,0 +1,22 @@ +const std = @import("std"); +const expect = std.testing.expect; +const common = @import("common.zig"); +const ldexp = @import("ldexp.zig"); + +comptime { + @export(&scalbn, .{ .name = "scalbn", .linkage = common.linkage, .visibility = common.visibility }); + @export(&scalbnf, .{ .name = "scalbnf", .linkage = common.linkage, .visibility = common.visibility }); + @export(&scalbnl, .{ .name = "scalbnl", .linkage = common.linkage, .visibility = common.visibility }); +} + +pub fn scalbn(x: f64, n: i32) callconv(.c) f64 { + return ldexp.ldexp(x, n); +} + +pub fn scalbnf(x: f32, n: i32) callconv(.c) f32 { + return ldexp.ldexpf(x, n); +} + +pub fn scalbnl(x: c_longdouble, n: i32) callconv(.c) c_longdouble { + return ldexp.ldexpl(x, n); +} From 0ee2ebfc1346d31f069ffc444a02ce229774c991 Mon Sep 17 00:00:00 2001 From: James Cox-Morton Date: Tue, 3 Jun 2025 20:40:58 +0100 Subject: [PATCH 3/6] Add scalbln implementation --- lib/compiler_rt.zig | 1 + lib/compiler_rt/scalbln.zig | 67 +++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 lib/compiler_rt/scalbln.zig diff --git a/lib/compiler_rt.zig b/lib/compiler_rt.zig index 6f14862ec1ed..076d883b061b 100644 --- a/lib/compiler_rt.zig +++ b/lib/compiler_rt.zig @@ -225,6 +225,7 @@ comptime { _ = @import("compiler_rt/fmin.zig"); _ = @import("compiler_rt/fmod.zig"); _ = @import("compiler_rt/ldexp.zig"); + _ = @import("compiler_rt/scalbln.zig"); _ = @import("compiler_rt/scalbn.zig"); _ = @import("compiler_rt/log.zig"); _ = @import("compiler_rt/log10.zig"); diff --git a/lib/compiler_rt/scalbln.zig b/lib/compiler_rt/scalbln.zig new file mode 100644 index 000000000000..eee1937d2cc9 --- /dev/null +++ b/lib/compiler_rt/scalbln.zig @@ -0,0 +1,67 @@ +const std = @import("std"); +const expect = std.testing.expect; +const math = std.math; +const common = @import("common.zig"); + +comptime { + @export(&scalbln, .{ .name = "scalbln", .linkage = common.linkage, .visibility = common.visibility }); + @export(&scalblnf, .{ .name = "scalblnf", .linkage = common.linkage, .visibility = common.visibility }); + @export(&scalblnl, .{ .name = "scalblnl", .linkage = common.linkage, .visibility = common.visibility }); +} + +pub fn scalbln(x: f64, n: c_long) callconv(.c) f64 { + // mirror musl implementation - clamp c_long to i32 + const clamped_n: i32 = @intCast(math.clamp(n, math.minInt(i32), math.maxInt(i32))); + return math.ldexp(x, clamped_n); +} + +test "scalbln" { + // Ported from libc-test + // https://repo.or.cz/libc-test.git/blob/HEAD:/src/math/sanity/ldexp.h + try expect(scalbln(-0x1.02239f3c6a8f1p+3, -2) == -0x1.02239f3c6a8f1p+1); +} + +test "scalbln.special" { + // Ported from libc-test + // https://repo.or.cz/libc-test.git/blob/HEAD:/src/math/special/ldexp.h + try expect(math.isNan(scalbln(math.nan(f64), 0))); + try expect(math.isPositiveInf(scalbln(math.inf(f64), 0))); +} + +pub fn scalblnf(x: f32, n: c_long) callconv(.c) f32 { + const clamped_n: i32 = @intCast(math.clamp(n, math.minInt(i32), math.maxInt(i32))); + return math.ldexp(x, clamped_n); +} + +test "scalblnf" { + // Ported from libc-test + // https://repo.or.cz/libc-test.git/blob/HEAD:/src/math/sanity/ldexpf.h + try expect(scalblnf(-0x1.0223ap+3, -2) == -0x1.0223ap+1); +} + +test "scalblnf.special" { + // Ported from libc-test + // https://repo.or.cz/libc-test.git/blob/HEAD:/src/math/special/ldexpf.h + try expect(math.isNan(scalblnf(math.nan(f32), 0))); + try expect(math.isPositiveInf(scalblnf(math.inf(f32), 0))); +} + +pub fn scalblnl(x: c_longdouble, n: c_long) callconv(.c) c_longdouble { + const clamped_n: i32 = @intCast(math.clamp(n, math.minInt(i32), math.maxInt(i32))); + return math.ldexp(x, clamped_n); +} + +test "scalblnl" { + // Ported from libc-test + // https://repo.or.cz/libc-test.git/blob/HEAD:/src/math/sanity/ldexpl.h + const x: c_longdouble = -0x1.02239f3c6a8f13dep+3; + const expected: c_longdouble = -0x1.02239f3c6a8f13dep+1; + try expect(scalblnl(x, -2) == expected); +} + +test "scalblnl.special" { + // Ported from libc-test + // https://repo.or.cz/libc-test.git/blob/HEAD:/src/math/special/ldexpl.h + try expect(math.isNan(scalblnl(math.nan(c_longdouble), 0))); + try expect(math.isPositiveInf(scalblnl(math.inf(c_longdouble), 0))); +} From 5dafb9706240277106109ae5ea3cf718e3611201 Mon Sep 17 00:00:00 2001 From: James Cox-Morton Date: Mon, 2 Jun 2025 20:34:53 +0100 Subject: [PATCH 4/6] Remove musl ldexp, scalbn, scalbln functions, we now export math.ldexp --- lib/libc/mingw/math/arm-common/ldexpl.c | 16 ---------- lib/libc/mingw/math/ldexpf.c | 13 -------- lib/libc/mingw/math/x86/ldexp.c | 23 -------------- lib/libc/mingw/math/x86/ldexpl.c | 23 -------------- lib/libc/mingw/math/x86/scalbn.S | 41 ------------------------- lib/libc/mingw/math/x86/scalbnf.S | 40 ------------------------ lib/libc/mingw/math/x86/scalbnl.S | 41 ------------------------- lib/libc/musl/src/math/i386/ldexp.s | 1 - lib/libc/musl/src/math/i386/ldexpf.s | 1 - lib/libc/musl/src/math/i386/ldexpl.s | 1 - lib/libc/musl/src/math/i386/scalbln.s | 1 - lib/libc/musl/src/math/i386/scalblnf.s | 1 - lib/libc/musl/src/math/i386/scalblnl.s | 1 - lib/libc/musl/src/math/i386/scalbn.s | 33 -------------------- lib/libc/musl/src/math/i386/scalbnf.s | 32 ------------------- lib/libc/musl/src/math/i386/scalbnl.s | 32 ------------------- lib/libc/musl/src/math/ldexp.c | 6 ---- lib/libc/musl/src/math/ldexpf.c | 6 ---- lib/libc/musl/src/math/ldexpl.c | 6 ---- lib/libc/musl/src/math/scalbln.c | 11 ------- lib/libc/musl/src/math/scalblnf.c | 11 ------- lib/libc/musl/src/math/scalblnl.c | 19 ------------ lib/libc/musl/src/math/scalbn.c | 33 -------------------- lib/libc/musl/src/math/scalbnf.c | 31 ------------------- lib/libc/musl/src/math/scalbnl.c | 36 ---------------------- src/libs/mingw.zig | 29 ----------------- src/libs/musl.zig | 18 ----------- src/libs/wasi_libc.zig | 9 ------ 28 files changed, 515 deletions(-) delete mode 100644 lib/libc/mingw/math/arm-common/ldexpl.c delete mode 100644 lib/libc/mingw/math/ldexpf.c delete mode 100644 lib/libc/mingw/math/x86/ldexp.c delete mode 100644 lib/libc/mingw/math/x86/ldexpl.c delete mode 100644 lib/libc/mingw/math/x86/scalbn.S delete mode 100644 lib/libc/mingw/math/x86/scalbnf.S delete mode 100644 lib/libc/mingw/math/x86/scalbnl.S delete mode 100644 lib/libc/musl/src/math/i386/ldexp.s delete mode 100644 lib/libc/musl/src/math/i386/ldexpf.s delete mode 100644 lib/libc/musl/src/math/i386/ldexpl.s delete mode 100644 lib/libc/musl/src/math/i386/scalbln.s delete mode 100644 lib/libc/musl/src/math/i386/scalblnf.s delete mode 100644 lib/libc/musl/src/math/i386/scalblnl.s delete mode 100644 lib/libc/musl/src/math/i386/scalbn.s delete mode 100644 lib/libc/musl/src/math/i386/scalbnf.s delete mode 100644 lib/libc/musl/src/math/i386/scalbnl.s delete mode 100644 lib/libc/musl/src/math/ldexp.c delete mode 100644 lib/libc/musl/src/math/ldexpf.c delete mode 100644 lib/libc/musl/src/math/ldexpl.c delete mode 100644 lib/libc/musl/src/math/scalbln.c delete mode 100644 lib/libc/musl/src/math/scalblnf.c delete mode 100644 lib/libc/musl/src/math/scalblnl.c delete mode 100644 lib/libc/musl/src/math/scalbn.c delete mode 100644 lib/libc/musl/src/math/scalbnf.c delete mode 100644 lib/libc/musl/src/math/scalbnl.c diff --git a/lib/libc/mingw/math/arm-common/ldexpl.c b/lib/libc/mingw/math/arm-common/ldexpl.c deleted file mode 100644 index 2c2a9e51a765..000000000000 --- a/lib/libc/mingw/math/arm-common/ldexpl.c +++ /dev/null @@ -1,16 +0,0 @@ -/** - * This file has no copyright assigned and is placed in the Public Domain. - * This file is part of the mingw-w64 runtime package. - * No warranty is given; refer to the file DISCLAIMER.PD within this package. - */ - -#include - -long double ldexpl(long double x, int n) -{ -#if defined(__arm__) || defined(_ARM_) || defined(__aarch64__) || defined(_ARM64_) - return ldexp(x, n); -#else -#error Not supported on your platform yet -#endif -} diff --git a/lib/libc/mingw/math/ldexpf.c b/lib/libc/mingw/math/ldexpf.c deleted file mode 100644 index 83cd89d41c2a..000000000000 --- a/lib/libc/mingw/math/ldexpf.c +++ /dev/null @@ -1,13 +0,0 @@ -/** - * This file has no copyright assigned and is placed in the Public Domain. - * This file is part of the mingw-w64 runtime package. - * No warranty is given; refer to the file DISCLAIMER.PD within this package. - */ -extern double __cdecl ldexp(double _X,int _Y); - -float ldexpf (float x, int expn); -float ldexpf (float x, int expn) -{ - return (float) ldexp (x, expn); -} - diff --git a/lib/libc/mingw/math/x86/ldexp.c b/lib/libc/mingw/math/x86/ldexp.c deleted file mode 100644 index 59917ac8d432..000000000000 --- a/lib/libc/mingw/math/x86/ldexp.c +++ /dev/null @@ -1,23 +0,0 @@ -/** - * This file has no copyright assigned and is placed in the Public Domain. - * This file is part of the mingw-w64 runtime package. - * No warranty is given; refer to the file DISCLAIMER.PD within this package. - */ -#include -#include - -double ldexp(double x, int expn) -{ - double res = 0.0; - if (!isfinite (x) || x == 0.0) - return x; - - __asm__ __volatile__ ("fscale" - : "=t" (res) - : "0" (x), "u" ((double) expn)); - - if (!isfinite (res) || res == 0.0L) - errno = ERANGE; - - return res; -} diff --git a/lib/libc/mingw/math/x86/ldexpl.c b/lib/libc/mingw/math/x86/ldexpl.c deleted file mode 100644 index fde31a23ca61..000000000000 --- a/lib/libc/mingw/math/x86/ldexpl.c +++ /dev/null @@ -1,23 +0,0 @@ -/** - * This file has no copyright assigned and is placed in the Public Domain. - * This file is part of the mingw-w64 runtime package. - * No warranty is given; refer to the file DISCLAIMER.PD within this package. - */ -#include -#include - -long double ldexpl(long double x, int expn) -{ - long double res = 0.0L; - if (!isfinite (x) || x == 0.0L) - return x; - - __asm__ __volatile__ ("fscale" - : "=t" (res) - : "0" (x), "u" ((long double) expn)); - - if (!isfinite (res) || res == 0.0L) - errno = ERANGE; - - return res; -} diff --git a/lib/libc/mingw/math/x86/scalbn.S b/lib/libc/mingw/math/x86/scalbn.S deleted file mode 100644 index 8afcf753638b..000000000000 --- a/lib/libc/mingw/math/x86/scalbn.S +++ /dev/null @@ -1,41 +0,0 @@ -/** - * This file has no copyright assigned and is placed in the Public Domain. - * This file is part of the mingw-w64 runtime package. - * No warranty is given; refer to the file DISCLAIMER.PD within this package. - */ -#include <_mingw_mac.h> - - .file "scalbn.S" - .text -#ifdef __x86_64__ - .align 8 -#else - .align 4 -#endif -.globl __MINGW_USYMBOL(scalbn) - .def __MINGW_USYMBOL(scalbn); .scl 2; .type 32; .endef -__MINGW_USYMBOL(scalbn): -#ifdef __x86_64__ - subq $24, %rsp - movq %rdx,(%rsp) - fildl (%rsp) - movsd %xmm0,(%rsp) - fldl (%rsp) - fscale - fstp %st(1) - fstpl (%rsp) - movsd (%rsp),%xmm0 - addq $24, %rsp - ret - -#else - fildl 12(%esp) - fldl 4(%esp) - fscale - fstp %st(1) - ret -#endif - -.globl __MINGW_USYMBOL(scalbln) - .set __MINGW_USYMBOL(scalbln),__MINGW_USYMBOL(scalbn) - diff --git a/lib/libc/mingw/math/x86/scalbnf.S b/lib/libc/mingw/math/x86/scalbnf.S deleted file mode 100644 index 93a11f2ab867..000000000000 --- a/lib/libc/mingw/math/x86/scalbnf.S +++ /dev/null @@ -1,40 +0,0 @@ -/** - * This file has no copyright assigned and is placed in the Public Domain. - * This file is part of the mingw-w64 runtime package. - * No warranty is given; refer to the file DISCLAIMER.PD within this package. - */ -#include <_mingw_mac.h> - - .file "scalbnf.S" - .text -#ifdef __x86_64__ - .align 8 -#else - .align 4 -#endif -.globl __MINGW_USYMBOL(scalbnf) - .def __MINGW_USYMBOL(scalbnf); .scl 2; .type 32; .endef -__MINGW_USYMBOL(scalbnf): -#ifdef __x86_64__ - subq $24, %rsp - movq %rdx,(%rsp) - fildl (%rsp) - movss %xmm0,(%rsp) - flds (%rsp) - fscale - fstp %st(1) - fstps (%rsp) - movss (%rsp),%xmm0 - addq $24, %rsp - ret -#else - fildl 8(%esp) - flds 4(%esp) - fscale - fstp %st(1) - ret -#endif - -.globl __MINGW_USYMBOL(scalblnf) - .set __MINGW_USYMBOL(scalblnf),__MINGW_USYMBOL(scalbnf) - diff --git a/lib/libc/mingw/math/x86/scalbnl.S b/lib/libc/mingw/math/x86/scalbnl.S deleted file mode 100644 index 5ff0a68f3912..000000000000 --- a/lib/libc/mingw/math/x86/scalbnl.S +++ /dev/null @@ -1,41 +0,0 @@ -/** - * This file has no copyright assigned and is placed in the Public Domain. - * This file is part of the mingw-w64 runtime package. - * No warranty is given; refer to the file DISCLAIMER.PD within this package. - */ -#include <_mingw_mac.h> - - .file "scalbnl.S" - .text -#ifdef __x86_64__ - .align 8 -#else - .align 4 -#endif -.globl __MINGW_USYMBOL(scalbnl) - .def __MINGW_USYMBOL(scalbnl); .scl 2; .type 32; .endef -__MINGW_USYMBOL(scalbnl): -#ifdef __x86_64__ - subq $24, %rsp - andl $-1, %r8d - movq %r8, (%rsp) - fildl (%rsp) - fldt (%rdx) - fscale - fstp %st(1) - movq %rcx,%rax - movq $0,8(%rcx) - fstpt (%rcx) - addq $24, %rsp - ret -#else - fildl 16(%esp) - fldt 4(%esp) - fscale - fstp %st(1) - ret -#endif - -.globl __MINGW_USYMBOL(scalblnl) - .set __MINGW_USYMBOL(scalblnl),__MINGW_USYMBOL(scalbnl) - diff --git a/lib/libc/musl/src/math/i386/ldexp.s b/lib/libc/musl/src/math/i386/ldexp.s deleted file mode 100644 index c430f7849700..000000000000 --- a/lib/libc/musl/src/math/i386/ldexp.s +++ /dev/null @@ -1 +0,0 @@ -# see scalbn.s diff --git a/lib/libc/musl/src/math/i386/ldexpf.s b/lib/libc/musl/src/math/i386/ldexpf.s deleted file mode 100644 index 3f8e4b95fc42..000000000000 --- a/lib/libc/musl/src/math/i386/ldexpf.s +++ /dev/null @@ -1 +0,0 @@ -# see scalbnf.s diff --git a/lib/libc/musl/src/math/i386/ldexpl.s b/lib/libc/musl/src/math/i386/ldexpl.s deleted file mode 100644 index 86fe5621bd11..000000000000 --- a/lib/libc/musl/src/math/i386/ldexpl.s +++ /dev/null @@ -1 +0,0 @@ -# see scalbnl.s diff --git a/lib/libc/musl/src/math/i386/scalbln.s b/lib/libc/musl/src/math/i386/scalbln.s deleted file mode 100644 index c430f7849700..000000000000 --- a/lib/libc/musl/src/math/i386/scalbln.s +++ /dev/null @@ -1 +0,0 @@ -# see scalbn.s diff --git a/lib/libc/musl/src/math/i386/scalblnf.s b/lib/libc/musl/src/math/i386/scalblnf.s deleted file mode 100644 index 3f8e4b95fc42..000000000000 --- a/lib/libc/musl/src/math/i386/scalblnf.s +++ /dev/null @@ -1 +0,0 @@ -# see scalbnf.s diff --git a/lib/libc/musl/src/math/i386/scalblnl.s b/lib/libc/musl/src/math/i386/scalblnl.s deleted file mode 100644 index 86fe5621bd11..000000000000 --- a/lib/libc/musl/src/math/i386/scalblnl.s +++ /dev/null @@ -1 +0,0 @@ -# see scalbnl.s diff --git a/lib/libc/musl/src/math/i386/scalbn.s b/lib/libc/musl/src/math/i386/scalbn.s deleted file mode 100644 index 8bf302f236bb..000000000000 --- a/lib/libc/musl/src/math/i386/scalbn.s +++ /dev/null @@ -1,33 +0,0 @@ -.global ldexp -.type ldexp,@function -ldexp: - nop - -.global scalbln -.type scalbln,@function -scalbln: - nop - -.global scalbn -.type scalbn,@function -scalbn: - mov 12(%esp),%eax - add $0x3ffe,%eax - cmp $0x7ffd,%eax - jb 1f - sub $0x3ffe,%eax - sar $31,%eax - xor $0xfff,%eax - add $0x3ffe,%eax -1: inc %eax - fldl 4(%esp) - mov %eax,12(%esp) - mov $0x80000000,%eax - mov %eax,8(%esp) - xor %eax,%eax - mov %eax,4(%esp) - fldt 4(%esp) - fmulp - fstpl 4(%esp) - fldl 4(%esp) - ret diff --git a/lib/libc/musl/src/math/i386/scalbnf.s b/lib/libc/musl/src/math/i386/scalbnf.s deleted file mode 100644 index 9cb9ef5fee44..000000000000 --- a/lib/libc/musl/src/math/i386/scalbnf.s +++ /dev/null @@ -1,32 +0,0 @@ -.global ldexpf -.type ldexpf,@function -ldexpf: - nop - -.global scalblnf -.type scalblnf,@function -scalblnf: - nop - -.global scalbnf -.type scalbnf,@function -scalbnf: - mov 8(%esp),%eax - add $0x3fe,%eax - cmp $0x7fd,%eax - jb 1f - sub $0x3fe,%eax - sar $31,%eax - xor $0x1ff,%eax - add $0x3fe,%eax -1: inc %eax - shl $20,%eax - flds 4(%esp) - mov %eax,8(%esp) - xor %eax,%eax - mov %eax,4(%esp) - fldl 4(%esp) - fmulp - fstps 4(%esp) - flds 4(%esp) - ret diff --git a/lib/libc/musl/src/math/i386/scalbnl.s b/lib/libc/musl/src/math/i386/scalbnl.s deleted file mode 100644 index 54414c2e9837..000000000000 --- a/lib/libc/musl/src/math/i386/scalbnl.s +++ /dev/null @@ -1,32 +0,0 @@ -.global ldexpl -.type ldexpl,@function -ldexpl: - nop - -.global scalblnl -.type scalblnl,@function -scalblnl: - nop - -.global scalbnl -.type scalbnl,@function -scalbnl: - mov 16(%esp),%eax - add $0x3ffe,%eax - cmp $0x7ffd,%eax - jae 1f - inc %eax - fldt 4(%esp) - mov %eax,12(%esp) - mov $0x80000000,%eax - mov %eax,8(%esp) - xor %eax,%eax - mov %eax,4(%esp) - fldt 4(%esp) - fmulp - ret -1: fildl 16(%esp) - fldt 4(%esp) - fscale - fstp %st(1) - ret diff --git a/lib/libc/musl/src/math/ldexp.c b/lib/libc/musl/src/math/ldexp.c deleted file mode 100644 index f4d1cd6af5d8..000000000000 --- a/lib/libc/musl/src/math/ldexp.c +++ /dev/null @@ -1,6 +0,0 @@ -#include - -double ldexp(double x, int n) -{ - return scalbn(x, n); -} diff --git a/lib/libc/musl/src/math/ldexpf.c b/lib/libc/musl/src/math/ldexpf.c deleted file mode 100644 index 3bad5f393f5a..000000000000 --- a/lib/libc/musl/src/math/ldexpf.c +++ /dev/null @@ -1,6 +0,0 @@ -#include - -float ldexpf(float x, int n) -{ - return scalbnf(x, n); -} diff --git a/lib/libc/musl/src/math/ldexpl.c b/lib/libc/musl/src/math/ldexpl.c deleted file mode 100644 index fd145ccc5658..000000000000 --- a/lib/libc/musl/src/math/ldexpl.c +++ /dev/null @@ -1,6 +0,0 @@ -#include - -long double ldexpl(long double x, int n) -{ - return scalbnl(x, n); -} diff --git a/lib/libc/musl/src/math/scalbln.c b/lib/libc/musl/src/math/scalbln.c deleted file mode 100644 index e6f3f195c856..000000000000 --- a/lib/libc/musl/src/math/scalbln.c +++ /dev/null @@ -1,11 +0,0 @@ -#include -#include - -double scalbln(double x, long n) -{ - if (n > INT_MAX) - n = INT_MAX; - else if (n < INT_MIN) - n = INT_MIN; - return scalbn(x, n); -} diff --git a/lib/libc/musl/src/math/scalblnf.c b/lib/libc/musl/src/math/scalblnf.c deleted file mode 100644 index d8e8166b10d6..000000000000 --- a/lib/libc/musl/src/math/scalblnf.c +++ /dev/null @@ -1,11 +0,0 @@ -#include -#include - -float scalblnf(float x, long n) -{ - if (n > INT_MAX) - n = INT_MAX; - else if (n < INT_MIN) - n = INT_MIN; - return scalbnf(x, n); -} diff --git a/lib/libc/musl/src/math/scalblnl.c b/lib/libc/musl/src/math/scalblnl.c deleted file mode 100644 index 854c51c4cb95..000000000000 --- a/lib/libc/musl/src/math/scalblnl.c +++ /dev/null @@ -1,19 +0,0 @@ -#include -#include -#include - -#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 -long double scalblnl(long double x, long n) -{ - return scalbln(x, n); -} -#else -long double scalblnl(long double x, long n) -{ - if (n > INT_MAX) - n = INT_MAX; - else if (n < INT_MIN) - n = INT_MIN; - return scalbnl(x, n); -} -#endif diff --git a/lib/libc/musl/src/math/scalbn.c b/lib/libc/musl/src/math/scalbn.c deleted file mode 100644 index 182f561068fd..000000000000 --- a/lib/libc/musl/src/math/scalbn.c +++ /dev/null @@ -1,33 +0,0 @@ -#include -#include - -double scalbn(double x, int n) -{ - union {double f; uint64_t i;} u; - double_t y = x; - - if (n > 1023) { - y *= 0x1p1023; - n -= 1023; - if (n > 1023) { - y *= 0x1p1023; - n -= 1023; - if (n > 1023) - n = 1023; - } - } else if (n < -1022) { - /* make sure final n < -53 to avoid double - rounding in the subnormal range */ - y *= 0x1p-1022 * 0x1p53; - n += 1022 - 53; - if (n < -1022) { - y *= 0x1p-1022 * 0x1p53; - n += 1022 - 53; - if (n < -1022) - n = -1022; - } - } - u.i = (uint64_t)(0x3ff+n)<<52; - x = y * u.f; - return x; -} diff --git a/lib/libc/musl/src/math/scalbnf.c b/lib/libc/musl/src/math/scalbnf.c deleted file mode 100644 index a5ad208b6992..000000000000 --- a/lib/libc/musl/src/math/scalbnf.c +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include - -float scalbnf(float x, int n) -{ - union {float f; uint32_t i;} u; - float_t y = x; - - if (n > 127) { - y *= 0x1p127f; - n -= 127; - if (n > 127) { - y *= 0x1p127f; - n -= 127; - if (n > 127) - n = 127; - } - } else if (n < -126) { - y *= 0x1p-126f * 0x1p24f; - n += 126 - 24; - if (n < -126) { - y *= 0x1p-126f * 0x1p24f; - n += 126 - 24; - if (n < -126) - n = -126; - } - } - u.i = (uint32_t)(0x7f+n)<<23; - x = y * u.f; - return x; -} diff --git a/lib/libc/musl/src/math/scalbnl.c b/lib/libc/musl/src/math/scalbnl.c deleted file mode 100644 index db44dab06482..000000000000 --- a/lib/libc/musl/src/math/scalbnl.c +++ /dev/null @@ -1,36 +0,0 @@ -#include "libm.h" - -#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 -long double scalbnl(long double x, int n) -{ - return scalbn(x, n); -} -#elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384 -long double scalbnl(long double x, int n) -{ - union ldshape u; - - if (n > 16383) { - x *= 0x1p16383L; - n -= 16383; - if (n > 16383) { - x *= 0x1p16383L; - n -= 16383; - if (n > 16383) - n = 16383; - } - } else if (n < -16382) { - x *= 0x1p-16382L * 0x1p113L; - n += 16382 - 113; - if (n < -16382) { - x *= 0x1p-16382L * 0x1p113L; - n += 16382 - 113; - if (n < -16382) - n = -16382; - } - } - u.f = 1.0; - u.i.se = 0x3fff + n; - return x * u.f; -} -#endif diff --git a/src/libs/mingw.zig b/src/libs/mingw.zig index 8b5197a43b91..589e1c12d3a5 100644 --- a/src/libs/mingw.zig +++ b/src/libs/mingw.zig @@ -107,15 +107,6 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre } } } else if (target.cpu.arch == .thumb) { - for (mingw32_arm_src) |dep| { - try c_source_files.append(.{ - .src_path = try comp.dirs.zig_lib.join(arena, &.{ - "libc", "mingw", dep, - }), - .extra_flags = crt_args.items, - .owner = undefined, - }); - } for (mingw32_arm32_src) |dep| { try c_source_files.append(.{ .src_path = try comp.dirs.zig_lib.join(arena, &.{ @@ -126,15 +117,6 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre }); } } else if (target.cpu.arch == .aarch64) { - for (mingw32_arm_src) |dep| { - try c_source_files.append(.{ - .src_path = try comp.dirs.zig_lib.join(arena, &.{ - "libc", "mingw", dep, - }), - .extra_flags = crt_args.items, - .owner = undefined, - }); - } for (mingw32_arm64_src) |dep| { try c_source_files.append(.{ .src_path = try comp.dirs.zig_lib.join(arena, &.{ @@ -587,7 +569,6 @@ const mingw32_generic_src = [_][]const u8{ "math" ++ path.sep_str ++ "isnan.c", "math" ++ path.sep_str ++ "isnanf.c", "math" ++ path.sep_str ++ "isnanl.c", - "math" ++ path.sep_str ++ "ldexpf.c", "math" ++ path.sep_str ++ "lgamma.c", "math" ++ path.sep_str ++ "lgammaf.c", "math" ++ path.sep_str ++ "lgammal.c", @@ -925,8 +906,6 @@ const mingw32_x86_src = [_][]const u8{ "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "fucom.c", "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "ilogbl.S", "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "internal_logl.S", - "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "ldexp.c", - "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "ldexpl.c", "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "log10l.S", "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "log1pl.S", "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "log2l.S", @@ -936,9 +915,6 @@ const mingw32_x86_src = [_][]const u8{ "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "powl.c", "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "remainderl.S", "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "remquol.S", - "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "scalbn.S", - "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "scalbnf.S", - "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "scalbnl.S", "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "sinl.c", "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "sinl_internal.S", "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "tanl.S", @@ -968,11 +944,6 @@ const mingw32_x86_32_src = [_][]const u8{ "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "fmodf.c", }; -const mingw32_arm_src = [_][]const u8{ - // mingwex - "math" ++ path.sep_str ++ "arm-common" ++ path.sep_str ++ "ldexpl.c", -}; - const mingw32_arm32_src = [_][]const u8{ // mingwex "math" ++ path.sep_str ++ "arm" ++ path.sep_str ++ "_chgsignl.S", diff --git a/src/libs/musl.zig b/src/libs/musl.zig index d208b0982747..99e3ff4d346a 100644 --- a/src/libs/musl.zig +++ b/src/libs/musl.zig @@ -968,9 +968,6 @@ const src_files = [_][]const u8{ "musl/src/math/i386/hypotf.s", "musl/src/math/i386/hypot.s", "musl/src/math/i386/__invtrigl.s", - "musl/src/math/i386/ldexpf.s", - "musl/src/math/i386/ldexpl.s", - "musl/src/math/i386/ldexp.s", "musl/src/math/i386/llrint.c", "musl/src/math/i386/llrintf.c", "musl/src/math/i386/llrintl.c", @@ -998,12 +995,6 @@ const src_files = [_][]const u8{ "musl/src/math/i386/rint.c", "musl/src/math/i386/rintf.c", "musl/src/math/i386/rintl.c", - "musl/src/math/i386/scalblnf.s", - "musl/src/math/i386/scalblnl.s", - "musl/src/math/i386/scalbln.s", - "musl/src/math/i386/scalbnf.s", - "musl/src/math/i386/scalbnl.s", - "musl/src/math/i386/scalbn.s", "musl/src/math/i386/sqrt.c", "musl/src/math/i386/sqrtf.c", "musl/src/math/i386/sqrtl.c", @@ -1020,9 +1011,6 @@ const src_files = [_][]const u8{ "musl/src/math/j1f.c", "musl/src/math/jn.c", "musl/src/math/jnf.c", - "musl/src/math/ldexp.c", - "musl/src/math/ldexpf.c", - "musl/src/math/ldexpl.c", "musl/src/math/lgamma.c", "musl/src/math/lgammaf.c", "musl/src/math/lgammaf_r.c", @@ -1179,12 +1167,6 @@ const src_files = [_][]const u8{ "musl/src/math/s390x/truncl.c", "musl/src/math/scalb.c", "musl/src/math/scalbf.c", - "musl/src/math/scalbln.c", - "musl/src/math/scalblnf.c", - "musl/src/math/scalblnl.c", - "musl/src/math/scalbn.c", - "musl/src/math/scalbnf.c", - "musl/src/math/scalbnl.c", "musl/src/math/__signbit.c", "musl/src/math/__signbitf.c", "musl/src/math/__signbitl.c", diff --git a/src/libs/wasi_libc.zig b/src/libs/wasi_libc.zig index aaff0da9ba0e..eedf961cd3f2 100644 --- a/src/libs/wasi_libc.zig +++ b/src/libs/wasi_libc.zig @@ -778,9 +778,6 @@ const libc_top_half_src_files = [_][]const u8{ "musl/src/math/j1f.c", "musl/src/math/jn.c", "musl/src/math/jnf.c", - "musl/src/math/ldexp.c", - "musl/src/math/ldexpf.c", - "musl/src/math/ldexpl.c", "musl/src/math/lgamma.c", "musl/src/math/lgammaf.c", "musl/src/math/lgammaf_r.c", @@ -859,12 +856,6 @@ const libc_top_half_src_files = [_][]const u8{ "musl/src/math/roundl.c", "musl/src/math/scalb.c", "musl/src/math/scalbf.c", - "musl/src/math/scalbln.c", - "musl/src/math/scalblnf.c", - "musl/src/math/scalblnl.c", - "musl/src/math/scalbn.c", - "musl/src/math/scalbnf.c", - "musl/src/math/scalbnl.c", "musl/src/math/signgam.c", "musl/src/math/significand.c", "musl/src/math/significandf.c", From 23127eef698e3d552aa68e44f17201f6f748d69b Mon Sep 17 00:00:00 2001 From: James Cox-Morton Date: Tue, 10 Jun 2025 21:18:44 +0100 Subject: [PATCH 5/6] Restore empty list to prevent merge conflicts --- src/libs/mingw.zig | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/libs/mingw.zig b/src/libs/mingw.zig index 589e1c12d3a5..2e62d068eda2 100644 --- a/src/libs/mingw.zig +++ b/src/libs/mingw.zig @@ -107,6 +107,15 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre } } } else if (target.cpu.arch == .thumb) { + for (mingw32_arm_src) |dep| { + try c_source_files.append(.{ + .src_path = try comp.dirs.zig_lib.join(arena, &.{ + "libc", "mingw", dep, + }), + .extra_flags = crt_args.items, + .owner = undefined, + }); + } for (mingw32_arm32_src) |dep| { try c_source_files.append(.{ .src_path = try comp.dirs.zig_lib.join(arena, &.{ @@ -117,6 +126,15 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre }); } } else if (target.cpu.arch == .aarch64) { + for (mingw32_arm_src) |dep| { + try c_source_files.append(.{ + .src_path = try comp.dirs.zig_lib.join(arena, &.{ + "libc", "mingw", dep, + }), + .extra_flags = crt_args.items, + .owner = undefined, + }); + } for (mingw32_arm64_src) |dep| { try c_source_files.append(.{ .src_path = try comp.dirs.zig_lib.join(arena, &.{ @@ -944,6 +962,8 @@ const mingw32_x86_32_src = [_][]const u8{ "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "fmodf.c", }; +const mingw32_arm_src = [_][]const u8{}; + const mingw32_arm32_src = [_][]const u8{ // mingwex "math" ++ path.sep_str ++ "arm" ++ path.sep_str ++ "_chgsignl.S", From 1e2c1a1562bf8e364bd641f16578abde2405913e Mon Sep 17 00:00:00 2001 From: James Cox-Morton Date: Tue, 10 Jun 2025 21:51:48 +0100 Subject: [PATCH 6/6] Extend test coverage of scaln* --- lib/compiler_rt/scalbln.zig | 48 ++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 9 deletions(-) diff --git a/lib/compiler_rt/scalbln.zig b/lib/compiler_rt/scalbln.zig index eee1937d2cc9..a6cb5b364400 100644 --- a/lib/compiler_rt/scalbln.zig +++ b/lib/compiler_rt/scalbln.zig @@ -17,15 +17,23 @@ pub fn scalbln(x: f64, n: c_long) callconv(.c) f64 { test "scalbln" { // Ported from libc-test - // https://repo.or.cz/libc-test.git/blob/HEAD:/src/math/sanity/ldexp.h + // https://repo.or.cz/libc-test.git/blob/HEAD:/src/math/sanity/scalbln.h try expect(scalbln(-0x1.02239f3c6a8f1p+3, -2) == -0x1.02239f3c6a8f1p+1); + try expect(scalbln(0x1.161868e18bc67p+2, -1) == 0x1.161868e18bc67p+1); + try expect(scalbln(0x1.288bbb0d6a1e6p+3, 2) == 0x1.288bbb0d6a1e6p+5); + try expect(scalbln(0x1.52efd0cd80497p-1, 3) == 0x1.52efd0cd80497p+2); + try expect(scalbln(0x1.1f9ef934745cbp-1, 5) == 0x1.1f9ef934745cbp+4); + try expect(scalbln(0x1.8c5db097f7442p-1, 6) == 0x1.8c5db097f7442p+5); } test "scalbln.special" { // Ported from libc-test - // https://repo.or.cz/libc-test.git/blob/HEAD:/src/math/special/ldexp.h + // https://repo.or.cz/libc-test.git/blob/HEAD:/src/math/special/scalbln.h try expect(math.isNan(scalbln(math.nan(f64), 0))); try expect(math.isPositiveInf(scalbln(math.inf(f64), 0))); + try expect(scalbln(0x1p+0, 0) == 0x1p+0); + try expect(scalbln(0x1p+0, 1) == 0x1p+1); + try expect(scalbln(0x1p+0, -1) == 0x1p-1); } pub fn scalblnf(x: f32, n: c_long) callconv(.c) f32 { @@ -35,15 +43,22 @@ pub fn scalblnf(x: f32, n: c_long) callconv(.c) f32 { test "scalblnf" { // Ported from libc-test - // https://repo.or.cz/libc-test.git/blob/HEAD:/src/math/sanity/ldexpf.h + // https://repo.or.cz/libc-test.git/blob/HEAD:/src/math/sanity/scalbnf.h try expect(scalblnf(-0x1.0223ap+3, -2) == -0x1.0223ap+1); + try expect(scalblnf(0x1.161868p+2, -1) == 0x1.161868p+1); + try expect(scalblnf(0x1.52efdp-1, 3) == 0x1.52efdp+2); + try expect(scalblnf(0x1.1f9efap-1, 5) == 0x1.1f9efap+4); + try expect(scalblnf(0x1.8c5dbp-1, 6) == 0x1.8c5dbp+5); } test "scalblnf.special" { // Ported from libc-test - // https://repo.or.cz/libc-test.git/blob/HEAD:/src/math/special/ldexpf.h + // https://repo.or.cz/libc-test.git/blob/HEAD:/src/math/special/scalbnf.h try expect(math.isNan(scalblnf(math.nan(f32), 0))); try expect(math.isPositiveInf(scalblnf(math.inf(f32), 0))); + try expect(scalblnf(0x1p+0, 0) == 0x1p+0); + try expect(scalblnf(0x1p+0, 1) == 0x1p+1); + try expect(scalblnf(0x1p+0, -1) == 0x1p-1); } pub fn scalblnl(x: c_longdouble, n: c_long) callconv(.c) c_longdouble { @@ -53,15 +68,30 @@ pub fn scalblnl(x: c_longdouble, n: c_long) callconv(.c) c_longdouble { test "scalblnl" { // Ported from libc-test - // https://repo.or.cz/libc-test.git/blob/HEAD:/src/math/sanity/ldexpl.h - const x: c_longdouble = -0x1.02239f3c6a8f13dep+3; - const expected: c_longdouble = -0x1.02239f3c6a8f13dep+1; - try expect(scalblnl(x, -2) == expected); + // https://repo.or.cz/libc-test.git/blob/HEAD:src/math/sanity/scalblnl.h + const cases = [_]struct { x: c_longdouble, n: c_int, expected: c_longdouble }{ + .{ .x = -0x1.02239f3c6a8f13dep+3, .n = -2, .expected = -0x1.02239f3c6a8f13dep+1 }, + .{ .x = 0x1.161868e18bc67782p+2, .n = -1, .expected = 0x1.161868e18bc67782p+1 }, + .{ .x = -0x1.0c34b3e01e6e682cp+3, .n = 0, .expected = -0x1.0c34b3e01e6e682cp+3 }, + .{ .x = -0x1.a206f0a19dcc3948p+2, .n = 1, .expected = -0x1.a206f0a19dcc3948p+3 }, + .{ .x = 0x1.288bbb0d6a1e5bdap+3, .n = 2, .expected = 0x1.288bbb0d6a1e5bdap+5 }, + .{ .x = 0x1.52efd0cd80496a5ap-1, .n = 3, .expected = 0x1.52efd0cd80496a5ap+2 }, + .{ .x = -0x1.a05cc754481d0bdp-2, .n = 4, .expected = -0x1.a05cc754481d0bdp+2 }, + .{ .x = 0x1.1f9ef934745cad6p-1, .n = 5, .expected = 0x1.1f9ef934745cad6p+4 }, + .{ .x = 0x1.8c5db097f744257ep-1, .n = 6, .expected = 0x1.8c5db097f744257ep+5 }, + .{ .x = -0x1.5b86ea8118a0e2bcp-1, .n = 7, .expected = -0x1.5b86ea8118a0e2bcp+6 }, + }; + for (cases) |case| { + try expect(scalblnl(case.x, case.n) == case.expected); + } } test "scalblnl.special" { // Ported from libc-test - // https://repo.or.cz/libc-test.git/blob/HEAD:/src/math/special/ldexpl.h + // https://repo.or.cz/libc-test.git/blob/HEAD:src/math/special/scalblnl.h try expect(math.isNan(scalblnl(math.nan(c_longdouble), 0))); try expect(math.isPositiveInf(scalblnl(math.inf(c_longdouble), 0))); + try expect(scalblnf(0x1p+0, 0) == 0x1p+0); + try expect(scalblnf(0x1p+0, 1) == 0x1p+1); + try expect(scalblnf(0x1p+0, -1) == 0x1p-1); }