Changeset View
Changeset View
Standalone View
Standalone View
lib/msun/tests/csqrt_test.c
Show All 27 Lines | ||||||||||||
* Tests for csqrt{,f}() | * Tests for csqrt{,f}() | |||||||||||
*/ | */ | |||||||||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | |||||||||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | |||||||||||
#include <sys/param.h> | #include <sys/param.h> | |||||||||||
#include <assert.h> | ||||||||||||
#include <complex.h> | #include <complex.h> | |||||||||||
#include <float.h> | #include <float.h> | |||||||||||
#include <math.h> | #include <math.h> | |||||||||||
#include <stdio.h> | #include <stdio.h> | |||||||||||
#include "test-utils.h" | #include "test-utils.h" | |||||||||||
/* | /* | |||||||||||
Show All 22 Lines | ||||||||||||
/* | /* | |||||||||||
* Compare d1 and d2 using special rules: NaN == NaN and +0 != -0. | * Compare d1 and d2 using special rules: NaN == NaN and +0 != -0. | |||||||||||
* Fail an assertion if they differ. | * Fail an assertion if they differ. | |||||||||||
*/ | */ | |||||||||||
static void | static void | |||||||||||
assert_equal(long double complex d1, long double complex d2) | assert_equal(long double complex d1, long double complex d2) | |||||||||||
{ | { | |||||||||||
assert(cfpequal(d1, d2)); | ATF_CHECK(cfpequal(d1, d2)); | |||||||||||
} | } | |||||||||||
/* | /* | |||||||||||
* Test csqrt for some finite arguments where the answer is exact. | * Test csqrt for some finite arguments where the answer is exact. | |||||||||||
* (We do not test if it produces correctly rounded answers when the | * (We do not test if it produces correctly rounded answers when the | |||||||||||
* result is inexact, nor do we check whether it throws spurious | * result is inexact, nor do we check whether it throws spurious | |||||||||||
* exceptions.) | * exceptions.) | |||||||||||
*/ | */ | |||||||||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | test_finite(void) | |||||||||||
unsigned i, j; | unsigned i, j; | |||||||||||
for (i = 0; i < nitems(tests); i += 4) { | for (i = 0; i < nitems(tests); i += 4) { | |||||||||||
for (j = 0; j < nitems(mults); j++) { | for (j = 0; j < nitems(mults); j++) { | |||||||||||
a = tests[i] * mults[j] * mults[j]; | a = tests[i] * mults[j] * mults[j]; | |||||||||||
b = tests[i + 1] * mults[j] * mults[j]; | b = tests[i + 1] * mults[j] * mults[j]; | |||||||||||
x = tests[i + 2] * mults[j]; | x = tests[i + 2] * mults[j]; | |||||||||||
y = tests[i + 3] * mults[j]; | y = tests[i + 3] * mults[j]; | |||||||||||
assert(t_csqrt(CMPLXL(a, b)) == CMPLXL(x, y)); | ATF_CHECK(t_csqrt(CMPLXL(a, b)) == CMPLXL(x, y)); | |||||||||||
} | } | |||||||||||
} | } | |||||||||||
} | } | |||||||||||
/* | /* | |||||||||||
* Test the handling of +/- 0. | * Test the handling of +/- 0. | |||||||||||
*/ | */ | |||||||||||
Show All 40 Lines | ||||||||||||
/* | /* | |||||||||||
* Test the handling of NaNs. | * Test the handling of NaNs. | |||||||||||
*/ | */ | |||||||||||
static void | static void | |||||||||||
test_nans(void) | test_nans(void) | |||||||||||
{ | { | |||||||||||
assert(creall(t_csqrt(CMPLXL(INFINITY, NAN))) == INFINITY); | ATF_CHECK(creall(t_csqrt(CMPLXL(INFINITY, NAN))) == INFINITY); | |||||||||||
assert(isnan(cimagl(t_csqrt(CMPLXL(INFINITY, NAN))))); | ATF_CHECK(isnan(cimagl(t_csqrt(CMPLXL(INFINITY, NAN))))); | |||||||||||
assert(isnan(creall(t_csqrt(CMPLXL(-INFINITY, NAN))))); | ATF_CHECK(isnan(creall(t_csqrt(CMPLXL(-INFINITY, NAN))))); | |||||||||||
assert(isinf(cimagl(t_csqrt(CMPLXL(-INFINITY, NAN))))); | ATF_CHECK(isinf(cimagl(t_csqrt(CMPLXL(-INFINITY, NAN))))); | |||||||||||
assert_equal(t_csqrt(CMPLXL(NAN, INFINITY)), | assert_equal(t_csqrt(CMPLXL(NAN, INFINITY)), | |||||||||||
CMPLXL(INFINITY, INFINITY)); | CMPLXL(INFINITY, INFINITY)); | |||||||||||
assert_equal(t_csqrt(CMPLXL(NAN, -INFINITY)), | assert_equal(t_csqrt(CMPLXL(NAN, -INFINITY)), | |||||||||||
CMPLXL(INFINITY, -INFINITY)); | CMPLXL(INFINITY, -INFINITY)); | |||||||||||
assert_equal(t_csqrt(CMPLXL(0.0, NAN)), CMPLXL(NAN, NAN)); | assert_equal(t_csqrt(CMPLXL(0.0, NAN)), CMPLXL(NAN, NAN)); | |||||||||||
assert_equal(t_csqrt(CMPLXL(-0.0, NAN)), CMPLXL(NAN, NAN)); | assert_equal(t_csqrt(CMPLXL(-0.0, NAN)), CMPLXL(NAN, NAN)); | |||||||||||
Show All 13 Lines | ||||||||||||
*/ | */ | |||||||||||
static void | static void | |||||||||||
test_overflow(int maxexp) | test_overflow(int maxexp) | |||||||||||
{ | { | |||||||||||
long double a, b; | long double a, b; | |||||||||||
long double complex result; | long double complex result; | |||||||||||
int exp, i; | int exp, i; | |||||||||||
assert(maxexp > 0 && maxexp % 2 == 0); | ATF_CHECK(maxexp > 0 && maxexp % 2 == 0); | |||||||||||
for (i = 0; i < 4; i++) { | for (i = 0; i < 4; i++) { | |||||||||||
exp = maxexp - 2 * i; | exp = maxexp - 2 * i; | |||||||||||
/* csqrt(115 + 252*I) == 14 + 9*I */ | /* csqrt(115 + 252*I) == 14 + 9*I */ | |||||||||||
a = ldexpl(115 * 0x1p-8, exp); | a = ldexpl(115 * 0x1p-8, exp); | |||||||||||
b = ldexpl(252 * 0x1p-8, exp); | b = ldexpl(252 * 0x1p-8, exp); | |||||||||||
result = t_csqrt(CMPLXL(a, b)); | result = t_csqrt(CMPLXL(a, b)); | |||||||||||
assert(creall(result) == ldexpl(14 * 0x1p-4, exp / 2)); | ATF_CHECK_EQ(creall(result), ldexpl(14 * 0x1p-4, exp / 2)); | |||||||||||
assert(cimagl(result) == ldexpl(9 * 0x1p-4, exp / 2)); | ATF_CHECK_EQ(cimagl(result), ldexpl(9 * 0x1p-4, exp / 2)); | |||||||||||
/* csqrt(-11 + 60*I) = 5 + 6*I */ | /* csqrt(-11 + 60*I) = 5 + 6*I */ | |||||||||||
a = ldexpl(-11 * 0x1p-6, exp); | a = ldexpl(-11 * 0x1p-6, exp); | |||||||||||
b = ldexpl(60 * 0x1p-6, exp); | b = ldexpl(60 * 0x1p-6, exp); | |||||||||||
result = t_csqrt(CMPLXL(a, b)); | result = t_csqrt(CMPLXL(a, b)); | |||||||||||
assert(creall(result) == ldexpl(5 * 0x1p-3, exp / 2)); | ATF_CHECK_EQ(creall(result), ldexpl(5 * 0x1p-3, exp / 2)); | |||||||||||
assert(cimagl(result) == ldexpl(6 * 0x1p-3, exp / 2)); | ATF_CHECK_EQ(cimagl(result), ldexpl(6 * 0x1p-3, exp / 2)); | |||||||||||
/* csqrt(225 + 0*I) == 15 + 0*I */ | /* csqrt(225 + 0*I) == 15 + 0*I */ | |||||||||||
a = ldexpl(225 * 0x1p-8, exp); | a = ldexpl(225 * 0x1p-8, exp); | |||||||||||
b = 0; | b = 0; | |||||||||||
result = t_csqrt(CMPLXL(a, b)); | result = t_csqrt(CMPLXL(a, b)); | |||||||||||
assert(creall(result) == ldexpl(15 * 0x1p-4, exp / 2)); | ATF_CHECK_EQ(creall(result), ldexpl(15 * 0x1p-4, exp / 2)); | |||||||||||
assert(cimagl(result) == 0); | ATF_CHECK_EQ(cimagl(result), 0); | |||||||||||
} | } | |||||||||||
} | } | |||||||||||
/* | /* | |||||||||||
* Test that precision is maintained for some large squares. Set all or | * Test that precision is maintained for some large squares. Set all or | |||||||||||
* some bits in the lower mantdig/2 bits, square the number, and try to | * some bits in the lower mantdig/2 bits, square the number, and try to | |||||||||||
* recover the sqrt. Note: | * recover the sqrt. Note: | |||||||||||
* (x + xI)**2 = 2xxI | * (x + xI)**2 = 2xxI | |||||||||||
*/ | */ | |||||||||||
static void | static void | |||||||||||
test_precision(int maxexp, int mantdig) | test_precision(int maxexp, int mantdig) | |||||||||||
{ | { | |||||||||||
long double b, x; | long double b, x; | |||||||||||
long double complex result; | long double complex result; | |||||||||||
uint64_t mantbits, sq_mantbits; | uint64_t mantbits, sq_mantbits; | |||||||||||
int exp, i; | int exp, i; | |||||||||||
assert(maxexp > 0 && maxexp % 2 == 0); | ATF_CHECK(maxexp > 0 && maxexp % 2 == 0); | |||||||||||
assert(mantdig <= 64); | ATF_CHECK(mantdig <= 64); | |||||||||||
mantdig = rounddown(mantdig, 2); | mantdig = rounddown(mantdig, 2); | |||||||||||
for (exp = 0; exp <= maxexp; exp += 2) { | for (exp = 0; exp <= maxexp; exp += 2) { | |||||||||||
mantbits = ((uint64_t)1 << (mantdig / 2 )) - 1; | mantbits = ((uint64_t)1 << (mantdig / 2 )) - 1; | |||||||||||
for (i = 0; | for (i = 0; | |||||||||||
i < 100 && mantbits > ((uint64_t)1 << (mantdig / 2 - 1)); | i < 100 && mantbits > ((uint64_t)1 << (mantdig / 2 - 1)); | |||||||||||
i++, mantbits--) { | i++, mantbits--) { | |||||||||||
sq_mantbits = mantbits * mantbits; | sq_mantbits = mantbits * mantbits; | |||||||||||
/* | /* | |||||||||||
* sq_mantibts is a mantdig-bit number. Divide by | * sq_mantibts is a mantdig-bit number. Divide by | |||||||||||
* 2**mantdig to normalize it to [0.5, 1), where, | * 2**mantdig to normalize it to [0.5, 1), where, | |||||||||||
* note, the binary power will be -1. Raise it by | * note, the binary power will be -1. Raise it by | |||||||||||
* 2**exp for the test. exp is even. Lower it by | * 2**exp for the test. exp is even. Lower it by | |||||||||||
* one to reach a final binary power which is also | * one to reach a final binary power which is also | |||||||||||
* even. The result should be exactly | * even. The result should be exactly | |||||||||||
* representable, given that mantdig is less than or | * representable, given that mantdig is less than or | |||||||||||
* equal to the available precision. | * equal to the available precision. | |||||||||||
*/ | */ | |||||||||||
b = ldexpl((long double)sq_mantbits, | b = ldexpl((long double)sq_mantbits, | |||||||||||
exp - 1 - mantdig); | exp - 1 - mantdig); | |||||||||||
x = ldexpl(mantbits, (exp - 2 - mantdig) / 2); | x = ldexpl(mantbits, (exp - 2 - mantdig) / 2); | |||||||||||
assert(b == x * x * 2); | ATF_CHECK_EQ(b, x * x * 2); | |||||||||||
result = t_csqrt(CMPLXL(0, b)); | result = t_csqrt(CMPLXL(0, b)); | |||||||||||
assert(creall(result) == x); | ATF_CHECK_EQ(x, creall(result)); | |||||||||||
assert(cimagl(result) == x); | ATF_CHECK_EQ(x, cimagl(result)); | |||||||||||
} | } | |||||||||||
} | } | |||||||||||
} | } | |||||||||||
int | ATF_TC_WITHOUT_HEAD(csqrt); | |||||||||||
main(void) | ATF_TC_BODY(csqrt, tc) | |||||||||||
{ | { | |||||||||||
printf("1..18\n"); | ||||||||||||
/* Test csqrt() */ | /* Test csqrt() */ | |||||||||||
ngie: Each of the test cases should be split up using `ATF_TP_ADD_TCS(tp)`. | ||||||||||||
Done Inline ActionsI've split it into csqrt/csqrtf/csqrtl tests. arichardson: I've split it into csqrt/csqrtf/csqrtl tests. | ||||||||||||
t_csqrt = _csqrt; | t_csqrt = _csqrt; | |||||||||||
test_finite(); | test_finite(); | |||||||||||
printf("ok 1 - csqrt\n"); | ||||||||||||
test_zeros(); | test_zeros(); | |||||||||||
printf("ok 2 - csqrt\n"); | ||||||||||||
test_infinities(); | test_infinities(); | |||||||||||
printf("ok 3 - csqrt\n"); | ||||||||||||
test_nans(); | test_nans(); | |||||||||||
printf("ok 4 - csqrt\n"); | ||||||||||||
test_overflow(DBL_MAX_EXP); | test_overflow(DBL_MAX_EXP); | |||||||||||
printf("ok 5 - csqrt\n"); | ||||||||||||
test_precision(DBL_MAX_EXP, DBL_MANT_DIG); | test_precision(DBL_MAX_EXP, DBL_MANT_DIG); | |||||||||||
printf("ok 6 - csqrt\n"); | } | |||||||||||
ATF_TC_WITHOUT_HEAD(csqrtf); | ||||||||||||
ATF_TC_BODY(csqrtf, tc) | ||||||||||||
{ | ||||||||||||
/* Now test csqrtf() */ | /* Now test csqrtf() */ | |||||||||||
t_csqrt = _csqrtf; | t_csqrt = _csqrtf; | |||||||||||
test_finite(); | test_finite(); | |||||||||||
printf("ok 7 - csqrt\n"); | ||||||||||||
test_zeros(); | test_zeros(); | |||||||||||
printf("ok 8 - csqrt\n"); | ||||||||||||
test_infinities(); | test_infinities(); | |||||||||||
printf("ok 9 - csqrt\n"); | ||||||||||||
test_nans(); | test_nans(); | |||||||||||
printf("ok 10 - csqrt\n"); | ||||||||||||
test_overflow(FLT_MAX_EXP); | test_overflow(FLT_MAX_EXP); | |||||||||||
printf("ok 11 - csqrt\n"); | ||||||||||||
test_precision(FLT_MAX_EXP, FLT_MANT_DIG); | test_precision(FLT_MAX_EXP, FLT_MANT_DIG); | |||||||||||
printf("ok 12 - csqrt\n"); | } | |||||||||||
ATF_TC_WITHOUT_HEAD(csqrtl); | ||||||||||||
ATF_TC_BODY(csqrtl, tc) | ||||||||||||
{ | ||||||||||||
/* Now test csqrtl() */ | /* Now test csqrtl() */ | |||||||||||
t_csqrt = csqrtl; | t_csqrt = csqrtl; | |||||||||||
test_finite(); | test_finite(); | |||||||||||
printf("ok 13 - csqrt\n"); | ||||||||||||
test_zeros(); | test_zeros(); | |||||||||||
printf("ok 14 - csqrt\n"); | ||||||||||||
test_infinities(); | test_infinities(); | |||||||||||
printf("ok 15 - csqrt\n"); | ||||||||||||
test_nans(); | test_nans(); | |||||||||||
printf("ok 16 - csqrt\n"); | ||||||||||||
test_overflow(LDBL_MAX_EXP); | test_overflow(LDBL_MAX_EXP); | |||||||||||
printf("ok 17 - csqrt\n"); | ||||||||||||
test_precision(LDBL_MAX_EXP, | test_precision(LDBL_MAX_EXP, | |||||||||||
/* FIXME: this seems wrong for non-x86? */ | ||||||||||||
#ifndef __i386__ | #ifndef __i386__ | |||||||||||
LDBL_MANT_DIG | LDBL_MANT_DIG | |||||||||||
#else | #else | |||||||||||
DBL_MANT_DIG | DBL_MANT_DIG | |||||||||||
#endif | #endif | |||||||||||
); | ); | |||||||||||
printf("ok 18 - csqrt\n"); | } | |||||||||||
return (0); | ATF_TP_ADD_TCS(tp) | |||||||||||
{ | ||||||||||||
ATF_TP_ADD_TC(tp, csqrt); | ||||||||||||
ATF_TP_ADD_TC(tp, csqrtf); | ||||||||||||
ATF_TP_ADD_TC(tp, csqrtl); | ||||||||||||
return (atf_no_error()); | ||||||||||||
} | } | |||||||||||
Done Inline Actions
Should add a newline. Would be better to bring up the test cases, as right now a failure will result in the whole test failing. ngie: Should add a newline.
Would be better to bring up the test cases, as right now a failure will… |
Each of the test cases should be split up using ATF_TP_ADD_TCS(tp).