From b074099cc6bdb81285a17e0248373f199c695719 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Wed, 5 Sep 2012 20:43:03 +0200 Subject: Add new binary conversion bifs Added: binary_to_integer/1,2, integer_to_binary/1,2 --- erts/doc/src/erlang.xml | 49 ++++- erts/emulator/beam/bif.c | 50 ++++- erts/emulator/beam/bif.tab | 4 + erts/emulator/beam/big.c | 247 ++++++++++++++++++++-- erts/emulator/beam/big.h | 3 + erts/emulator/beam/binary.c | 92 +++++++++ erts/emulator/test/hash_SUITE.erl | 4 +- erts/emulator/test/num_bif_SUITE.erl | 382 +++++++++++++++++++++-------------- erts/preloaded/src/erlang.erl | 104 +++++----- 9 files changed, 723 insertions(+), 212 deletions(-) (limited to 'erts') diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml index 5a63aaadc6..36d606130f 100644 --- a/erts/doc/src/erlang.xml +++ b/erts/doc/src/erlang.xml @@ -299,6 +299,32 @@

Failure: badarg if the atom does not already exist.

+ + + Convert from text representation to an integer + +

Returns an integer whose text representation is + Binary.

+
+> binary_to_integer(<<"123">>).
+123
+

Failure: badarg if Binary contains a bad + representation of an integer.

+
+
+ + + Convert from text representation to an integer + +

Returns an integer whose text representation in base + Base is Binary.

+
+> binary_to_integer(<<"3FF">>, 16).
+1023
+

Failure: badarg if Binary contains a bad + representation of an integer.

+
+
Convert a binary to a list @@ -1429,7 +1455,28 @@ os_prompt% {one,new,two,three} - + + + Text representation of an integer + +

Returns a binary which corresponds to the text + representation of Integer.

+
+> integer_to_binary(77).
+<<"77">>
+
+
+ + + Text representation of an integer + +

Returns a binary which corresponds to the text + representation of Integer in base Base.

