diff --git a/libc/log/die.c b/libc/log/die.c index 29216b49..066c2768 100644 --- a/libc/log/die.c +++ b/libc/log/die.c @@ -17,12 +17,9 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/bits/bits.h" -#include "libc/bits/weaken.h" #include "libc/dce.h" #include "libc/log/backtrace.internal.h" #include "libc/log/log.h" -#include "libc/runtime/runtime.h" -#include "libc/stdio/stdio.h" /** * Aborts process after printing a backtrace. @@ -32,13 +29,10 @@ relegated wontreturn void __die(void) { static bool once; if (cmpxchg(&once, false, true)) { - if (weaken(fflush)) { - weaken(fflush)(NULL); - } if (!IsTiny()) { if (IsDebuggerPresent(false)) DebugBreak(); ShowBacktrace(2, NULL); } } - _exit(77); + exit(77); } diff --git a/libc/log/onkill.c b/libc/log/onkill.c index f296ceca..4e12fc7c 100644 --- a/libc/log/onkill.c +++ b/libc/log/onkill.c @@ -20,6 +20,8 @@ #include "libc/calls/calls.h" #include "libc/calls/sigbits.h" #include "libc/calls/struct/sigaction.h" +#include "libc/calls/struct/siginfo.h" +#include "libc/calls/ucontext.h" #include "libc/dce.h" #include "libc/log/log.h" #include "libc/macros.internal.h" @@ -34,9 +36,6 @@ * @see also libc/oncrash.c */ -struct ucontext; -struct siginfo; - static const int sigs[] = { SIGHUP, /* hangup aka ctrl_close_event */ SIGINT, /* ctrl+c aka ^C aka ETX aka \003 aka ♥ */ diff --git a/libc/nt/master.sh b/libc/nt/master.sh index e8c947b8..31f68142 100755 --- a/libc/nt/master.sh +++ b/libc/nt/master.sh @@ -7698,7 +7698,7 @@ imp '_memccpy' _memccpy ntdll 2198 imp '_memicmp' _memicmp ntdll 2199 imp '_onexit' _onexit KernelBase 1846 imp '_purecall' _purecall KernelBase 1847 -imp 'sys__setjmp_nt' _setjmp ntdll 2200 +imp 'sys__setjmp_nt' _setjmp ntdll 2200 imp '_setjmpex' _setjmpex ntdll 2201 imp '_time64' _time64 KernelBase 1848 imp '_wmakepath_s' _wmakepath_s ntdll 2245 @@ -7707,7 +7707,7 @@ imp '_wtoi' _wtoi ntdll 2247 imp '_wtoi64' _wtoi64 ntdll 2248 imp '_wtol' _wtol ntdll 2249 imp 'sys_abs_nt' abs ntdll 2250 -imp '__sys_accept_nt' accept ws2_32 1 +imp '__sys_accept_nt' accept ws2_32 1 imp 'sys_atan_nt' atan ntdll 2251 imp 'sys_atan2_nt' atan2 ntdll 2252 imp 'sys_atexit_nt' atexit KernelBase 1849 @@ -7718,12 +7718,12 @@ imp 'bDeleteLDC' bDeleteLDC gdi32 1949 imp 'bInitSystemAndFontsDirectories' bInitSystemAndFontsDirectoriesW gdi32 1950 imp 'bMakePathName' bMakePathNameW gdi32 1951 imp '__sys_bind_nt' bind ws2_32 2 3 -imp 'sys_bsearch_nt' bsearch ntdll 2255 +imp 'sys_bsearch_nt' bsearch ntdll 2255 imp 'bsearch_s' bsearch_s ntdll 2256 imp 'cGetTTFFromFOT' cGetTTFFromFOT gdi32 1952 imp 'sys_ceil_nt' ceil ntdll 2257 imp '__sys_closesocket_nt' closesocket ws2_32 3 1 -imp '__sys_connect_nt' connect ws2_32 4 +imp '__sys_connect_nt' connect ws2_32 4 imp 'sys_cos_nt' cos ntdll 2258 imp 'dwLBSubclass' dwLBSubclass comdlg32 128 imp 'dwOKSubclass' dwOKSubclass comdlg32 129 @@ -7745,7 +7745,7 @@ imp 'sys_gethostname_nt' gethostname ws2_32 57 imp 'sys_getnameinfo_nt' getnameinfo ws2_32 192 imp '__sys_getpeername_nt' getpeername ws2_32 5 3 imp 'sys_getprotobyname_nt' getprotobyname ws2_32 53 -imp 'sys_getprotobynumber_nt' getprotobynumber ws2_32 54 +imp 'sys_getprotobynumber_nt' getprotobynumber ws2_32 54 imp 'sys_getservbyname_nt' getservbyname ws2_32 55 imp 'sys_getservbyport_nt' getservbyport ws2_32 56 imp '__sys_getsockname_nt' getsockname ws2_32 6 3 @@ -7758,24 +7758,24 @@ imp '__sys_ioctlsocket_nt' ioctlsocket ws2_32 10 3 imp 'iswascii' iswascii ntdll 2273 imp 'keybd_event' keybd_event user32 2580 imp 'sys_labs_nt' labs ntdll 2282 -imp '__sys_listen_nt' listen ws2_32 13 2 +imp '__sys_listen_nt' listen ws2_32 13 2 imp 'sys_log_nt' log ntdll 2283 -imp 'sys_longjmp_nt' longjmp ntdll 2284 +imp 'sys_longjmp_nt' longjmp ntdll 2284 imp 'mouse_event' mouse_event user32 2583 imp 'pGdiDevCaps' pGdiDevCaps gdi32 1961 imp 'pGdiSharedHandleTable' pGdiSharedHandleTable gdi32 1962 imp 'pGdiSharedMemory' pGdiSharedMemory gdi32 1963 imp 'pldcGet' pldcGet gdi32 1964 imp 'sys_recv_nt' recv ws2_32 16 -imp '__sys_recvfrom_nt' recvfrom ws2_32 17 -imp '__sys_select_nt' select ws2_32 18 5 +imp '__sys_recvfrom_nt' recvfrom ws2_32 17 +imp '__sys_select_nt' select ws2_32 18 5 imp 'semDxTrimNotification' semDxTrimNotification gdi32 1965 imp 'sys_send_nt' send ws2_32 19 -imp '__sys_sendto_nt' sendto ws2_32 20 +imp '__sys_sendto_nt' sendto ws2_32 20 imp '__sys_setsockopt_nt' setsockopt ws2_32 21 5 -imp '__sys_shutdown_nt' shutdown ws2_32 22 2 +imp '__sys_shutdown_nt' shutdown ws2_32 22 2 imp 'sys_sin_nt' sin ntdll 2296 -imp '__sys_socket_nt' socket ws2_32 23 +imp '__sys_socket_nt' socket ws2_32 23 imp 'timeBeginPeriod' timeBeginPeriod kernel32 1609 imp 'timeEndPeriod' timeEndPeriod kernel32 1610 imp 'timeGetDevCaps' timeGetDevCaps kernel32 1611 diff --git a/libc/tinymath/copysign.S b/libc/tinymath/copysign.S index bbfed88b..e97fba7c 100644 --- a/libc/tinymath/copysign.S +++ b/libc/tinymath/copysign.S @@ -36,9 +36,9 @@ copysign: .rodata.cst16 .Lnan: .long 0xffffffff .long 0x7fffffff - .long 0 - .long 0 -.Lneg0: .long 0 - .long -2147483648 - .long 0 - .long 0 + .long 0x00000000 + .long 0x00000000 +.Lneg0: .long 0x00000000 + .long 0x80000000 + .long 0x00000000 + .long 0x00000000 diff --git a/libc/tinymath/cos.S b/libc/tinymath/cos.S index 79e42d96..ee183c06 100644 --- a/libc/tinymath/cos.S +++ b/libc/tinymath/cos.S @@ -17,7 +17,6 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/macros.internal.h" -.source __FILE__ // Returns cosine of 𝑥. // diff --git a/libc/tinymath/exp10.S b/libc/tinymath/exp10.S index 29ae89b8..2865646c 100644 --- a/libc/tinymath/exp10.S +++ b/libc/tinymath/exp10.S @@ -23,8 +23,7 @@ // @param 𝑥 is double scalar in low half of %xmm0 // @return double scalar in low half of %xmm0 // @see pow(), exp() -exp10: - ezlea exp10l,ax +exp10: ezlea exp10l,ax jmp _d2ld2 .endfn exp10,globl .alias exp10,pow10 diff --git a/libc/tinymath/fabsl.S b/libc/tinymath/fabsl.S index eb77c7e7..d6e7738a 100644 --- a/libc/tinymath/fabsl.S +++ b/libc/tinymath/fabsl.S @@ -17,7 +17,6 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/macros.internal.h" -.source __FILE__ // Returns absolute value of 𝑥. // diff --git a/libc/tinymath/powl.c b/libc/tinymath/powl.c new file mode 100644 index 00000000..b1e4345d --- /dev/null +++ b/libc/tinymath/powl.c @@ -0,0 +1,67 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/math.h" + +/** + * Returns 𝑥^𝑦. + */ +long double powl(long double x, long double y) { + long double t, u; + if (!isunordered(x, y)) { + if (!isinf(y)) { + if (!isinf(x)) { + if (x) { + asm("fyl2x" : "=t"(u) : "0"(fabsl(x)), "u"(y) : "st(1)"); + asm("fprem" : "=t"(t) : "0"(u), "u"(1.L)); + asm("f2xm1" : "=t"(t) : "0"(t)); + asm("fscale" : "=t"(t) : "0"(t + 1), "u"(u)); + return copysignl(t, x); + } else if (y > 0) { + return 0; + } else if (!y) { + return 1; + } else if (y == truncl(y) && ((int64_t)y & 1)) { + return copysignl(INFINITY, x); + } else { + return INFINITY; + } + } else if (signbit(x)) { + if (!y) return 1; + x = y < 0 ? 0 : INFINITY; + if (y == truncl(y) && ((int64_t)y & 1)) x = -x; + return x; + } else if (y < 0) { + return 0; + } else if (y > 0) { + return INFINITY; + } else { + return 1; + } + } else { + x = fabsl(x); + if (x < 1) return signbit(y) ? INFINITY : 0; + if (x > 1) return signbit(y) ? 0 : INFINITY; + return 1; + } + } else if (!y || x == 1) { + return 1; + } else { + return NAN; + } +} diff --git a/libc/tinymath/powl.S b/libc/tinymath/powlfinite.c similarity index 64% rename from libc/tinymath/powl.S rename to libc/tinymath/powlfinite.c index f9865d64..0b95b9bc 100644 --- a/libc/tinymath/powl.S +++ b/libc/tinymath/powlfinite.c @@ -1,7 +1,7 @@ -/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ ╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ │ │ │ Permission to use, copy, modify, and/or distribute this software for │ │ any purpose with or without fee is hereby granted, provided that the │ @@ -16,37 +16,8 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/runtime/pc.internal.h" -#include "libc/macros.internal.h" +#include "libc/math.h" -// Returns 𝑥^𝑦. -// -// @param 𝑥 is an 80-bit long double passed on stack in 16-bytes -// @param 𝑦 is the power, also pushed on stack, in reverse order -// @return result of exponentiation on FPU stack in %st -// @note Sun's fdlibm needs 2kLOC to do this for RISC lool -// @define z=y*log2(fabs(x)),copysign(trunc(exp2(fmod(z,1)))*exp2(z),x) -powl: push %rbp - mov %rsp,%rbp - .profilable - fldt 32(%rbp) - fldt 16(%rbp) - fxam - fstsw - fabs - fyl2x - fld1 - fld %st(1) - fprem - f2xm1 - faddp - fscale - fxch - fstp %st - test $FPU_C1>>8,%ah - jz 1f - fchs -1: pop %rbp - ret - .endfn powl,globl - .alias powl,__powl_finite +long double __powl_finite(long double x, long double y) { + return powl(x, y); +} diff --git a/libc/tinymath/truncl.S b/libc/tinymath/truncl.S index f8af463c..f679c50e 100644 --- a/libc/tinymath/truncl.S +++ b/libc/tinymath/truncl.S @@ -17,18 +17,23 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/macros.internal.h" -.source __FILE__ -truncl: .profilable - sub $24,%rsp - fldt 32(%rsp) - fnstcw 14(%rsp) - movzwl 14(%rsp),%eax +// Rounds to integer, toward zero. +// +// @param 𝑥 is long double passed on stack +// @return long double in %st +truncl: pushq %rbp + mov %rsp,%rbp + .profilable + sub $16,%rsp + fnstcw -2(%rbp) + fldt 16(%rbp) + movzwl -2(%rbp),%eax or $0b1100,%ah # round to zero - mov %ax,12(%rsp) - fldcw 12(%rsp) + mov %ax,-4(%rbp) + fldcw -4(%rbp) frndint - fldcw 14(%rsp) - add $24,%rsp + fldcw -2(%rbp) + leave ret .endfn truncl,globl diff --git a/libc/x/xdtoal.c b/libc/x/xdtoal.c index c5786a0a..e36933e5 100644 --- a/libc/x/xdtoal.c +++ b/libc/x/xdtoal.c @@ -29,5 +29,6 @@ char *xdtoal(long double d) { char *p = xmalloc(32); g_xfmt_p(p, &d, 16, 32, 2); + /* g_xfmt_p(p, &d, 20, 32, 2); */ return p; } diff --git a/test/libc/tinymath/exp10_test.c b/test/libc/tinymath/exp10_test.c index 9300c629..5ec7b0c1 100644 --- a/test/libc/tinymath/exp10_test.c +++ b/test/libc/tinymath/exp10_test.c @@ -28,6 +28,7 @@ TEST(exp10l, test) { EXPECT_STREQ("1", gc(xdtoal(exp10l(0)))); EXPECT_STREQ("1", gc(xdtoal(exp10l(-0.)))); + EXPECT_STREQ(".01", gc(xdtoal(exp10l(-2.)))); EXPECT_STREQ("INFINITY", gc(xdtoal(exp10l(INFINITY)))); EXPECT_STREQ("0", gc(xdtoal(exp10l(-INFINITY)))); EXPECT_STREQ("NAN", gc(xdtoal(exp10l(NAN)))); @@ -38,6 +39,7 @@ TEST(exp10l, test) { TEST(exp10, test) { EXPECT_STREQ("1", gc(xdtoa(exp10(0)))); EXPECT_STREQ("1", gc(xdtoa(exp10(-0.)))); + EXPECT_STREQ(".01", gc(xdtoa(exp10(-2.)))); EXPECT_STREQ("INFINITY", gc(xdtoa(exp10(INFINITY)))); EXPECT_STREQ("0", gc(xdtoa(exp10(-INFINITY)))); EXPECT_STREQ("NAN", gc(xdtoa(exp10(NAN)))); @@ -48,6 +50,7 @@ TEST(exp10, test) { TEST(exp10f, test) { EXPECT_STREQ("1", gc(xdtoaf(exp10f(0)))); EXPECT_STREQ("1", gc(xdtoaf(exp10f(-0.)))); + EXPECT_STREQ(".01", gc(xdtoaf(exp10f(-2.)))); EXPECT_STREQ("INFINITY", gc(xdtoaf(exp10f(INFINITY)))); EXPECT_STREQ("0", gc(xdtoaf(exp10f(-INFINITY)))); EXPECT_STREQ("NAN", gc(xdtoaf(exp10f(NAN)))); diff --git a/test/libc/tinymath/powl_test.c b/test/libc/tinymath/powl_test.c index b68bbcc8..3b927b8d 100644 --- a/test/libc/tinymath/powl_test.c +++ b/test/libc/tinymath/powl_test.c @@ -19,7 +19,9 @@ #include "libc/calls/struct/sigaction.h" #include "libc/calls/struct/siginfo.h" #include "libc/calls/ucontext.h" +#include "libc/macros.internal.h" #include "libc/math.h" +#include "libc/rand/rand.h" #include "libc/runtime/gc.h" #include "libc/runtime/pc.internal.h" #include "libc/stdio/stdio.h" @@ -29,7 +31,12 @@ #include "libc/testlib/testlib.h" #include "libc/x/x.h" -TEST(powl, testLongDouble) { +int rando; +void SetUp(void) { + rando = rand() & 0xffff; +} + +TEST(powl, test) { EXPECT_STREQ("27", gc(xdtoal(powl(3, 3)))); EXPECT_STREQ("-27", gc(xdtoal(powl(-3, 3)))); EXPECT_STREQ("-1", gc(xdtoal(powl(-1, 1.1)))); @@ -37,21 +44,143 @@ TEST(powl, testLongDouble) { EXPECT_STREQ("INFINITY", gc(xdtoal(powl(10, 4933)))); EXPECT_STREQ("0", gc(xdtoal(powl(10, -5000)))); EXPECT_STREQ("1.063382396627933e+37", gc(xdtoal(powl(2, 123)))); - EXPECT_STARTSWITH(".4248496805467504", gc(xdtoal(powl(0.7, 2.4)))); + EXPECT_STARTSWITH(".4248496805467504", gc(xdtoal(powl(.7, 2.4)))); + EXPECT_STREQ("1", gc(xdtoal(powl(1, NAN)))); + EXPECT_STREQ("1", gc(xdtoal(powl(1, rando)))); + EXPECT_STREQ("1", gc(xdtoal(powl(NAN, 0)))); + EXPECT_STREQ("1", gc(xdtoal(powl(rando, 0)))); + EXPECT_STREQ("0", gc(xdtoal(powl(0, 1)))); + EXPECT_STREQ("0", gc(xdtoal(powl(0, 2)))); + EXPECT_STREQ("0", gc(xdtoal(powl(0, 2.1)))); + EXPECT_STREQ("1", gc(xdtoal(powl(-1, INFINITY)))); + EXPECT_STREQ("1", gc(xdtoal(powl(-1, -INFINITY)))); + EXPECT_STREQ("INFINITY", gc(xdtoal(powl(1. / MAX(2, rando), -INFINITY)))); + EXPECT_STREQ("0", gc(xdtoal(powl(1.1, -INFINITY)))); + EXPECT_STREQ("0", gc(xdtoal(powl(MAX(2, rando), -INFINITY)))); + EXPECT_STREQ("0", gc(xdtoal(powl(1. / MAX(2, rando), INFINITY)))); + EXPECT_STREQ("INFINITY", gc(xdtoal(powl(MAX(2, rando), INFINITY)))); + EXPECT_STREQ("-0", gc(xdtoal(powl(-INFINITY, -1)))); + EXPECT_STREQ("0", gc(xdtoal(powl(-INFINITY, -1.1)))); + EXPECT_STREQ("0", gc(xdtoal(powl(-INFINITY, -2)))); + EXPECT_STREQ("0", gc(xdtoal(powl(-INFINITY, -2.1)))); + EXPECT_STREQ("-0", gc(xdtoal(powl(-INFINITY, -3)))); + EXPECT_STREQ("0", gc(xdtoal(powl(-INFINITY, -3.1)))); + EXPECT_STREQ("-INFINITY", gc(xdtoal(powl(-INFINITY, 1)))); + EXPECT_STREQ("INFINITY", gc(xdtoal(powl(-INFINITY, 1.1)))); + EXPECT_STREQ("INFINITY", gc(xdtoal(powl(-INFINITY, 2)))); + EXPECT_STREQ("INFINITY", gc(xdtoal(powl(-INFINITY, 2.1)))); + EXPECT_STREQ("-INFINITY", gc(xdtoal(powl(-INFINITY, 3)))); + EXPECT_STREQ("INFINITY", gc(xdtoal(powl(-INFINITY, 3.1)))); + EXPECT_STREQ("0", gc(xdtoal(powl(INFINITY, -1)))); + EXPECT_STREQ("0", gc(xdtoal(powl(INFINITY, -.1)))); + EXPECT_STREQ("INFINITY", gc(xdtoal(powl(INFINITY, 1)))); + EXPECT_STREQ("INFINITY", gc(xdtoal(powl(INFINITY, .1)))); + EXPECT_STREQ("1", gc(xdtoal(powl(INFINITY, 0)))); + EXPECT_STREQ("1", gc(xdtoal(powl(INFINITY, -0.)))); + EXPECT_STREQ("1", gc(xdtoal(powl(0, 0)))); + EXPECT_STREQ("1", gc(xdtoal(powl(0, -0.)))); + EXPECT_STREQ("INFINITY", gc(xdtoal(powl(0, -(MAX(rando, 1) | 1))))); + EXPECT_STREQ("-INFINITY", gc(xdtoal(powl(-0., -(MAX(rando, 1) | 1))))); + EXPECT_STREQ("INFINITY", gc(xdtoal(powl(0, -(rando & -2))))); + EXPECT_STREQ("INFINITY", gc(xdtoal(powl(-0., -(rando & -2))))); } -TEST(powl, testDouble) { +TEST(pow, test) { EXPECT_STREQ("27", gc(xdtoa(pow(3, 3)))); EXPECT_STREQ("-27", gc(xdtoa(pow(-3, 3)))); + EXPECT_STREQ("-1", gc(xdtoa(pow(-1, 1.1)))); EXPECT_STREQ("1e+308", gc(xdtoa(pow(10, 308)))); EXPECT_STREQ("INFINITY", gc(xdtoa(pow(10, 309)))); - EXPECT_STARTSWITH(".42484968054675", gc(xdtoa(pow(0.7, 2.4)))); + EXPECT_STREQ("0", gc(xdtoa(pow(10, -5000)))); + EXPECT_STREQ("1.06338239662793e+37", gc(xdtoa(pow(2, 123)))); + EXPECT_STARTSWITH(".42484968054675", gc(xdtoa(pow(.7, 2.4)))); + EXPECT_STREQ("1", gc(xdtoa(pow(1, NAN)))); + EXPECT_STREQ("1", gc(xdtoa(pow(1, rando)))); + EXPECT_STREQ("1", gc(xdtoa(pow(NAN, 0)))); + EXPECT_STREQ("1", gc(xdtoa(pow(rando, 0)))); + EXPECT_STREQ("0", gc(xdtoa(pow(0, 1)))); + EXPECT_STREQ("0", gc(xdtoa(pow(0, 2)))); + EXPECT_STREQ("0", gc(xdtoa(pow(0, 2.1)))); + EXPECT_STREQ("1", gc(xdtoa(pow(-1, INFINITY)))); + EXPECT_STREQ("1", gc(xdtoa(pow(-1, -INFINITY)))); + EXPECT_STREQ("INFINITY", gc(xdtoa(pow(1. / MAX(2, rando), -INFINITY)))); + EXPECT_STREQ("0", gc(xdtoa(pow(1.1, -INFINITY)))); + EXPECT_STREQ("0", gc(xdtoa(pow(MAX(2, rando), -INFINITY)))); + EXPECT_STREQ("0", gc(xdtoa(pow(1. / MAX(2, rando), INFINITY)))); + EXPECT_STREQ("INFINITY", gc(xdtoa(pow(MAX(2, rando), INFINITY)))); + EXPECT_STREQ("-0", gc(xdtoa(pow(-INFINITY, -1)))); + EXPECT_STREQ("0", gc(xdtoa(pow(-INFINITY, -1.1)))); + EXPECT_STREQ("0", gc(xdtoa(pow(-INFINITY, -2)))); + EXPECT_STREQ("0", gc(xdtoa(pow(-INFINITY, -2.1)))); + EXPECT_STREQ("-0", gc(xdtoa(pow(-INFINITY, -3)))); + EXPECT_STREQ("0", gc(xdtoa(pow(-INFINITY, -3.1)))); + EXPECT_STREQ("-INFINITY", gc(xdtoa(pow(-INFINITY, 1)))); + EXPECT_STREQ("INFINITY", gc(xdtoa(pow(-INFINITY, 1.1)))); + EXPECT_STREQ("INFINITY", gc(xdtoa(pow(-INFINITY, 2)))); + EXPECT_STREQ("INFINITY", gc(xdtoa(pow(-INFINITY, 2.1)))); + EXPECT_STREQ("-INFINITY", gc(xdtoa(pow(-INFINITY, 3)))); + EXPECT_STREQ("INFINITY", gc(xdtoa(pow(-INFINITY, 3.1)))); + EXPECT_STREQ("0", gc(xdtoa(pow(INFINITY, -1)))); + EXPECT_STREQ("0", gc(xdtoa(pow(INFINITY, -.1)))); + EXPECT_STREQ("INFINITY", gc(xdtoa(pow(INFINITY, 1)))); + EXPECT_STREQ("INFINITY", gc(xdtoa(pow(INFINITY, .1)))); + EXPECT_STREQ("1", gc(xdtoa(pow(INFINITY, 0)))); + EXPECT_STREQ("1", gc(xdtoa(pow(INFINITY, -0.)))); + EXPECT_STREQ("1", gc(xdtoa(pow(0, 0)))); + EXPECT_STREQ("1", gc(xdtoa(pow(0, -0.)))); + EXPECT_STREQ("INFINITY", gc(xdtoa(pow(0, -(MAX(rando, 1) | 1))))); + EXPECT_STREQ("-INFINITY", gc(xdtoa(pow(-0., -(MAX(rando, 1) | 1))))); + EXPECT_STREQ("INFINITY", gc(xdtoa(pow(0, -(rando & -2))))); + EXPECT_STREQ("INFINITY", gc(xdtoa(pow(-0., -(rando & -2))))); } -TEST(powl, testFloat) { +TEST(powf, test) { EXPECT_STREQ("27", gc(xdtoaf(powf(3, 3)))); EXPECT_STREQ("-27", gc(xdtoaf(powf(-3, 3)))); - EXPECT_STARTSWITH(".4248496", gc(xdtoa(powf(0.7f, 2.4f)))); + EXPECT_STREQ("-1", gc(xdtoaf(powf(-1, 1.1)))); + EXPECT_STREQ("1e+38", gc(xdtoaf(powf(10, 38)))); + EXPECT_STREQ("INFINITY", gc(xdtoaf(powf(10, 39)))); + EXPECT_STREQ("0", gc(xdtoaf(powf(10, -5000)))); + EXPECT_STREQ("1.06338e+37", gc(xdtoaf(powf(2, 123)))); + EXPECT_STARTSWITH(".42485", gc(xdtoaf(powf(.7, 2.4)))); + EXPECT_STREQ("1", gc(xdtoaf(powf(1, NAN)))); + EXPECT_STREQ("1", gc(xdtoaf(powf(1, rando)))); + EXPECT_STREQ("1", gc(xdtoaf(powf(NAN, 0)))); + EXPECT_STREQ("1", gc(xdtoaf(powf(rando, 0)))); + EXPECT_STREQ("0", gc(xdtoaf(powf(0, 1)))); + EXPECT_STREQ("0", gc(xdtoaf(powf(0, 2)))); + EXPECT_STREQ("0", gc(xdtoaf(powf(0, 2.1)))); + EXPECT_STREQ("1", gc(xdtoaf(powf(-1, INFINITY)))); + EXPECT_STREQ("1", gc(xdtoaf(powf(-1, -INFINITY)))); + EXPECT_STREQ("INFINITY", gc(xdtoaf(powf(1. / MAX(2, rando), -INFINITY)))); + EXPECT_STREQ("0", gc(xdtoaf(powf(1.1, -INFINITY)))); + EXPECT_STREQ("0", gc(xdtoaf(powf(MAX(2, rando), -INFINITY)))); + EXPECT_STREQ("0", gc(xdtoaf(powf(1. / MAX(2, rando), INFINITY)))); + EXPECT_STREQ("INFINITY", gc(xdtoaf(powf(MAX(2, rando), INFINITY)))); + EXPECT_STREQ("-0", gc(xdtoaf(powf(-INFINITY, -1)))); + EXPECT_STREQ("0", gc(xdtoaf(powf(-INFINITY, -1.1)))); + EXPECT_STREQ("0", gc(xdtoaf(powf(-INFINITY, -2)))); + EXPECT_STREQ("0", gc(xdtoaf(powf(-INFINITY, -2.1)))); + EXPECT_STREQ("-0", gc(xdtoaf(powf(-INFINITY, -3)))); + EXPECT_STREQ("0", gc(xdtoaf(powf(-INFINITY, -3.1)))); + EXPECT_STREQ("-INFINITY", gc(xdtoaf(powf(-INFINITY, 1)))); + EXPECT_STREQ("INFINITY", gc(xdtoaf(powf(-INFINITY, 1.1)))); + EXPECT_STREQ("INFINITY", gc(xdtoaf(powf(-INFINITY, 2)))); + EXPECT_STREQ("INFINITY", gc(xdtoaf(powf(-INFINITY, 2.1)))); + EXPECT_STREQ("-INFINITY", gc(xdtoaf(powf(-INFINITY, 3)))); + EXPECT_STREQ("INFINITY", gc(xdtoaf(powf(-INFINITY, 3.1)))); + EXPECT_STREQ("0", gc(xdtoaf(powf(INFINITY, -1)))); + EXPECT_STREQ("0", gc(xdtoaf(powf(INFINITY, -.1)))); + EXPECT_STREQ("INFINITY", gc(xdtoaf(powf(INFINITY, 1)))); + EXPECT_STREQ("INFINITY", gc(xdtoaf(powf(INFINITY, .1)))); + EXPECT_STREQ("1", gc(xdtoaf(powf(INFINITY, 0)))); + EXPECT_STREQ("1", gc(xdtoaf(powf(INFINITY, -0.)))); + EXPECT_STREQ("1", gc(xdtoaf(powf(0, 0)))); + EXPECT_STREQ("1", gc(xdtoaf(powf(0, -0.)))); + EXPECT_STREQ("INFINITY", gc(xdtoaf(powf(0, -(MAX(rando, 1) | 1))))); + EXPECT_STREQ("-INFINITY", gc(xdtoaf(powf(-0., -(MAX(rando, 1) | 1))))); + EXPECT_STREQ("INFINITY", gc(xdtoaf(powf(0, -(rando & -2))))); + EXPECT_STREQ("INFINITY", gc(xdtoaf(powf(-0., -(rando & -2))))); } BENCH(powl, bench) { diff --git a/test/libc/tinymath/test.mk b/test/libc/tinymath/test.mk index cd96e229..64169313 100644 --- a/test/libc/tinymath/test.mk +++ b/test/libc/tinymath/test.mk @@ -29,6 +29,7 @@ TEST_LIBC_TINYMATH_DIRECTDEPS = \ LIBC_MEM \ LIBC_NEXGEN32E \ LIBC_RAND \ + LIBC_STDIO \ LIBC_RUNTIME \ LIBC_STR \ LIBC_STUBS \ diff --git a/tool/build/lib/fpu.c b/tool/build/lib/fpu.c index 3ed71fb2..af5d2b98 100644 --- a/tool/build/lib/fpu.c +++ b/tool/build/lib/fpu.c @@ -171,7 +171,8 @@ static long double fyl2xp1(long double x, long double y) { } static long double fscale(long double significand, long double exponent) { - return scalbl(trunc(significand), exponent); + if (isunordered(significand, exponent)) return NAN; + return ldexp(significand, exponent); } static long double x87remainder(long double x, long double y, uint32_t *sw,