authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-03-18 06:34:19+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-03-18 06:34:19+01:00
log820308b3d44ed7ca2cabd07a11b2099992ed4e6b
treea966df79d83872d0a077cb2579e9fd1f6db1e7d3
parentf8997aca8f62eef4968e4abf817ece4eb4e91c38
parent153990d407e53d965bbb0c2c9ece333737c90363

Merge pull request '`libzigc`: Implement `tanhf`, `tanh`, `modfl`, `modff`, `modf`, `acoshf`, `asin`' (#31536) from mihael/zig:libzigc/more-math-functions into master

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/31536 Reviewed-by: Andrew Kelley <andrew@ziglang.org>

15 files changed, 133 insertions(+), 487 deletions(-)

lib/c/math.zig+133-17
...@@ -2,6 +2,10 @@ const builtin = @import("builtin");...@@ -2,6 +2,10 @@ const builtin = @import("builtin");
22
3const std = @import("std");3const std = @import("std");
4const math = std.math;4const math = std.math;
5const expect = std.testing.expect;
6const expectEqual = std.testing.expectEqual;
7const expectApproxEqAbs = std.testing.expectApproxEqAbs;
8const expectApproxEqRel = std.testing.expectApproxEqRel;
59
6const symbol = @import("../c.zig").symbol;10const symbol = @import("../c.zig").symbol;
711
...@@ -34,14 +38,19 @@ comptime {...@@ -34,14 +38,19 @@ comptime {
34 symbol(&coshf, "coshf");38 symbol(&coshf, "coshf");
35 symbol(&hypotf, "hypotf");39 symbol(&hypotf, "hypotf");
36 symbol(&hypotl, "hypotl");40 symbol(&hypotl, "hypotl");
41 symbol(&modff, "modff");
42 symbol(&modfl, "modfl");
37 symbol(&nan, "nan");43 symbol(&nan, "nan");
38 symbol(&nanf, "nanf");44 symbol(&nanf, "nanf");
39 symbol(&nanl, "nanl");45 symbol(&nanl, "nanl");
46 symbol(&tanhf, "tanhf");
40 }47 }
4148
42 if (builtin.target.isMuslLibC() or builtin.target.isWasiLibC()) {49 if (builtin.target.isMuslLibC() or builtin.target.isWasiLibC()) {
43 symbol(&acos, "acos");50 symbol(&acos, "acos");
44 symbol(&acosf, "acosf");51 symbol(&acosf, "acosf");
52 symbol(&acoshf, "acoshf");
53 symbol(&asin, "asin");
45 symbol(&atan, "atan");54 symbol(&atan, "atan");
46 symbol(&atanf, "atanf");55 symbol(&atanf, "atanf");
47 symbol(&atanl, "atanl");56 symbol(&atanl, "atanl");
...@@ -51,9 +60,11 @@ comptime {...@@ -51,9 +60,11 @@ comptime {
51 symbol(&exp10, "exp10");60 symbol(&exp10, "exp10");
52 symbol(&exp10f, "exp10f");61 symbol(&exp10f, "exp10f");
53 symbol(&hypot, "hypot");62 symbol(&hypot, "hypot");
63 symbol(&modf, "modf");
54 symbol(&pow, "pow");64 symbol(&pow, "pow");
55 symbol(&pow10, "pow10");65 symbol(&pow10, "pow10");
56 symbol(&pow10f, "pow10f");66 symbol(&pow10f, "pow10f");
67 symbol(&tanh, "tanh");
57 }68 }
5869
59 if (builtin.target.isMuslLibC()) {70 if (builtin.target.isMuslLibC()) {
...@@ -70,7 +81,15 @@ fn acos(x: f64) callconv(.c) f64 {...@@ -70,7 +81,15 @@ fn acos(x: f64) callconv(.c) f64 {
70}81}
7182
72fn acosf(x: f32) callconv(.c) f32 {83fn acosf(x: f32) callconv(.c) f32 {
73 return std.math.acos(x);84 return math.acos(x);
85}
86
87fn acoshf(x: f32) callconv(.c) f32 {
88 return math.acosh(x);
89}
90
91fn asin(x: f64) callconv(.c) f64 {
92 return math.asin(x);
74}93}
7594
76fn atan(x: f64) callconv(.c) f64 {95fn atan(x: f64) callconv(.c) f64 {
...@@ -152,6 +171,95 @@ fn isnanl(x: c_longdouble) callconv(.c) c_int {...@@ -152,6 +171,95 @@ fn isnanl(x: c_longdouble) callconv(.c) c_int {
152 return if (math.isNan(x)) 1 else 0;171 return if (math.isNan(x)) 1 else 0;
153}172}
154173
174fn modfGeneric(comptime T: type, x: T, iptr: *T) T {
175 if (math.isNegativeInf(x)) {
176 iptr.* = -math.inf(T);
177 return -0.0;
178 }
179
180 if (math.isPositiveInf(x)) {
181 iptr.* = math.inf(T);
182 return 0.0;
183 }
184
185 if (math.isNan(x)) {
186 iptr.* = math.nan(T);
187 return math.nan(T);
188 }
189
190 const r = math.modf(x);
191 iptr.* = r.ipart;
192
193 // If the result is a negative zero, we must be explicit about
194 // returning a negative zero.
195 return if (math.isNegativeZero(x) or (x < 0.0 and x == r.ipart)) -0.0 else r.fpart;
196}
197
198fn modf(x: f64, iptr: *f64) callconv(.c) f64 {
199 return modfGeneric(f64, x, iptr);
200}
201
202fn modff(x: f32, iptr: *f32) callconv(.c) f32 {
203 return modfGeneric(f32, x, iptr);
204}
205
206fn modfl(x: c_longdouble, iptr: *c_longdouble) callconv(.c) c_longdouble {
207 return modfGeneric(c_longdouble, x, iptr);
208}
209
210fn testModf(comptime T: type) !void {
211 // Choose the appropriate `modf` impl to test based on type
212 const f = switch (T) {
213 f32 => modff,
214 f64 => modf,
215 c_longdouble => modfl,
216 else => @compileError("modf not implemented for " ++ @typeName(T)),
217 };
218
219 var int: T = undefined;
220 const iptr = &int;
221 const eps_val: comptime_float = @max(1e-6, math.floatEps(T));
222
223 const normal_frac = f(@as(T, 1234.567), iptr);
224 // Account for precision error
225 const expected = 1234.567 - @as(T, 1234);
226 try expectApproxEqAbs(expected, normal_frac, eps_val);
227 try expectApproxEqRel(@as(T, 1234.0), iptr.*, eps_val);
228
229 // When `x` is a NaN, NaN is returned and `*iptr` is set to NaN
230 const nan_frac = f(math.nan(T), iptr);
231 try expect(math.isNan(nan_frac));
232 try expect(math.isNan(iptr.*));
233
234 // When `x` is positive infinity, +0 is returned and `*iptr` is set to
235 // positive infinity
236 const pos_zero_frac = f(math.inf(T), iptr);
237 try expect(math.isPositiveZero(pos_zero_frac));
238 try expect(math.isPositiveInf(iptr.*));
239
240 // When `x` is negative infinity, -0 is returned and `*iptr` is set to
241 // negative infinity
242 const neg_zero_frac = f(-math.inf(T), iptr);
243 try expect(math.isNegativeZero(neg_zero_frac));
244 try expect(math.isNegativeInf(iptr.*));
245
246 // Return -0 when `x` is a negative integer
247 const nz_frac = f(@as(T, -1000.0), iptr);
248 try expect(math.isNegativeZero(nz_frac));
249 try expectEqual(@as(T, -1000.0), iptr.*);
250
251 // Return +0 when `x` is a positive integer
252 const pz_frac = f(@as(T, 1000.0), iptr);
253 try expect(math.isPositiveZero(pz_frac));
254 try expectEqual(@as(T, 1000.0), iptr.*);
255}
256
257test "modf" {
258 try testModf(f32);
259 try testModf(f64);
260 try testModf(c_longdouble);
261}
262
155fn nan(_: [*:0]const c_char) callconv(.c) f64 {263fn nan(_: [*:0]const c_char) callconv(.c) f64 {
156 return math.nan(f64);264 return math.nan(f64);
157}265}
...@@ -177,7 +285,7 @@ fn pow10f(x: f32) callconv(.c) f32 {...@@ -177,7 +285,7 @@ fn pow10f(x: f32) callconv(.c) f32 {
177}285}
178286
179fn rint(x: f64) callconv(.c) f64 {287fn rint(x: f64) callconv(.c) f64 {
180 const toint: f64 = 1.0 / @as(f64, std.math.floatEps(f64));288 const toint: f64 = 1.0 / @as(f64, math.floatEps(f64));
181 const a: u64 = @bitCast(x);289 const a: u64 = @bitCast(x);
182 const e = a >> 52 & 0x7ff;290 const e = a >> 52 & 0x7ff;
183 const s = a >> 63;291 const s = a >> 63;
...@@ -199,35 +307,43 @@ fn rint(x: f64) callconv(.c) f64 {...@@ -199,35 +307,43 @@ fn rint(x: f64) callconv(.c) f64 {
199307
200test "rint" {308test "rint" {
201 // Positive numbers round correctly309 // Positive numbers round correctly
202 try std.testing.expectEqual(@as(f64, 42.0), rint(42.2));310 try expectEqual(@as(f64, 42.0), rint(42.2));
203 try std.testing.expectEqual(@as(f64, 42.0), rint(41.8));311 try expectEqual(@as(f64, 42.0), rint(41.8));
204312
205 // Negative numbers round correctly313 // Negative numbers round correctly
206 try std.testing.expectEqual(@as(f64, -6.0), rint(-5.9));314 try expectEqual(@as(f64, -6.0), rint(-5.9));
207 try std.testing.expectEqual(@as(f64, -6.0), rint(-6.1));315 try expectEqual(@as(f64, -6.0), rint(-6.1));
208316
209 // No rounding needed test317 // No rounding needed test
210 try std.testing.expectEqual(@as(f64, 5.0), rint(5.0));318 try expectEqual(@as(f64, 5.0), rint(5.0));
211 try std.testing.expectEqual(@as(f64, -10.0), rint(-10.0));319 try expectEqual(@as(f64, -10.0), rint(-10.0));
212 try std.testing.expectEqual(@as(f64, 0.0), rint(0.0));320 try expectEqual(@as(f64, 0.0), rint(0.0));
213321
214 // Very large numbers return unchanged322 // Very large numbers return unchanged
215 const large: f64 = 9007199254740992.0; // 2^53323 const large: f64 = 9007199254740992.0; // 2^53
216 try std.testing.expectEqual(large, rint(large));324 try expectEqual(large, rint(large));
217 try std.testing.expectEqual(-large, rint(-large));325 try expectEqual(-large, rint(-large));
218326
219 // Small positive numbers round to zero327 // Small positive numbers round to zero
220 const pos_result = rint(0.3);328 const pos_result = rint(0.3);
221 try std.testing.expectEqual(@as(f64, 0.0), pos_result);329 try expectEqual(@as(f64, 0.0), pos_result);
222 try std.testing.expect(@as(u64, @bitCast(pos_result)) == 0);330 try expect(@as(u64, @bitCast(pos_result)) == 0);
223331
224 // Small negative numbers round to negative zero332 // Small negative numbers round to negative zero
225 const neg_result = rint(-0.3);333 const neg_result = rint(-0.3);
226 try std.testing.expectEqual(@as(f64, 0.0), neg_result);334 try expectEqual(@as(f64, 0.0), neg_result);
227 const bits: u64 = @bitCast(neg_result);335 const bits: u64 = @bitCast(neg_result);
228 try std.testing.expect((bits >> 63) == 1);336 try expect((bits >> 63) == 1);
229337
230 // Exact half rounds to nearest even (banker's rounding)338 // Exact half rounds to nearest even (banker's rounding)
231 try std.testing.expectEqual(@as(f64, 2.0), rint(2.5));339 try expectEqual(@as(f64, 2.0), rint(2.5));
232 try std.testing.expectEqual(@as(f64, 4.0), rint(3.5));340 try expectEqual(@as(f64, 4.0), rint(3.5));
341}
342
343fn tanh(x: f64) callconv(.c) f64 {
344 return math.tanh(x);
345}
346
347fn tanhf(x: f32) callconv(.c) f32 {
348 return math.tanh(x);
233}349}
lib/libc/mingw/math/modff.c deleted-42
...@@ -1,42 +0,0 @@
1/**
2 * This file has no copyright assigned and is placed in the Public Domain.
3 * This file is part of the mingw-w64 runtime package.
4 * No warranty is given; refer to the file DISCLAIMER.PD within this package.
5 */
6#include <fenv.h>
7#include <math.h>
8#include <errno.h>
9
10float
11modff (float value, float* iptr)
12{
13 float int_part = 0.0F;
14 /* truncate */
15 /* truncate */
16#if (defined(_AMD64_) && !defined(_ARM64EC_)) || (defined(__x86_64__) && !defined(__arm64ec__))
17 asm volatile ("subq $8, %%rsp\n"
18 "fnstcw 4(%%rsp)\n"
19 "movzwl 4(%%rsp), %%eax\n"
20 "orb $12, %%ah\n"
21 "movw %%ax, (%%rsp)\n"
22 "fldcw (%%rsp)\n"
23 "frndint\n"
24 "fldcw 4(%%rsp)\n"
25 "addq $8, %%rsp\n" : "=t" (int_part) : "0" (value) : "eax"); /* round */
26#elif defined(_X86_) || defined(__i386__)
27 asm volatile ("push %%eax\n\tsubl $8, %%esp\n"
28 "fnstcw 4(%%esp)\n"
29 "movzwl 4(%%esp), %%eax\n"
30 "orb $12, %%ah\n"
31 "movw %%ax, (%%esp)\n"
32 "fldcw (%%esp)\n"
33 "frndint\n"
34 "fldcw 4(%%esp)\n"
35 "addl $8, %%esp\n\tpop %%eax\n" : "=t" (int_part) : "0" (value) : "eax"); /* round */
36#else
37 int_part = truncf(value);
38#endif
39 if (iptr)
40 *iptr = int_part;
41 return (isinf (value) ? 0.0F : value - int_part);
42}
lib/libc/mingw/math/modfl.c deleted-41
...@@ -1,41 +0,0 @@
1/**
2 * This file has no copyright assigned and is placed in the Public Domain.
3 * This file is part of the mingw-w64 runtime package.
4 * No warranty is given; refer to the file DISCLAIMER.PD within this package.
5 */
6#include <fenv.h>
7#include <math.h>
8#include <errno.h>
9
10long double
11modfl (long double value, long double* iptr)
12{
13 long double int_part = 0.0L;
14 /* truncate */
15#if (defined(_AMD64_) && !defined(_ARM64EC_)) || (defined(__x86_64__) && !defined(__arm64ec__))
16 asm volatile ("subq $8, %%rsp\n"
17 "fnstcw 4(%%rsp)\n"
18 "movzwl 4(%%rsp), %%eax\n"
19 "orb $12, %%ah\n"
20 "movw %%ax, (%%rsp)\n"
21 "fldcw (%%rsp)\n"
22 "frndint\n"
23 "fldcw 4(%%rsp)\n"
24 "addq $8, %%rsp\n" : "=t" (int_part) : "0" (value) : "eax"); /* round */
25#elif defined(_X86_) || defined(__i386__)
26 asm volatile ("push %%eax\n\tsubl $8, %%esp\n"
27 "fnstcw 4(%%esp)\n"
28 "movzwl 4(%%esp), %%eax\n"
29 "orb $12, %%ah\n"
30 "movw %%ax, (%%esp)\n"
31 "fldcw (%%esp)\n"
32 "frndint\n"
33 "fldcw 4(%%esp)\n"
34 "addl $8, %%esp\n\tpop %%eax\n" : "=t" (int_part) : "0" (value) : "eax"); /* round */
35#else
36 int_part = truncl(value);
37#endif
38 if (iptr)
39 *iptr = int_part;
40 return (isinf (value) ? 0.0L : value - int_part);
41}
lib/libc/mingw/math/tanhf.c deleted-10
...@@ -1,10 +0,0 @@
1/**
2 * This file has no copyright assigned and is placed in the Public Domain.
3 * This file is part of the mingw-w64 runtime package.
4 * No warranty is given; refer to the file DISCLAIMER.PD within this package.
5 */
6#include <math.h>
7float tanhf (float x)
8{
9 return (float) tanh (x);
10}
lib/libc/musl/src/math/acoshf.c deleted-26
...@@ -1,26 +0,0 @@
1#include "libm.h"
2
3#if FLT_EVAL_METHOD==2
4#undef sqrtf
5#define sqrtf sqrtl
6#elif FLT_EVAL_METHOD==1
7#undef sqrtf
8#define sqrtf sqrt
9#endif
10
11/* acosh(x) = log(x + sqrt(x*x-1)) */
12float acoshf(float x)
13{
14 union {float f; uint32_t i;} u = {x};
15 uint32_t a = u.i & 0x7fffffff;
16
17 if (a < 0x3f800000+(1<<23))
18 /* |x| < 2, invalid if x < 1 */
19 /* up to 2ulp error in [1,1.125] */
20 return log1pf(x-1 + sqrtf((x-1)*(x-1)+2*(x-1)));
21 if (u.i < 0x3f800000+(12<<23))
22 /* 2 <= x < 0x1p12 */
23 return logf(2*x - 1/(x+sqrtf(x*x-1)));
24 /* x >= 0x1p12 or x <= -2 or nan */
25 return logf(x) + 0.693147180559945309417232121458176568f;
26}
lib/libc/musl/src/math/asin.c deleted-107
...@@ -1,107 +0,0 @@
1/* origin: FreeBSD /usr/src/lib/msun/src/e_asin.c */
2/*
3 * ====================================================
4 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5 *
6 * Developed at SunSoft, a Sun Microsystems, Inc. business.
7 * Permission to use, copy, modify, and distribute this
8 * software is freely granted, provided that this notice
9 * is preserved.
10 * ====================================================
11 */
12/* asin(x)
13 * Method :
14 * Since asin(x) = x + x^3/6 + x^5*3/40 + x^7*15/336 + ...
15 * we approximate asin(x) on [0,0.5] by
16 * asin(x) = x + x*x^2*R(x^2)
17 * where
18 * R(x^2) is a rational approximation of (asin(x)-x)/x^3
19 * and its remez error is bounded by
20 * |(asin(x)-x)/x^3 - R(x^2)| < 2^(-58.75)
21 *
22 * For x in [0.5,1]
23 * asin(x) = pi/2-2*asin(sqrt((1-x)/2))
24 * Let y = (1-x), z = y/2, s := sqrt(z), and pio2_hi+pio2_lo=pi/2;
25 * then for x>0.98
26 * asin(x) = pi/2 - 2*(s+s*z*R(z))
27 * = pio2_hi - (2*(s+s*z*R(z)) - pio2_lo)
28 * For x<=0.98, let pio4_hi = pio2_hi/2, then
29 * f = hi part of s;
30 * c = sqrt(z) - f = (z-f*f)/(s+f) ...f+c=sqrt(z)
31 * and
32 * asin(x) = pi/2 - 2*(s+s*z*R(z))
33 * = pio4_hi+(pio4-2s)-(2s*z*R(z)-pio2_lo)
34 * = pio4_hi+(pio4-2f)-(2s*z*R(z)-(pio2_lo+2c))
35 *
36 * Special cases:
37 * if x is NaN, return x itself;
38 * if |x|>1, return NaN with invalid signal.
39 *
40 */
41
42#include "libm.h"
43
44static const double
45pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */
46pio2_lo = 6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */
47/* coefficients for R(x^2) */
48pS0 = 1.66666666666666657415e-01, /* 0x3FC55555, 0x55555555 */
49pS1 = -3.25565818622400915405e-01, /* 0xBFD4D612, 0x03EB6F7D */
50pS2 = 2.01212532134862925881e-01, /* 0x3FC9C155, 0x0E884455 */
51pS3 = -4.00555345006794114027e-02, /* 0xBFA48228, 0xB5688F3B */
52pS4 = 7.91534994289814532176e-04, /* 0x3F49EFE0, 0x7501B288 */
53pS5 = 3.47933107596021167570e-05, /* 0x3F023DE1, 0x0DFDF709 */
54qS1 = -2.40339491173441421878e+00, /* 0xC0033A27, 0x1C8A2D4B */
55qS2 = 2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */
56qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */
57qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */
58
59static double R(double z)
60{
61 double_t p, q;
62 p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5)))));
63 q = 1.0+z*(qS1+z*(qS2+z*(qS3+z*qS4)));
64 return p/q;
65}
66
67double asin(double x)
68{
69 double z,r,s;
70 uint32_t hx,ix;
71
72 GET_HIGH_WORD(hx, x);
73 ix = hx & 0x7fffffff;
74 /* |x| >= 1 or nan */
75 if (ix >= 0x3ff00000) {
76 uint32_t lx;
77 GET_LOW_WORD(lx, x);
78 if ((ix-0x3ff00000 | lx) == 0)
79 /* asin(1) = +-pi/2 with inexact */
80 return x*pio2_hi + 0x1p-120f;
81 return 0/(x-x);
82 }
83 /* |x| < 0.5 */
84 if (ix < 0x3fe00000) {
85 /* if 0x1p-1022 <= |x| < 0x1p-26, avoid raising underflow */
86 if (ix < 0x3e500000 && ix >= 0x00100000)
87 return x;
88 return x + x*R(x*x);
89 }
90 /* 1 > |x| >= 0.5 */
91 z = (1 - fabs(x))*0.5;
92 s = sqrt(z);
93 r = R(z);
94 if (ix >= 0x3fef3333) { /* if |x| > 0.975 */
95 x = pio2_hi-(2*(s+s*r)-pio2_lo);
96 } else {
97 double f,c;
98 /* f+c = sqrt(z) */
99 f = s;
100 SET_LOW_WORD(f,0);
101 c = (z-f*f)/(s+f);
102 x = 0.5*pio2_hi - (2*s*r - (pio2_lo-2*c) - (0.5*pio2_hi-2*f));
103 }
104 if (hx >> 31)
105 return -x;
106 return x;
107}
lib/libc/musl/src/math/i386/asin.s deleted-21
...@@ -1,21 +0,0 @@
1.global asin
2.type asin,@function
3asin:
4 fldl 4(%esp)
5 mov 8(%esp),%eax
6 add %eax,%eax
7 cmp $0x00200000,%eax
8 jb 1f
9 fld %st(0)
10 fld1
11 fsub %st(0),%st(1)
12 fadd %st(2)
13 fmulp
14 fsqrt
15 fpatan
16 fstpl 4(%esp)
17 fldl 4(%esp)
18 ret
19 # subnormal x, return x with underflow
201: fsts 4(%esp)
21 ret
lib/libc/musl/src/math/modf.c deleted-34
...@@ -1,34 +0,0 @@
1#include "libm.h"
2
3double modf(double x, double *iptr)
4{
5 union {double f; uint64_t i;} u = {x};
6 uint64_t mask;
7 int e = (int)(u.i>>52 & 0x7ff) - 0x3ff;
8
9 /* no fractional part */
10 if (e >= 52) {
11 *iptr = x;
12 if (e == 0x400 && u.i<<12 != 0) /* nan */
13 return x;
14 u.i &= 1ULL<<63;
15 return u.f;
16 }
17
18 /* no integral part*/
19 if (e < 0) {
20 u.i &= 1ULL<<63;
21 *iptr = u.f;
22 return x;
23 }
24
25 mask = -1ULL>>12>>e;
26 if ((u.i & mask) == 0) {
27 *iptr = x;
28 u.i &= 1ULL<<63;
29 return u.f;
30 }
31 u.i &= ~mask;
32 *iptr = u.f;
33 return x - u.f;
34}
lib/libc/musl/src/math/modff.c deleted-34
...@@ -1,34 +0,0 @@
1#include "libm.h"
2
3float modff(float x, float *iptr)
4{
5 union {float f; uint32_t i;} u = {x};
6 uint32_t mask;
7 int e = (int)(u.i>>23 & 0xff) - 0x7f;
8
9 /* no fractional part */
10 if (e >= 23) {
11 *iptr = x;
12 if (e == 0x80 && u.i<<9 != 0) { /* nan */
13 return x;
14 }
15 u.i &= 0x80000000;
16 return u.f;
17 }
18 /* no integral part */
19 if (e < 0) {
20 u.i &= 0x80000000;
21 *iptr = u.f;
22 return x;
23 }
24
25 mask = 0x007fffff>>e;
26 if ((u.i & mask) == 0) {
27 *iptr = x;
28 u.i &= 0x80000000;
29 return u.f;
30 }
31 u.i &= ~mask;
32 *iptr = u.f;
33 return x - u.f;
34}
lib/libc/musl/src/math/modfl.c deleted-53
...@@ -1,53 +0,0 @@
1#include "libm.h"
2
3#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
4long double modfl(long double x, long double *iptr)
5{
6 double d;
7 long double r;
8
9 r = modf(x, &d);
10 *iptr = d;
11 return r;
12}
13#elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384
14
15static const long double toint = 1/LDBL_EPSILON;
16
17long double modfl(long double x, long double *iptr)
18{
19 union ldshape u = {x};
20 int e = (u.i.se & 0x7fff) - 0x3fff;
21 int s = u.i.se >> 15;
22 long double absx;
23 long double y;
24
25 /* no fractional part */
26 if (e >= LDBL_MANT_DIG-1) {
27 *iptr = x;
28 if (isnan(x))
29 return x;
30 return s ? -0.0 : 0.0;
31 }
32
33 /* no integral part*/
34 if (e < 0) {
35 *iptr = s ? -0.0 : 0.0;
36 return x;
37 }
38
39 /* raises spurious inexact */
40 absx = s ? -x : x;
41 y = absx + toint - toint - absx;
42 if (y == 0) {
43 *iptr = x;
44 return s ? -0.0 : 0.0;
45 }
46 if (y > 0)
47 y -= 1;
48 if (s)
49 y = -y;
50 *iptr = x + y;
51 return -y;
52}
53#endif
lib/libc/musl/src/math/tanh.c deleted-45
...@@ -1,45 +0,0 @@
1#include "libm.h"
2
3/* tanh(x) = (exp(x) - exp(-x))/(exp(x) + exp(-x))
4 * = (exp(2*x) - 1)/(exp(2*x) - 1 + 2)
5 * = (1 - exp(-2*x))/(exp(-2*x) - 1 + 2)
6 */
7double tanh(double x)
8{
9 union {double f; uint64_t i;} u = {.f = x};
10 uint32_t w;
11 int sign;
12 double_t t;
13
14 /* x = |x| */
15 sign = u.i >> 63;
16 u.i &= (uint64_t)-1/2;
17 x = u.f;
18 w = u.i >> 32;
19
20 if (w > 0x3fe193ea) {
21 /* |x| > log(3)/2 ~= 0.5493 or nan */
22 if (w > 0x40340000) {
23 /* |x| > 20 or nan */
24 /* note: this branch avoids raising overflow */
25 t = 1 - 0/x;
26 } else {
27 t = expm1(2*x);
28 t = 1 - 2/(t+2);
29 }
30 } else if (w > 0x3fd058ae) {
31 /* |x| > log(5/3)/2 ~= 0.2554 */
32 t = expm1(2*x);
33 t = t/(t+2);
34 } else if (w >= 0x00100000) {
35 /* |x| >= 0x1p-1022, up to 2ulp error in [0.1,0.2554] */
36 t = expm1(-2*x);
37 t = -t/(t+2);
38 } else {
39 /* |x| is subnormal */
40 /* note: the branch above would not raise underflow in [0x1p-1023,0x1p-1022) */
41 FORCE_EVAL((float)x);
42 t = x;
43 }
44 return sign ? -t : t;
45}
lib/libc/musl/src/math/tanhf.c deleted-39
...@@ -1,39 +0,0 @@
1#include "libm.h"
2
3float tanhf(float x)
4{
5 union {float f; uint32_t i;} u = {.f = x};
6 uint32_t w;
7 int sign;
8 float t;
9
10 /* x = |x| */
11 sign = u.i >> 31;
12 u.i &= 0x7fffffff;
13 x = u.f;
14 w = u.i;
15
16 if (w > 0x3f0c9f54) {
17 /* |x| > log(3)/2 ~= 0.5493 or nan */
18 if (w > 0x41200000) {
19 /* |x| > 10 */
20 t = 1 + 0/x;
21 } else {
22 t = expm1f(2*x);
23 t = 1 - 2/(t+2);
24 }
25 } else if (w > 0x3e82c578) {
26 /* |x| > log(5/3)/2 ~= 0.2554 */
27 t = expm1f(2*x);
28 t = t/(t+2);
29 } else if (w >= 0x00800000) {
30 /* |x| >= 0x1p-126 */
31 t = expm1f(-2*x);
32 t = -t/(t+2);
33 } else {
34 /* |x| is subnormal */
35 FORCE_EVAL(x*x);
36 t = x;
37 }
38 return sign ? -t : t;
39}
src/libs/mingw.zig-3
...@@ -619,7 +619,6 @@ const mingw32_generic_src = [_][]const u8{...@@ -619,7 +619,6 @@ const mingw32_generic_src = [_][]const u8{
619 "math" ++ path.sep_str ++ "lgamma.c",619 "math" ++ path.sep_str ++ "lgamma.c",
620 "math" ++ path.sep_str ++ "lgammaf.c",620 "math" ++ path.sep_str ++ "lgammaf.c",
621 "math" ++ path.sep_str ++ "lgammal.c",621 "math" ++ path.sep_str ++ "lgammal.c",
622 "math" ++ path.sep_str ++ "modfl.c",
623 "math" ++ path.sep_str ++ "powi.c",622 "math" ++ path.sep_str ++ "powi.c",
624 "math" ++ path.sep_str ++ "powif.c",623 "math" ++ path.sep_str ++ "powif.c",
625 "math" ++ path.sep_str ++ "powil.c",624 "math" ++ path.sep_str ++ "powil.c",
...@@ -977,10 +976,8 @@ const mingw32_x86_src = [_][]const u8{...@@ -977,10 +976,8 @@ const mingw32_x86_src = [_][]const u8{
977976
978const mingw32_x86_32_src = [_][]const u8{977const mingw32_x86_32_src = [_][]const u8{
979 // ucrtbase978 // ucrtbase
980 "math" ++ path.sep_str ++ "modff.c",
981 "math" ++ path.sep_str ++ "powf.c",979 "math" ++ path.sep_str ++ "powf.c",
982 "math" ++ path.sep_str ++ "sinhf.c",980 "math" ++ path.sep_str ++ "sinhf.c",
983 "math" ++ path.sep_str ++ "tanhf.c",
984 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "acosf.c",981 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "acosf.c",
985 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "asinf.c",982 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "asinf.c",
986 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "atan2f.c",983 "math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "atan2f.c",
src/libs/musl.zig-8
...@@ -796,12 +796,10 @@ const src_files = [_][]const u8{...@@ -796,12 +796,10 @@ const src_files = [_][]const u8{
796 "musl/src/math/aarch64/nearbyintf.c",796 "musl/src/math/aarch64/nearbyintf.c",
797 "musl/src/math/aarch64/rintf.c",797 "musl/src/math/aarch64/rintf.c",
798 "musl/src/math/acosh.c",798 "musl/src/math/acosh.c",
799 "musl/src/math/acoshf.c",
800 "musl/src/math/acoshl.c",799 "musl/src/math/acoshl.c",
801 "musl/src/math/acosl.c",800 "musl/src/math/acosl.c",
802 "musl/src/math/arm/fma.c",801 "musl/src/math/arm/fma.c",
803 "musl/src/math/arm/fmaf.c",802 "musl/src/math/arm/fmaf.c",
804 "musl/src/math/asin.c",
805 "musl/src/math/asinf.c",803 "musl/src/math/asinf.c",
806 "musl/src/math/asinh.c",804 "musl/src/math/asinh.c",
807 "musl/src/math/asinhf.c",805 "musl/src/math/asinhf.c",
...@@ -849,7 +847,6 @@ const src_files = [_][]const u8{...@@ -849,7 +847,6 @@ const src_files = [_][]const u8{
849 "musl/src/math/i386/acosl.s",847 "musl/src/math/i386/acosl.s",
850 "musl/src/math/i386/asinf.s",848 "musl/src/math/i386/asinf.s",
851 "musl/src/math/i386/asinl.s",849 "musl/src/math/i386/asinl.s",
852 "musl/src/math/i386/asin.s",
853 "musl/src/math/i386/atan2f.s",850 "musl/src/math/i386/atan2f.s",
854 "musl/src/math/i386/atan2l.s",851 "musl/src/math/i386/atan2l.s",
855 "musl/src/math/i386/atan2.s",852 "musl/src/math/i386/atan2.s",
...@@ -937,9 +934,6 @@ const src_files = [_][]const u8{...@@ -937,9 +934,6 @@ const src_files = [_][]const u8{
937 "musl/src/math/__math_uflowf.c",934 "musl/src/math/__math_uflowf.c",
938 "musl/src/math/__math_xflow.c",935 "musl/src/math/__math_xflow.c",
939 "musl/src/math/__math_xflowf.c",936 "musl/src/math/__math_xflowf.c",
940 "musl/src/math/modf.c",
941 "musl/src/math/modff.c",
942 "musl/src/math/modfl.c",
943 "musl/src/math/nearbyint.c",937 "musl/src/math/nearbyint.c",
944 "musl/src/math/nearbyintf.c",938 "musl/src/math/nearbyintf.c",
945 "musl/src/math/nearbyintl.c",939 "musl/src/math/nearbyintl.c",
...@@ -1009,8 +1003,6 @@ const src_files = [_][]const u8{...@@ -1009,8 +1003,6 @@ const src_files = [_][]const u8{
1009 "musl/src/math/sinl.c",1003 "musl/src/math/sinl.c",
1010 "musl/src/math/__tan.c",1004 "musl/src/math/__tan.c",
1011 "musl/src/math/__tandf.c",1005 "musl/src/math/__tandf.c",
1012 "musl/src/math/tanh.c",
1013 "musl/src/math/tanhf.c",
1014 "musl/src/math/tanhl.c",1006 "musl/src/math/tanhl.c",
1015 "musl/src/math/__tanl.c",1007 "musl/src/math/__tanl.c",
1016 "musl/src/math/tanl.c",1008 "musl/src/math/tanl.c",
src/libs/wasi_libc.zig-7
...@@ -665,10 +665,8 @@ const libc_top_half_src_files = [_][]const u8{...@@ -665,10 +665,8 @@ const libc_top_half_src_files = [_][]const u8{
665 "musl/src/locale/wcscoll.c",665 "musl/src/locale/wcscoll.c",
666 "musl/src/locale/wcsxfrm.c",666 "musl/src/locale/wcsxfrm.c",
667 "musl/src/math/acosh.c",667 "musl/src/math/acosh.c",
668 "musl/src/math/acoshf.c",
669 "musl/src/math/acoshl.c",668 "musl/src/math/acoshl.c",
670 "musl/src/math/acosl.c",669 "musl/src/math/acosl.c",
671 "musl/src/math/asin.c",
672 "musl/src/math/asinf.c",670 "musl/src/math/asinf.c",
673 "musl/src/math/asinh.c",671 "musl/src/math/asinh.c",
674 "musl/src/math/asinhf.c",672 "musl/src/math/asinhf.c",
...@@ -757,9 +755,6 @@ const libc_top_half_src_files = [_][]const u8{...@@ -757,9 +755,6 @@ const libc_top_half_src_files = [_][]const u8{
757 "musl/src/math/__math_uflowf.c",755 "musl/src/math/__math_uflowf.c",
758 "musl/src/math/__math_xflow.c",756 "musl/src/math/__math_xflow.c",
759 "musl/src/math/__math_xflowf.c",757 "musl/src/math/__math_xflowf.c",
760 "musl/src/math/modf.c",
761 "musl/src/math/modff.c",
762 "musl/src/math/modfl.c",
763 "musl/src/math/nearbyintl.c",758 "musl/src/math/nearbyintl.c",
764 "musl/src/math/nextafter.c",759 "musl/src/math/nextafter.c",
765 "musl/src/math/nextafterf.c",760 "musl/src/math/nextafterf.c",
...@@ -798,8 +793,6 @@ const libc_top_half_src_files = [_][]const u8{...@@ -798,8 +793,6 @@ const libc_top_half_src_files = [_][]const u8{
798 "musl/src/math/sinl.c",793 "musl/src/math/sinl.c",
799 "musl/src/math/__tan.c",794 "musl/src/math/__tan.c",
800 "musl/src/math/__tandf.c",795 "musl/src/math/__tandf.c",
801 "musl/src/math/tanh.c",
802 "musl/src/math/tanhf.c",
803 "musl/src/math/tanhl.c",796 "musl/src/math/tanhl.c",
804 "musl/src/math/__tanl.c",797 "musl/src/math/__tanl.c",
805 "musl/src/math/tanl.c",798 "musl/src/math/tanl.c",