commit 7f6eab270493592d4c3e5788dfcb34fdbca80539 (tree)
parent ecea8cc16d783518d38c1022278336b422215232
Author: GasInfinity <me@gasinfinity.dev>
Date: Thu, 8 Jan 2026 13:38:40 +0100
feat(libzigc): add `nan`, `nanf`, `nanl` and `bsearch`
* also remove musl implementation
Diffstat:
13 files changed, 78 insertions(+), 166 deletions(-)
diff --git a/lib/c/math.zig b/lib/c/math.zig
@@ -10,6 +10,27 @@ comptime {
@export(&isnanf, .{ .name = "__isnanf", .linkage = common.linkage, .visibility = common.visibility });
@export(&isnanl, .{ .name = "isnanl", .linkage = common.linkage, .visibility = common.visibility });
@export(&isnanl, .{ .name = "__isnanl", .linkage = common.linkage, .visibility = common.visibility });
+
+ @export(&std.math.nan(f64), .{ .name = "__QNAN", .linkage = common.linkage, .visibility = common.visibility });
+ @export(&std.math.snan(f64), .{ .name = "__SNAN", .linkage = common.linkage, .visibility = common.visibility });
+ @export(&std.math.inf(f64), .{ .name = "__INF", .linkage = common.linkage, .visibility = common.visibility });
+ @export(&std.math.floatTrueMin(f64), .{ .name = "__DENORM", .linkage = common.linkage, .visibility = common.visibility });
+
+ @export(&std.math.nan(f32), .{ .name = "__QNANF", .linkage = common.linkage, .visibility = common.visibility });
+ @export(&std.math.snan(f32), .{ .name = "__SNANF", .linkage = common.linkage, .visibility = common.visibility });
+ @export(&std.math.inf(f32), .{ .name = "__INFF", .linkage = common.linkage, .visibility = common.visibility });
+ @export(&std.math.floatTrueMin(f32), .{ .name = "__DENORMF", .linkage = common.linkage, .visibility = common.visibility });
+
+ @export(&std.math.nan(c_longdouble), .{ .name = "__QNANL", .linkage = common.linkage, .visibility = common.visibility });
+ @export(&std.math.snan(c_longdouble), .{ .name = "__SNANL", .linkage = common.linkage, .visibility = common.visibility });
+ @export(&std.math.inf(c_longdouble), .{ .name = "__INFL", .linkage = common.linkage, .visibility = common.visibility });
+ @export(&std.math.floatTrueMin(c_longdouble), .{ .name = "__DENORML", .linkage = common.linkage, .visibility = common.visibility });
+ }
+
+ if (builtin.target.isMinGW() or builtin.target.isMuslLibC() or builtin.target.isWasiLibC()) {
+ @export(&nan, .{ .name = "nan", .linkage = common.linkage, .visibility = common.visibility });
+ @export(&nanf, .{ .name = "nanf", .linkage = common.linkage, .visibility = common.visibility });
+ @export(&nanl, .{ .name = "nanl", .linkage = common.linkage, .visibility = common.visibility });
}
}
@@ -24,3 +45,15 @@ fn isnanf(x: f32) callconv(.c) c_int {
fn isnanl(x: c_longdouble) callconv(.c) c_int {
return if (std.math.isNan(x)) 1 else 0;
}
+
+fn nan(_: [*:0]const c_char) callconv(.c) f64 {
+ return std.math.nan(f64);
+}
+
+fn nanf(_: [*:0]const c_char) callconv(.c) f32 {
+ return std.math.nan(f32);
+}
+
+fn nanl(_: [*:0]const c_char) callconv(.c) c_longdouble {
+ return std.math.nan(c_longdouble);
+}
diff --git a/lib/c/stdlib.zig b/lib/c/stdlib.zig
@@ -18,6 +18,8 @@ comptime {
@export(&qsort_r, .{ .name = "qsort_r", .linkage = common.linkage, .visibility = common.visibility });
@export(&qsort, .{ .name = "qsort", .linkage = common.linkage, .visibility = common.visibility });
+
+ @export(&bsearch, .{ .name = "bsearch", .linkage = common.linkage, .visibility = common.visibility });
}
}
@@ -95,6 +97,26 @@ fn qsort(base: *anyopaque, n: usize, size: usize, compare: *const fn (a: *const
}).wrap, @constCast(compare));
}
+// NOTE: Despite its name, `bsearch` doesn't need to be implemented using binary search or make any complexity guarantee.
+fn bsearch(key: *const anyopaque, base: *const anyopaque, n: usize, size: usize, compare: *const fn (a: *const anyopaque, b: *const anyopaque) callconv(.c) c_int) callconv(.c) ?*anyopaque {
+ const base_bytes: [*]const u8 = @ptrCast(base);
+ var low: usize = 0;
+ var high: usize = n;
+
+ while (low < high) {
+ // Avoid overflowing in the midpoint calculation
+ const mid = low + (high - low) / 2;
+ const elem = &base_bytes[mid * size];
+
+ switch (std.math.order(compare(key, elem), 0)) {
+ .eq => return @constCast(elem),
+ .gt => low = mid + 1,
+ .lt => high = mid,
+ }
+ }
+ return null;
+}
+
test abs {
const val: c_int = -10;
try std.testing.expectEqual(10, abs(val));
@@ -124,3 +146,26 @@ test lldiv {
const expected: lldiv_t = .{ .quot = 1, .rem = 2 };
try std.testing.expectEqual(expected, lldiv(5, 3));
}
+
+test bsearch {
+ const Comparison = struct {
+ pub fn compare(a: *const anyopaque, b: *const anyopaque) callconv(.c) c_int {
+ const a_u16: *const u16 = @ptrCast(@alignCast(a));
+ const b_u16: *const u16 = @ptrCast(@alignCast(b));
+
+ return switch (std.math.order(a_u16.*, b_u16.*)) {
+ .gt => 1,
+ .eq => 0,
+ .lt => -1,
+ };
+ }
+ };
+
+ const items: []const u16 = &.{ 0, 5, 7, 9, 10, 200, 512, 768 };
+
+ try std.testing.expectEqual(@as(?*anyopaque, null), bsearch(&@as(u16, 2000), items.ptr, items.len, @sizeOf(u16), Comparison.compare));
+
+ for (items) |*value| {
+ try std.testing.expectEqual(@as(*const anyopaque, value), bsearch(value, items.ptr, items.len, @sizeOf(u16), Comparison.compare));
+ }
+}
diff --git a/lib/libc/mingw/math/fp_consts.c b/lib/libc/mingw/math/fp_consts.c
@@ -1,20 +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 "fp_consts.h"
-const union _ieee_rep __QNAN = { __DOUBLE_QNAN_REP };
-const union _ieee_rep __SNAN = { __DOUBLE_SNAN_REP };
-const union _ieee_rep __INF = { __DOUBLE_INF_REP };
-const union _ieee_rep __DENORM = { __DOUBLE_DENORM_REP };
-
-/* ISO C99 */
-#undef nan
-/* FIXME */
-double nan (const char *);
-double nan (const char * tagp __attribute__((unused)) )
-{
- return __QNAN.double_val;
-}
-
diff --git a/lib/libc/mingw/math/fp_consts.h b/lib/libc/mingw/math/fp_consts.h
@@ -1,50 +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.
- */
-#ifndef _FP_CONSTS_H
-#define _FP_CONSTS_H
-
-/*
-According to IEEE 754 a QNaN has exponent bits of all 1 values and
-initial significand bit of 1. A SNaN has has an exponent of all 1
-values and initial significand bit of 0 (with one or more other
-significand bits of 1). An Inf has significand of 0 and
-exponent of all 1 values. A denormal value has all exponent bits of 0.
-*/
-
-
-#define __DOUBLE_INF_REP { 0, 0, 0, 0x7ff0 }
-#define __DOUBLE_QNAN_REP { 0, 0, 0, 0x7ff8 }
-#define __DOUBLE_SNAN_REP { 0, 0, 0, 0x7ff0 }
-#define __DOUBLE_DENORM_REP {1, 0, 0, 0}
-
-#define D_NAN_MASK 0x7ff0000000000000LL /* this will mask NaN's and Inf's */
-
-#define __FLOAT_INF_REP { 0, 0x7f80 }
-#define __FLOAT_QNAN_REP { 0, 0x7fc0 }
-#define __FLOAT_SNAN_REP { 0, 0x7f80 }
-#define __FLOAT_DENORM_REP {1,0}
-
-#define F_NAN_MASK 0x7f800000
-
-/*
- This assumes no implicit (hidden) bit in extended mode.
- Padded to 96 bits
- */
-#define __LONG_DOUBLE_INF_REP { 0, 0, 0, 0x8000, 0x7fff, 0 }
-#define __LONG_DOUBLE_QNAN_REP { 0, 0, 0, 0xc000, 0x7fff, 0 }
-#define __LONG_DOUBLE_SNAN_REP { 0, 0, 0, 0x8000, 0x7fff, 0 }
-#define __LONG_DOUBLE_DENORM_REP {1, 0, 0, 0, 0, 0}
-
-union _ieee_rep
-{
- unsigned short rep[6];
- float float_val;
- double double_val;
- long double ldouble_val;
-};
-
-#endif /* _FP_CONSTS_H */
-
diff --git a/lib/libc/mingw/math/fp_constsf.c b/lib/libc/mingw/math/fp_constsf.c
@@ -1,22 +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 "fp_consts.h"
-
-const union _ieee_rep __QNANF = { __FLOAT_QNAN_REP };
-const union _ieee_rep __SNANF = { __FLOAT_SNAN_REP };
-const union _ieee_rep __INFF = { __FLOAT_INF_REP };
-const union _ieee_rep __DENORMF = { __FLOAT_DENORM_REP };
-
-/* ISO C99 */
-#undef nanf
-/* FIXME */
-float nanf(const char *);
-
-float nanf(const char * tagp __attribute__((unused)) )
-{
- return __QNANF.float_val;
-}
-
diff --git a/lib/libc/mingw/math/fp_constsl.c b/lib/libc/mingw/math/fp_constsl.c
@@ -1,25 +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 "fp_consts.h"
-#include <math.h>
-
-const union _ieee_rep __QNANL = { __LONG_DOUBLE_QNAN_REP };
-const union _ieee_rep __SNANL = { __LONG_DOUBLE_SNAN_REP };
-const union _ieee_rep __INFL = { __LONG_DOUBLE_INF_REP };
-const union _ieee_rep __DENORML = { __LONG_DOUBLE_DENORM_REP };
-
-#undef nanl
-/* FIXME */
-long double nanl (const char *);
-long double nanl (const char * tagp __attribute__((unused)) )
-{
-#if __SIZEOF_LONG_DOUBLE__ == __SIZEOF_DOUBLE__
- return nan("");
-#else
- return __QNANL.ldouble_val;
-#endif
-}
-
diff --git a/lib/libc/musl/src/math/nan.c b/lib/libc/musl/src/math/nan.c
@@ -1,6 +0,0 @@
-#include <math.h>
-
-double nan(const char *s)
-{
- return NAN;
-}
diff --git a/lib/libc/musl/src/math/nanf.c b/lib/libc/musl/src/math/nanf.c
@@ -1,6 +0,0 @@
-#include <math.h>
-
-float nanf(const char *s)
-{
- return NAN;
-}
diff --git a/lib/libc/musl/src/math/nanl.c b/lib/libc/musl/src/math/nanl.c
@@ -1,6 +0,0 @@
-#include <math.h>
-
-long double nanl(const char *s)
-{
- return NAN;
-}
diff --git a/lib/libc/musl/src/stdlib/bsearch.c b/lib/libc/musl/src/stdlib/bsearch.c
@@ -1,20 +0,0 @@
-#include <stdlib.h>
-
-void *bsearch(const void *key, const void *base, size_t nel, size_t width, int (*cmp)(const void *, const void *))
-{
- void *try;
- int sign;
- while (nel > 0) {
- try = (char *)base + width*(nel/2);
- sign = cmp(key, try);
- if (sign < 0) {
- nel /= 2;
- } else if (sign > 0) {
- base = (char *)try + width;
- nel -= nel/2+1;
- } else {
- return try;
- }
- }
- return NULL;
-}
diff --git a/src/libs/mingw.zig b/src/libs/mingw.zig
@@ -610,9 +610,6 @@ const mingw32_generic_src = [_][]const u8{
"gdtoa" ++ path.sep_str ++ "sum.c",
"gdtoa" ++ path.sep_str ++ "ulp.c",
"math" ++ path.sep_str ++ "coshl.c",
- "math" ++ path.sep_str ++ "fp_consts.c",
- "math" ++ path.sep_str ++ "fp_constsf.c",
- "math" ++ path.sep_str ++ "fp_constsl.c",
"math" ++ path.sep_str ++ "fpclassify.c",
"math" ++ path.sep_str ++ "fpclassifyf.c",
"math" ++ path.sep_str ++ "fpclassifyl.c",
diff --git a/src/libs/musl.zig b/src/libs/musl.zig
@@ -1045,9 +1045,6 @@ const src_files = [_][]const u8{
"musl/src/math/modf.c",
"musl/src/math/modff.c",
"musl/src/math/modfl.c",
- "musl/src/math/nan.c",
- "musl/src/math/nanf.c",
- "musl/src/math/nanl.c",
"musl/src/math/nearbyint.c",
"musl/src/math/nearbyintf.c",
"musl/src/math/nearbyintl.c",
@@ -1717,7 +1714,6 @@ const src_files = [_][]const u8{
"musl/src/stdlib/atoi.c",
"musl/src/stdlib/atol.c",
"musl/src/stdlib/atoll.c",
- "musl/src/stdlib/bsearch.c",
"musl/src/stdlib/ecvt.c",
"musl/src/stdlib/fcvt.c",
"musl/src/stdlib/gcvt.c",
diff --git a/src/libs/wasi_libc.zig b/src/libs/wasi_libc.zig
@@ -818,9 +818,6 @@ const libc_top_half_src_files = [_][]const u8{
"musl/src/math/modf.c",
"musl/src/math/modff.c",
"musl/src/math/modfl.c",
- "musl/src/math/nan.c",
- "musl/src/math/nanf.c",
- "musl/src/math/nanl.c",
"musl/src/math/nearbyintl.c",
"musl/src/math/nextafter.c",
"musl/src/math/nextafterf.c",
@@ -1007,7 +1004,6 @@ const libc_top_half_src_files = [_][]const u8{
"musl/src/stdlib/atoi.c",
"musl/src/stdlib/atol.c",
"musl/src/stdlib/atoll.c",
- "musl/src/stdlib/bsearch.c",
"musl/src/stdlib/ecvt.c",
"musl/src/stdlib/fcvt.c",
"musl/src/stdlib/gcvt.c",