aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLev Walkin <vlm@lionet.info>2004-09-27 22:16:18 +0000
committerLev Walkin <vlm@lionet.info>2004-09-27 22:16:18 +0000
commitc51e7d67a2a02f32a76f8d4aff002f97d4132e6a (patch)
treeccbc4f418b7d0338a7d96af10488f0b2e45bc188
parent2a789d9e628f26a96e62e9905be29cc4574fbdf1 (diff)
infinity handling
-rw-r--r--skeletons/REAL.c82
-rw-r--r--skeletons/tests/check-REAL.c6
2 files changed, 39 insertions, 49 deletions
diff --git a/skeletons/REAL.c b/skeletons/REAL.c
index 2373dde9..6ce124ee 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 e61a54a0..89ab3260 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");