www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Endiannes & Splitting Values

reply BitGuy <fsdfsd sdfs.com> writes:
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?
Jul 06 2016
next sibling parent Lodovico Giaretta <lodovico giaretart.net> writes:
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));
Jul 06 2016
prev sibling next sibling parent Alex Parrill <initrd.gz gmail.com> writes:
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.
Jul 06 2016
prev sibling parent reply Gary Willoughby <dev nomad.so> writes:
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); }
Jul 07 2016
parent reply Lodovico Giaretta <lodovico giaretart.net> writes:
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?
Jul 07 2016
parent reply Gary Willoughby <dev nomad.so> writes:
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.
Jul 07 2016
parent reply Lodovico Giaretta <lodovico giaretart.net> writes:
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.
Jul 07 2016
parent Gary Willoughby <dev nomad.so> writes:
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; } }
Jul 07 2016