Make pow() conform to standard definition

This commit is contained in:
Justine Tunney 2021-03-03 09:05:21 -08:00
parent 754974faaa
commit 8af91bcbe7
15 changed files with 253 additions and 85 deletions

View file

@ -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);
}

View file

@ -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 ♥ */

View file

@ -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

View file

@ -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

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/macros.internal.h"
.source __FILE__
// Returns cosine of 𝑥.
//

View file

@ -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

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/macros.internal.h"
.source __FILE__
// Returns absolute value of 𝑥.
//

67
libc/tinymath/powl.c Normal file
View file

@ -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;
}
}

View file

@ -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);
}

View file

@ -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

View file

@ -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;
}

View file

@ -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))));

View file

@ -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) {

View file

@ -29,6 +29,7 @@ TEST_LIBC_TINYMATH_DIRECTDEPS = \
LIBC_MEM \
LIBC_NEXGEN32E \
LIBC_RAND \
LIBC_STDIO \
LIBC_RUNTIME \
LIBC_STR \
LIBC_STUBS \

View file

@ -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,