Complexity Shock Horror II: the Sequel (was Re: MD5 in erlang.)
Raimo Niskanen
raimo.niskanen@REDACTED
Sun Mar 30 03:09:27 CEST 2003
Hi Happi. I am digging into the I/O system for performance reasons, so
this time I will add the any-base printing to io_lib for R9C.
Not exactly as your suggestion, though.
As I read your code, you suggested:
io_lib:format("~#", [-31,16]) -> "-16#1f"
io_lib:format("~B", [-30]) -> "-1111110"
io_lib:format("~b", [18]) -> "00000000000000000000000000010010"
io_lib:format("~.8b", [-18]) -> "11101110"
io_lib:format("~x", [-31]) -> "-0x1f"
io_lib:format("~X", [-31]) -> "-0x1F"
And, first I do not want 0x-prefix for hex notation. That is C, not
Erlang. A user definable prefix would be better.
Second, I would like to be able to choose either upper or lowercase for
"~#".
Third, I don't see why binary notation would deserve a letter of its
own, base 2 without prefix would do the job. So I want a possibility to
loose the prefix.
So I will most probably implement (if no-one convinces me that I must
change something):
io_lib:format("~.16b", [-31]) -> "-16#1f"
io_lib:format("~.16B", [-31]) -> "-16#1F"
io_lib:format("~.16x", [-31,"0x"]) -> "-0x1f"
io_lib:format("~.16X", [-31,"0x"]) -> "-0x1F"
io_lib:format("~.2.0u", [18,32]) -> "00000000000000000000000000010010"
io_lib:format("~.2u", [-18,8]) -> "11101110"
io_lib:format("~.16u", [31,16]) -> "1f"
io_lib:format("~.16U", [-31,16]) -> "FFEE"
I.e b/B for Erlang signed any-Base notation.
x/X for eXplicitly prefiXed signed any-base notation.
u/U for unprefixed unsigned words of any width.
The precision field chooses number base.
Second mandatory argument for x/X chooses prefix,
for u/U word width.
Default base is 10.
I am not too happy with my choice of letters, but the best were taken.
/ Raimo Niskanen, Erlang/OTP
Erik Stenman wrote:
> Chris Pressey wrote:
> [...]
>
>>Every few months this comes up and every time it does I get more
>>irritated.
>
> [...]
>
> Here we go agian, my pet peeve ;)
>
> We have had the posibility to format integers in different bases in our
> local HiPE system for several years now,
> but for some reason the OTP team does not want to add it to the
> distribution.
> Robert Virding has also promised to implement it but that implementation has
> not made it into the distribution either.
>
> Please, please add this functionallity to stdlib!
> (I can write the documentation if that is a problem ;)
>
> /Erik
> --------------------------------------
> I'm Happi, you should be happy.
> Praeterea censeo "0xCA" scribere Erlang posse.
>
>
> Index: lib/stdlib/src/io_lib_format.erl
> ===================================================================
> RCS file:
> /it/project/fo/hipe/repository/otp/lib/stdlib/src/io_lib_format.erl,v
> retrieving revision 1.1.1.1
> retrieving revision 1.4
> diff -u -r1.1.1.1 -r1.4
> --- lib/stdlib/src/io_lib_format.erl 26 Mar 2001 18:36:34 -0000 1.1.1.1
> +++ lib/stdlib/src/io_lib_format.erl 27 Mar 2002 16:47:22 -0000 1.4
> @@ -101,11 +101,16 @@
> collect_cc([$p|Fmt], [A|Args]) -> {$p,[A],Fmt,Args};
> collect_cc([$W|Fmt], [A,Depth|Args]) -> {$W,[A,Depth],Fmt,Args};
> collect_cc([$P|Fmt], [A,Depth|Args]) -> {$P,[A,Depth],Fmt,Args};
> +collect_cc([$#|Fmt], [A,Base|Args]) -> {$#,[A,Base],Fmt,Args};
> +collect_cc([$B|Fmt], [A|Args]) -> {$B,[A],Fmt,Args};
> +collect_cc([$b|Fmt], [A|Args]) -> {$b,[A],Fmt,Args};
> collect_cc([$s|Fmt], [A|Args]) -> {$s,[A],Fmt,Args};
> collect_cc([$e|Fmt], [A|Args]) -> {$e,[A],Fmt,Args};
> collect_cc([$f|Fmt], [A|Args]) -> {$f,[A],Fmt,Args};
> collect_cc([$g|Fmt], [A|Args]) -> {$g,[A],Fmt,Args};
> collect_cc([$c|Fmt], [A|Args]) -> {$c,[A],Fmt,Args};
> +collect_cc([$x|Fmt], [A|Args]) -> {$x,[A],Fmt,Args};
> +collect_cc([$X|Fmt], [A|Args]) -> {$X,[A],Fmt,Args};
> collect_cc([$~|Fmt], Args) -> {$~,[],Fmt,Args};
> collect_cc([$n|Fmt], Args) -> {$n,[],Fmt,Args};
> collect_cc([$i|Fmt], [A|Args]) -> {$i,[A],Fmt,Args}.
> @@ -155,6 +160,20 @@
> term(io_lib:write(A, Depth), F, Adj, P, Pad);
> control($P, [A,Depth], F, Adj, P, Pad, I) when integer(Depth) ->
> print(A, Depth, F, Adj, P, Pad, I);
> +control($#, [A,Base], F, Adj, P, Pad, I) when integer(Base),
> + 2 =< Base,
> + Base =< 16->
> + string(int_to_base(A, Base), F, Adj, P, Pad);
> +control($B, [A], F, Adj, P, Pad, I) ->
> + string(
> + if A < 0 -> [$- | int_to_base(-A, [], 2)];
> + true -> int_to_base(A, [], 2)
> + end,
> + F, Adj, P, Pad);
> +control($b, [A], F, Adj, none, Pad, I) ->
> + string(int_to_binary(A, 32), F, Adj, none, Pad);
> +control($b, [A], F, Adj, P, Pad, I) ->
> + string(int_to_binary(A, P), F, Adj, P, Pad);
> control($s, [A], F, Adj, P, Pad, I) when atom(A) ->
> string(atom_to_list(A), F, Adj, P, Pad);
> control($s, [L], F, Adj, P, Pad, I) ->
> @@ -168,6 +187,10 @@
> fwrite_g(A, F, Adj, P, Pad);
> control($c, [A], F, Adj, P, Pad, I) when integer(A) ->
> char(A band 255, F, Adj, P, Pad);
> +control($x, [A], F, Adj, P, Pad, I) when integer(A) ->
> + string(int_to_hex(A), F, Adj, P, Pad);
> +control($X, [A], F, Adj, P, Pad, I) when integer(A) ->
> + string(int_to_Hex(A), F, Adj, P, Pad);
> control($~, [], F, Adj, P, Pad, I) -> char($~, F, Adj, P, Pad);
> control($n, [], F, Adj, P, Pad, I) -> newline(F, Adj, P, Pad);
> control($i, [A], F, Adj, P, Pad, I) -> [].
> @@ -388,3 +411,58 @@
> flat_length([H|T], L) ->
> flat_length(T, L + 1);
> flat_length([], L) -> L.
> +
> +int_to_hex(N) -> int_to_hex(N, $a-10).
> +int_to_Hex(N) -> int_to_hex(N, $A-10).
> +
> +int_to_hex(N, LetterBase) ->
> + if N < 0 -> [$-, $0, $x | int_to_hex(-N, [], LetterBase)];
> + true -> [$0, $x | int_to_hex(N, [], LetterBase)]
> + end.
> +
> +int_to_hex(N, Tail, LetterBase) ->
> + NewN = N bsr 4,
> + Digit = N band 15,
> + Char =
> + if Digit < 10 -> Digit+$0;
> + true -> Digit+LetterBase
> + end,
> + NewTail = [Char | Tail],
> + if NewN =:= 0 -> NewTail;
> + true -> int_to_hex(NewN, NewTail, LetterBase)
> + end.
> +
> +int_to_binary(N, Wordsize) ->
> + if N < 0 ->
> + Bits = int_to_base(-N, [],2),
> + pad(length(Bits),Bits,Wordsize,$1);
> + true ->
> + Bits = int_to_base(N, [], 2),
> + pad(length(Bits),Bits,Wordsize,$0)
> + end.
> +
> +pad(N,Bits,Wordsize, Pad) ->
> + if N < Wordsize ->
> + pad(N+1,[Pad|Bits],Wordsize,Pad);
> + true ->
> + Bits
> + end.
> +
> +
> +int_to_base(N, Base) ->
> + if N < 0 -> [$- | integer_to_list(Base)]
> + ++ [$# | int_to_base(-N, [], Base)];
> + true -> integer_to_list(Base) ++ [$# | int_to_base(N, [], Base)]
> + end.
> +
> +int_to_base(N, Tail, Base) ->
> + NewN = N div Base,
> + Digit = N - (NewN*Base),
> + Char =
> + if Digit < 10 -> Digit+$0;
> + true -> Digit+$a-10
> + end,
> + NewTail = [Char | Tail],
> + if NewN =:= 0 -> NewTail;
> + true -> int_to_base(NewN, NewTail, Base)
> + end.
>
More information about the erlang-questions
mailing list