Complexity Shock Horror II: the Sequel (was Re: MD5 in erlang.)
Raimo Niskanen
raimo.niskanen@REDACTED
Wed Apr 2 10:00:02 CEST 2003
I have convinced myself into a small change of my io_lib:format
implementation improvement.
The Erlang style Base#Integer notation is such an odd freak that it also
should not have a letter of its own. I will use b/B for signed
unprefixed instead so you won't have to use x/X with empty prefix.
This gives the general x/X:
io_lib:format("~.16x", [-31,"0x"]) -> "-0x1f"
io_lib:format("~.16X", [-31,"0x"]) -> "-0x1F"
b/B is just x/X with empty prefix:
io_lib:format("~.16b", [-31]) -> "-1f"
io_lib:format("~.16B", [-31]) -> "-1F"
and u/U is the same as b/B with the argument integer 'band'ed with
((1<<WordSize)-1):
io_lib:format("~.16U", [31,32]) -> "1F"
io_lib:format("~.16u", [-31,32]) -> "ffffffe1"
io_lib:format("~8.16.0u", [31,32]) -> "0000001f"
io_lib:format("~8.16.0U", [-31,32]) -> "FFFFFFE1"
Objections, anyone?
/ Raimo Niskanen, Erlang/OTP
Raimo Niskanen wrote:
> 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