[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

**To**:**lib-bug-people%netbsd.org@localhost,gnats-admin%netbsd.org@localhost,netbsd-bugs%netbsd.org@localhost****Subject**:**lib/49240: Some corner cases for pow() fail to work correctly****From**:**he%NetBSD.org@localhost**- Date: Sun, 28 Sep 2014 16:25:01 +0000 (UTC)

>Number: 49240 >Category: lib >Synopsis: Some corner cases for pow() fail to work correctly >Confidential: no >Severity: serious >Priority: medium >Responsible: lib-bug-people >State: open >Class: sw-bug >Submitter-Id: net >Arrival-Date: Sun Sep 28 16:25:01 +0000 2014 >Originator: Havard Eidnes >Release: NetBSD 6.1_STABLE >Organization: >Environment: System: NetBSD smistad.uninett.no 6.1_STABLE NetBSD 6.1_STABLE (MAANEN) #0: Mon Sep 1 14:42:18 CEST 2014 root%smistad.uninett.no@localhost:/usr/obj/sys/arch/i386/compile/MAANEN i386 Architecture: i386 Machine: i386 >Description: While working on pkgsrc-wip/v8's test suite, I found one of them which failed which excercise the pow() function, by first doing some simple sanity checking and then trying out various corner cases. The v8 test bails out on the first test failure. I've translated the tests into C, which runs through all the tests counting up the successes and failures, displaying the result of each test, with details for the failing tests. Mostly, the failing tests on NetBSD appear also to contradict the comments about the "Special cases" near the top of our lib/libm/src/e_pow.c. The test failures and the special case confirming the test is OK and our code is not are: Test failure: NaN == pow(1, Infinity) a == nan b == 1.000000 Test failure: NaN == pow(1, -Infinity) a == nan b == 1.000000 * 9. +-1 ** +-INF is NAN Test failure: Infinity == pow(+0.0, -1.1) a == inf b == -inf Test failure: Infinity == pow(+0.0, -2) a == inf b == -inf * 12. +0 ** (-anything except 0, NAN) is +INF Test failure: Infinity == pow(-0.0, -3.1) a == inf b == -inf Test failure: Infinity == pow(-0.0, -2) a == inf b == -inf Test failure: +Infinity == pow(-0.0, -0.5) a == inf b == -inf Test failure: +Infinity == pow(-0.0, -0.6) a == inf b == -inf * 13. -0 ** (-anything except 0, NAN, odd integer) is +INF >How-To-Repeat: Compile and run this program, and watch it fail 8 of our tests on netbsd-6 and netbsd-7. (The meat of the code is (c) Google with a 3-clause BSD-like license, but this is a translation into C by myself.) ------------------------------ snip #include <string.h> #include <math.h> #include <stdio.h> #include <stdlib.h> #define Infinity INFINITY #define NaN NAN #define assertEquals(a, b) \ do { \ if ((a) != (b)) { \ char s1[64], s2[64]; \ sprintf(s1, "%f", (double)(a)); \ sprintf(s2, "%f", (double)(b)); \ if ((strcmp(s1, "nan") == 0) || \ (strcmp(s2, "nan") == 0)) { \ if (strcmp(s1, s2) != 0) { \ printf("Test failure: %s == %s\n", #a, #b); \ printf(" a == %s\n", s1); \ printf(" b == %s\n", s2); \ failures++; \ } else { \ printf("Test OK : %s == %s\n", #a, #b); \ ok++; \ } \ } else { \ printf("Test failure: %s == %s\n", #a, #b); \ printf(" a == %f\n", (double)(a)); \ printf(" b == %f\n", (double)(b)); \ failures++; \ } \ } else { \ printf("Test OK : %s == %s\n", #a, #b); \ ok++; \ } \ } while(0) int main(int argc, char **argv) { int failures = 0; int ok = 0; // These two need to work for the tests to work // Verify the "nan" dance in the assertEquals macro... assertEquals(NaN, NaN); assertEquals(Infinity, Infinity); // Spec tests assertEquals(NaN, pow(2, NaN)); assertEquals(NaN, pow(+0.0, NaN)); assertEquals(NaN, pow(-0.0, NaN)); assertEquals(NaN, pow(Infinity, NaN)); assertEquals(NaN, pow(-Infinity, NaN)); assertEquals(1, pow(NaN, +0.0)); assertEquals(1, pow(NaN, -0.0)); assertEquals(NaN, pow(NaN, NaN)); assertEquals(NaN, pow(NaN, 2.2)); assertEquals(NaN, pow(NaN, 1)); assertEquals(NaN, pow(NaN, -1)); assertEquals(NaN, pow(NaN, -2.2)); assertEquals(NaN, pow(NaN, Infinity)); assertEquals(NaN, pow(NaN, -Infinity)); assertEquals(Infinity, pow(1.1, Infinity)); assertEquals(Infinity, pow(-1.1, Infinity)); assertEquals(Infinity, pow(2, Infinity)); assertEquals(Infinity, pow(-2, Infinity)); // Because +0 == -0, we need to compare 1/{+,-}0 to {+,-}Infinity assertEquals(+Infinity, 1/pow(1.1, -Infinity)); assertEquals(+Infinity, 1/pow(-1.1, -Infinity)); assertEquals(+Infinity, 1/pow(2, -Infinity)); assertEquals(+Infinity, 1/pow(-2, -Infinity)); assertEquals(NaN, pow(1, Infinity)); assertEquals(NaN, pow(1, -Infinity)); assertEquals(NaN, pow(-1, Infinity)); assertEquals(NaN, pow(-1, -Infinity)); assertEquals(+0.0, pow(0.1, Infinity)); assertEquals(+0.0, pow(-0.1, Infinity)); assertEquals(+0.0, pow(0.999, Infinity)); assertEquals(+0.0, pow(-0.999, Infinity)); assertEquals(Infinity, pow(0.1, -Infinity)); assertEquals(Infinity, pow(-0.1, -Infinity)); assertEquals(Infinity, pow(0.999, -Infinity)); assertEquals(Infinity, pow(-0.999, -Infinity)); assertEquals(Infinity, pow(Infinity, 0.1)); assertEquals(Infinity, pow(Infinity, 2)); assertEquals(+Infinity, 1/pow(Infinity, -0.1)); assertEquals(+Infinity, 1/pow(Infinity, -2)); assertEquals(-Infinity, pow(-Infinity, 3)); assertEquals(-Infinity, pow(-Infinity, 13)); assertEquals(Infinity, pow(-Infinity, 3.1)); assertEquals(Infinity, pow(-Infinity, 2)); assertEquals(-Infinity, 1/pow(-Infinity, -3)); assertEquals(-Infinity, 1/pow(-Infinity, -13)); assertEquals(+Infinity, 1/pow(-Infinity, -3.1)); assertEquals(+Infinity, 1/pow(-Infinity, -2)); assertEquals(+Infinity, 1/pow(+0.0, 1.1)); assertEquals(+Infinity, 1/pow(+0.0, 2)); assertEquals(Infinity, pow(+0.0, -1.1)); assertEquals(Infinity, pow(+0.0, -2)); assertEquals(-Infinity, 1/pow(-0.0, 3)); assertEquals(-Infinity, 1/pow(-0.0, 13)); assertEquals(+Infinity, 1/pow(-0.0, 3.1)); assertEquals(+Infinity, 1/pow(-0.0, 2)); assertEquals(-Infinity, pow(-0.0, -3)); assertEquals(-Infinity, pow(-0.0, -13)); assertEquals(Infinity, pow(-0.0, -3.1)); assertEquals(Infinity, pow(-0.0, -2)); assertEquals(NaN, pow(-0.00001, 1.1)); assertEquals(NaN, pow(-0.00001, -1.1)); assertEquals(NaN, pow(-1.1, 1.1)); assertEquals(NaN, pow(-1.1, -1.1)); assertEquals(NaN, pow(-2, 1.1)); assertEquals(NaN, pow(-2, -1.1)); assertEquals(NaN, pow(-1000, 1.1)); assertEquals(NaN, pow(-1000, -1.1)); assertEquals(+Infinity, 1/pow(-0.0, 0.5)); assertEquals(+Infinity, 1/pow(-0.0, 0.6)); assertEquals(-Infinity, 1/pow(-0.0, 1)); assertEquals(-Infinity, 1/pow(-0.0, 10000000001.0)); assertEquals(+Infinity, pow(-0.0, -0.5)); assertEquals(+Infinity, pow(-0.0, -0.6)); assertEquals(-Infinity, pow(-0.0, -1)); assertEquals(-Infinity, pow(-0.0, -10000000001.0)); assertEquals(4, pow(16, 0.5)); assertEquals(NaN, pow(-16, 0.5)); assertEquals(0.25, pow(16, -0.5)); assertEquals(NaN, pow(-16, -0.5)); // Test detecting and converting integer value as double. assertEquals(8, pow(2, sqrt(9))); // Tests from Mozilla 15.8.2.13. assertEquals(Infinity, pow(-Infinity, Infinity)); assertEquals(0, pow(-Infinity, -Infinity)); assertEquals(1, pow(0, 0)); assertEquals(0, pow(0, Infinity)); assertEquals(NaN, pow(NaN, 0.5)); assertEquals(NaN, pow(NaN, -0.5)); // Tests from Sputnik S8.5_A13_T1. assertEquals( (1*((pow(2,53))-1)*(pow(2,-1074))), 4.4501477170144023e-308); assertEquals( (1*(pow(2,52))*(pow(2,-1074))), 2.2250738585072014e-308); assertEquals( (-1*(pow(2,52))*(pow(2,-1074))), -2.2250738585072014e-308); printf("\n"); printf("Failed tests: %d\n", failures); printf("Successful tests: %d\n", ok); exit(failures != 0); } ------------------------------ snip >Fix: Sorry, no fix proposed. The pcc maintainer tested this with pcc on netbsd-6, and interestingly these two tests succeed with pcc but fail with gcc (with the same libm!): Test OK : NaN == pow(1, Infinity) Test OK : NaN == pow(1, -Infinity) Also of interest is that there's been a regression between netbsd-5 and netbsd-6 on the number of test failures: these two succeed on netbsd-5: Test OK : Infinity == pow(-0.0, -2) Test OK : Infinity == pow(+0.0, -2) but fail on netbsd-6 or netbsd-7: Test failure: Infinity == pow(+0.0, -2) a == inf b == -inf Test failure: Infinity == pow(-0.0, -2) a == inf b == -inf This is seen both for macppc and amd64.

- Prev by Date:
**Re: kern/49207** - Next by Date:
**NetBSD Nightly Trouble Ticket Report** - Previous by Thread:
**PR/44218 CVS commit: src/sbin/gpt** - Next by Thread:
**Re: lib/49240: Some corner cases for pow() fail to work correctly** - Indexes: