diff --git a/skeletons/REAL.c b/skeletons/REAL.c index 2373dde9bc24bd2280e0f01c74f1edb2d4df526e..6ce124ee8eb922f2ca814c008aca31c50da6e678 100644 --- a/skeletons/REAL.c +++ b/skeletons/REAL.c @@ -12,13 +12,9 @@ #undef INT_MAX #define INT_MAX ((int)(((unsigned int)-1) >> 1)) -#ifndef INFINITY -#define INFINITY HUGE_VAL -#endif - #ifndef NAN -static const double real_nan0; -#define NAN (real_nan0/real_nan0) +static const double real_zero; +#define NAN (real_zero/real_zero) #endif /* @@ -52,40 +48,31 @@ REAL__dump(double d, int canonical, asn_app_consume_bytes_f *cb, void *app_key) ssize_t buflen = sizeof(local_buf); const char *fmt = canonical?"%.15E":"%.15f"; ssize_t ret; - int expval; /* * Check whether it is a special value. */ - /* - * ilogb(+-0) returns -INT_MAX or INT_MIN (platform-dependent) - * ilogb(+-inf) returns INT_MAX - * ilogb(NaN) returns INT_MIN or INT_MAX (platform-dependent) - */ - expval = ilogb(d); - if(expval <= -INT_MAX /* Also catches +-0 and maybe isnan() */ - || expval == INT_MAX /* catches isfin() and maybe isnan() */ - ) { - /* fpclassify(3) is not portable yet */ - if(isnan(d)) { - buf = "<NOT-A-NUMBER/>"; - buflen = 15; - } else if(expval <= -INT_MAX) { - if(copysign(1.0, d) < 0.0) { - buf = "-0"; - buflen = 2; - } else { - buf = "0"; - buflen = 1; - } - } else { /* isinf() */ - if(copysign(1.0, d) < 0.0) { - buf = "<MINUS-INFINITY/>"; - buflen = 17; - } else { - buf = "<PLUS-INFINITY/>"; - buflen = 16; - } + /* fpclassify(3) is not portable yet */ + if(isnan(d)) { + buf = "<NOT-A-NUMBER/>"; + buflen = 15; + return (cb(buf, buflen, app_key) < 0) ? -1 : buflen; + } else if(isinf(d)) { + if(copysign(1.0, d) < 0.0) { + buf = "<MINUS-INFINITY/>"; + buflen = 17; + } else { + buf = "<PLUS-INFINITY/>"; + buflen = 16; + } + return (cb(buf, buflen, app_key) < 0) ? -1 : buflen; + } else if(ilogb(d) <= -INT_MAX) { + if(copysign(1.0, d) < 0.0) { + buf = "-0"; + buflen = 2; + } else { + buf = "0"; + buflen = 1; } return (cb(buf, buflen, app_key) < 0) ? -1 : buflen; } @@ -259,10 +246,10 @@ asn1_REAL2double(const REAL_t *st, double *dbl_value) { switch(st->buf[0]) { case 0x40: /* 01000000: PLUS-INFINITY */ - *dbl_value = INFINITY; + *dbl_value = 1.0/real_zero; return 0; case 0x41: /* 01000001: MINUS-INFINITY */ - *dbl_value = -INFINITY; + *dbl_value = -1.0/real_zero; return 0; /* * The following cases are defined by @@ -429,23 +416,24 @@ asn1_double2REAL(REAL_t *st, double dbl_value) { st->buf[0] = 0x42; /* NaN */ st->buf[1] = 0; st->size = 1; - } else if(expval <= -INT_MAX) { + } else if(isinf(dbl_value)) { + if(copysign(1.0, dbl_value) < 0.0) { + st->buf[0] = 0x41; /* MINUS-INFINITY */ + } else { + st->buf[0] = 0x40; /* PLUS-INFINITY */ + } + st->buf[1] = 0; + st->size = 1; + } else { if(copysign(1.0, dbl_value) < 0.0) { st->buf[0] = 0x80 | 0x40; st->buf[1] = 0; st->size = 2; } else { + /* no content octets: positive zero */ st->buf[0] = 0; /* JIC */ st->size = 0; } - } else { /* isinf() */ - if(copysign(1.0, dbl_value) < 0.0) { - st->buf[0] = 0x41; /* MINUS-INFINITY */ - } else { - st->buf[0] = 0x40; /* PLUS-INFINITY */ - } - st->buf[1] = 0; - st->size = 1; } return 0; } diff --git a/skeletons/tests/check-REAL.c b/skeletons/tests/check-REAL.c index e61a54a05df10669fa49872730da34325c25f27c..89ab3260ea4051672ba355a38b4ef03af9322b90 100644 --- a/skeletons/tests/check-REAL.c +++ b/skeletons/tests/check-REAL.c @@ -143,13 +143,15 @@ check_buf(uint8_t *buf, size_t bufsize, double verify, const char *sample, const int main() { REAL_t rn; - static const double c_NaN = 0.0; + static const double zero = 0.0; 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"); /* minus-zero */ + check(&rn, zero/zero, "<NOT-A-NUMBER/>", "<NOT-A-NUMBER/>"); + check(&rn, 1.0/zero, "<PLUS-INFINITY/>", "<PLUS-INFINITY/>"); + check(&rn, -1.0/zero, "<MINUS-INFINITY/>", "<MINUS-INFINITY/>"); check(&rn, 1.0, "1.0", "1.0E0"); check(&rn, -1.0, "-1.0", "-1.0E0"); check(&rn, 1.5, "1.5", "1.5E0");