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. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/bits/bits.h" #include "libc/bits/bits.h"
#include "libc/bits/weaken.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/log/backtrace.internal.h" #include "libc/log/backtrace.internal.h"
#include "libc/log/log.h" #include "libc/log/log.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
/** /**
* Aborts process after printing a backtrace. * Aborts process after printing a backtrace.
@ -32,13 +29,10 @@
relegated wontreturn void __die(void) { relegated wontreturn void __die(void) {
static bool once; static bool once;
if (cmpxchg(&once, false, true)) { if (cmpxchg(&once, false, true)) {
if (weaken(fflush)) {
weaken(fflush)(NULL);
}
if (!IsTiny()) { if (!IsTiny()) {
if (IsDebuggerPresent(false)) DebugBreak(); if (IsDebuggerPresent(false)) DebugBreak();
ShowBacktrace(2, NULL); ShowBacktrace(2, NULL);
} }
} }
_exit(77); exit(77);
} }

View file

@ -20,6 +20,8 @@
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/sigbits.h" #include "libc/calls/sigbits.h"
#include "libc/calls/struct/sigaction.h" #include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/siginfo.h"
#include "libc/calls/ucontext.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/log/log.h" #include "libc/log/log.h"
#include "libc/macros.internal.h" #include "libc/macros.internal.h"
@ -34,9 +36,6 @@
* @see also libc/oncrash.c * @see also libc/oncrash.c
*/ */
struct ucontext;
struct siginfo;
static const int sigs[] = { static const int sigs[] = {
SIGHUP, /* hangup aka ctrl_close_event */ SIGHUP, /* hangup aka ctrl_close_event */
SIGINT, /* ctrl+c aka ^C aka ETX aka \003 aka ♥ */ SIGINT, /* ctrl+c aka ^C aka ETX aka \003 aka ♥ */

View file

@ -36,9 +36,9 @@ copysign:
.rodata.cst16 .rodata.cst16
.Lnan: .long 0xffffffff .Lnan: .long 0xffffffff
.long 0x7fffffff .long 0x7fffffff
.long 0 .long 0x00000000
.long 0 .long 0x00000000
.Lneg0: .long 0 .Lneg0: .long 0x00000000
.long -2147483648 .long 0x80000000
.long 0 .long 0x00000000
.long 0 .long 0x00000000

View file

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

View file

@ -23,8 +23,7 @@
// @param 𝑥 is double scalar in low half of %xmm0 // @param 𝑥 is double scalar in low half of %xmm0
// @return double scalar in low half of %xmm0 // @return double scalar in low half of %xmm0
// @see pow(), exp() // @see pow(), exp()
exp10: exp10: ezlea exp10l,ax
ezlea exp10l,ax
jmp _d2ld2 jmp _d2ld2
.endfn exp10,globl .endfn exp10,globl
.alias exp10,pow10 .alias exp10,pow10

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/macros.internal.h" #include "libc/macros.internal.h"
.source __FILE__
// Returns absolute value of 𝑥. // 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 -*-│ /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi 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 Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the 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 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/runtime/pc.internal.h" #include "libc/math.h"
#include "libc/macros.internal.h"
// Returns 𝑥^𝑦. long double __powl_finite(long double x, long double y) {
// return powl(x, y);
// @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

View file

@ -17,18 +17,23 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/macros.internal.h" #include "libc/macros.internal.h"
.source __FILE__
truncl: .profilable // Rounds to integer, toward zero.
sub $24,%rsp //
fldt 32(%rsp) // @param 𝑥 is long double passed on stack
fnstcw 14(%rsp) // @return long double in %st
movzwl 14(%rsp),%eax 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 or $0b1100,%ah # round to zero
mov %ax,12(%rsp) mov %ax,-4(%rbp)
fldcw 12(%rsp) fldcw -4(%rbp)
frndint frndint
fldcw 14(%rsp) fldcw -2(%rbp)
add $24,%rsp leave
ret ret
.endfn truncl,globl .endfn truncl,globl

View file

@ -29,5 +29,6 @@
char *xdtoal(long double d) { char *xdtoal(long double d) {
char *p = xmalloc(32); char *p = xmalloc(32);
g_xfmt_p(p, &d, 16, 32, 2); g_xfmt_p(p, &d, 16, 32, 2);
/* g_xfmt_p(p, &d, 20, 32, 2); */
return p; return p;
} }

View file

@ -28,6 +28,7 @@
TEST(exp10l, test) { TEST(exp10l, test) {
EXPECT_STREQ("1", gc(xdtoal(exp10l(0)))); EXPECT_STREQ("1", gc(xdtoal(exp10l(0))));
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("INFINITY", gc(xdtoal(exp10l(INFINITY))));
EXPECT_STREQ("0", gc(xdtoal(exp10l(-INFINITY)))); EXPECT_STREQ("0", gc(xdtoal(exp10l(-INFINITY))));
EXPECT_STREQ("NAN", gc(xdtoal(exp10l(NAN)))); EXPECT_STREQ("NAN", gc(xdtoal(exp10l(NAN))));
@ -38,6 +39,7 @@ TEST(exp10l, test) {
TEST(exp10, test) { TEST(exp10, test) {
EXPECT_STREQ("1", gc(xdtoa(exp10(0)))); EXPECT_STREQ("1", gc(xdtoa(exp10(0))));
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("INFINITY", gc(xdtoa(exp10(INFINITY))));
EXPECT_STREQ("0", gc(xdtoa(exp10(-INFINITY)))); EXPECT_STREQ("0", gc(xdtoa(exp10(-INFINITY))));
EXPECT_STREQ("NAN", gc(xdtoa(exp10(NAN)))); EXPECT_STREQ("NAN", gc(xdtoa(exp10(NAN))));
@ -48,6 +50,7 @@ TEST(exp10, test) {
TEST(exp10f, test) { TEST(exp10f, test) {
EXPECT_STREQ("1", gc(xdtoaf(exp10f(0)))); EXPECT_STREQ("1", gc(xdtoaf(exp10f(0))));
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("INFINITY", gc(xdtoaf(exp10f(INFINITY))));
EXPECT_STREQ("0", gc(xdtoaf(exp10f(-INFINITY)))); EXPECT_STREQ("0", gc(xdtoaf(exp10f(-INFINITY))));
EXPECT_STREQ("NAN", gc(xdtoaf(exp10f(NAN)))); EXPECT_STREQ("NAN", gc(xdtoaf(exp10f(NAN))));

View file

@ -19,7 +19,9 @@
#include "libc/calls/struct/sigaction.h" #include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/siginfo.h" #include "libc/calls/struct/siginfo.h"
#include "libc/calls/ucontext.h" #include "libc/calls/ucontext.h"
#include "libc/macros.internal.h"
#include "libc/math.h" #include "libc/math.h"
#include "libc/rand/rand.h"
#include "libc/runtime/gc.h" #include "libc/runtime/gc.h"
#include "libc/runtime/pc.internal.h" #include "libc/runtime/pc.internal.h"
#include "libc/stdio/stdio.h" #include "libc/stdio/stdio.h"
@ -29,7 +31,12 @@
#include "libc/testlib/testlib.h" #include "libc/testlib/testlib.h"
#include "libc/x/x.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("-27", gc(xdtoal(powl(-3, 3)))); EXPECT_STREQ("-27", gc(xdtoal(powl(-3, 3))));
EXPECT_STREQ("-1", gc(xdtoal(powl(-1, 1.1)))); 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("INFINITY", gc(xdtoal(powl(10, 4933))));
EXPECT_STREQ("0", gc(xdtoal(powl(10, -5000)))); EXPECT_STREQ("0", gc(xdtoal(powl(10, -5000))));
EXPECT_STREQ("1.063382396627933e+37", gc(xdtoal(powl(2, 123)))); 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("-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("1e+308", gc(xdtoa(pow(10, 308))));
EXPECT_STREQ("INFINITY", gc(xdtoa(pow(10, 309)))); 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_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) { BENCH(powl, bench) {

View file

@ -29,6 +29,7 @@ TEST_LIBC_TINYMATH_DIRECTDEPS = \
LIBC_MEM \ LIBC_MEM \
LIBC_NEXGEN32E \ LIBC_NEXGEN32E \
LIBC_RAND \ LIBC_RAND \
LIBC_STDIO \
LIBC_RUNTIME \ LIBC_RUNTIME \
LIBC_STR \ LIBC_STR \
LIBC_STUBS \ 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) { 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, static long double x87remainder(long double x, long double y, uint32_t *sw,