+
+> integer_to_binary(1023, 16).
+<<"3FF">>
+
+
Text representation of an integer diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c index df084e1185..a596068527 100644 --- a/erts/emulator/beam/bif.c +++ b/erts/emulator/beam/bif.c @@ -2895,20 +2895,64 @@ BIF_RETTYPE string_to_integer_1(BIF_ALIST_1) BIF_RET(TUPLE2(hp, res, tail)); } } - BIF_RETTYPE list_to_integer_1(BIF_ALIST_1) -{ + { + /* Using do_list_to_integer is about twice as fast as using + erts_chars_to_integer because we do not have to copy the + entire list */ Eterm res; Eterm dummy; /* must be a list */ - if (do_list_to_integer(BIF_P,BIF_ARG_1,&res,&dummy) != LTI_ALL_INTEGER) { BIF_ERROR(BIF_P,BADARG); } BIF_RET(res); } +BIF_RETTYPE list_to_integer_2(BIF_ALIST_2) +{ + + /* Bif implementation is about 50% faster than pure erlang, + and since we have erts_chars_to_integer now it is simpler + as well. This could be optmized further if we did not have to + copy the list to buf. */ + int i; + Eterm res; + char *buf = NULL; + int base; + + i = list_length(BIF_ARG_1); + if (i < 0) + BIF_ERROR(BIF_P, BADARG); + + base = signed_val(BIF_ARG_2); + + if (base < 2 || base > 36) + BIF_ERROR(BIF_P, BADARG); + + /* Take fast path if base it 10 */ + if (base == 10) + return list_to_integer_1(BIF_P,&BIF_ARG_1); + + buf = (char *) erts_alloc(ERTS_ALC_T_TMP, i + 1); + + if (intlist_to_buf(BIF_ARG_1, buf, i) < 0) + goto list_to_integer_1_error; + buf[i] = '\0'; /* null terminal */ + + if ((res = erts_chars_to_integer(BIF_P,buf,i,base)) == THE_NON_VALUE) + goto list_to_integer_1_error; + + erts_free(ERTS_ALC_T_TMP, (void *) buf); + BIF_RET(res); + + list_to_integer_1_error: + erts_free(ERTS_ALC_T_TMP, (void *) buf); + BIF_ERROR(BIF_P, BADARG); + + } + /**********************************************************************/ /* convert a float to a list of ascii characters */ diff --git a/erts/emulator/beam/bif.tab b/erts/emulator/beam/bif.tab index e313188901..aa6105de73 100644 --- a/erts/emulator/beam/bif.tab +++ b/erts/emulator/beam/bif.tab @@ -561,6 +561,10 @@ bif erlang:prepare_loading/2 bif erlang:finish_loading/1 bif erlang:insert_element/3 bif erlang:delete_element/2 +bif erlang:binary_to_integer/1 +bif erlang:binary_to_integer/2 +bif erlang:integer_to_binary/1 +bif erlang:list_to_integer/2 # # Obsolete diff --git a/erts/emulator/beam/big.c b/erts/emulator/beam/big.c index 5a5b162b9c..acfcc845e4 100644 --- a/erts/emulator/beam/big.c +++ b/erts/emulator/beam/big.c @@ -1674,26 +1674,26 @@ int big_decimal_estimate(Wterm x) ** Convert a bignum into a string of decimal numbers */ -static void write_big(Wterm x, void (*write_func)(void *, char), void *arg) +static Uint write_big(Wterm x, void (*write_func)(void *, char), void *arg) { Eterm* xp = big_val(x); ErtsDigit* dx = BIG_V(xp); dsize_t xl = BIG_SIZE(xp); short sign = BIG_SIGN(xp); ErtsDigit rem; + Uint n = 0; if (xl == 1 && *dx < D_DECIMAL_BASE) { rem = *dx; - if (rem == 0) - (*write_func)(arg, '0'); - else { + if (rem == 0) { + (*write_func)(arg, '0'); n++; + } else { while(rem) { - (*write_func)(arg, (rem % 10) + '0'); + (*write_func)(arg, (rem % 10) + '0'); n++; rem /= 10; } } - } - else { + } else { ErtsDigit* tmp = (ErtsDigit*) erts_alloc(ERTS_ALC_T_TMP, sizeof(ErtsDigit)*xl); dsize_t tmpl = xl; @@ -1704,15 +1704,14 @@ static void write_big(Wterm x, void (*write_func)(void *, char), void *arg) tmpl = D_div(tmp, tmpl, D_DECIMAL_BASE, tmp, &rem); if (tmpl == 1 && *tmp == 0) { while(rem) { - (*write_func)(arg, (rem % 10)+'0'); + (*write_func)(arg, (rem % 10)+'0'); n++; rem /= 10; } break; - } - else { + } else { int i = D_DECIMAL_EXP; while(i--) { - (*write_func)(arg, (rem % 10)+'0'); + (*write_func)(arg, (rem % 10)+'0'); n++; rem /= 10; } } @@ -1720,8 +1719,10 @@ static void write_big(Wterm x, void (*write_func)(void *, char), void *arg) erts_free(ERTS_ALC_T_TMP, (void *) tmp); } - if (sign) - (*write_func)(arg, '-'); + if (sign) { + (*write_func)(arg, '-'); n++; + } + return n; } struct big_list__ { @@ -1762,6 +1763,20 @@ char *erts_big_to_string(Wterm x, char *buf, Uint buf_sz) return big_str; } +/* Bignum to binary bytes + * e.g. 1 bsl 64 -> "18446744073709551616" + */ + +Uint erts_big_to_binary_bytes(Eterm x, char *buf, Uint buf_sz) +{ + char *big_str = buf + buf_sz; + Uint n; + n = write_big(x, write_string, (void *) &big_str); + ASSERT(buf <= big_str && big_str <= buf + buf_sz); + return n; +} + + /* ** Normalize a bignum given thing pointer length in digits and a sign ** patch zero if odd length @@ -2467,3 +2482,209 @@ int term_equals_2pow32(Eterm x) return 0; } } + + +#define IS_VALID_CHARACTER(CHAR,BASE) \ + (CHAR < '0' \ + || (CHAR > ('0' + BASE - 1) \ + && !(BASE > 10 \ + && ((CHAR >= 'a' && CHAR < ('a' + BASE - 10)) \ + || (CHAR >= 'A' && CHAR < ('A' + BASE - 10)))))) +#define CHARACTER_FROM_BASE(CHAR) \ + ((CHAR <= '9') ? CHAR - '0' : 10 + ((CHAR <= 'Z') ? CHAR - 'A' : CHAR - 'a')) +#define D_BASE_EXP(BASE) (d_base_exp_lookup[BASE-2]) +#define D_BASE_BASE(BASE) (d_base_base_lookup[BASE-2]) +#define LG2_LOOKUP(BASE) (lg2_lookup[base-2]) + +/* + * for i in 2..64 do + * lg2_lookup[i-2] = log2(i) + * end + * How many bits are needed to store string of size n + */ +const double lg2_lookup[] = { 1.0, 1.58496, 2, 2.32193, 2.58496, 2.80735, 3.0, + 3.16993, 3.32193, 3.45943, 3.58496, 3.70044, 3.80735, 3.90689, 4.0, + 4.08746, 4.16993, 4.24793, 4.32193, 4.39232, 4.45943, 4.52356, 4.58496, + 4.64386, 4.70044, 4.75489, 4.80735, 4.85798, 4.90689, 4.9542, 5.0, + 5.04439, 5.08746, 5.12928, 5.16993, 5.20945, 5.24793, 5.2854, 5.32193, + 5.35755, 5.39232, 5.42626, 5.45943, 5.49185, 5.52356, 5.55459, 5.58496, + 5.61471, 5.64386, 5.67243, 5.70044, 5.72792, 5.75489, 5.78136, 5.80735, + 5.83289, 5.85798, 5.88264, 5.90689, 5.93074, 5.9542, 5.97728, 6.0 }; + +/* + * for i in 2..64 do + * d_base_exp_lookup[i-2] = 31 / lg2_lookup[i-2]; + * end + * How many characters can fit in 31 bits + */ +const byte d_base_exp_lookup[] = { 31, 19, 15, 13, 11, 11, 10, 9, 9, 8, 8, 8, 8, + 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5 }; + +/* + * for i in 2..64 do + * d_base_base_lookup[i-2] = pow(i,d_base_exp_lookup[i-2]); + * end + * How much can the characters which fit in 31 bit represent + */ +const Uint d_base_base_lookup[] = { 2147483648, 1162261467, 1073741824, + 1220703125, 362797056, 1977326743, 1073741824, 387420489, 1000000000, + 214358881, 429981696, 815730721, 1475789056, 170859375, 268435456, + 410338673, 612220032, 893871739, 1280000000, 1801088541, 113379904, + 148035889, 191102976, 244140625, 308915776, 387420489, 481890304, + 594823321, 729000000, 887503681, 1073741824, 1291467969, 1544804416, + 1838265625, 60466176, 69343957, 79235168, 90224199, 102400000, + 115856201, 130691232, 147008443, 164916224, 184528125, 205962976, + 229345007, 254803968, 282475249, 312500000, 345025251, 380204032, + 418195493, 459165024, 503284375, 550731776, 601692057, 656356768, + 714924299, 777600000, 844596301, 916132832, 992436543, 1073741824 }; + +Eterm erts_chars_to_integer(Process *BIF_P, char *bytes, + Uint size, const int base) { + Eterm res; + Sint i = 0; + int n = 0; + int neg = 0; + byte b; + Eterm *hp, *hp_end; + int m; + int lg2; + + if (size == 0) + goto bytebuf_to_integer_1_error; + + if (bytes[0] == '-') { + neg = 1; + bytes++; + size--; + + } else if (bytes[0] == '+') { + bytes++; + size--; + } + + if (size < SMALL_DIGITS && base <= 10) { + /* * + * Take shortcut if we know that all chars are '0' < b < '9' and + * fit in a small. This improves speed by about 10% over the generic + * small case. + * */ + while (size--) { + b = *bytes++; + + if (b < '0' || b > ('0'+base-1)) + goto bytebuf_to_integer_1_error; + + i = i * base + b - '0'; + } + + if (neg) + i = -i; + res = make_small(i); + goto bytebuf_to_integer_1_done; + } + + /* + * Calculate the maximum number of bits which will + * be needed to represent the binary + */ + lg2 = ((size+2)*LG2_LOOKUP(base)+1); + + if (lg2 < SMALL_BITS) { + /* Take shortcut if we know it will fit in a small. + * This improves speed by about 30%. + */ + while (size) { + b = *bytes++; + size--; + + if (IS_VALID_CHARACTER(b,base)) + goto bytebuf_to_integer_1_error; + + i = i * base + CHARACTER_FROM_BASE(b); + + } + + if (neg) + i = -i; + res = make_small(i); + goto bytebuf_to_integer_1_done; + + } + + /* Start calculating bignum */ + m = (lg2 + D_EXP-1)/D_EXP; + m = BIG_NEED_SIZE(m); + + hp = HAlloc(BIF_P, m); + hp_end = hp + m; + + if ((i = (size % D_BASE_EXP(base))) == 0) + i = D_BASE_EXP(base); + + n = size - i; + m = 0; + + while (i--) { + b = *bytes++; + + if (IS_VALID_CHARACTER(b,base)) { + HRelease(BIF_P, hp_end, hp); + goto bytebuf_to_integer_1_error; + } + + m = base * m + CHARACTER_FROM_BASE(b); + } + + res = small_to_big(m, hp); + + while (n) { + i = D_BASE_EXP(base); + n -= D_BASE_EXP(base); + m = 0; + while (i--) { + b = *bytes++; + + if (IS_VALID_CHARACTER(b,base)) { + HRelease(BIF_P, hp_end, hp); + goto bytebuf_to_integer_1_error; + } + + m = base * m + CHARACTER_FROM_BASE(b); + } + if (is_small(res)) { + res = small_to_big(signed_val(res), hp); + } + res = big_times_small(res, D_BASE_BASE(base), hp); + if (is_small(res)) { + res = small_to_big(signed_val(res), hp); + } + res = big_plus_small(res, m, hp); + } + + if (is_big(res)) /* check if small */ + res = big_plus_small(res, 0, hp); /* includes conversion to small */ + + if (neg) { + if (is_small(res)) + res = make_small(-signed_val(res)); + else { + Uint *big = big_val(res); /* point to thing */ + *big = bignum_header_neg(*big); + } + } + + if (is_big(res)) { + hp += (big_arity(res) + 1); + } + HRelease(BIF_P, hp_end, hp); + goto bytebuf_to_integer_1_done; + +bytebuf_to_integer_1_error: + return THE_NON_VALUE; + +bytebuf_to_integer_1_done: + return res; + +} diff --git a/erts/emulator/beam/big.h b/erts/emulator/beam/big.h index 7eb1e5afe2..c74283b9e5 100644 --- a/erts/emulator/beam/big.h +++ b/erts/emulator/beam/big.h @@ -117,6 +117,7 @@ typedef Uint dsize_t; /* Vector size type */ int big_decimal_estimate(Wterm); Eterm erts_big_to_list(Eterm, Eterm**); char *erts_big_to_string(Wterm x, char *buf, Uint buf_sz); +Uint erts_big_to_binary_bytes(Eterm x, char *buf, Uint buf_sz); Eterm small_times(Sint, Sint, Eterm*); @@ -165,5 +166,7 @@ int term_equals_2pow32(Eterm); Eterm erts_uint64_to_big(Uint64, Eterm **); Eterm erts_sint64_to_big(Sint64, Eterm **); +Eterm erts_chars_to_integer(Process *, char*, Uint, const int); + #endif diff --git a/erts/emulator/beam/binary.c b/erts/emulator/beam/binary.c index dad13f1067..33abac2f3d 100644 --- a/erts/emulator/beam/binary.c +++ b/erts/emulator/beam/binary.c @@ -240,6 +240,98 @@ erts_bin_bytes_to_list(Eterm previous, Eterm* hp, byte* bytes, Uint size, Uint b return previous; } +BIF_RETTYPE binary_to_integer_1(BIF_ALIST_1) +{ + byte *temp_alloc = NULL; + char *bytes; + Uint size; + Eterm res; + + if ((bytes = (char*)erts_get_aligned_binary_bytes(BIF_ARG_1, &temp_alloc)) + == NULL ) + goto binary_to_integer_1_error; + + size = binary_size(BIF_ARG_1); + + if ((res = erts_chars_to_integer(BIF_P,bytes,size,10)) != THE_NON_VALUE) { + erts_free_aligned_binary_bytes(temp_alloc); + return res; + } + + binary_to_integer_1_error: + erts_free_aligned_binary_bytes(temp_alloc); + BIF_ERROR(BIF_P, BADARG); +} + +BIF_RETTYPE binary_to_integer_2(BIF_ALIST_2) +{ + byte *temp_alloc = NULL; + char *bytes; + Uint size; + int base; + Eterm res; + + if (!is_small(BIF_ARG_2)) + BIF_ERROR(BIF_P, BADARG); + + base = signed_val(BIF_ARG_2); + + if (base < 2 || base > 36) + BIF_ERROR(BIF_P, BADARG); + + if ((bytes = (char*)erts_get_aligned_binary_bytes(BIF_ARG_1, &temp_alloc)) + == NULL ) + goto binary_to_integer_2_error; + + size = binary_size(BIF_ARG_1); + + if ((res = erts_chars_to_integer(BIF_P,bytes,size,base)) != THE_NON_VALUE) { + erts_free_aligned_binary_bytes(temp_alloc); + return res; + } + + binary_to_integer_2_error: + + erts_free_aligned_binary_bytes(temp_alloc); + BIF_ERROR(BIF_P, BADARG); + +} + +BIF_RETTYPE integer_to_binary_1(BIF_ALIST_1) +{ + Uint size; + Eterm res; + + if (is_not_integer(BIF_ARG_1)) { + BIF_ERROR(BIF_P, BADARG); + } + + if (is_small(BIF_ARG_1)) { + char *c; + struct Sint_buf ibuf; + + /* Enhancement: If we can calculate the buffer size exactly + * we could avoid an unnecessary copy of buffers. + * Useful if size determination is faster than a copy. + */ + c = Sint_to_buf(signed_val(BIF_ARG_1), &ibuf); + size = sys_strlen(c); + res = new_binary(BIF_P, (byte *)c, size); + } else { + byte* bytes; + Uint n = 0; + + /* Here we also have multiple copies of buffers + * due to new_binary interface + */ + size = big_decimal_estimate(BIF_ARG_1) - 1; /* remove null */ + bytes = (byte*) erts_alloc(ERTS_ALC_T_TMP, sizeof(byte)*size); + n = erts_big_to_binary_bytes(BIF_ARG_1, (char *)bytes, size); + res = new_binary(BIF_P, bytes + size - n, n); + erts_free(ERTS_ALC_T_TMP, (void *) bytes); + } + BIF_RET(res); +} BIF_RETTYPE binary_to_list_1(BIF_ALIST_1) { diff --git a/erts/emulator/test/hash_SUITE.erl b/erts/emulator/test/hash_SUITE.erl index 830ed91da9..ee7a9fb9de 100644 --- a/erts/emulator/test/hash_SUITE.erl +++ b/erts/emulator/test/hash_SUITE.erl @@ -253,7 +253,7 @@ spread_test(N) -> integer_to_bytelist(X,[]) end), ?line test_fun(N,{erlang,phash},16#50000000000,fun(X) -> - integer_to_binary(X) + integer_to_binary_value(X) end). @@ -711,7 +711,7 @@ collect_hits() -> init_table(), N. -integer_to_binary(N) -> +integer_to_binary_value(N) -> list_to_binary(lists:reverse(integer_to_bytelist(N,[]))). integer_to_bytelist(0,Acc) -> diff --git a/erts/emulator/test/num_bif_SUITE.erl b/erts/emulator/test/num_bif_SUITE.erl index c625e655ce..92ef456fe8 100644 --- a/erts/emulator/test/num_bif_SUITE.erl +++ b/erts/emulator/test/num_bif_SUITE.erl @@ -31,19 +31,23 @@ %% list_to_integer/1 %% round/1 %% trunc/1 - --export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, - init_per_group/2,end_per_group/2, t_abs/1, t_float/1, - t_float_to_list/1, t_integer_to_list/1, - t_list_to_integer/1, +%% integer_to_binary/1 +%% integer_to_binary/2 +%% binary_to_integer/1 + +-export([all/0, suite/0, groups/0, init_per_suite/1, end_per_suite/1, + init_per_group/2, end_per_group/2, t_abs/1, t_float/1, + t_float_to_list/1, t_integer_to_string/1, + t_string_to_integer/1, t_list_to_float_safe/1, t_list_to_float_risky/1, - t_round/1, t_trunc/1]). + t_round/1, t_trunc/1 + ]). suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> - [t_abs, t_float, t_float_to_list, t_integer_to_list, - {group, t_list_to_float}, t_list_to_integer, t_round, + [t_abs, t_float, t_float_to_list, t_integer_to_string, + {group, t_list_to_float}, t_string_to_integer, t_round, t_trunc]. groups() -> @@ -65,53 +69,46 @@ end_per_group(_GroupName, Config) -> t_abs(Config) when is_list(Config) -> %% Floats. - ?line 5.5 = abs(id(5.5)), - ?line 0.0 = abs(id(0.0)), - ?line 100.0 = abs(id(-100.0)), + 5.5 = abs(id(5.5)), + 0.0 = abs(id(0.0)), + 100.0 = abs(id(-100.0)), %% Integers. - ?line 5 = abs(id(5)), - ?line 0 = abs(id(0)), - ?line 100 = abs(id(-100)), + 5 = abs(id(5)), + 0 = abs(id(0)), + 100 = abs(id(-100)), %% The largest smallnum. OTP-3190. - ?line X = id((1 bsl 27) - 1), - ?line X = abs(X), - ?line X = abs(X-1)+1, - ?line X = abs(X+1)-1, - ?line X = abs(-X), - ?line X = abs(-X-1)-1, - ?line X = abs(-X+1)+1, + X = id((1 bsl 27) - 1), + X = abs(X), + X = abs(X-1)+1, + X = abs(X+1)-1, + X = abs(-X), + X = abs(-X-1)-1, + X = abs(-X+1)+1, %% Bignums. BigNum = id(13984792374983749), - ?line BigNum = abs(BigNum), - ?line BigNum = abs(-BigNum), + BigNum = abs(BigNum), + BigNum = abs(-BigNum), ok. t_float(Config) when is_list(Config) -> - ?line 0.0 = float(id(0)), - ?line 2.5 = float(id(2.5)), - ?line 0.0 = float(id(0.0)), - ?line -100.55 = float(id(-100.55)), - ?line 42.0 = float(id(42)), - ?line -100.0 = float(id(-100)), + 0.0 = float(id(0)), + 2.5 = float(id(2.5)), + 0.0 = float(id(0.0)), + -100.55 = float(id(-100.55)), + 42.0 = float(id(42)), + -100.0 = float(id(-100)), %% Bignums. - ?line 4294967305.0 = float(id(4294967305)), - ?line -4294967305.0 = float(id(-4294967305)), + 4294967305.0 = float(id(4294967305)), + -4294967305.0 = float(id(-4294967305)), %% Extremly big bignums. - ?line Big = id(list_to_integer(id(lists:duplicate(2000, $1)))), - ?line {'EXIT', {badarg, _}} = (catch float(Big)), - - %% Invalid types and lists. - ?line {'EXIT', {badarg, _}} = (catch list_to_integer(id(atom))), - ?line {'EXIT', {badarg, _}} = (catch list_to_integer(id(123))), - ?line {'EXIT', {badarg, _}} = (catch list_to_integer(id([$1,[$2]]))), - ?line {'EXIT', {badarg, _}} = (catch list_to_integer(id("1.2"))), - ?line {'EXIT', {badarg, _}} = (catch list_to_integer(id("a"))), - ?line {'EXIT', {badarg, _}} = (catch list_to_integer(id(""))), + Big = id(list_to_integer(id(lists:duplicate(2000, $1)))), + {'EXIT', {badarg, _}} = (catch float(Big)), + ok. @@ -193,37 +190,21 @@ remove_zeros([Char|Rest], Result) -> remove_zeros([], Result) -> Result. -%% Tests integer_to_list/1. - -t_integer_to_list(Config) when is_list(Config) -> - ?line "0" = integer_to_list(id(0)), - ?line "42" = integer_to_list(id(42)), - ?line "-42" = integer_to_list(id(-42)), - ?line "32768" = integer_to_list(id(32768)), - ?line "268435455" = integer_to_list(id(268435455)), - ?line "-268435455" = integer_to_list(id(-268435455)), - ?line "123456932798748738738" = integer_to_list(id(123456932798748738738)), - ?line Big_List = id(lists:duplicate(2000, id($1))), - ?line Big = list_to_integer(Big_List), - ?line Big_List = integer_to_list(Big), - ok. - %% Tests list_to_float/1. - t_list_to_float_safe(Config) when is_list(Config) -> - ?line 0.0 = list_to_float(id("0.0")), - ?line 0.0 = list_to_float(id("-0.0")), - ?line 0.5 = list_to_float(id("0.5")), - ?line -0.5 = list_to_float(id("-0.5")), - ?line 100.0 = list_to_float(id("1.0e2")), - ?line 127.5 = list_to_float(id("127.5")), - ?line -199.5 = list_to_float(id("-199.5")), - - ?line {'EXIT',{badarg,_}} = (catch list_to_float(id("0"))), - ?line {'EXIT',{badarg,_}} = (catch list_to_float(id("0..0"))), - ?line {'EXIT',{badarg,_}} = (catch list_to_float(id("0e12"))), - ?line {'EXIT',{badarg,_}} = (catch list_to_float(id("--0.0"))), + 0.0 = list_to_float(id("0.0")), + 0.0 = list_to_float(id("-0.0")), + 0.5 = list_to_float(id("0.5")), + -0.5 = list_to_float(id("-0.5")), + 100.0 = list_to_float(id("1.0e2")), + 127.5 = list_to_float(id("127.5")), + -199.5 = list_to_float(id("-199.5")), + + {'EXIT',{badarg,_}} = (catch list_to_float(id("0"))), + {'EXIT',{badarg,_}} = (catch list_to_float(id("0..0"))), + {'EXIT',{badarg,_}} = (catch list_to_float(id("0e12"))), + {'EXIT',{badarg,_}} = (catch list_to_float(id("--0.0"))), ok. @@ -231,107 +212,214 @@ t_list_to_float_safe(Config) when is_list(Config) -> %% (Known to crash the Unix version of Erlang 4.4.1) t_list_to_float_risky(Config) when is_list(Config) -> - ?line Many_Ones = lists:duplicate(25000, id($1)), - ?line id(list_to_float("2."++Many_Ones)), - ?line {'EXIT', {badarg, _}} = (catch list_to_float("2"++Many_Ones)), - ok. - -%% Tests list_to_integer/1. - -t_list_to_integer(Config) when is_list(Config) -> - ?line 0 = list_to_integer(id("0")), - ?line 0 = list_to_integer(id("00")), - ?line 0 = list_to_integer(id("-0")), - ?line 1 = list_to_integer(id("1")), - ?line -1 = list_to_integer(id("-1")), - ?line 42 = list_to_integer(id("42")), - ?line -12 = list_to_integer(id("-12")), - ?line 32768 = list_to_integer(id("32768")), - ?line 268435455 = list_to_integer(id("268435455")), - ?line -268435455 = list_to_integer(id("-268435455")), - - %% Bignums. - ?line 123456932798748738738 = list_to_integer(id("123456932798748738738")), - ?line id(list_to_integer(lists:duplicate(2000, id($1)))), + Many_Ones = lists:duplicate(25000, id($1)), + id(list_to_float("2."++Many_Ones)), + {'EXIT', {badarg, _}} = (catch list_to_float("2"++Many_Ones)), ok. %% Tests round/1. t_round(Config) when is_list(Config) -> - ?line 0 = round(id(0.0)), - ?line 0 = round(id(0.4)), - ?line 1 = round(id(0.5)), - ?line 0 = round(id(-0.4)), - ?line -1 = round(id(-0.5)), - ?line 255 = round(id(255.3)), - ?line 256 = round(id(255.6)), - ?line -1033 = round(id(-1033.3)), - ?line -1034 = round(id(-1033.6)), + 0 = round(id(0.0)), + 0 = round(id(0.4)), + 1 = round(id(0.5)), + 0 = round(id(-0.4)), + -1 = round(id(-0.5)), + 255 = round(id(255.3)), + 256 = round(id(255.6)), + -1033 = round(id(-1033.3)), + -1034 = round(id(-1033.6)), % OTP-3722: - ?line X = id((1 bsl 27) - 1), - ?line MX = -X, - ?line MXm1 = -X-1, - ?line MXp1 = -X+1, - ?line F = id(X + 0.0), - ?line X = round(F), - ?line X = round(F+1)-1, - ?line X = round(F-1)+1, - ?line MX = round(-F), - ?line MXm1 = round(-F-1), - ?line MXp1 = round(-F+1), - - ?line X = round(F+0.1), - ?line X = round(F+1+0.1)-1, - ?line X = round(F-1+0.1)+1, - ?line MX = round(-F+0.1), - ?line MXm1 = round(-F-1+0.1), - ?line MXp1 = round(-F+1+0.1), - - ?line X = round(F-0.1), - ?line X = round(F+1-0.1)-1, - ?line X = round(F-1-0.1)+1, - ?line MX = round(-F-0.1), - ?line MXm1 = round(-F-1-0.1), - ?line MXp1 = round(-F+1-0.1), - - ?line 0.5 = abs(round(F+0.5)-(F+0.5)), - ?line 0.5 = abs(round(F-0.5)-(F-0.5)), - ?line 0.5 = abs(round(-F-0.5)-(-F-0.5)), - ?line 0.5 = abs(round(-F+0.5)-(-F+0.5)), + X = id((1 bsl 27) - 1), + MX = -X, + MXm1 = -X-1, + MXp1 = -X+1, + F = id(X + 0.0), + X = round(F), + X = round(F+1)-1, + X = round(F-1)+1, + MX = round(-F), + MXm1 = round(-F-1), + MXp1 = round(-F+1), + + X = round(F+0.1), + X = round(F+1+0.1)-1, + X = round(F-1+0.1)+1, + MX = round(-F+0.1), + MXm1 = round(-F-1+0.1), + MXp1 = round(-F+1+0.1), + + X = round(F-0.1), + X = round(F+1-0.1)-1, + X = round(F-1-0.1)+1, + MX = round(-F-0.1), + MXm1 = round(-F-1-0.1), + MXp1 = round(-F+1-0.1), + + 0.5 = abs(round(F+0.5)-(F+0.5)), + 0.5 = abs(round(F-0.5)-(F-0.5)), + 0.5 = abs(round(-F-0.5)-(-F-0.5)), + 0.5 = abs(round(-F+0.5)-(-F+0.5)), %% Bignums. - ?line 4294967296 = round(id(4294967296.1)), - ?line 4294967297 = round(id(4294967296.9)), - ?line -4294967296 = -round(id(4294967296.1)), - ?line -4294967297 = -round(id(4294967296.9)), + 4294967296 = round(id(4294967296.1)), + 4294967297 = round(id(4294967296.9)), + -4294967296 = -round(id(4294967296.1)), + -4294967297 = -round(id(4294967296.9)), ok. t_trunc(Config) when is_list(Config) -> - ?line 0 = trunc(id(0.0)), - ?line 5 = trunc(id(5.3333)), - ?line -10 = trunc(id(-10.978987)), + 0 = trunc(id(0.0)), + 5 = trunc(id(5.3333)), + -10 = trunc(id(-10.978987)), % The largest smallnum, converted to float (OTP-3722): - ?line X = id((1 bsl 27) - 1), - ?line F = id(X + 0.0), + X = id((1 bsl 27) - 1), + F = id(X + 0.0), io:format("X = ~p/~w/~w, F = ~p/~w/~w, trunc(F) = ~p/~w/~w~n", [X, X, binary_to_list(term_to_binary(X)), F, F, binary_to_list(term_to_binary(F)), trunc(F), trunc(F), binary_to_list(term_to_binary(trunc(F)))]), - ?line X = trunc(F), - ?line X = trunc(F+1)-1, - ?line X = trunc(F-1)+1, - ?line X = -trunc(-F), - ?line X = -trunc(-F-1)-1, - ?line X = -trunc(-F+1)+1, + X = trunc(F), + X = trunc(F+1)-1, + X = trunc(F-1)+1, + X = -trunc(-F), + X = -trunc(-F-1)-1, + X = -trunc(-F+1)+1, + + %% Bignums. + 4294967305 = trunc(id(4294967305.7)), + -4294967305 = trunc(id(-4294967305.7)), + ok. + +%% Tests integer_to_binary/1. + +t_integer_to_string(Config) when is_list(Config) -> + test_its("0",0), + test_its("42",42), + test_its("-42",-42), + test_its("32768",32768), + test_its("268435455",268435455), + test_its("-268435455",-268435455), + test_its("123456932798748738738",123456932798748738738), + + %% 1 bsl 33, just beyond 32 bit + test_its("8589934592",8589934592), + test_its("-8589934592",-8589934592), + %% 1 bsl 65, just beyond 64 bit + test_its("36893488147419103232",36893488147419103232), + test_its("-36893488147419103232",-36893488147419103232), + + %% Bignums. + BigBin = id(list_to_binary(lists:duplicate(2000, id($1)))), + Big = erlang:binary_to_integer(BigBin), + BigBin = erlang:integer_to_binary(Big), + + %% Invalid types + lists:foreach(fun(Value) -> + {'EXIT', {badarg, _}} = + (catch erlang:integer_to_binary(Value)), + {'EXIT', {badarg, _}} = + (catch erlang:integer_to_list(Value)) + end,[atom,1.2,0.0,[$1,[$2]]]), + + ok. + +test_its(List,Int) -> + Int = list_to_integer(List), + Int = binary_to_integer(list_to_binary(List)). + +%% Tests binary_to_integer/1. + +t_string_to_integer(Config) when is_list(Config) -> + 0 = erlang:binary_to_integer(id(<<"00">>)), + 0 = erlang:binary_to_integer(id(<<"-0">>)), + 0 = erlang:binary_to_integer(id(<<"+0">>)), + + test_sti(0), + test_sti(1), + test_sti(-1), + test_sti(42), + test_sti(-12), + test_sti(32768), + test_sti(268435455), + test_sti(-268435455), + + %% 1 bsl 28 - 1, just before 32 bit bignum + test_sti(1 bsl 28 - 1), + %% 1 bsl 28, just beyond 32 bit small + test_sti(1 bsl 28), + %% 1 bsl 33, just beyond 32 bit + test_sti(1 bsl 33), + %% 1 bsl 60 - 1, just before 64 bit bignum + test_sti(1 bsl 60 - 1), + %% 1 bsl 60, just beyond 64 bit small + test_sti(1 bsl 60), + %% 1 bsl 65, just beyond 64 bit + test_sti(1 bsl 65), %% Bignums. - ?line 4294967305 = trunc(id(4294967305.7)), - ?line -4294967305 = trunc(id(-4294967305.7)), + test_sti(123456932798748738738,16), + test_sti(list_to_integer(lists:duplicate(2000, $1))), + + %% unalign string + Str = <<"10">>, + UnalignStr = <<0:3, (id(Str))/binary, 0:5>>, + <<_:3, SomeStr:2/binary, _:5>> = id(UnalignStr), + 10 = erlang:binary_to_integer(SomeStr), + + %% Invalid types + lists:foreach(fun(Value) -> + {'EXIT', {badarg, _}} = + (catch binary_to_integer(Value)), + {'EXIT', {badarg, _}} = + (catch erlang:list_to_integer(Value)) + end,[atom,1.2,0.0,[$1,[$2]]]), + + % Default base error cases + lists:foreach(fun(Value) -> + {'EXIT', {badarg, _}} = + (catch erlang:binary_to_integer( + list_to_binary(Value))), + {'EXIT', {badarg, _}} = + (catch erlang:list_to_integer(Value)) + end,["1.0"," 1"," -1",""]), + + % Custom base error cases + lists:foreach(fun({Value,Base}) -> + {'EXIT', {badarg, _}} = + (catch binary_to_integer( + list_to_binary(Value),Base)), + {'EXIT', {badarg, _}} = + (catch erlang:list_to_integer(Value,Base)) + end,[{" 1",1},{" 1",37},{"2",2},{"C",11}, + {"1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111z",16}, + {"1z111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111",16}, + {"111z11111111",16}]), + ok. +test_sti(Num) -> + [begin + io:format("Testing ~p:~p",[Num,Base]), + test_sti(Num,Base) + end|| Base <- lists:seq(2,36)]. + +test_sti(Num,Base) -> + Num = list_to_integer(int2list(Num,Base),Base), + Num = -1*list_to_integer(int2list(Num*-1,Base),Base), + Num = binary_to_integer(int2bin(Num,Base),Base), + Num = -1*binary_to_integer(int2bin(Num*-1,Base),Base). + % Calling this function (which is not supposed to be inlined) prevents % the compiler from calculating the answer, so we don't test the compiler % instead of the newest runtime system. id(X) -> X. + +%% Uses the printing library to to integer_to_binary conversions. +int2bin(Int,Base) when Base < 37 -> + iolist_to_binary(int2list(Int,Base)). + +int2list(Int,Base) when Base < 37 -> + lists:flatten(io_lib:format("~."++integer_to_list(Base)++"B",[Int])). diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl index 115e1b03c4..744527aeff 100644 --- a/erts/preloaded/src/erlang.erl +++ b/erts/preloaded/src/erlang.erl @@ -36,7 +36,8 @@ -export([set_cookie/2, get_cookie/0]). -export([nodes/0]). --export([list_to_integer/2,integer_to_list/2]). +-export([integer_to_list/2]). +-export([integer_to_binary/2]). -export([flush_monitor_message/2]). -export([set_cpu_topology/1, format_cpu_topology/1]). -export([await_proc_exit/3]). @@ -73,7 +74,9 @@ -export([adler32/1, adler32/2, adler32_combine/3, append_element/2]). -export([atom_to_binary/2, atom_to_list/1, binary_part/2, binary_part/3]). --export([binary_to_atom/2, binary_to_existing_atom/2, binary_to_list/1]). +-export([binary_to_atom/2, binary_to_existing_atom/2]). +-export([binary_to_integer/1,binary_to_integer/2]). +-export([binary_to_list/1]). -export([binary_to_list/3, binary_to_term/1, binary_to_term/2]). -export([bit_size/1, bitsize/1, bitstr_to_list/1, bitstring_to_list/1]). -export([bump_reductions/1, byte_size/1, call_on_load_function/1]). @@ -91,11 +94,13 @@ -export([get_module_info/1, get_stacktrace/0, group_leader/0]). -export([group_leader/2, halt/0, halt/1, halt/2, hash/2, hibernate/3]). -export([insert_element/3]). --export([integer_to_list/1, iolist_size/1, iolist_to_binary/1]). +-export([integer_to_binary/1, integer_to_list/1]). +-export([iolist_size/1, iolist_to_binary/1]). -export([is_alive/0, is_builtin/3, is_process_alive/1, length/1, link/1]). -export([list_to_atom/1, list_to_binary/1, list_to_bitstr/1]). -export([list_to_bitstring/1, list_to_existing_atom/1, list_to_float/1]). --export([list_to_integer/1, list_to_pid/1, list_to_tuple/1, loaded/0]). +-export([list_to_integer/1, list_to_integer/2]). +-export([list_to_pid/1, list_to_tuple/1, loaded/0]). -export([localtime/0, make_ref/0, match_spec_test/3, md5/1, md5_final/1]). -export([md5_init/0, md5_update/2, module_loaded/1, monitor/2]). -export([monitor_node/2, monitor_node/3, nif_error/1, nif_error/2 @@ -317,6 +322,19 @@ binary_to_atom(_Binary, _Encoding) -> binary_to_existing_atom(_Binary, _Encoding) -> erlang:nif_error(undefined). +%% binary_to_integer/1 +-spec binary_to_integer(Binary) -> integer() when + Binary :: binary(). +binary_to_integer(_Binary) -> + erlang:nif_error(undefined). + +%% binary_to_integer/2 +-spec binary_to_integer(Binary,Base) -> integer() when + Binary :: binary(), + Base :: 2..36. +binary_to_integer(_Binary,_Base) -> + erlang:nif_error(undefined). + %% binary_to_list/1 -spec binary_to_list(Binary) -> [byte()] when Binary :: binary(). @@ -850,6 +868,12 @@ hibernate(_Module, _Function, _Args) -> insert_element(_Index, _Tuple1, _Term) -> erlang:nif_error(undefined). +%% integer_to_binary/1 +-spec integer_to_binary(Integer) -> binary() when + Integer :: integer(). +integer_to_binary(_Integer) -> + erlang:nif_error(undefined). + %% integer_to_list/1 -spec integer_to_list(Integer) -> string() when Integer :: integer(). @@ -942,6 +966,13 @@ list_to_float(_String) -> list_to_integer(_String) -> erlang:nif_error(undefined). +%% list_to_integer/2 +-spec list_to_integer(String, Base) -> integer() when + String :: string(), + Base :: 2..36. +list_to_integer(_String,_Base) -> + erlang:nif_error(undefined). + %% list_to_pid/1 -spec list_to_pid(String) -> pid() when String :: string(). @@ -2838,51 +2869,32 @@ integer_to_list(I0, Base, R0) -> integer_to_list(I1, Base, R1) end. - --spec list_to_integer(String, Base) -> integer() when - String :: string(), +-spec integer_to_binary(Integer, Base) -> binary() when + Integer :: integer(), Base :: 2..36. -list_to_integer(L, 10) -> - erlang:list_to_integer(L); -list_to_integer(L, Base) - when erlang:is_list(L), erlang:is_integer(Base), +integer_to_binary(I, 10) -> + erlang:integer_to_binary(I); +integer_to_binary(I, Base) + when erlang:is_integer(I), erlang:is_integer(Base), Base >= 2, Base =< 1+$Z-$A+10 -> - case list_to_integer_sign(L, Base) of - I when erlang:is_integer(I) -> - I; - Fault -> - erlang:error(Fault, [L,Base]) - end; -list_to_integer(L, Base) -> - erlang:error(badarg, [L,Base]). - -list_to_integer_sign([$-|[_|_]=L], Base) -> - case list_to_integer(L, Base, 0) of - I when erlang:is_integer(I) -> - -I; - I -> - I + if I < 0 -> + <<"$-",(integer_to_binary(-I, Base, []))/binary>>; + true -> + integer_to_binary(I, Base, <<>>) end; -list_to_integer_sign([$+|[_|_]=L], Base) -> - list_to_integer(L, Base, 0); -list_to_integer_sign([_|_]=L, Base) -> - list_to_integer(L, Base, 0); -list_to_integer_sign(_, _) -> - badarg. - -list_to_integer([D|L], Base, I) - when erlang:is_integer(D), D >= $0, D =< $9, D < Base+$0 -> - list_to_integer(L, Base, I*Base + D-$0); -list_to_integer([D|L], Base, I) - when erlang:is_integer(D), D >= $A, D < Base+$A-10 -> - list_to_integer(L, Base, I*Base + D-$A+10); -list_to_integer([D|L], Base, I) - when erlang:is_integer(D), D >= $a, D < Base+$a-10 -> - list_to_integer(L, Base, I*Base + D-$a+10); -list_to_integer([], _, I) -> - I; -list_to_integer(_, _, _) -> - badarg. +integer_to_binary(I, Base) -> + erlang:error(badarg, [I, Base]). + +integer_to_binary(0, _Base, R0) -> + R0; +integer_to_binary(I0, Base, R0) -> + D = I0 rem Base, + I1 = I0 div Base, + if D >= 10 -> + integer_to_binary(I1,Base,<<(D-10+$A),R0/binary>>); + true -> + integer_to_binary(I1,Base,<<(D+$0),R0/binary>>) + end. %% erlang:flush_monitor_message/2 is for internal use only! %% -- cgit v1.2.3 From 5279b3af4efee5d3e7d9755f0f06bd7b0f5dd05c Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Fri, 8 Feb 2013 18:23:22 +0100 Subject: Add float_to_binary and binary_to_float --- erts/doc/src/erlang.xml | 53 +++++++--- erts/emulator/beam/bif.c | 187 +++++++++++++++++++++++---------- erts/emulator/beam/bif.tab | 3 + erts/emulator/test/num_bif_SUITE.erl | 193 ++++++++++++++++++++--------------- erts/preloaded/src/erlang.erl | 31 +++++- 5 files changed, 313 insertions(+), 154 deletions(-) (limited to 'erts') diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml index 36d606130f..06fefa8efb 100644 --- a/erts/doc/src/erlang.xml +++ b/erts/doc/src/erlang.xml @@ -299,6 +299,18 @@

Failure: badarg if the atom does not already exist.

+ + + Convert from text representation to a float + +

Returns the float whose text representation is Binary.

+
+> binary_to_float(<<"2.2017764e+0">>).
+2.2017764
+

Failure: badarg if Binary contains a bad + representation of a float.

+
+
Convert from text representation to an integer @@ -987,26 +999,38 @@ true - + Text representation of a float -

Returns a string which corresponds to the text - representation of Float.

+

The same as float_to_binary(Float,[{scientific,20}]).

+
+
+ + + Text representation of a float formatted using given options + +

Returns a binary which corresponds to the text + representation of Float using fixed decimal + point formatting. The Options behave in the same + way as float_to_list/2. +

-> float_to_list(7.0).
-"7.00000000000000000000e+00"
+> float_to_binary(7.12, [{decimals, 4}]). +<<"7.1200">> +> float_to_binary(7.12, [{decimals, 4}, compact]). +<<"7.12">> +
+
+ + + Text representation of a float + +

The same as float_to_list(Float,[{scientific,20}]).

- float_to_list(Float, Options) -> string() + Text representation of a float formatted using given options - - Float = float() - Options = [Option] - Option = {decimals, Decimals::0..253} | - {scientific, Decimals::0..249} | - compact -

Returns a string which corresponds to the text representation of Float using fixed decimal point formatting. @@ -1019,7 +1043,8 @@ true only meaningful together with the decimals option). When scientific option is provided, the float will be formatted using scientific notation with Decimals digits of precision. If - Options is [] the function behaves like float_to_list/1. + Options is [] the function behaves like + float_to_list/1.

 > float_to_list(7.12, [{decimals, 4}]).
diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c
index a596068527..5adcf6d5c7 100644
--- a/erts/emulator/beam/bif.c
+++ b/erts/emulator/beam/bif.c
@@ -39,6 +39,7 @@
 #include "erl_thr_progress.h"
 #define ERTS_PTAB_WANT_BIF_IMPL__
 #include "erl_ptab.h"
+#include "erl_bits.h"
 
 static Export* flush_monitor_message_trap = NULL;
 static Export* set_cpu_topology_trap = NULL;
@@ -2955,29 +2956,9 @@ BIF_RETTYPE list_to_integer_2(BIF_ALIST_2)
 
 /**********************************************************************/
 
-/* convert a float to a list of ascii characters */
+static int do_float_to_charbuf(Process *p, Eterm efloat, Eterm list, 
+			char *fbuf, int sizeof_fbuf) {
 
-BIF_RETTYPE float_to_list_1(BIF_ALIST_1)
-{
-     int i;
-     Uint need;
-     Eterm* hp;
-     FloatDef f;
-     char fbuf[30];
-     
-     /* check the arguments */
-     if (is_not_float(BIF_ARG_1))
-	 BIF_ERROR(BIF_P, BADARG);
-     GET_DOUBLE(BIF_ARG_1, f);
-     if ((i = sys_double_to_chars(f.fd, fbuf, sizeof(fbuf))) <= 0)
-	 BIF_ERROR(BIF_P, EXC_INTERNAL_ERROR);
-     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;
@@ -2986,16 +2967,11 @@ BIF_RETTYPE float_to_list_2(BIF_ALIST_2)
         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))
+    if (is_not_float(efloat))
         goto badarg;
 
     for(; is_list(list); list = CDR(list_val(list))) {
@@ -3023,22 +2999,64 @@ BIF_RETTYPE float_to_list_2(BIF_ALIST_2)
         goto badarg;
     }
 
-    GET_DOUBLE(BIF_ARG_1, f);
+    GET_DOUBLE(efloat, f);
 
     if (fmt_type == FMT_FIXED) {
-        if ((i = sys_double_to_chars_fast(f.fd, fbuf, sizeof(fbuf),
-                decimals, compact)) <= 0)
-            goto badarg;
+        return sys_double_to_chars_fast(f.fd, fbuf, sizeof_fbuf,
+                decimals, compact);
     } else {
-        if ((i = sys_double_to_chars_ext(f.fd, fbuf, sizeof(fbuf), decimals)) <= 0)
-            goto badarg;
+        return sys_double_to_chars_ext(f.fd, fbuf, sizeof_fbuf, decimals);
     }
 
-    need = i*2;
-    hp = HAlloc(BIF_P, need);
-    BIF_RET(buf_to_intlist(&hp, fbuf, i, NIL));
 badarg:
+    return -1;
+}
+
+/* convert a float to a list of ascii characters */
+
+static BIF_RETTYPE do_float_to_list(Process *BIF_P, Eterm arg, Eterm opts) {
+  int used;
+  Eterm* hp;
+  char fbuf[256];
+  
+  if ((used = do_float_to_charbuf(BIF_P,arg,opts,fbuf,sizeof(fbuf))) <= 0) {
     BIF_ERROR(BIF_P, BADARG);
+  }
+  hp = HAlloc(BIF_P, (Uint)used*2);
+  BIF_RET(buf_to_intlist(&hp, fbuf, (Uint)used, NIL));
+}
+  
+
+BIF_RETTYPE float_to_list_1(BIF_ALIST_1)
+{
+  return do_float_to_list(BIF_P,BIF_ARG_1,NIL);
+}
+
+BIF_RETTYPE float_to_list_2(BIF_ALIST_2)
+{
+  return do_float_to_list(BIF_P,BIF_ARG_1,BIF_ARG_2);
+}
+
+/* convert a float to a binary of ascii characters */
+
+static BIF_RETTYPE do_float_to_binary(Process *BIF_P, Eterm arg, Eterm opts) {
+  int used;
+  char fbuf[256];
+  
+  if ((used = do_float_to_charbuf(BIF_P,arg,opts,fbuf,sizeof(fbuf))) <= 0) {
+    BIF_ERROR(BIF_P, BADARG);
+  }
+  BIF_RET(new_binary(BIF_P, (byte*)fbuf, (Uint)used));
+}
+
+BIF_RETTYPE float_to_binary_1(BIF_ALIST_1)
+{
+  return do_float_to_binary(BIF_P,BIF_ARG_1,NIL);
+}
+
+BIF_RETTYPE float_to_binary_2(BIF_ALIST_2)
+{
+  return do_float_to_binary(BIF_P,BIF_ARG_1,BIF_ARG_2);
 }
 
 /**********************************************************************/
