Commit 2a789d9e authored by Lev Walkin's avatar Lev Walkin

nan handling

parent 36ee690c
...@@ -17,8 +17,8 @@ ...@@ -17,8 +17,8 @@
#endif #endif
#ifndef NAN #ifndef NAN
static const double nan0; static const double real_nan0;
#define NAN (nan0/nan0) #define NAN (real_nan0/real_nan0)
#endif #endif
/* /*
...@@ -60,13 +60,17 @@ REAL__dump(double d, int canonical, asn_app_consume_bytes_f *cb, void *app_key) ...@@ -60,13 +60,17 @@ REAL__dump(double d, int canonical, asn_app_consume_bytes_f *cb, void *app_key)
/* /*
* ilogb(+-0) returns -INT_MAX or INT_MIN (platform-dependent) * ilogb(+-0) returns -INT_MAX or INT_MIN (platform-dependent)
* ilogb(+-inf) returns INT_MAX * ilogb(+-inf) returns INT_MAX
* ilogb(NaN) returns INT_MIN or INT_MAX (platform-dependent)
*/ */
expval = ilogb(d); expval = ilogb(d);
if(expval <= -INT_MAX /* Also catches (d == 0) */ if(expval <= -INT_MAX /* Also catches +-0 and maybe isnan() */
|| expval == INT_MAX /* catches finite() which catches isnan() */ || expval == INT_MAX /* catches isfin() and maybe isnan() */
) { ) {
/* fpclassify(3) is not portable yet */ /* fpclassify(3) is not portable yet */
if(expval <= -INT_MAX) { if(isnan(d)) {
buf = "<NOT-A-NUMBER/>";
buflen = 15;
} else if(expval <= -INT_MAX) {
if(copysign(1.0, d) < 0.0) { if(copysign(1.0, d) < 0.0) {
buf = "-0"; buf = "-0";
buflen = 2; buflen = 2;
...@@ -74,7 +78,7 @@ REAL__dump(double d, int canonical, asn_app_consume_bytes_f *cb, void *app_key) ...@@ -74,7 +78,7 @@ REAL__dump(double d, int canonical, asn_app_consume_bytes_f *cb, void *app_key)
buf = "0"; buf = "0";
buflen = 1; buflen = 1;
} }
} else if(isinf(d)) { } else { /* isinf() */
if(copysign(1.0, d) < 0.0) { if(copysign(1.0, d) < 0.0) {
buf = "<MINUS-INFINITY/>"; buf = "<MINUS-INFINITY/>";
buflen = 17; buflen = 17;
...@@ -82,9 +86,6 @@ REAL__dump(double d, int canonical, asn_app_consume_bytes_f *cb, void *app_key) ...@@ -82,9 +86,6 @@ REAL__dump(double d, int canonical, asn_app_consume_bytes_f *cb, void *app_key)
buf = "<PLUS-INFINITY/>"; buf = "<PLUS-INFINITY/>";
buflen = 16; buflen = 16;
} }
} else {
buf = "<NOT-A-NUMBER/>";
buflen = 15;
} }
return (cb(buf, buflen, app_key) < 0) ? -1 : buflen; return (cb(buf, buflen, app_key) < 0) ? -1 : buflen;
} }
...@@ -271,7 +272,7 @@ asn1_REAL2double(const REAL_t *st, double *dbl_value) { ...@@ -271,7 +272,7 @@ asn1_REAL2double(const REAL_t *st, double *dbl_value) {
*dbl_value = NAN; *dbl_value = NAN;
return 0; return 0;
case 0x43: /* 01000011: minus zero */ case 0x43: /* 01000011: minus zero */
*dbl_value = NAN; *dbl_value = -0.0;
return 0; return 0;
} }
...@@ -412,11 +413,11 @@ asn1_double2REAL(REAL_t *st, double dbl_value) { ...@@ -412,11 +413,11 @@ asn1_double2REAL(REAL_t *st, double dbl_value) {
/* /*
* ilogb(+-0) returns -INT_MAX or INT_MIN (platform-dependent) * ilogb(+-0) returns -INT_MAX or INT_MIN (platform-dependent)
* ilogb(+-inf) returns INT_MAX * ilogb(+-inf) returns INT_MAX
* ilogb(NaN) returns INT_MIN or INT_MAX (platform-dependent)
*/ */
expval = ilogb(dbl_value); expval = ilogb(dbl_value);
if(expval <= -INT_MAX /* Also catches +-0 and maybe isnan() */
if(expval <= -INT_MAX /* Also catches (dbl_value == 0) */ || expval == INT_MAX /* catches isfin() and maybe isnan() */
|| expval == INT_MAX /* catches finite() which catches isnan() */
) { ) {
if(!st->buf || st->size < 2) { if(!st->buf || st->size < 2) {
ptr = (uint8_t *)MALLOC(2); ptr = (uint8_t *)MALLOC(2);
...@@ -424,7 +425,11 @@ asn1_double2REAL(REAL_t *st, double dbl_value) { ...@@ -424,7 +425,11 @@ asn1_double2REAL(REAL_t *st, double dbl_value) {
st->buf = ptr; st->buf = ptr;
} }
/* fpclassify(3) is not portable yet */ /* fpclassify(3) is not portable yet */
if(expval <= -INT_MAX) { if(isnan(dbl_value)) {
st->buf[0] = 0x42; /* NaN */
st->buf[1] = 0;
st->size = 1;
} else if(expval <= -INT_MAX) {
if(copysign(1.0, dbl_value) < 0.0) { if(copysign(1.0, dbl_value) < 0.0) {
st->buf[0] = 0x80 | 0x40; st->buf[0] = 0x80 | 0x40;
st->buf[1] = 0; st->buf[1] = 0;
...@@ -433,7 +438,7 @@ asn1_double2REAL(REAL_t *st, double dbl_value) { ...@@ -433,7 +438,7 @@ asn1_double2REAL(REAL_t *st, double dbl_value) {
st->buf[0] = 0; /* JIC */ st->buf[0] = 0; /* JIC */
st->size = 0; st->size = 0;
} }
} else if(isinf(dbl_value)) { } else { /* isinf() */
if(copysign(1.0, dbl_value) < 0.0) { if(copysign(1.0, dbl_value) < 0.0) {
st->buf[0] = 0x41; /* MINUS-INFINITY */ st->buf[0] = 0x41; /* MINUS-INFINITY */
} else { } else {
...@@ -441,10 +446,6 @@ asn1_double2REAL(REAL_t *st, double dbl_value) { ...@@ -441,10 +446,6 @@ asn1_double2REAL(REAL_t *st, double dbl_value) {
} }
st->buf[1] = 0; st->buf[1] = 0;
st->size = 1; st->size = 1;
} else {
st->buf[0] = 0x42; /* NaN */
st->buf[1] = 0;
st->size = 1;
} }
return 0; return 0;
} }
......
...@@ -75,7 +75,7 @@ check(REAL_t *rn, double orig_dbl, const char *sample, const char *canonical_sam ...@@ -75,7 +75,7 @@ check(REAL_t *rn, double orig_dbl, const char *sample, const char *canonical_sam
printf("converted into ["); printf("converted into [");
for(p = rn->buf, end = p + rn->size; p < end; p++) for(p = rn->buf, end = p + rn->size; p < end; p++)
printf("%02x", *p); printf("%02x", *p);
printf("]\n"); printf("]: %d\n", rn->size);
ret = asn1_REAL2double(rn, &val); ret = asn1_REAL2double(rn, &val);
assert(ret == 0); assert(ret == 0);
...@@ -86,8 +86,7 @@ check(REAL_t *rn, double orig_dbl, const char *sample, const char *canonical_sam ...@@ -86,8 +86,7 @@ check(REAL_t *rn, double orig_dbl, const char *sample, const char *canonical_sam
printf("] (ilogb %d)\n", ilogb(val)); printf("] (ilogb %d)\n", ilogb(val));
printf("%.12f vs %.12f\n", orig_dbl, val); printf("%.12f vs %.12f\n", orig_dbl, val);
assert(orig_dbl == val || (isnan(orig_dbl) && isnan(val)));
assert(orig_dbl == val);
printf("OK\n"); printf("OK\n");
check_str_repr(val, sample, canonical_sample); check_str_repr(val, sample, canonical_sample);
...@@ -144,9 +143,11 @@ check_buf(uint8_t *buf, size_t bufsize, double verify, const char *sample, const ...@@ -144,9 +143,11 @@ check_buf(uint8_t *buf, size_t bufsize, double verify, const char *sample, const
int int
main() { main() {
REAL_t rn; REAL_t rn;
static const double c_NaN = 0.0;
memset(&rn, 0, sizeof(rn)); memset(&rn, 0, sizeof(rn));
check(&rn, c_NaN/c_NaN, "<NOT-A-NUMBER/>", "<NOT-A-NUMBER/>");
check(&rn, 0.0, "0", "0"); check(&rn, 0.0, "0", "0");
check(&rn, -0.0, "-0", "-0"); /* minus-zero */ check(&rn, -0.0, "-0", "-0"); /* minus-zero */
check(&rn, 1.0, "1.0", "1.0E0"); check(&rn, 1.0, "1.0", "1.0E0");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment