diff --git a/README.md b/README.md index d0a5fa43..89dda1dc 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ five files to get started: wget https://justine.lol/cosmopolitan/cosmopolitan.zip unzip cosmopolitan.zip printf 'main() { printf("hello world\\n"); }\n' >hello.c -gcc -g -Og -static -nostdlib -nostdinc -fno-pie -no-pie -mno-red-zone \ +gcc -g -Os -static -nostdlib -nostdinc -fno-pie -no-pie -mno-red-zone \ -fno-omit-frame-pointer -pg -mnop-mcount \ -o hello.com.dbg hello.c -fuse-ld=bfd -Wl,-T,ape.lds \ -include cosmopolitan.h crt.o ape.o cosmopolitan.a @@ -52,13 +52,13 @@ find o -name \*.com | xargs ls -rShal | less ## Support Vector -| Platform | Min Version | Circa | -| :--- | ---: | ---: | -| AMD | K8 Venus | 2005 | -| Intel | Core | 2006 | -| New Technology | Vista | 2006 | -| GNU/Systemd | 2.6.18 | 2007 | -| XNU's Not UNIX | 15.6 | 2018 | -| FreeBSD | 12 | 2018 | -| OpenBSD | 6.4 | 2018 | -| NetBSD | 9.1 | 2020 | +| Platform | Min Version | Circa | +| :--- | ---: | ---: | +| AMD | K8 Venus | 2005 | +| Intel | Core | 2006 | +| New Technology | Vista | 2006 | +| GNU/Systemd | 2.6.18 | 2007 | +| XNU's Not UNIX! | 15.6 | 2018 | +| FreeBSD | 12 | 2018 | +| OpenBSD | 6.4 | 2018 | +| NetBSD | 9.1 | 2020 | diff --git a/libc/tinymath/powl.c b/libc/tinymath/powl.c index b1e4345d..fc332a1a 100644 --- a/libc/tinymath/powl.c +++ b/libc/tinymath/powl.c @@ -31,7 +31,11 @@ long double powl(long double x, long double y) { 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); + if (signbit(x)) { + if (y != truncl(y)) return -NAN; + if (!signbit(y) || ((int64_t)y & 1)) t = -t; + } + return t; } else if (y > 0) { return 0; } else if (!y) { diff --git a/test/libc/fmt/palandprintf_test.c b/test/libc/fmt/palandprintf_test.c index b7baeae1..6600356d 100644 --- a/test/libc/fmt/palandprintf_test.c +++ b/test/libc/fmt/palandprintf_test.c @@ -406,6 +406,7 @@ TEST(sprintf, test_float) { #ifndef __FINITE_MATH_ONLY__ EXPECT_STREQ("nan", Format("%.4f", NAN)); #endif + EXPECT_STREQ("-0.0000", Format("%.4f", -0.)); EXPECT_STREQ("3.1415", Format("%.4f", 3.1415354)); EXPECT_STREQ("30343.142", Format("%.3f", 30343.1415354)); EXPECT_STREQ("34", Format("%.0f", 34.1415354)); diff --git a/test/libc/tinymath/powl_test.c b/test/libc/tinymath/powl_test.c index 3b927b8d..0b576c9d 100644 --- a/test/libc/tinymath/powl_test.c +++ b/test/libc/tinymath/powl_test.c @@ -39,7 +39,6 @@ void SetUp(void) { 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)))); EXPECT_STREQ("1e+4932", gc(xdtoal(powl(10, 4932)))); EXPECT_STREQ("INFINITY", gc(xdtoal(powl(10, 4933)))); EXPECT_STREQ("0", gc(xdtoal(powl(10, -5000)))); @@ -83,12 +82,15 @@ TEST(powl, test) { 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))))); + EXPECT_TRUE(isnan(powl(-3, 1. / MAX(rando, 2)))); + EXPECT_TRUE(isnan(powl(-3, -(1. / MAX(rando, 2))))); + EXPECT_STREQ("-.3333333333333333", gc(xdtoal(powl(-3, -1)))); + EXPECT_STREQ(".1111111111111111", gc(xdtoal(powl(-3, -2)))); } 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_STREQ("0", gc(xdtoa(pow(10, -5000)))); @@ -132,12 +134,13 @@ TEST(pow, test) { 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))))); + EXPECT_STREQ("-.333333333333333", gc(xdtoa(pow(-3, -1)))); + EXPECT_STREQ(".111111111111111", gc(xdtoa(pow(-3, -2)))); } TEST(powf, test) { EXPECT_STREQ("27", gc(xdtoaf(powf(3, 3)))); EXPECT_STREQ("-27", gc(xdtoaf(powf(-3, 3)))); - 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)))); @@ -181,6 +184,8 @@ TEST(powf, test) { 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))))); + EXPECT_STREQ("-.333333", gc(xdtoaf(powf(-3, -1)))); + EXPECT_STREQ(".111111", gc(xdtoaf(powf(-3, -2)))); } BENCH(powl, bench) { diff --git a/tool/build/calculator.ctest b/tool/build/calculator.ctest index 9fa50e38..ed20b54d 100755 --- a/tool/build/calculator.ctest +++ b/tool/build/calculator.ctest @@ -7,7 +7,7 @@ 81 3 // 27 = assert 2 8 ** 256 = assert 17 10 % 7 = assert -17 10 mod 7 = assert +17 10 fmod 7 = assert # FLOATING POINT .1 .2 + .3 - abs epsilon < assert diff --git a/tool/build/calculator.inc b/tool/build/calculator.inc index 0abefe63..479ac996 100644 --- a/tool/build/calculator.inc +++ b/tool/build/calculator.inc @@ -29,11 +29,13 @@ M(1, i, "ungray", Ungray, ungray(x), "inverse gray coding") M(1, i, "popcnt", Popcnt, Popcnt(x), "count bits") M(1, g, "abs", Abs, fabsl(x), "absolute value") -M(2, g, "min", Min, MIN(x, y), "pops two values and pushes minimum") -M(2, g, "max", Max, MAX(x, y), "pops two values and pushes maximum") +M(2, g, "min", Min, fminl(x, y), "pops two values and pushes minimum") +M(2, g, "max", Max, fmaxl(x, y), "pops two values and pushes maximum") -M(2, g, "mod", Euclidean, emodl(x, y), "euclidean remainder") -M(2, g, "rem", Remainder, remainderl(x, y), "float remainder") +M(2, g, "fmod", Fmod, fmodl(x, y), "trunc remainder") +M(2, g, "emod", Emod, emodl(x, y), "euclidean remainder") +M(2, g, "remainder", Remainder, remainderl(x, y), "rint remainder") +M(2, g, "hypot", Hypot, hypotl(x, y), "euclidean distance") M(0, i, "false", False, 0, "0") M(0, i, "true", True, 1, "1") @@ -49,16 +51,21 @@ M(0, f, "l2t", Fldl2t, M_LOG2_10, "log₂10") M(0, f, "lg2", Fldlg2, M_LOG10_2, "log₁₀2") M(0, f, "ln2", Fldln2, M_LN2, "logₑ2") M(0, f, "l2e", Fldl2e, M_LOG2E, "logₑ10") +M(2, f, "nextafter", Nextafter, nextafterl(x, y), "next ulp") +M(1, f, "significand", Significand, significandl(x), "mantissa") M(1, f, "sqrt", Sqrt, sqrtl(x), "√𝑥") M(1, f, "exp", Exp, expl(x), "𝑒ˣ") +M(1, g, "expm1", Expm1, expm1l(x), "𝑒ˣ-1") M(1, g, "exp2", Exp2, exp2l(x), "2ˣ") M(1, g, "exp10", Exp10, exp10l(x), "10ˣ") M(2, g, "ldexp", Ldexp, ldexpl(x, y), "𝑥×2ʸ") +M(2, g, "scalb", Scalb, scalbl(x, y), "𝑥×2ʸ") M(1, f, "log", Log, logl(x), "logₑ𝑥") M(1, g, "log2", Log2, log2l(x), "log₂𝑥") M(1, g, "log10", Log10, log10l(x), "log₁₀𝑥") +M(1, g, "ilogb", Ilogb, ilogbl(x), "exponent") M(1, g, "sin", Sin, sinl(x), "sine") M(1, g, "cos", Cos, cosl(x), "cosine") @@ -68,10 +75,17 @@ M(1, g, "acos", Acos, acosl(x), "arccosine") M(1, g, "atan", Atan, atanl(x), "arctangent") M(2, g, "atan2", Atan2, atan2l(x, y), "arctangent of 𝑥/𝑦") +M(1, g, "sinh", Sinh, sinhl(x), "hyperbolic sine") +M(1, g, "cosh", Cosh, coshl(x), "hyperbolic cosine") +M(1, g, "tanh", Tanh, tanhl(x), "hyperbolic tangent") +M(1, g, "asinh", Asinh, asinhl(x), "hyperbolic arcsine") +M(1, g, "acosh", Acosh, acoshl(x), "hyperbolic arccosine") +M(1, g, "atanh", Atanh, atanhl(x), "hyperbolic arctangent") + M(1, g, "round", Round, roundl(x), "round away from zero") M(1, g, "trunc", Trunc, truncl(x), "round towards zero") M(1, g, "rint", Rint, rintl(x), "round to even") -M(1, g, "nearbyint", Nearbyint, nearbyint(x), "round to nearest integer") +M(1, g, "nearbyint", Nearbyint, nearbyintl(x), "round to nearest integer") M(1, g, "ceil", Ceil, ceill(x), "smallest integral not less than 𝑥") M(1, g, "floor", Floor, floorl(x), "largest integral not greater than 𝑥")