ubytes to ulong problem

John Colvin john.loughran.colvin at gmail.com
Sat Dec 21 15:13:17 PST 2013


On Saturday, 21 December 2013 at 22:22:09 UTC, Charles Hixson 
wrote:
> I was planning to ask if there were a better way to do this, 
> but instead I need to ask what's my mistake?
> For some reason, if called with an uninitialized ubyte array, 
> and an index of 0, it returns a value of 8, even though all the 
> values in the array are 0.
> The error has to be somewhere in the "ret = " statement, but I 
> sure don't see it.
>
> /**    Convert 8 consecutive bytes sliced from a ubyte[] into a 
> ulong
>  * @param    block    The array from which to slice.
>  * @param    n    The starting index within the block    */
> ulong    ubytesToUlong(ubyte[] block, int n)
> {    ulong    ret;
>     assert (n >= 0);
>     assert (n + 8 <= block.length);
>     writefln ("n = %s", n);
>     writefln ("block[0] = %s", cast(ulong)block[0]);
>     writefln ("block[1] = %s", cast(ulong)block[1]);
>     writefln ("block[2] = %s", cast(ulong)block[2]);
>     writefln ("block[3] = %s", cast(ulong)block[3]);
>     writefln ("block[4] = %s", cast(ulong)block[4]);
>     writefln ("block[5] = %s", cast(ulong)block[5]);
>     writefln ("block[6] = %s", cast(ulong)block[6]);
>     writefln ("block[7] = %s", cast(ulong)block[7]);
>     ret    =    cast(ulong)block[n] * 2^21
>             +    cast(ulong)block[n+1] * 2^18
>             +    cast(ulong)block[n+2] * 2^15
>             +    cast(ulong)block[n+3] * 2^12
>             +    cast(ulong)block[n+4] * 2^9
>             +    cast(ulong)block[n+5] * 2^6
>             +    cast(ulong)block[n+6] * 2^3
>             +    cast(ulong)block[n+7] * 2^0;
>     writefln ("ret = %s", ret);
>     return    ret;
> }

As pointed out before, you're using '^' which is xor, instead of 
^^. Ideally the compiler will optimise your version to be fast, 
but you may find you get better performance by doing the bit 
manipulations eplicitly:

/**Convert 8 consecutive bytes sliced from a ubyte[]
  * to a ulong using bigendian byte ordering.
  * @param    block    The array from which to slice.
  * @param    n    The starting index within the block, default 0*/
ulong ubytesToUlong(ubyte[] block, size_t n = 0)
in
{
     assert (n >= 0);
     assert (n + 8 <= block.length);
}
body
{
     return ((cast(ulong)block[n  ]) << 56)
          | ((cast(ulong)block[n+1]) << 48)
          | ((cast(ulong)block[n+2]) << 40)
          | ((cast(ulong)block[n+3]) << 32)
          | ((cast(ulong)block[n+4]) << 24)
          | ((cast(ulong)block[n+5]) << 16)
          | ((cast(ulong)block[n+6]) <<  8)
          |  (cast(ulong)block[n+7]);
}

unittest
{
     ubyte[8] a = [0,0,0,0,0,0,0,0];
	
     assert(a[].ubytesToUlong() == 0);
	
     a[7] = 3;
     a[6] = 1;
	
     assert(a[].ubytesToUlong() == 259);
}


More information about the Digitalmars-d-learn mailing list