Skip to content

Instantly share code, notes, and snippets.

@cyfdecyf
Last active April 23, 2021 09:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cyfdecyf/63f4e7339bbe5a5a23474fda66375742 to your computer and use it in GitHub Desktop.
Save cyfdecyf/63f4e7339bbe5a5a23474fda66375742 to your computer and use it in GitHub Desktop.
strtod inf & nan parsing test
#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