@@ -3223,36 +3241,101 @@ BIF_RETTYPE string_to_float_1(BIF_ALIST_1)
     BIF_RET(tup);
 }
 
+static BIF_RETTYPE do_charbuf_to_float(Process *BIF_P,char *buf) {
+  FloatDef f;
+  Eterm res;
+  Eterm* hp;
+
+  if (sys_chars_to_double(buf, &f.fd) != 0)
+    BIF_ERROR(BIF_P, BADARG);
+
+  hp = HAlloc(BIF_P, FLOAT_SIZE_OBJECT);
+  res = make_float(hp);
+  PUT_DOUBLE(f, hp);
+  BIF_RET(res);
+
+}
 
 BIF_RETTYPE list_to_float_1(BIF_ALIST_1)
 {
     int i;
-    FloatDef f;
     Eterm res;
-    Eterm* hp;
     char *buf = NULL;
 
     i = list_length(BIF_ARG_1);
-    if (i < 0) {
-    badarg:
-	if (buf)
-	    erts_free(ERTS_ALC_T_TMP, (void *) buf);
-	BIF_ERROR(BIF_P, BADARG);
-    }
-
+    if (i < 0)
+      BIF_ERROR(BIF_P, BADARG);
+    
     buf = (char *) erts_alloc(ERTS_ALC_T_TMP, i + 1);
     
     if (intlist_to_buf(BIF_ARG_1, buf, i) < 0)
-	goto badarg;
+      goto list_to_float_1_error;
     buf[i] = '\0';		/* null terminal */
+    
+    if ((res = do_charbuf_to_float(BIF_P,buf)) == THE_NON_VALUE)
+      goto list_to_float_1_error;
+    
+    erts_free(ERTS_ALC_T_TMP, (void *) buf);
+    BIF_RET(res);
+    
+ list_to_float_1_error:
+    erts_free(ERTS_ALC_T_TMP, (void *) buf);
+    BIF_ERROR(BIF_P, BADARG);
+
+}
+
+BIF_RETTYPE binary_to_float_1(BIF_ALIST_1)
+{
+    Eterm res;
+    Eterm binary = BIF_ARG_1;
+    Sint size;
+    byte* bytes, *buf;
+    Eterm* real_bin;
+    Uint offs = 0;
+    Uint bit_offs = 0;
+
+    if (is_not_binary(binary) || (size = binary_size(binary)) == 0)
+      BIF_ERROR(BIF_P, BADARG);
+
+    /* 
+     *  Unfortunately we have to copy the binary because we have to insert
+     *  the '\0' at the end of the binary for strtod to work 
+     *  (there is no nstrtod :( )
+     */
+
+    buf = erts_alloc(ERTS_ALC_T_TMP, size + 1);
+
+    real_bin = binary_val(binary);
+    if (*real_bin == HEADER_SUB_BIN) {
+	ErlSubBin* sb = (ErlSubBin *) real_bin;
+	if (sb->bitsize) {
+	    goto binary_to_float_1_error;
+	}
+	offs = sb->offs;
+	bit_offs = sb->bitoffs;
+	real_bin = binary_val(sb->orig);
+    } 
+    if (*real_bin == HEADER_PROC_BIN) {
+	bytes = ((ProcBin *) real_bin)->bytes + offs;
+    } else {
+	bytes = (byte *)(&(((ErlHeapBin *) real_bin)->data)) + offs;
+    }
+    if (bit_offs)
+      erts_copy_bits(bytes, bit_offs, 1, buf, 0, 1, size*8);
+    else
+      memcpy(buf, bytes, size);
+    
+    buf[size] = '\0';
+    
+    if ((res = do_charbuf_to_float(BIF_P,(char*)buf)) == THE_NON_VALUE)
+	goto binary_to_float_1_error;
 
-    if (sys_chars_to_double(buf, &f.fd) != 0)
-	goto badarg;
-    hp = HAlloc(BIF_P, FLOAT_SIZE_OBJECT);
-    res = make_float(hp);
-    PUT_DOUBLE(f, hp);
     erts_free(ERTS_ALC_T_TMP, (void *) buf);
     BIF_RET(res);
+
+ binary_to_float_1_error:
+    erts_free(ERTS_ALC_T_TMP, (void *) buf);
+    BIF_ERROR(BIF_P, BADARG);
 }
 
 /**********************************************************************/
