Skip to content
Permalink
Browse files
Encode floating point numbers as short as possible
Floating point numbers are no longer encoded as a one to one mapping
of their binary representation, but as short as possible (while still
being acurate). The double-conversion library [1] is used to do the
hard work.

The ECMAScript compatible conversion is used.

[1] https://code.google.com/p/double-conversion/
  • Loading branch information
vmx committed Feb 24, 2013
1 parent ee788ca commit d0f1ea00fc037d3936e80b30ba933f4d5ab415d0
Show file tree
Hide file tree
Showing 8 changed files with 63 additions and 15 deletions.
@@ -20,7 +20,7 @@ devmarker:


depends: devmarker
@if test ! -d ./deps; then \
@if test ! -d ./deps/proper; then \
$(REBAR) get-deps; \
fi

@@ -25,7 +25,7 @@ Errors are raised as exceptions.
2> Doc = {[{foo, [<<"bing">>, 2.3, true]}]}.
{[{foo,[<<"bing">>,2.3,true]}]}
3> jiffy:encode(Doc).
<<"{\"foo\":[\"bing\",2.2999999999999998224,true]}">>
<<"{\"foo\":[\"bing\",2.3,true]}">>


Data Format
@@ -0,0 +1,31 @@
#include <string.h>

#include "double-conversion.h"


using namespace double_conversion;


#ifdef __cplusplus
extern "C" {
#endif

// Returns the length of the string
int
double_to_shortest(char *buf, size_t size, double val)
{
int len = -1;

StringBuilder builder(buf, size);
const DoubleToStringConverter& dc =
DoubleToStringConverter::EcmaScriptConverter();

dc.ToShortest(val, &builder);
len = builder.position();
buf = builder.Finalize();
return len;
}

#ifdef __cplusplus
}
#endif
@@ -399,8 +399,7 @@ enc_double(Encoder* e, double val)

start = &(e->p[e->i]);

sprintf(start, "%0.20g", val);
len = strlen(start);
len = double_to_shortest(start, e->curr->size, val);

// Check if we have a decimal point
for(i = 0; i < len; i++) {
@@ -41,4 +41,6 @@ int unicode_to_utf8(int c, unsigned char* buf);
int unicode_from_pair(int hi, int lo);
int unicode_uescape(int c, char* buf);

int double_to_shortest(char *buf, size_t size, double val);

#endif // Included JIFFY_H
@@ -1,7 +1,12 @@
{port_specs, [{"priv/jiffy.so", ["c_src/*.c"]}]}.
{port_specs, [
{"priv/jiffy.so", ["c_src/*.c*", "deps/double-conversion/src/*.cc"]}
]}.

{port_env, [
{".*", "CFLAGS", "$CFLAGS -g -Wall"},
{".*", "CXXFLAGS", "$CXXFLAGS -g -Wall -Ideps/double-conversion/src"},

{"(linux|solaris|freebsd|netbsd|openbsd|dragonfly|darwin)",
"LDFLAGS", "$LDFLAGS -lstdc++"},

%% OS X Leopard flags for 64-bit
{"darwin9.*-64$", "CXXFLAGS", "-m64"},
@@ -23,3 +28,7 @@
}}
]}.

{deps, [
{'double-conversion', ".*",
{git, "https://code.google.com/p/double-conversion/", "master"}, [raw]}
]}.
@@ -11,16 +11,23 @@ ErlOpts = {erl_opts, [
{d, 'JIFFY_DEV'}
]},

Deps = {deps, [
Proper = [
{proper, ".*", {git, "git://github.com/manopapad/proper.git", "master"}}
]},
],

ConfigPath = filename:dirname(SCRIPT),
DevMarker = filename:join([ConfigPath, ".jiffy.dev"]),

case filelib:is_file(DevMarker) of
true ->
CONFIG ++ [ErlOpts, Deps];
% Don't override existing dependencies
NewConfig = case lists:keyfind(deps, 1, CONFIG) of
false ->
CONFIG ++ [{deps, Proper}];
{deps, DepsList} ->
lists:keyreplace(deps, 1, CONFIG, {deps, DepsList ++ Proper})
end,
NewConfig ++ [ErlOpts];
false ->
CONFIG
end.
@@ -23,12 +23,12 @@ good() ->
{
<<"1234567890123456789012345.0">>,
1.23456789012345678e24,
<<"1.2345678901234568245e+24">>
<<"1.2345678901234568e+24">>
},
{
<<"1234567890123456789012345.0E3">>,
1.2345678901234569e27,
<<"1.2345678901234568502e+27">>
<<"1.2345678901234569e+27">>
},
{
<<"1234567890123456789012345012">>,
@@ -39,12 +39,12 @@ good() ->
{
<<"0.000000000000000000000000000000000001">>,
1.0E-36,
<<"9.9999999999999994104e-37">>
<<"1e-36">>
},
{<<"0.75">>, 0.75},
{<<"2.0123456789">>, 2.0123456789, <<"2.0123456789000000455">>},
{<<"2.4234324E24">>, 2.4234324E24, <<"2.4234323999999998107e+24">>},
{<<"-3.1416">>, -3.1416, <<"-3.1415999999999999481">>},
{<<"2.0123456789">>, 2.0123456789, <<"2.0123456789">>},
{<<"2.4234324E24">>, 2.4234324E24, <<"2.4234324e+24">>},
{<<"-3.1416">>, -3.1416, <<"-3.1416">>},
{<<"1E4">>, 10000.0, <<"10000.0">>},
{<<"1.0E+01">>, 10.0, <<"10.0">>},
{<<"1e1">>, 10.0, <<"10.0">>},

0 comments on commit d0f1ea0

Please sign in to comment.