aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLev Walkin <vlm@lionet.info>2016-01-24 22:40:00 -0800
committerLev Walkin <vlm@lionet.info>2016-01-24 22:40:00 -0800
commit8ca13c8a984a13e033231000aa786575c8ed915f (patch)
tree04886259eb4a81af5b145cee0feb25ce27b5932c
parent104af19d65bc356c1e7df2d628e13ff8021bfb91 (diff)
test subnormals
-rw-r--r--skeletons/REAL.c107
-rw-r--r--skeletons/tests/check-REAL.c20
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 <stdio.h>
#include <assert.h>
#include <math.h>
+#include <float.h>
#include <REAL.h>
@@ -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