From a6a8805b906dc9be2ec3ecba647997335e345182 Mon Sep 17 00:00:00 2001 From: Steve Vinoski Date: Sat, 29 May 2010 12:07:32 -0400 Subject: compact IEEE 754 double encoding in external binary format for ei Implement the compact IEEE 754 double encoding in external binary format for ei. Encoding for ei now always produces the NEW_FLOAT_EXT format. Decoding and term printing handle both the old ERL_FLOAT_EXT encoding and the new NEW_FLOAT_EXT encoding. Legacy erl_interface code also handles the new encoding, but still produces the ERL_FLOAT_EXT encoding by default. Also enable the DFLAG_NEW_FLOATS distribution flag. Reduce the number of copies of the code for encoding and decoding doubles throughout ei and erl_interface by instead calling the ei encoding and decoding functions wherever possible. Restore commented-out float tests in ei_decode_SUITE and ei_encode_SUITE in lib/erl_interface/test. Modify them to make them match the style of other tests in the same suites. These changes are based on an ei float patch from Serge Aleynikov originally submitted against R12B-2 in July 2008. --- lib/erl_interface/src/misc/ei_decode_term.c | 13 +++++-------- lib/erl_interface/src/misc/ei_printterm.c | 1 + lib/erl_interface/src/misc/putget.h | 28 ++++++++++++++++++++++++++++ lib/erl_interface/src/misc/show_msg.c | 1 + 4 files changed, 35 insertions(+), 8 deletions(-) (limited to 'lib/erl_interface/src/misc') diff --git a/lib/erl_interface/src/misc/ei_decode_term.c b/lib/erl_interface/src/misc/ei_decode_term.c index 7b95ff232f..32aec988e1 100644 --- a/lib/erl_interface/src/misc/ei_decode_term.c +++ b/lib/erl_interface/src/misc/ei_decode_term.c @@ -25,9 +25,9 @@ #include "ei_decode_term.h" #include "putget.h" -/* Returns 1 if term is decoded, 0 if term is OK, but not decoded here - and -1 if something is wrong. - ONLY changes index if term is decoded (return value 1)! */ +/* Returns 0 on successful encoding, -1 on error, and 1 if the term seems + alright, but does not fit in the term structure. If it returns 0, the + index will be incremented, and the term contains the decoded term. */ int ei_decode_ei_term(const char* buf, int* index, ei_term* term) { @@ -46,11 +46,8 @@ int ei_decode_ei_term(const char* buf, int* index, ei_term* term) term->value.i_val = get32be(s); break; case ERL_FLOAT_EXT: - if (s[30]) return -1; - if (sscanf(s, "%lf", &f) != 1) return -1; - s += 31; - term->value.d_val = f; - break; + case NEW_FLOAT_EXT: + return ei_decode_double(buf, index, &term->value.d_val); case ERL_ATOM_EXT: len = get16be(s); memcpy(term->value.atom_name, s, len); diff --git a/lib/erl_interface/src/misc/ei_printterm.c b/lib/erl_interface/src/misc/ei_printterm.c index 8d0eef5e79..00f98ba0a1 100644 --- a/lib/erl_interface/src/misc/ei_printterm.c +++ b/lib/erl_interface/src/misc/ei_printterm.c @@ -272,6 +272,7 @@ static int print_term(FILE* fp, ei_x_buff* x, break; case ERL_FLOAT_EXT: + case NEW_FLOAT_EXT: if (ei_decode_double(buf, index, &d) < 0) goto err; ch_written += xprintf(fp, x, "%f", d); break; diff --git a/lib/erl_interface/src/misc/putget.h b/lib/erl_interface/src/misc/putget.h index 98d9ebb64c..f0fbd9a211 100644 --- a/lib/erl_interface/src/misc/putget.h +++ b/lib/erl_interface/src/misc/putget.h @@ -54,6 +54,18 @@ (s) += 4; \ } while (0) +#define put64be(s,n) do { \ + (s)[0] = ((n) >> 56) & 0xff; \ + (s)[1] = ((n) >> 48) & 0xff; \ + (s)[2] = ((n) >> 40) & 0xff; \ + (s)[3] = ((n) >> 32) & 0xff; \ + (s)[4] = ((n) >> 24) & 0xff; \ + (s)[5] = ((n) >> 16) & 0xff; \ + (s)[6] = ((n) >> 8) & 0xff; \ + (s)[7] = (n) & 0xff; \ + (s) += 8; \ +} while (0) + #define get8(s) \ ((s) += 1, \ ((unsigned char *)(s))[-1] & 0xff) @@ -82,4 +94,20 @@ (((unsigned char *)(s))[-2] << 8) | \ ((unsigned char *)(s))[-1])) +#define get64be(s) \ + ((s) += 8, \ + (((EI_ULONGLONG)((unsigned char *)(s))[-8] << 56) | \ + ((EI_ULONGLONG)((unsigned char *)(s))[-7] << 48) | \ + ((EI_ULONGLONG)((unsigned char *)(s))[-6] << 40) | \ + ((EI_ULONGLONG)((unsigned char *)(s))[-5] << 32) | \ + ((EI_ULONGLONG)((unsigned char *)(s))[-4] << 24) | \ + ((EI_ULONGLONG)((unsigned char *)(s))[-3] << 16) | \ + ((EI_ULONGLONG)((unsigned char *)(s))[-2] << 8) | \ + (EI_ULONGLONG)((unsigned char *)(s))[-1])) + +typedef union float_ext { + double d; + EI_ULONGLONG val; +} FloatExt; + #endif /* _PUTGET_H */ diff --git a/lib/erl_interface/src/misc/show_msg.c b/lib/erl_interface/src/misc/show_msg.c index 25865d6f8e..9ed27f49d5 100644 --- a/lib/erl_interface/src/misc/show_msg.c +++ b/lib/erl_interface/src/misc/show_msg.c @@ -400,6 +400,7 @@ static void show_term(const char *termbuf, int *index, FILE *stream) break; case ERL_FLOAT_EXT: + case NEW_FLOAT_EXT: ei_decode_double(termbuf,index,&fnum); fprintf(stream,"%f",fnum); break; -- cgit v1.2.3