[m-rev.] for review: add bitwise rotations for uint32s

Julien Fischer jfischer at opturion.com
Sun Mar 28 03:49:15 AEDT 2021


Hi Zoltan,

On Sun, 28 Mar 2021, Zoltan Somogyi wrote:

> 2021-03-28 02:22 GMT+11:00 "Julien Fischer" <jfischer at opturion.com>:
>> +    % unchecked_rotate_left(U, D) = N:
>> +    %
>> +    % N is the value obtained by rotating the binary representation of U
>> +    % left by the lowest 5 bits of D.
>> +    %
>> +:- func unchecked_rotate_left(uint32, uint) = uint32.
>
> I would reword the end of the comment as "by an amount given by the lowest ..."

Done.

,,,

>> +rotate_left(X, N) =
>> +    ( if N < 32u then
>> +        unchecked_rotate_left(X, N)
>> +    else
>> +        func_error($pred, "second argument exceeds 31 bits")
>> +    ).
>
> s/second argument/shift amount/

Perhaps "rotate amount" rather than "shift amount"?

>> +:- pragma foreign_proc("C",
>> +    unchecked_rotate_left(X::in, N::in) = (Result::out),
>> +    [will_not_call_mercury, promise_pure, thread_safe],
>> +"
>> +    N &= 31;
>> +    // This implementation is from https://blog.regehr.org/archives/1063.
>> +    // It is intended to avoid undefined behaviour in C and be recognisable by
>> +    // C compilers as a rotate operation. (On architectures that have a rotate
>> +    // instruction
>
> Add a comma after "instruction".

Done.

>> +    N &= 31;
>> +    Result = (X << (int) N) | (X >> (int) (-N & 31));
>> +").
>> +
>> +:- pragma foreign_proc("Java",
>> +    unchecked_rotate_left(X::in, N::in) = (Result::out),
>> +    [will_not_call_mercury, promise_pure, thread_safe],
>> +"
>> +    Result = java.lang.Integer.rotateLeft(X, N);
>> +").
>
> The Java version has no N &= 31. Why?
>
> And the same for the _right versions.

It's unecessary.  The rotateLeft and rotateRight methods in Java
do that anyway.

>> +*** Test 'rotate_left' ***
>
> I would change the test case code to print the results of unchecked_rotate_dir for a given
> pair of input args just after rotate_dir, so that these two lines would be next to each other
> (and lined up to make a visual diff trivial).
>
>> +                      rotate_left(00000000000000000000000000000001, 0) = 00000000000000000000000000000001
>> +unchecked_rotate_left(00000000000000000000000000000001, 0) = 00000000000000000000000000000001
>
>> +:- func to_binary_string_lz(uint32::in) = (string::uo) is det.
>
> What is the _lz for?

lz == leading zeros

> We have string.int_to_base_string in the standard library. This looks like a case for
> adding unsigned and size-specific versions of it as well. In fact, any kind of conversion
> to string that exists for any integer type should exist for all ten integer types.

True, I'll look into adding the missing ones.

> The diff is otherwise fine.

Thanks for the review.

Julien.


More information about the reviews mailing list