Skip to content
Snippets Groups Projects
Commit c51e7d67 authored by Lev Walkin's avatar Lev Walkin
Browse files

infinity handling

parent 2a789d9e
No related branches found
No related tags found
No related merge requests found
...@@ -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");
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment