Commit c51e7d67 authored by Lev Walkin's avatar Lev Walkin

infinity handling

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