feat(libzigc): add nan, nanf, nanl and bsearch

* also remove musl implementation
This commit is contained in:
GasInfinity
2026-01-08 13:38:40 +01:00
committed by Andrew Kelley
parent ecea8cc16d
commit 7f6eab2704
13 changed files with 78 additions and 166 deletions
+33
View File
@@ -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);
}
+45
View File
@@ -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));
}
}
-20
View File
@@ -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;
}
-50
View File
@@ -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 */
-22
View File
@@ -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;
}
-25
View File
@@ -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
}
-6
View File
@@ -1,6 +0,0 @@
#include <math.h>
double nan(const char *s)
{
return NAN;
}
-6
View File
@@ -1,6 +0,0 @@
#include <math.h>
float nanf(const char *s)
{
return NAN;
}
-6
View File
@@ -1,6 +0,0 @@
#include <math.h>
long double nanl(const char *s)
{
return NAN;
}
-20
View File
@@ -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;
}
-3
View File
@@ -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",
-4
View File
@@ -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",
-4
View File
@@ -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",