diff --git a/erts/emulator/beam/bif.tab b/erts/emulator/beam/bif.tab
index aa6105de73..b74dc5c3fe 100644
--- a/erts/emulator/beam/bif.tab
+++ b/erts/emulator/beam/bif.tab
@@ -565,6 +565,9 @@ bif erlang:binary_to_integer/1
 bif erlang:binary_to_integer/2
 bif erlang:integer_to_binary/1
 bif erlang:list_to_integer/2
+bif erlang:float_to_binary/1
+bif erlang:float_to_binary/2
+bif erlang:binary_to_float/1
 
 #
 # Obsolete
diff --git a/erts/emulator/test/num_bif_SUITE.erl b/erts/emulator/test/num_bif_SUITE.erl
index 92ef456fe8..b92a0e2059 100644
--- a/erts/emulator/test/num_bif_SUITE.erl
+++ b/erts/emulator/test/num_bif_SUITE.erl
@@ -37,22 +37,22 @@
 
 -export([all/0, suite/0, groups/0, init_per_suite/1, end_per_suite/1, 
 	 init_per_group/2, end_per_group/2, t_abs/1, t_float/1,
-	 t_float_to_list/1, t_integer_to_string/1,
+	 t_float_to_string/1, t_integer_to_string/1,
 	 t_string_to_integer/1,
-	 t_list_to_float_safe/1, t_list_to_float_risky/1,
+	 t_string_to_float_safe/1, t_string_to_float_risky/1,
 	 t_round/1, t_trunc/1
      ]).
 
 suite() -> [{ct_hooks,[ts_install_cth]}].
 
 all() -> 
