Thread overview
Endiannes & Splitting Values
Jul 06, 2016
BitGuy
Jul 06, 2016
Lodovico Giaretta
Jul 06, 2016
Alex Parrill
Jul 07, 2016
Gary Willoughby
Jul 07, 2016
Lodovico Giaretta
Jul 07, 2016
Gary Willoughby
Jul 07, 2016
Lodovico Giaretta
Jul 07, 2016
Gary Willoughby
July 06, 2016
I'm trying to implement a feistel cipher that'll give the same results regardless of the endianness of the machine it runs on. To make the cipher I need to split a 64bit value into two 32bit values, mess with them, and then put them back together. I can think of a few ways to split a 64bit value with versions or the endianness functions in bitmanip but it all seems pretty messy for just wanting to split a value... I'm thinking maybe I can just cast and bitshift so I can forget about the endianness but I'm not really sure about the casting down rules and if that'd work?
July 06, 2016
On Wednesday, 6 July 2016 at 21:44:37 UTC, BitGuy wrote:
> I'm trying to implement a feistel cipher that'll give the same results regardless of the endianness of the machine it runs on. To make the cipher I need to split a 64bit value into two 32bit values, mess with them, and then put them back together. I can think of a few ways to split a 64bit value with versions or the endianness functions in bitmanip but it all seems pretty messy for just wanting to split a value... I'm thinking maybe I can just cast and bitshift so I can forget about the endianness but I'm not really sure about the casting down rules and if that'd work?

You can just use bitwise operations, without casts (with Value Range Propagation, the compiler knows that the two halves fit a uint each). The recomposition will require a cast, however.

ulong value = ...
uint low = value & uint.max;
uint high = value >>> 32;
assert(value == ((cast(ulong)high << 32) | low));


July 06, 2016
On Wednesday, 6 July 2016 at 21:44:37 UTC, BitGuy wrote:
> I'm trying to implement a feistel cipher that'll give the same results regardless of the endianness of the machine it runs on. To make the cipher I need to split a 64bit value into two 32bit values, mess with them, and then put them back together. I can think of a few ways to split a 64bit value with versions or the endianness functions in bitmanip but it all seems pretty messy for just wanting to split a value... I'm thinking maybe I can just cast and bitshift so I can forget about the endianness but I'm not really sure about the casting down rules and if that'd work?

Bitshifts and binary operators work the same regardless of endianness. Just shift by 32/mask  with 0xFFFFFFFF and cast.

It's only if you are accessing a value as a byte array that you have to worry about endianness.
July 07, 2016
On Wednesday, 6 July 2016 at 21:44:37 UTC, BitGuy wrote:
> I'm trying to implement a feistel cipher that'll give the same results regardless of the endianness of the machine it runs on. To make the cipher I need to split a 64bit value into two 32bit values, mess with them, and then put them back together. I can think of a few ways to split a 64bit value with versions or the endianness functions in bitmanip but it all seems pretty messy for just wanting to split a value... I'm thinking maybe I can just cast and bitshift so I can forget about the endianness but I'm not really sure about the casting down rules and if that'd work?

What about something like:

import std.stdio;

union Value
{
    ulong full;

    static struct Bits
    {
        uint high;
        uint low;
    }

    Bits bits;
    alias bits this;

    this(ulong value)
    {
        this.full = value;
    }
}

void main(string[] args)
{
    auto value = Value(77309411348);

    writefln("%s, (%b)", value.high, value.high);
    writefln("%s, (%b)", value.low, value.low);
    writefln("%s, (%b)", value.full, value.full);
}
July 07, 2016
On Thursday, 7 July 2016 at 08:14:40 UTC, Gary Willoughby wrote:
>
> What about something like:
>
> import std.stdio;
>
> union Value
> {
>     ulong full;
>
>     static struct Bits
>     {
>         uint high;
>         uint low;
>     }
>
>     Bits bits;
>     alias bits this;
>
>     this(ulong value)
>     {
>         this.full = value;
>     }
> }
>
> void main(string[] args)
> {
>     auto value = Value(77309411348);
>
>     writefln("%s, (%b)", value.high, value.high);
>     writefln("%s, (%b)", value.low, value.low);
>     writefln("%s, (%b)", value.full, value.full);
> }

Hi,
Are you sure that this works in both big-endian and little-endian systems?
July 07, 2016
On Thursday, 7 July 2016 at 08:21:53 UTC, Lodovico Giaretta wrote:
> Are you sure that this works in both big-endian and little-endian systems?

It shouldn't matter. You're just interested in the high and low 4 byte chunks (which are to be interpreted as an int) which will return in the relevant endianess of your machine.
July 07, 2016
On Thursday, 7 July 2016 at 10:45:12 UTC, Gary Willoughby wrote:
> On Thursday, 7 July 2016 at 08:21:53 UTC, Lodovico Giaretta wrote:
>> Are you sure that this works in both big-endian and little-endian systems?
>
> It shouldn't matter. You're just interested in the high and low 4 byte chunks (which are to be interpreted as an int) which will return in the relevant endianess of your machine.

But are the high 4 bytes the first 4 or the second 4? It depends on endianness. So your high and low variables may be switched, if I understand correctly.
July 07, 2016
On Thursday, 7 July 2016 at 10:48:56 UTC, Lodovico Giaretta wrote:
> On Thursday, 7 July 2016 at 10:45:12 UTC, Gary Willoughby wrote:
>> On Thursday, 7 July 2016 at 08:21:53 UTC, Lodovico Giaretta wrote:
>>> Are you sure that this works in both big-endian and little-endian systems?
>>
>> It shouldn't matter. You're just interested in the high and low 4 byte chunks (which are to be interpreted as an int) which will return in the relevant endianess of your machine.
>
> But are the high 4 bytes the first 4 or the second 4? It depends on endianness. So your high and low variables may be switched, if I understand correctly.

Ah, I see. You could modify it like this:

union Value
{
    ulong full;

    static struct Bits
    {
        version (BigEndian)
        {
            uint high;
            uint low;
        }
        else
        {
            uint low;
            uint high;
        }

    }

    Bits bits;
    alias bits this;

    this(ulong value)
    {
        this.full = value;
    }
}