diff options
author | Lev Walkin <vlm@lionet.info> | 2004-10-26 09:35:25 +0000 |
---|---|---|
committer | Lev Walkin <vlm@lionet.info> | 2004-10-26 09:35:25 +0000 |
commit | 1aea6983964471c272e1c831255a2f1ca9bc9cb2 (patch) | |
tree | a8ca56e9c0a8e377049f17af551af4b622f1a648 /skeletons | |
parent | 337001658820b2bfb07468b6d6b6497cee0ab8c6 (diff) |
fight with signalling NANs and floating point exceptions on alpha64
Diffstat (limited to 'skeletons')
-rw-r--r-- | skeletons/REAL.c | 41 | ||||
-rw-r--r-- | skeletons/tests/check-REAL.c | 23 |
2 files changed, 46 insertions, 18 deletions
diff --git a/skeletons/REAL.c b/skeletons/REAL.c index 3316ee5a..9380c9d1 100644 --- a/skeletons/REAL.c +++ b/skeletons/REAL.c @@ -3,8 +3,9 @@ * Redistribution and modifications are permitted subject to BSD license. */ #if defined(__alpha) -#define _ISOC99_SOURCE /* For quiet NAN, indirectly through bits/nan.h */ -#define _BSD_SOURCE /* To reintroduce finite(3) */ +#define _ISOC99_SOURCE /* For quiet NAN, through bits/nan.h */ +#define _BSD_SOURCE /* To reintroduce finite(3) */ +#include <sys/resource.h> /* For INFINITY */ #endif #include <asn_internal.h> #include <stdlib.h> /* for strtod(3) */ @@ -16,10 +17,15 @@ #undef INT_MAX #define INT_MAX ((int)(((unsigned int)-1) >> 1)) -static volatile double real_zero = 0.0; +#if !(defined(NAN) || defined(INFINITY)) +static volatile double real_zero __attribute__ ((unused)) = 0.0; +#endif #ifndef NAN #define NAN (real_zero/real_zero) #endif +#ifndef INFINITY +#define INFINITY (1.0/real_zero) +#endif /* * REAL basic type description. @@ -54,12 +60,12 @@ typedef enum specialRealValue { static struct specialRealValue_s { char *string; size_t length; - double dv; + long dv; } specialRealValue[] = { #define SRV_SET(foo, val) { foo, sizeof(foo) - 1, val } - SRV_SET("<NOT-A-NUMBER/>", 0.0), - SRV_SET("<MINUS-INFINITY/>", -1.0), - SRV_SET("<PLUS-INFINITY/>", 1.0), + SRV_SET("<NOT-A-NUMBER/>", 0), + SRV_SET("<MINUS-INFINITY/>", -1), + SRV_SET("<PLUS-INFINITY/>", 1), #undef SRV_SET }; @@ -269,12 +275,25 @@ REAL__xer_body_decode(void *sptr, void *chunk_buf, size_t chunk_size) { for(i = 0; i < sizeof(specialRealValue) / sizeof(specialRealValue[0]); i++) { struct specialRealValue_s *srv = &specialRealValue[i]; + double dv; + if(srv->length != chunk_size || memcmp(srv->string, chunk_buf, chunk_size)) continue; - if(asn_double2REAL(st, srv->dv / real_zero)) - return -1; + /* + * It could've been done using + * (double)srv->dv / real_zero, + * but it summons fp exception on some platforms. + */ + switch(srv->dv) { + case -1: dv = - INFINITY; break; + case 0: dv = NAN; break; + case 1: dv = INFINITY; break; + default: return -1; + } + + if(asn_double2REAL(st, dv)) return -1; return chunk_size; } @@ -337,10 +356,10 @@ asn_REAL2double(const REAL_t *st, double *dbl_value) { switch(st->buf[0]) { case 0x40: /* 01000000: PLUS-INFINITY */ - *dbl_value = 1.0/real_zero; + *dbl_value = INFINITY; return 0; case 0x41: /* 01000001: MINUS-INFINITY */ - *dbl_value = -1.0/real_zero; + *dbl_value = - INFINITY; return 0; /* * The following cases are defined by diff --git a/skeletons/tests/check-REAL.c b/skeletons/tests/check-REAL.c index 094017d2..dc8de267 100644 --- a/skeletons/tests/check-REAL.c +++ b/skeletons/tests/check-REAL.c @@ -88,8 +88,8 @@ check(REAL_t *rn, double orig_dbl, const char *sample, const char *canonical_sam printf("%02x", *p); printf("] (ilogb %d)\n", ilogb(val)); - printf("%.12f vs %.12f\n", orig_dbl, val); - assert(orig_dbl == val || (isnan(orig_dbl) && isnan(val))); + printf("%.12f vs %.12f\n", val, orig_dbl); + assert((isnan(orig_dbl) && isnan(val)) || val == orig_dbl); printf("OK\n"); check_str_repr(val, sample, canonical_sample); @@ -98,7 +98,7 @@ check(REAL_t *rn, double orig_dbl, const char *sample, const char *canonical_sam uint8_t buf_1_0[] = { 0x80, 0xcc, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; uint8_t buf_1_1[] = { 0x80, 0xcc, 0x11, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a }; uint8_t buf_3_14[] = { 0x80, 0xcd, 0x19, 0x1e, 0xb8, 0x51, 0xeb, 0x85, 0x1f }; -/* These ones are very interesting! It checks mantissa overflow! */ +/* These ones are very interesting! They check mantissa overflow! */ uint8_t buf_mo1[] = { 0xC0, 0xc5, 0x19, 0x1e, 0xb8, 0x51, 0xeb, 0x85, 0x1f,3}; uint8_t buf_mo2[] = { 0x80, 0xbd, 0x19, 0x1e, 0xb8, 0x51, 0xeb, 0x85, 0x1f,3,2}; @@ -189,11 +189,11 @@ check_xer(int fuzzy, double orig_value) { ret = asn_REAL2double(newst1, &value1); assert(ret == 0); - assert(value0 == orig_value - || (isnan(value0) && isnan(orig_value)) + assert((isnan(value0) && isnan(orig_value)) + || value0 == orig_value || fuzzy); - assert(value1 == orig_value - || (isnan(value1) && isnan(orig_value))); + assert((isnan(value1) && isnan(orig_value)) + || value1 == orig_value); assert(newst0->size == st.size || fuzzy); assert(newst1->size == st.size); @@ -250,9 +250,18 @@ main() { check_buf(buf_mo2, sizeof(buf_mo2), 3.14, "3.14", "3.14E0"); +#ifdef NAN + check_xer(0, NAN); /* "<NOT-A-NUMBER/>" */ +#else check_xer(0, zero/zero); /* "<NOT-A-NUMBER/>" */ +#endif +#ifdef INFINITY + check_xer(0, INFINITY); /* "<PLUS-INFINITY/>" */ + check_xer(0, -INFINITY); /* "<MINUS-INFINITY/>" */ +#else check_xer(0, 1.0/zero); /* "<PLUS-INFINITY/>" */ check_xer(0, -1.0/zero); /* "<MINUS-INFINITY/>" */ +#endif check_xer(0, 1.0); check_xer(0, -1.0); check_xer(0, 1.5); |