-    [t_abs, t_float, t_float_to_list, t_integer_to_string,
-     {group, t_list_to_float}, t_string_to_integer, t_round,
+    [t_abs, t_float, t_float_to_string, t_integer_to_string,
+     {group, t_string_to_float}, t_string_to_integer, t_round,
      t_trunc].
 
 groups() -> 
-    [{t_list_to_float, [],
-      [t_list_to_float_safe, t_list_to_float_risky]}].
+    [{t_string_to_float, [],
+      [t_string_to_float_safe, t_string_to_float_risky]}].
 
 init_per_suite(Config) ->
     Config.
@@ -112,111 +112,136 @@ t_float(Config) when is_list(Config) ->
     ok.
 
 
-%% Tests float_to_list/1, float_to_list/2.
-
-t_float_to_list(Config) when is_list(Config) ->
-    test_ftl("0.0e+0", 0.0),
-    test_ftl("2.5e+1", 25.0),
-    test_ftl("2.5e+0", 2.5),
-    test_ftl("2.5e-1", 0.25),
-    test_ftl("-3.5e+17", -350.0e15),
-    "1.00000000000000000000e+00"  = float_to_list(1.0),
-    "1.00000000000000000000e+00"  = float_to_list(1.0,  []),
-    "-1.00000000000000000000e+00" = float_to_list(-1.0, []),
-    "-1.00000000000000000000"     = float_to_list(-1.0, [{decimals, 20}]),
-    {'EXIT', {badarg, _}}         = (catch float_to_list(1.0,  [{decimals, -1}])),
-    {'EXIT', {badarg, _}}         = (catch float_to_list(1.0,  [{decimals, 254}])),
-    {'EXIT', {badarg, _}}         = (catch float_to_list(1.0,  [{scientific, 250}])),
-    {'EXIT', {badarg, _}}         = (catch float_to_list(1.0e+300, [{decimals, 1}])),
-    "1.0e+300"                    = float_to_list(1.0e+300, [{scientific, 1}]),
-    "1.0"                         = float_to_list(1.0, [{decimals, 249}, compact]),
-    "1"                           = float_to_list(1.0, [{decimals, 0}]),
-    "2"                           = float_to_list(1.9, [{decimals, 0}]),
-    "123456789012345680.0"        = erlang:float_to_list(
-                                        123456789012345678.0, [{decimals, 236}, compact]),
-    {'EXIT', {badarg, _}}         = (catch float_to_list(
-                                        123456789012345678.0, [{decimals, 237}])),
-    Expected = "1." ++ string:copies("0", 249) ++ "e+00",
-    Expected = float_to_list(1.0,  [{scientific, 249}, compact]),
+%% Tests float_to_list/1, float_to_list/2, float_to_binary/1, float_to_binary/2
+
+t_float_to_string(Config) when is_list(Config) ->
+    test_fts("0.00000000000000000000e+00", 0.0),
+    test_fts("2.50000000000000000000e+01", 25.0),
+    test_fts("2.50000000000000000000e+00", 2.5),
+    test_fts("2.50000000000000000000e-01", 0.25),
+    test_fts("-3.50000000000000000000e+17", -350.0e15),
+    test_fts("1.00000000000000000000e+00",1.0),
+    test_fts("1.00000000000000000000e+00",1.0,  []),
+    test_fts("-1.00000000000000000000e+00",-1.0, []),
+    test_fts("-1.00000000000000000000",-1.0, [{decimals, 20}]),
+    {'EXIT', {badarg, _}} = (catch float_to_list(1.0,  [{decimals, -1}])),
+    {'EXIT', {badarg, _}} = (catch float_to_list(1.0,  [{decimals, 254}])),
+    {'EXIT', {badarg, _}} = (catch float_to_list(1.0,  [{scientific, 250}])),
+    {'EXIT', {badarg, _}} = (catch float_to_list(1.0e+300, [{decimals, 1}])),
+    {'EXIT', {badarg, _}} = (catch float_to_binary(1.0,  [{decimals, -1}])),
+    {'EXIT', {badarg, _}} = (catch float_to_binary(1.0,  [{decimals, 254}])),
+    {'EXIT', {badarg, _}} = (catch float_to_binary(1.0,  [{scientific, 250}])),
+    {'EXIT', {badarg, _}} = (catch float_to_binary(1.0e+300, [{decimals, 1}])),
+    test_fts("1.0e+300",1.0e+300, [{scientific, 1}]),
+    test_fts("1.0",1.0,  [{decimals,   249}, compact]),
+    test_fts("1",1.0,[{decimals,0}]),
+    test_fts("2",1.9,[{decimals,0}]),
+    test_fts("123456789012345680.0",123456789012345678.0,
+	     [{decimals, 236}, compact]),
+    {'EXIT', {badarg, _}} = (catch float_to_list(
+				     123456789012345678.0, [{decimals, 237}])),
+    {'EXIT', {badarg, _}} = (catch float_to_binary(
+				     123456789012345678.0, [{decimals, 237}])),
+    test_fts("1." ++ string:copies("0", 249) ++ "e+00",
+	     1.0,  [{scientific, 249}, compact]),
 
     X1 = float_to_list(1.0),
     X2 = float_to_list(1.0, [{scientific, 20}]),
     X1 = X2,
-    "1.000e+00" = float_to_list(1.0,   [{scientific, 3}]),
-    "1.000"     = float_to_list(1.0,   [{decimals, 3}]),
-    "1.0"       = float_to_list(1.0,   [{decimals, 1}]),
-    "1.0"       = float_to_list(1.0,   [{decimals, 3}, compact]),
-    "1.12"      = float_to_list(1.123, [{decimals, 2}]),
-    "1.123"     = float_to_list(1.123, [{decimals, 3}]),
-    "1.123"     = float_to_list(1.123, [{decimals, 3}, compact]),
-    "1.1230"    = float_to_list(1.123, [{decimals, 4}]),
-    "1.12300"   = float_to_list(1.123, [{decimals, 5}]),
-    "1.123"     = float_to_list(1.123, [{decimals, 5}, compact]),
-    "1.1234"    = float_to_list(1.1234,[{decimals, 6}, compact]),
-    "1.01"      = float_to_list(1.005, [{decimals, 2}]),
-    "-1.01"     = float_to_list(-1.005,[{decimals, 2}]),
-    "0.999"     = float_to_list(0.999, [{decimals, 3}]),
-    "-0.999"    = float_to_list(-0.999,[{decimals, 3}]),
-    "1.0"       = float_to_list(0.999, [{decimals, 2}, compact]),
-    "-1.0"      = float_to_list(-0.999,[{decimals, 2}, compact]),
-    "0.5"       = float_to_list(0.5,   [{decimals, 1}]),
-    "-0.5"      = float_to_list(-0.5,  [{decimals, 1}]),
+
+    Y1 = float_to_binary(1.0),
+    Y2 = float_to_binary(1.0, [{scientific, 20}]),
+    Y1 = Y2,
+
+    test_fts("1.000e+00",1.0,   [{scientific, 3}]),
+    test_fts("1.000",1.0,   [{decimals,   3}]),
+    test_fts("1.0",1.0, [{decimals, 1}]),
+    test_fts("1.0",1.0, [{decimals, 3}, compact]),
+    test_fts("1.12",1.123, [{decimals, 2}]),
+    test_fts("1.123",1.123, [{decimals, 3}]),
+    test_fts("1.123",1.123, [{decimals, 3}, compact]),
+    test_fts("1.1230",1.123, [{decimals, 4}]),
+    test_fts("1.12300",1.123, [{decimals, 5}]),
+    test_fts("1.123",1.123, [{decimals, 5}, compact]),
+    test_fts("1.1234",1.1234,[{decimals, 6}, compact]),
+    test_fts("1.01",1.005, [{decimals, 2}]),
+    test_fts("-1.01",-1.005,[{decimals, 2}]),
+    test_fts("0.999",0.999, [{decimals, 3}]),
+    test_fts("-0.999",-0.999,[{decimals, 3}]),
+    test_fts("1.0",0.999, [{decimals, 2}, compact]),
+    test_fts("-1.0",-0.999,[{decimals, 2}, compact]),
+    test_fts("0.5",0.5,   [{decimals, 1}]),
+    test_fts("-0.5",-0.5,  [{decimals, 1}]),
     "2.333333"  = erlang:float_to_list(7/3, [{decimals, 6}, compact]),
     "2.333333"  = erlang:float_to_list(7/3, [{decimals, 6}]),
-    "0.00000000000000000000e+00" = float_to_list(0.0, [compact]),
-    "0.0"       = float_to_list(0.0,   [{decimals, 10}, compact]),
-    "123000000000000000000.0"    = float_to_list(1.23e20, [{decimals,   10}, compact]),
-    "1.2300000000e+20"           = float_to_list(1.23e20, [{scientific, 10}, compact]),
-    "1.23000000000000000000e+20" = float_to_list(1.23e20, []),
+    <<"2.333333">>  = erlang:float_to_binary(7/3, [{decimals, 6}, compact]),
+    <<"2.333333">>  = erlang:float_to_binary(7/3, [{decimals, 6}]),
+    test_fts("0.00000000000000000000e+00",0.0, [compact]),
+    test_fts("0.0",0.0,   [{decimals, 10}, compact]),
+    test_fts("123000000000000000000.0",1.23e20, [{decimals,   10}, compact]),
+    test_fts("1.2300000000e+20",1.23e20, [{scientific, 10}, compact]),
+    test_fts("1.23000000000000000000e+20",1.23e20, []),
     ok.
     
-test_ftl(Expect, Float) ->
-    %% No ?line on the next line -- we want the line number from t_float_to_list.
-    Expect = remove_zeros(lists:reverse(float_to_list(Float)), []).
-
-%% Removes any non-significant zeros in a floating point number.
-%% Example: 2.500000e+01 -> 2.5e+1
-
-remove_zeros([$+, $e|Rest], [$0, X|Result]) ->
-    remove_zeros([$+, $e|Rest], [X|Result]);
-remove_zeros([$-, $e|Rest], [$0, X|Result]) ->
-    remove_zeros([$-, $e|Rest], [X|Result]);
-remove_zeros([$0, $.|Rest], [$e|Result]) ->
-    remove_zeros(Rest, [$., $0, $e|Result]);
-remove_zeros([$0|Rest], [$e|Result]) ->
-    remove_zeros(Rest, [$e|Result]);
-remove_zeros([Char|Rest], Result) ->
-    remove_zeros(Rest, [Char|Result]);
-remove_zeros([], Result) ->
-    Result.
+test_fts(Expect, Float) ->
+    Expect = float_to_list(Float),
+    BinExpect = list_to_binary(Expect),
+    BinExpect = float_to_binary(Float).
+
+test_fts(Expect, Float, Args) ->
+    Expect = float_to_list(Float,Args),
+    BinExpect = list_to_binary(Expect),
+    BinExpect = float_to_binary(Float,Args).
+
 
 %% Tests list_to_float/1.
 
-t_list_to_float_safe(Config) when is_list(Config) ->
-    0.0 = list_to_float(id("0.0")),
-    0.0 = list_to_float(id("-0.0")),
-    0.5 = list_to_float(id("0.5")),
-    -0.5 = list_to_float(id("-0.5")),
-    100.0 = list_to_float(id("1.0e2")),
-    127.5 = list_to_float(id("127.5")),
-    -199.5 = list_to_float(id("-199.5")),
+t_string_to_float_safe(Config) when is_list(Config) ->
+    test_stf(0.0,"0.0"),
+    test_stf(0.0,"-0.0"),
+    test_stf(0.5,"0.5"),
+    test_stf(-0.5,"-0.5"),
+    test_stf(100.0,"1.0e2"),
+    test_stf(127.5,"127.5"),
+    test_stf(-199.5,"-199.5"),
 
     {'EXIT',{badarg,_}} = (catch list_to_float(id("0"))),
     {'EXIT',{badarg,_}} = (catch list_to_float(id("0..0"))),
     {'EXIT',{badarg,_}} = (catch list_to_float(id("0e12"))),
     {'EXIT',{badarg,_}} = (catch list_to_float(id("--0.0"))),
+    {'EXIT',{badarg,_}} = (catch binary_to_float(id(<<"0">>))),
+    {'EXIT',{badarg,_}} = (catch binary_to_float(id(<<"0..0">>))),
+    {'EXIT',{badarg,_}} = (catch binary_to_float(id(<<"0e12">>))),
+    {'EXIT',{badarg,_}} = (catch binary_to_float(id(<<"--0.0">>))),
+
+    UBin = <<0:3,(id(<<"0.0">>))/binary,0:5>>,
+    <<_:3,UnAlignedBin:3/binary,0:5>> = id(UBin),
+    0.0 = binary_to_float(UnAlignedBin),
+
+    ABin = <<0:8,(id(<<"1.0">>))/binary,0:8>>,
+    <<_:8,AlignedBin:3/binary,0:8>> = id(ABin),
+    1.0 = binary_to_float(AlignedBin),
 
     ok.
 
 %% This might crash the emulator...
 %% (Known to crash the Unix version of Erlang 4.4.1)
 
-t_list_to_float_risky(Config) when is_list(Config) ->
+t_string_to_float_risky(Config) when is_list(Config) ->
     Many_Ones = lists:duplicate(25000, id($1)),
     id(list_to_float("2."++Many_Ones)),
     {'EXIT', {badarg, _}} = (catch list_to_float("2"++Many_Ones)),
+
+    id(binary_to_float(list_to_binary("2."++Many_Ones))),
+    {'EXIT', {badarg, _}} = (catch binary_to_float(
+				     list_to_binary("2"++Many_Ones))),
     ok.
 
+test_stf(Expect,List) ->
+    Expect = list_to_float(List),
+    Bin = list_to_binary(List),
+    Expect = binary_to_float(Bin).
+
 %% Tests round/1.
 
 t_round(Config) when is_list(Config) ->
diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl
index 744527aeff..8e4a471a82 100644
--- a/erts/preloaded/src/erlang.erl
+++ b/erts/preloaded/src/erlang.erl
@@ -74,7 +74,7 @@
 
 -export([adler32/1, adler32/2, adler32_combine/3, append_element/2]).
 -export([atom_to_binary/2, atom_to_list/1, binary_part/2, binary_part/3]).
--export([binary_to_atom/2, binary_to_existing_atom/2]).
+-export([binary_to_atom/2, binary_to_existing_atom/2, binary_to_float/1]).
 -export([binary_to_integer/1,binary_to_integer/2]).
 -export([binary_to_list/1]).
 -export([binary_to_list/3, binary_to_term/1, binary_to_term/2]).
@@ -87,7 +87,8 @@
 -export([display_nl/0, display_string/1, dist_exit/3, erase/0, erase/1]).
 -export([error/1, error/2, exit/1, exit/2, external_size/1]).
 -export([external_size/2, finish_after_on_load/2, finish_loading/1, float/1]).
--export([float_to_list/1, float_to_list/2]).
+-export([float_to_binary/1, float_to_binary/2,
+	 float_to_list/1, float_to_list/2]).
 -export([fun_info/2, fun_to_list/1, function_exported/3]).
 -export([garbage_collect/0, garbage_collect/1]).
 -export([garbage_collect_message_area/0, get/0, get/1, get_keys/1]).
@@ -322,6 +323,12 @@ binary_to_atom(_Binary, _Encoding) ->
 binary_to_existing_atom(_Binary, _Encoding) ->
     erlang:nif_error(undefined).
 
+%% binary_to_float/1
+-spec binary_to_float(Binary) -> float() when
+      Binary :: binary().
+binary_to_float(_Binary) ->
+    erlang:nif_error(undefined).
+
 %% binary_to_integer/1
 -spec binary_to_integer(Binary) -> integer() when
       Binary :: binary().
@@ -724,6 +731,22 @@ finish_after_on_load(_P1, _P2) ->
 float(_Number) ->
     erlang:nif_error(undefined).
 
+%% float_to_binary/1
+-spec float_to_binary(Float) -> binary() when
+      Float :: float().
+float_to_binary(_Float) ->
+    erlang:nif_error(undefined).
+
+%% float_to_binary/2
+-spec float_to_binary(Float, Options) -> binary() when
+      Float :: float(),
+      Options :: [Option],
+      Option  :: {decimals, Decimals :: 0..253} |
+                 {scientific, Decimals :: 0..249} |
+                 compact.
+float_to_binary(_Float, _Options) ->
+    erlang:nif_error(undefined).
+
 %% float_to_list/1
 -spec float_to_list(Float) -> string() when
       Float :: float().
@@ -734,8 +757,8 @@ float_to_list(_Float) ->
 -spec float_to_list(Float, Options) -> string() when
       Float :: float(),
       Options :: [Option],
-      Option  :: {decimals, non_neg_integer()} |
-                 {scientific, non_neg_integer()} |
+      Option  :: {decimals, Decimals :: 0..253} |
+                 {scientific, Decimals :: 0..249} |
                  compact.
 float_to_list(_Float, _Options) ->
     erlang:nif_error(undefined).
-- 
cgit v1.2.3


From 2f3526bb1c4c915a8528cd7d36c3a5b793e0ca3f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= 
Date: Tue, 11 Sep 2012 12:01:12 +0200
Subject: erts: Remove ?line macro from hash_SUITE

---
 erts/emulator/test/hash_SUITE.erl | 84 +++++++++++++++++++--------------------
 1 file changed, 42 insertions(+), 42 deletions(-)

(limited to 'erts')

diff --git a/erts/emulator/test/hash_SUITE.erl b/erts/emulator/test/hash_SUITE.erl
index ee7a9fb9de..898eae8c15 100644
--- a/erts/emulator/test/hash_SUITE.erl
+++ b/erts/emulator/test/hash_SUITE.erl
@@ -75,7 +75,7 @@ config(priv_dir,_) ->
 	 test_phash2/1,otp_5292/1,bit_level_binaries/1,otp_7127/1,
 	 end_per_testcase/2,init_per_testcase/2]).
 init_per_testcase(_Case, Config) ->
