Changeset View
Changeset View
Standalone View
Standalone View
lib/msun/tests/nan_test.c
Show All 27 Lines | |||||
* Test for nan(), nanf(), and nanl(). We also test that strtod("nan(...)") | * Test for nan(), nanf(), and nanl(). We also test that strtod("nan(...)") | ||||
* and sscanf("nan(...)", ...) work identically. | * and sscanf("nan(...)", ...) work identically. | ||||
*/ | */ | ||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <assert.h> | |||||
#include <fenv.h> | #include <fenv.h> | ||||
#include <float.h> | #include <float.h> | ||||
#include <locale.h> | #include <locale.h> | ||||
#include <math.h> | #include <math.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include "test-utils.h" | |||||
static void | static void | ||||
testnan(const char *nan_format) | testnan(const char *nan_format) | ||||
{ | { | ||||
char nan_str[128]; | char nan_str[128]; | ||||
char *end; | char *end; | ||||
long double ald[4]; | long double ald[4]; | ||||
double ad[4]; | double ad[4]; | ||||
float af[4]; | float af[4]; | ||||
unsigned i; | unsigned i; | ||||
snprintf(nan_str, sizeof(nan_str), "nan(%s)", nan_format); | snprintf(nan_str, sizeof(nan_str), "nan(%s)", nan_format); | ||||
for (i = 0; i < nitems(ad); i++) { | for (i = 0; i < nitems(ad); i++) { | ||||
/* | /* | ||||
* x86 has an 80-bit long double stored in 96 bits, | * x86 has an 80-bit long double stored in 96 bits, | ||||
* so we need to initialize the memory for the memcmp() | * so we need to initialize the memory for the memcmp() | ||||
* checks below to work. | * checks below to work. | ||||
*/ | */ | ||||
bzero(&af[i], sizeof(float)); | bzero(&af[i], sizeof(float)); | ||||
bzero(&ad[i], sizeof(double)); | bzero(&ad[i], sizeof(double)); | ||||
bzero(&ald[i], sizeof(long double)); | bzero(&ald[i], sizeof(long double)); | ||||
} | } | ||||
af[0] = nanf(nan_format); | af[0] = nanf(nan_format); | ||||
assert(isnan(af[0])); | ATF_REQUIRE(isnan(af[0])); | ||||
af[1] = strtof(nan_str, &end); | af[1] = strtof(nan_str, &end); | ||||
assert(end == nan_str + strlen(nan_str)); | ATF_REQUIRE(end == nan_str + strlen(nan_str)); | ||||
assert(sscanf(nan_str, "%e", &af[2]) == 1); | ATF_REQUIRE(sscanf(nan_str, "%e", &af[2]) == 1); | ||||
assert(memcmp(&af[0], &af[1], sizeof(float)) == 0); | ATF_REQUIRE(memcmp(&af[0], &af[1], sizeof(float)) == 0); | ||||
assert(memcmp(&af[1], &af[2], sizeof(float)) == 0); | ATF_REQUIRE(memcmp(&af[1], &af[2], sizeof(float)) == 0); | ||||
if (*nan_format == '\0') { | if (*nan_format == '\0') { | ||||
/* nanf("") == strtof("nan") */ | /* nanf("") == strtof("nan") */ | ||||
af[3] = strtof("nan", NULL); | af[3] = strtof("nan", NULL); | ||||
assert(memcmp(&af[2], &af[3], sizeof(float)) == 0); | ATF_REQUIRE(memcmp(&af[2], &af[3], sizeof(float)) == 0); | ||||
} | } | ||||
ad[0] = nan(nan_format); | ad[0] = nan(nan_format); | ||||
assert(isnan(ad[0])); | ATF_REQUIRE(isnan(ad[0])); | ||||
ad[1] = strtod(nan_str, &end); | ad[1] = strtod(nan_str, &end); | ||||
assert(end == nan_str + strlen(nan_str)); | ATF_REQUIRE(end == nan_str + strlen(nan_str)); | ||||
assert(sscanf(nan_str, "%le", &ad[2]) == 1); | ATF_REQUIRE(sscanf(nan_str, "%le", &ad[2]) == 1); | ||||
assert(memcmp(&ad[0], &ad[1], sizeof(double)) == 0); | ATF_REQUIRE(memcmp(&ad[0], &ad[1], sizeof(double)) == 0); | ||||
assert(memcmp(&ad[1], &ad[2], sizeof(double)) == 0); | ATF_REQUIRE(memcmp(&ad[1], &ad[2], sizeof(double)) == 0); | ||||
if (*nan_format == '\0') { | if (*nan_format == '\0') { | ||||
/* nan("") == strtod("nan") */ | /* nan("") == strtod("nan") */ | ||||
ad[3] = strtod("nan", NULL); | ad[3] = strtod("nan", NULL); | ||||
assert(memcmp(&ad[2], &ad[3], sizeof(double)) == 0); | ATF_REQUIRE(memcmp(&ad[2], &ad[3], sizeof(double)) == 0); | ||||
} | } | ||||
ald[0] = nanl(nan_format); | ald[0] = nanl(nan_format); | ||||
assert(isnan(ald[0])); | ATF_REQUIRE(isnan(ald[0])); | ||||
ald[1] = strtold(nan_str, &end); | ald[1] = strtold(nan_str, &end); | ||||
assert(end == nan_str + strlen(nan_str)); | ATF_REQUIRE(end == nan_str + strlen(nan_str)); | ||||
assert(sscanf(nan_str, "%Le", &ald[2]) == 1); | ATF_REQUIRE(sscanf(nan_str, "%Le", &ald[2]) == 1); | ||||
assert(memcmp(&ald[0], &ald[1], sizeof(long double)) == 0); | ATF_REQUIRE(memcmp(&ald[0], &ald[1], sizeof(long double)) == 0); | ||||
assert(memcmp(&ald[1], &ald[2], sizeof(long double)) == 0); | ATF_REQUIRE(memcmp(&ald[1], &ald[2], sizeof(long double)) == 0); | ||||
if (*nan_format == '\0') { | if (*nan_format == '\0') { | ||||
/* nanl("") == strtold("nan") */ | /* nanl("") == strtold("nan") */ | ||||
ald[3] = strtold("nan", NULL); | ald[3] = strtold("nan", NULL); | ||||
assert(memcmp(&ald[2], &ald[3], sizeof(long double)) == 0); | ATF_REQUIRE(memcmp(&ald[2], &ald[3], sizeof(long double)) == 0); | ||||
} | } | ||||
} | } | ||||
int | ATF_TC_WITHOUT_HEAD(nan); | ||||
main(void) | ATF_TC_BODY(nan, tc) | ||||
{ | { | ||||
printf("1..1\n"); | |||||
/* Die if a signalling NaN is returned */ | /* Die if a signalling NaN is returned */ | ||||
feenableexcept(FE_INVALID); | feenableexcept(FE_INVALID); | ||||
testnan("0x1234"); | testnan("0x1234"); | ||||
testnan(""); | testnan(""); | ||||
} | |||||
printf("ok 1 - nan\n"); | ATF_TP_ADD_TCS(tp) | ||||
{ | |||||
ATF_TP_ADD_TC(tp, nan); | |||||
return (0); | return (atf_no_error()); | ||||
} | } | ||||
ngie: newline |
newline