Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I cannot use SHL (shift left) with int64 variables

Tags:

delphi

 Result:= b8;
 Result:= Result+ (b7  SHL  8);
 Result:= Result+ (b6  SHL 16);
 Result:= Result+ (b5  SHL 24);
 Result:= Result+ (b4  SHL 32);
 Result:= Result+ (b3  SHL 40);      <------ here
 Result:= Result+ (b2  SHL 48);
 Result:= Result+ (MSB SHL 56);

(Result is int64 and b1-b8 is byte).

But the compiler complains about "constant exp violates subrange bounds". Then I have found this warning "The compiler will reject hardcoded shift right values that exceed 32, unless the data type is Int64. The same is not true for Shl" on a web site. Delphi Help says nothing about it. Why is there a limit? Can I stop it? Maybe a compiler directive or something? I can use a multiplication to get over it, but it will be slower. There is a faster way to do it?

Edit: I am thinking also in creating two cardinals because I can use SHL on cardinals, then to merge the cardinals together. This will require only one multiplication. Any other ideas?

Edit2: The code is part of an algorithm that converts a number form base 255 to base 256 (and the other way around). I do this 50000 million times; so speed is important.

like image 459
Server Overflow Avatar asked May 16 '11 09:05

Server Overflow


1 Answers

I'd avoid all arithmetic (your code has additions and shifts) and do it like this:

Int64Rec(Result).Bytes[0] := b8;
Int64Rec(Result).Bytes[1] := b7;
//etc.

Int64Rec is defined in SysUtils like this:

Int64Rec = packed record
  case Integer of
    0: (Lo, Hi: Cardinal);
    1: (Cardinals: array [0..1] of Cardinal);
    2: (Words: array [0..3] of Word);
    3: (Bytes: array [0..7] of Byte);
end;

If you stored your bytes in an array then you could wrap it all up in a for loop.

like image 104
David Heffernan Avatar answered Sep 19 '22 22:09

David Heffernan