-    ?line Dog=test_server:timetrap(test_server:minutes(10)),
+    Dog=test_server:timetrap(test_server:minutes(10)),
     [{watchdog, Dog}|Config].
  
 end_per_testcase(_Case, Config) ->
@@ -169,24 +169,24 @@ otp_7127(Config) when is_list(Config) ->
 %% define -DSTANDALONE when compiling.
 %%
 basic_test() ->
-    ?line 685556714 = erlang:phash({a,b,c},16#FFFFFFFF),
-    ?line 14468079 = erlang:hash({a,b,c},16#7FFFFFF),
-    ?line 37442646 =  erlang:phash([a,b,c,{1,2,3},c:pid(0,2,3),
+    685556714 = erlang:phash({a,b,c},16#FFFFFFFF),
+    14468079 = erlang:hash({a,b,c},16#7FFFFFF),
+    37442646 =  erlang:phash([a,b,c,{1,2,3},c:pid(0,2,3),
 				    16#77777777777777],16#FFFFFFFF),
-    ?line Comment = case erlang:hash([a,b,c,{1,2,3},c:pid(0,2,3),
+    Comment = case erlang:hash([a,b,c,{1,2,3},c:pid(0,2,3),
 				      16#77777777777777],16#7FFFFFF) of
 			102727602 ->
-			    ?line big = erlang:system_info(endian),
+			    big = erlang:system_info(endian),
 			    "Big endian machine";
 			105818829 ->
-			    ?line little = erlang:system_info(endian),
+			    little = erlang:system_info(endian),
 			    "Little endian machine"
 		    end,
     ExternalReference = <<131,114,0,3,100,0,13,110,111,110,111,100,101,64,
 			 110,111,104,111,115,116,0,0,0,0,122,0,0,0,0,0,0,0,0>>,
-    ?line 1113403635 = erlang:phash(binary_to_term(ExternalReference),
+    1113403635 = erlang:phash(binary_to_term(ExternalReference),
 				    16#FFFFFFFF),
-    ?line 123 = erlang:hash(binary_to_term(ExternalReference),
+    123 = erlang:hash(binary_to_term(ExternalReference),
 			    16#7FFFFFF),
     ExternalFun = <<131,117,0,0,0,3,103,100,0,13,110,111,110,111,100,101,64,
 		   110,111,104,111,115,116,0,0,0,38,0,0,0,0,0,100,0,8,101,
@@ -204,9 +204,9 @@ basic_test() ->
 		   104,101,108,108,100,0,10,108,111,99,97,108,95,102,117,
 		   110,99,108,0,0,0,1,103,100,0,13,110,111,110,111,100,101,
 		   64,110,111,104,111,115,116,0,0,0,22,0,0,0,0,0,106>>,
-    ?line 170987488 = erlang:phash(binary_to_term(ExternalFun),
+    170987488 = erlang:phash(binary_to_term(ExternalFun),
 				   16#FFFFFFFF),
-    ?line 124460689 = erlang:hash(binary_to_term(ExternalFun),
+    124460689 = erlang:hash(binary_to_term(ExternalFun),
 				  16#7FFFFFF),
     case (catch erlang:phash(1,0)) of
 	{'EXIT',{badarg, _}} ->
@@ -237,22 +237,22 @@ range_test() ->
     
 
 spread_test(N) ->
-    ?line test_fun(N,{erlang,phash},16#50000000000,fun(X) ->
+    test_fun(N,{erlang,phash},16#50000000000,fun(X) ->
 						     X
 					     end),
-    ?line test_fun(N,{erlang,phash},0,fun(X) ->
+    test_fun(N,{erlang,phash},0,fun(X) ->
 					X
 				end),
-    ?line test_fun(N,{erlang,phash},16#123456789ABCDEF123456789ABCDEF,fun(X) ->
+    test_fun(N,{erlang,phash},16#123456789ABCDEF123456789ABCDEF,fun(X) ->
 									X
 								end),
-    ?line test_fun(N,{erlang,phash},16#50000000000,fun(X) ->
+    test_fun(N,{erlang,phash},16#50000000000,fun(X) ->
 						     integer_to_list(X)
 					     end),
-    ?line test_fun(N,{erlang,phash},16#50000000000,fun(X) ->
+    test_fun(N,{erlang,phash},16#50000000000,fun(X) ->
 						     integer_to_bytelist(X,[])
 					     end),
-    ?line test_fun(N,{erlang,phash},16#50000000000,fun(X) ->
+    test_fun(N,{erlang,phash},16#50000000000,fun(X) ->
 						     integer_to_binary_value(X)
 					     end).
     
@@ -265,14 +265,14 @@ cmp_test(N) ->
 do_cmp_hashes(0,_) ->
     ok;
 do_cmp_hashes(N,Steps) ->
-    ?line R0 = random:uniform(1 bsl Steps - 1) + random:uniform(16#FFFFFFFF),
-    ?line R = case random:uniform(2) of
+    R0 = random:uniform(1 bsl Steps - 1) + random:uniform(16#FFFFFFFF),
+    R = case random:uniform(2) of
 	    1 ->
 		R0;
 	    _ ->
 		-R0
 	end,
-    ?line NSteps = case N rem 10 of
+    NSteps = case N rem 10 of
 		 0 ->
 		     case (Steps + 8) rem 1024 of
 			 0 ->
@@ -283,9 +283,9 @@ do_cmp_hashes(N,Steps) ->
 		 _ ->
 		     Steps
 	     end,
-    ?line X = erlang:phash(R,16#FFFFFFFF),
-    ?line Y = make_hash(R,16#FFFFFFFF),
-    ?line case X =:= Y of
+    X = erlang:phash(R,16#FFFFFFFF),
+    Y = make_hash(R,16#FFFFFFFF),
+    case X =:= Y of
 	true ->
 	    do_cmp_hashes(N - 1, NSteps);
 	_ ->
@@ -469,8 +469,8 @@ phash2_test() ->
     SpecFun = fun(S) -> sofs:no_elements(S) > 1 end,
     F = sofs:relation_to_family(sofs:converse(sofs:relation(L))),
     D = sofs:to_external(sofs:family_specification(SpecFun, F)),
-    ?line [] = D,
-    ?line [] = [{E,H,H2} || {E,H} <- L, (H2 = erlang:phash2(E, Max)) =/= H],
+    [] = D,
+    [] = [{E,H,H2} || {E,H} <- L, (H2 = erlang:phash2(E, Max)) =/= H],
     ok.
 
 -ifdef(FALSE).
@@ -497,17 +497,17 @@ otp_5292_test() ->
             end,
     S2 = md5([md5(hash_int(S, E, PH)) || {Start, N, Sz} <- d(), 
                                          {S, E} <- int(Start, N, Sz)]),
-    ?line Comment = case S1 of 
+    Comment = case S1 of 
 			<<4,248,208,156,200,131,7,1,173,13,239,173,112,81,16,174>> ->
-			    ?line big = erlang:system_info(endian),
+			    big = erlang:system_info(endian),
                             "Big endian machine";
                         <<180,28,33,231,239,184,71,125,76,47,227,241,78,184,176,233>> ->
-			    ?line little = erlang:system_info(endian),
+			    little = erlang:system_info(endian),
                             "Little endian machine"
                     end,
-    ?line <<124,81,198,121,174,233,19,137,10,83,33,80,226,111,238,99>> = S2,
-    ?line 2 = erlang:hash(1, (1 bsl 27) -1),
-    ?line {'EXIT', _} = (catch erlang:hash(1, (1 bsl 27))),
+    <<124,81,198,121,174,233,19,137,10,83,33,80,226,111,238,99>> = S2,
+    2 = erlang:hash(1, (1 bsl 27) -1),
+    {'EXIT', _} = (catch erlang:hash(1, (1 bsl 27))),
     {comment, Comment}.
 
 d() ->
@@ -528,21 +528,21 @@ md5(T) ->
     erlang:md5(term_to_binary(T)).   
 
 bit_level_binaries() ->
-    ?line [3511317,7022633,14044578,28087749,56173436,112344123,90467083|_] =
+    [3511317,7022633,14044578,28087749,56173436,112344123,90467083|_] =
 	bit_level_all_different(fun erlang:hash/2),
-    ?line [3511317,7022633,14044578,28087749,56173436,112344123,90467083|_] =
+    [3511317,7022633,14044578,28087749,56173436,112344123,90467083|_] =
 	bit_level_all_different(fun erlang:phash/2),
-    ?line [102233154,19716,102133857,4532024,123369135,24565730,109558721|_] =
+    [102233154,19716,102133857,4532024,123369135,24565730,109558721|_] =
 	bit_level_all_different(fun erlang:phash2/2),
 
-    ?line 13233341 = test_hash_phash(<<42:7>>, 16#7FFFFFF),
-    ?line 79121243 = test_hash_phash(<<99:7>>, 16#7FFFFFF),
-    ?line 95517726 = test_hash_phash(<<16#378ABF73:31>>, 16#7FFFFFF),
+    13233341 = test_hash_phash(<<42:7>>, 16#7FFFFFF),
+    79121243 = test_hash_phash(<<99:7>>, 16#7FFFFFF),
+    95517726 = test_hash_phash(<<16#378ABF73:31>>, 16#7FFFFFF),
 
-    ?line 64409098 = test_phash2(<<99:7>>, 16#7FFFFFF),
-    ?line 55555814 = test_phash2(<<123,19:2>>, 16#7FFFFFF),
-    ?line 83868582 = test_phash2(<<123,45,6:3>>, 16#7FFFFFF),
-    ?line 2123204 = test_phash2(<<123,45,7:3>>, 16#7FFFFFF),
+    64409098 = test_phash2(<<99:7>>, 16#7FFFFFF),
+    55555814 = test_phash2(<<123,19:2>>, 16#7FFFFFF),
+    83868582 = test_phash2(<<123,45,6:3>>, 16#7FFFFFF),
+    2123204 = test_phash2(<<123,45,7:3>>, 16#7FFFFFF),
 
     ok.
 
@@ -579,7 +579,7 @@ test_phash2(Bitstr, Rem) ->
 
 otp_7127_test() ->
     %% Used to return 2589127136.
-    ?line 38990304 = erlang:phash2(<<"Scott9">>),
+    38990304 = erlang:phash2(<<"Scott9">>),
     ok.
 
 %%
-- 
cgit v1.2.3