Thread overview |
---|
January 30, 2021 Bit rotation question/challenge | ||||
---|---|---|---|---|
| ||||
I have a static array of `ubyte`s of arbitrary size: ```d ubyte[4] x = [ // in reality, ubyte[64] 0b00001000, 0b00000001, 0b00010101, 0b11110010, ]; ``` Now I want to bit-rotate the array as if it is one big integer. So: ```d ubyte[n] rotateRight(size_t n)(ref const ubyte[n] array, uint rotation) { // ? } // same for rotateLeft ubyte[4] y = [ 0b11111001, 0b00000100, 0b00000000, 0b10001010, ]; assert(x.rotateRight(9) == y); assert(y.rotateLeft(9) == x); ``` Any ideas how this could be achieved? I.e. what should go at the "?" for rotateRight and rotateLeft? |
January 30, 2021 Re: Bit rotation question/challenge | ||||
---|---|---|---|---|
| ||||
Posted in reply to burt | On Saturday, 30 January 2021 at 13:30:49 UTC, burt wrote: > I have a static array of `ubyte`s of arbitrary size: > > ```d > ubyte[4] x = [ // in reality, ubyte[64] > 0b00001000, > 0b00000001, > 0b00010101, > 0b11110010, > ]; > ``` > > Now I want to bit-rotate the array as if it is one big integer. You may find `std.bitmanip.BitArray` useful for this: http://phobos.dpldocs.info/std.bitmanip.BitArray.html |
January 30, 2021 Re: Bit rotation question/challenge | ||||
---|---|---|---|---|
| ||||
Posted in reply to burt | On Saturday, 30 January 2021 at 13:30:49 UTC, burt wrote:
> I have a static array of `ubyte`s of arbitrary size:
>
> ```d
> ubyte[4] x = [ // in reality, ubyte[64]
> 0b00001000,
> 0b00000001,
> 0b00010101,
> 0b11110010,
> ];
> ```
>
> Now I want to bit-rotate the array as if it is one big integer. So:
>
> ```d
> ubyte[n] rotateRight(size_t n)(ref const ubyte[n] array, uint rotation)
> {
> // ?
> }
> // same for rotateLeft
>
> ubyte[4] y = [
> 0b11111001,
> 0b00000100,
> 0b00000000,
> 0b10001010,
> ];
> assert(x.rotateRight(9) == y);
> assert(y.rotateLeft(9) == x);
> ```
>
> Any ideas how this could be achieved? I.e. what should go at the "?" for rotateRight and rotateLeft?
cast as uint and shift. cast the result as ubyte[4].
|
January 30, 2021 Re: Bit rotation question/challenge | ||||
---|---|---|---|---|
| ||||
Posted in reply to Afgdr | On Saturday, 30 January 2021 at 14:40:49 UTC, Afgdr wrote:
> On Saturday, 30 January 2021 at 13:30:49 UTC, burt wrote:
>> I have a static array of `ubyte`s of arbitrary size:
>>
>> ```d
>> ubyte[4] x = [ // in reality, ubyte[64]
>> 0b00001000,
>> 0b00000001,
>> 0b00010101,
>> 0b11110010,
>> ];
>> ```
>>
>> Now I want to bit-rotate the array as if it is one big integer. So:
>>
>> ```d
>> ubyte[n] rotateRight(size_t n)(ref const ubyte[n] array, uint rotation)
>> {
>> // ?
>> }
>> // same for rotateLeft
>>
>> ubyte[4] y = [
>> 0b11111001,
>> 0b00000100,
>> 0b00000000,
>> 0b10001010,
>> ];
>> assert(x.rotateRight(9) == y);
>> assert(y.rotateLeft(9) == x);
>> ```
>>
>> Any ideas how this could be achieved? I.e. what should go at the "?" for rotateRight and rotateLeft?
>
> cast as uint and shift. cast the result as ubyte[4].
obiously, that works for n=4 with uint and n=8 for ulong, only.
|
January 30, 2021 Re: Bit rotation question/challenge | ||||
---|---|---|---|---|
| ||||
Posted in reply to Paul Backus | On Saturday, 30 January 2021 at 14:17:06 UTC, Paul Backus wrote: > On Saturday, 30 January 2021 at 13:30:49 UTC, burt wrote: >> [...] >> >> Now I want to bit-rotate the array as if it is one big integer. > > You may find `std.bitmanip.BitArray` useful for this: > > http://phobos.dpldocs.info/std.bitmanip.BitArray.html Thank you, this is indeed what I am looking for! For future reference, this is how I implemented it: ```d ubyte[n] rotateRight(size_t n)(ubyte[n] x, uint rotation) { import std.bitmanip : BitArray; ubyte[n] x2; foreach (i, value; x) // have to swap because of endianness x2[n - 1 - i] = value; auto copy = x2; auto bitArray1 = BitArray(cast(void[]) x2[], n * 8); auto bitArray2 = BitArray(cast(void[]) copy[], n * 8); bitArray1 >>= rotation; bitArray2 <<= n * 8 - rotation; bitArray1 |= bitArray2; foreach (i, value; x2) // swap back x[n - 1 - i] = value; return x; } ubyte[4] x = [ 0b00011000, 0b00100001, 0b00010101, 0b11110010, ]; writefln!"%(%8b,\n%)"(x.rotateRight(4)); ``` |
January 30, 2021 Re: Bit rotation question/challenge | ||||
---|---|---|---|---|
| ||||
Posted in reply to Afgdr | On Saturday, 30 January 2021 at 14:41:59 UTC, Afgdr wrote:
> On Saturday, 30 January 2021 at 14:40:49 UTC, Afgdr wrote:
>> On Saturday, 30 January 2021 at 13:30:49 UTC, burt wrote:
>>> [...]
>>
>> cast as uint and shift. cast the result as ubyte[4].
>
> obiously, that works for n=4 with uint and n=8 for ulong, only.
Yes I used to do this, but then I needed it for n > 8.
|
January 30, 2021 Re: Bit rotation question/challenge | ||||
---|---|---|---|---|
| ||||
Posted in reply to burt | On Saturday, 30 January 2021 at 14:56:14 UTC, burt wrote:
> On Saturday, 30 January 2021 at 14:41:59 UTC, Afgdr wrote:
>> On Saturday, 30 January 2021 at 14:40:49 UTC, Afgdr wrote:
>>> On Saturday, 30 January 2021 at 13:30:49 UTC, burt wrote:
>>>> [...]
>>>
>>> cast as uint and shift. cast the result as ubyte[4].
>>
>> obiously, that works for n=4 with uint and n=8 for ulong, only.
>
> Yes I used to do this, but then I needed it for n > 8.
As suggested in the other answer BitArray may be the best generic solution.
|
January 30, 2021 Re: Bit rotation question/challenge | ||||
---|---|---|---|---|
| ||||
Posted in reply to burt | On Saturday, 30 January 2021 at 14:56:14 UTC, burt wrote: > On Saturday, 30 January 2021 at 14:41:59 UTC, Afgdr wrote: >> On Saturday, 30 January 2021 at 14:40:49 UTC, Afgdr wrote: >>> On Saturday, 30 January 2021 at 13:30:49 UTC, burt wrote: >>>> [...] >>> >>> cast as uint and shift. cast the result as ubyte[4]. >> >> obiously, that works for n=4 with uint and n=8 for ulong, only. > > Yes I used to do this, but then I needed it for n > 8. You can try somethink like this: https://run.dlang.io/is/POQgnb import std.range : cycle, take, drop; import std.algorithm : copy; import std.stdio; version (LittleEndian) ubyte[n] rotateRight(size_t n)(ref const ubyte[n] array, uint rotation){ typeof(return) result; array[] .cycle() .drop(n - (rotation / 8) % n) .take(n) .copy(result[]); const ubyte bit_rotation = rotation % 8; enum ubyte full = 0b1111_1111; if(bit_rotation == 0) return result; ubyte next_prefix(const ubyte elm){ const ubyte suffix = (elm & ~(full << bit_rotation)); const ubyte prefix = cast(ubyte)(suffix << (8 - bit_rotation)); return prefix; } ubyte prefix = next_prefix(result[$-1]); foreach(ref ubyte elm; result[]){ const new_prefix = next_prefix(elm); elm = (elm >> bit_rotation) | prefix; prefix = new_prefix; } return result; } void main(){ ubyte[4] x = [ 0b00011000, 0b00100001, 0b00010101, 0b11110010, ]; writefln!"%(%8b,\n%)"(x.rotateRight(4)); } |
Copyright © 1999-2021 by the D Language Foundation