From 8ca13c8a984a13e033231000aa786575c8ed915f Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Sun, 24 Jan 2016 22:40:00 -0800 Subject: test subnormals --- skeletons/REAL.c | 107 ++++++++++++++++++++++++++----------------- skeletons/tests/check-REAL.c | 20 ++++++-- 2 files changed, 82 insertions(+), 45 deletions(-) diff --git a/skeletons/REAL.c b/skeletons/REAL.c index 1212050c..af72167f 100644 --- a/skeletons/REAL.c +++ b/skeletons/REAL.c @@ -137,9 +137,16 @@ REAL__dump(double d, int canonical, asn_app_consume_bytes_f *cb, void *app_key) * Transform the "[-]d.dddE+-dd" output into "[-]d.dddE[-]d" * Check that snprintf() constructed the output correctly. */ - char *dot, *E; + char *dot; char *end = buf + buflen; char *last_zero; + char *prev_zero; + char *s; + + enum { + LZSTATE_NOTHING, + LZSTATE_SEEN_ZERO + } lz_state = LZSTATE_NOTHING; dot = (buf[0] == 0x2d /* '-' */) ? (buf + 2) : (buf + 1); if(*dot >= 0x30) { @@ -149,51 +156,67 @@ REAL__dump(double d, int canonical, asn_app_consume_bytes_f *cb, void *app_key) } *dot = 0x2e; /* Replace possible comma */ - for(last_zero = dot + 2, E = dot; dot < end; E++) { - if(*E == 0x45) { - char *expptr = ++E; - char *s = expptr; - int sign; - if(*expptr == 0x2b /* '+' */) { - /* Skip the "+" */ - buflen -= 1; - sign = 0; - } else { - sign = 1; - s++; - } - expptr++; - if(expptr > end) { - if(buf != local_buf) FREEMEM(buf); - errno = EINVAL; - return -1; - } - if(*expptr == 0x30) { - buflen--; - expptr++; - } - if(*last_zero == 0x30) { - *last_zero = 0x45; /* E */ - buflen -= s - (last_zero + 1); - s = last_zero + 1; - if(sign) { - *s++ = 0x2d /* '-' */; - buflen++; - } - } - for(; expptr <= end; s++, expptr++) - *s = *expptr; - break; - } else if(*E == 0x30) { - if(*last_zero != 0x30) - last_zero = E; - } - } - if(E == end) { + for(prev_zero = last_zero = s = dot + 2; s < end; s++) { + switch(*s) { + case 0x45: /* 'E' */ + if(lz_state == LZSTATE_SEEN_ZERO) + last_zero = prev_zero; + break; + case 0x30: /* '0' */ + if(lz_state == LZSTATE_NOTHING) + prev_zero = s; + lz_state = LZSTATE_SEEN_ZERO; + continue; + default: + lz_state = LZSTATE_NOTHING; + continue; + } + break; + } + + if(s == end) { if(buf != local_buf) FREEMEM(buf); errno = EINVAL; return -1; /* No promised E */ } + + assert(*s == 0x45); + { + char *E = s; + char *expptr = ++E; + char *s = expptr; + int sign; + + if(*expptr == 0x2b /* '+' */) { + /* Skip the "+" */ + buflen -= 1; + sign = 0; + } else { + sign = 1; + s++; + } + expptr++; + if(expptr > end) { + if(buf != local_buf) FREEMEM(buf); + errno = EINVAL; + return -1; + } + if(*expptr == 0x30) { + buflen--; + expptr++; + } + if(*last_zero == 0x30) { + *last_zero = 0x45; /* E */ + buflen -= s - (last_zero + 1); + s = last_zero + 1; + if(sign) { + *s++ = 0x2d /* '-' */; + buflen++; + } + } + for(; expptr <= end; s++, expptr++) + *s = *expptr; + } } else { /* * Remove trailing zeros. diff --git a/skeletons/tests/check-REAL.c b/skeletons/tests/check-REAL.c index 18bf8a59..f9b9acce 100644 --- a/skeletons/tests/check-REAL.c +++ b/skeletons/tests/check-REAL.c @@ -1,6 +1,7 @@ #include #include #include +#include #include @@ -45,14 +46,14 @@ check_str_representation(double d, const char *sample, const char *canonical_sam s1 = d2s(d, 1); if(sample) { - printf("%03d: Checking %f->[\"%s\"] against [\"%s\"]%s\n", + printf("%03d: Checking %g->[\"%s\"] against [\"%s\"]%s\n", lineno, d, s0, sample, canonical_sample ? " (canonical follows...)" : "" ); assert(!strcmp(s0, sample)); } if(canonical_sample) { - printf("%03d: Checking %f->[\"%s\"] against [\"%s\"] (canonical)\n", + printf("%03d: Checking %g->[\"%s\"] against [\"%s\"] (canonical)\n", lineno, d, s1, canonical_sample); assert(!strcmp(s1, canonical_sample)); } @@ -655,7 +656,20 @@ main() { check(&rn,-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001, 0, 0); check(&rn,-3.33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333, 0, 0); check(&rn, 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000033333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333, 0, 0); - check(&rn, -0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001, 0, 0); + check(&rn, 0.25, "0.25", "2.5E-1"); + check(&rn, -0.25, "-0.25", "-2.5E-1"); + check(&rn, 0.03, "0.03", "3.0E-2"); + check(&rn, -0.03, "-0.03", "-3.0E-2"); + + check(&rn, 4.01E-50, "0.0", "4.01E-50"); + check(&rn, -4.01E-50, "-0.0", "-4.01E-50"); + check(&rn, -4.9406564584124654E-324, "-0.0", "-4.940656458412465E-324"); /* MIN */ + check(&rn, DBL_MIN, "0.0", "2.225073858507201E-308"); /* MIN */ + check(&rn, -DBL_MIN, "-0.0", "-2.225073858507201E-308"); /* -MIN */ + check(&rn, DBL_MAX, "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0", "1.797693134862316E308"); /* MAX */ + check(&rn, -DBL_MAX, "-179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0", "-1.797693134862316E308"); /* MAX */ + check(&rn, -DBL_TRUE_MIN, "-0.0", "-4.940656458412465E-324"); /* subnorm */ + check(&rn, DBL_TRUE_MIN, "0.0", "4.940656458412465E-324"); /* subnorm */ #ifdef NAN -- cgit v1.2.3