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