Last active
April 23, 2021 09:06
-
-
Save cyfdecyf/63f4e7339bbe5a5a23474fda66375742 to your computer and use it in GitHub Desktop.
strtod inf & nan parsing test
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <cstdlib> | |
#include <cerrno> | |
#include <limits> | |
#include <cmath> | |
#include <cassert> | |
#include <cstring> | |
static const char* AtofPrecise(const char* p, double* out) { | |
char* end; | |
*out = std::strtod(p, &end); | |
if (end == p) { | |
printf("no conversion to double for: %s\n", p); | |
} | |
if (errno == ERANGE) { | |
printf("convert to double got underflow or overflow: %s\n", p); | |
} | |
if (std::isnan(*out)) { | |
if (p[0] == '-') { | |
*out = -std::numeric_limits<double>::quiet_NaN(); | |
} | |
} | |
return end; | |
} | |
int main(int argc, const char* argv[]) { | |
double neg_snan = std::numeric_limits<double>::signaling_NaN(); | |
double snan = -std::numeric_limits<double>::signaling_NaN(); | |
if (memcmp(&neg_snan, &snan, sizeof(double)) == 0) { | |
printf("negative signaling NaN should be different with signaling NaN\n"); | |
} | |
double neg_nan = std::numeric_limits<double>::quiet_NaN(); | |
double nan = -std::numeric_limits<double>::quiet_NaN(); | |
if (memcmp(&neg_nan, &nan, sizeof(double)) == 0) { | |
printf("negative quiet NaN should be different with quiet NaN\n"); | |
} | |
if (memcmp(&snan, &nan, sizeof(double)) == 0) { | |
printf("signaling and quiet NaN should be different\n"); | |
} | |
struct { | |
const char* str; | |
double d; | |
} test_cases[] = { | |
{ "inf", std::numeric_limits<double>::infinity() }, | |
{ "Inf", std::numeric_limits<double>::infinity() }, | |
{ "INF", std::numeric_limits<double>::infinity() }, | |
{ "-inf", -std::numeric_limits<double>::infinity() }, | |
{ "-Inf", -std::numeric_limits<double>::infinity() }, | |
{ "-INF", -std::numeric_limits<double>::infinity() }, | |
{ "nan", std::numeric_limits<double>::quiet_NaN() }, | |
{ "-nan", -std::numeric_limits<double>::quiet_NaN() }, | |
{ "NaN", std::numeric_limits<double>::quiet_NaN() }, | |
{ "-NaN", -std::numeric_limits<double>::quiet_NaN() }, | |
{ "NAN", std::numeric_limits<double>::quiet_NaN() }, | |
{ "-NAN", -std::numeric_limits<double>::quiet_NaN() }, | |
}; | |
for (int i = 0; i < sizeof(test_cases) / sizeof(test_cases[0]); ++i) { | |
auto test = test_cases[i]; | |
double d = 0; | |
const char* end = AtofPrecise(test.str, &d); | |
if (end == test.str) { | |
printf("fail to parse %s", test.str); | |
continue; | |
} | |
if (std::isnan(test.d)) { | |
if (!std::isnan(d)) { | |
printf("parse %s behavior mismatch expected:%f got:%f\n", test.str, test.d, d); | |
} | |
if (memcmp(&d, &test.d, sizeof(double)) != 0) { | |
printf("parsed %s is NOT binary same expected:%f got:%f\n", test.str, test.d, d); | |
} | |
} else if (test.d < 0) { | |
if (! ((d < 0) && (std::isinf(d)) && (d == test.d))) { | |
printf("parse %s behavior mismatch expected:%f got:%f\n", test.str, test.d, d); | |
} | |
} else if (test.d > 0) { | |
if (! ((d > 0) && (std::isinf(d)) && (d == test.d))) { | |
printf("parse %s behavior mismatch expected:%f got:%f\n", test.str, test.d, d); | |
} | |
} else { | |
assert(false); | |
} | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment