diff options
Diffstat (limited to 'erts/emulator/beam')
-rw-r--r-- | erts/emulator/beam/atom.names | 3 | ||||
-rw-r--r-- | erts/emulator/beam/bif.c | 68 | ||||
-rw-r--r-- | erts/emulator/beam/bif.tab | 1 | ||||
-rw-r--r-- | erts/emulator/beam/sys.h | 3 |
4 files changed, 74 insertions, 1 deletions
diff --git a/erts/emulator/beam/atom.names b/erts/emulator/beam/atom.names index c47a608215..b74e2785e5 100644 --- a/erts/emulator/beam/atom.names +++ b/erts/emulator/beam/atom.names @@ -144,6 +144,7 @@ atom close atom closed atom code atom command +atom compact atom compat_rel atom compile atom compressed @@ -165,6 +166,7 @@ atom current_location atom current_stacktrace atom data atom debug_flags +atom decimals atom delay_trap atom dexit atom depth @@ -480,6 +482,7 @@ atom scheduler atom scheduler_id atom schedulers_online atom scheme +atom scientific atom scope atom sensitive atom sequential_tracer diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c index 97c8114437..182129cd36 100644 --- a/erts/emulator/beam/bif.c +++ b/erts/emulator/beam/bif.c @@ -2917,7 +2917,73 @@ BIF_RETTYPE float_to_list_1(BIF_ALIST_1) need = i*2; hp = HAlloc(BIF_P, need); BIF_RET(buf_to_intlist(&hp, fbuf, i, NIL)); - } +} + +BIF_RETTYPE float_to_list_2(BIF_ALIST_2) +{ + const static int arity_two = make_arityval(2); + int decimals = SYS_DEFAULT_FLOAT_DECIMALS; + int compact = 0; + enum fmt_type_ { + FMT_LEGACY, + FMT_FIXED, + FMT_SCIENTIFIC + } fmt_type = FMT_LEGACY; + Eterm list = BIF_ARG_2; + Eterm arg; + int i; + Uint need; + Eterm* hp; + FloatDef f; + char fbuf[256]; + + /* check the arguments */ + if (is_not_float(BIF_ARG_1)) + goto badarg; + + for(; is_list(list); list = CDR(list_val(list))) { + arg = CAR(list_val(list)); + if (arg == am_compact) { + compact = 1; + continue; + } else if (is_tuple(arg)) { + Eterm* tp = tuple_val(arg); + if (*tp == arity_two && is_small(tp[2])) { + decimals = signed_val(tp[2]); + if (decimals > 0 && decimals < sizeof(fbuf) - 6 /* "X." ++ "e+YY" */) + switch (tp[1]) { + case am_decimals: + fmt_type = FMT_FIXED; + continue; + case am_scientific: + fmt_type = FMT_SCIENTIFIC; + continue; + } + } + } + goto badarg; + } + if (is_not_nil(list)) { + goto badarg; + } + + GET_DOUBLE(BIF_ARG_1, f); + + if (fmt_type == FMT_FIXED) { + if ((i = sys_double_to_chars_fast(f.fd, fbuf, sizeof(fbuf), + decimals, compact)) <= 0) + goto badarg; + } else { + if ((i = sys_double_to_chars_ext(f.fd, fbuf, sizeof(fbuf), decimals)) <= 0) + goto badarg; + } + + need = i*2; + hp = HAlloc(BIF_P, need); + BIF_RET(buf_to_intlist(&hp, fbuf, i, NIL)); +badarg: + BIF_ERROR(BIF_P, BADARG); +} /**********************************************************************/ diff --git a/erts/emulator/beam/bif.tab b/erts/emulator/beam/bif.tab index 59a91cd40c..a79feb6da3 100644 --- a/erts/emulator/beam/bif.tab +++ b/erts/emulator/beam/bif.tab @@ -64,6 +64,7 @@ bif erlang:external_size/1 bif erlang:external_size/2 ubif erlang:float/1 bif erlang:float_to_list/1 +bif erlang:float_to_list/2 bif erlang:fun_info/2 bif erlang:garbage_collect/0 bif erlang:garbage_collect/1 diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h index 898a30b010..cecaff54a4 100644 --- a/erts/emulator/beam/sys.h +++ b/erts/emulator/beam/sys.h @@ -729,9 +729,12 @@ char * getenv_string(GETENV_STATE *); void fini_getenv_state(GETENV_STATE *); /* xxxP */ +#define SYS_DEFAULT_FLOAT_DECIMALS 20 void init_sys_float(void); int sys_chars_to_double(char*, double*); int sys_double_to_chars(double, char*, size_t); +int sys_double_to_chars_ext(double, char*, size_t, size_t); +int sys_double_to_chars_fast(double, char*, int, int, int); void sys_get_pid(char *, size_t); /* erts_sys_putenv() returns, 0 on success and a value != 0 on failure. */ |