Search code examples
delphidelphi-6

How can I write comparison functions for unsigned 64 bit integers for versions of the compiler without support for UInt64?


How can I do that with Delphi 6? UInt64 is not known in Delphi 6. It was introduced in later versions.

var
  i, j: Int64;

  if UInt64(i) < UInt64(j) then ...


I am thinking of an asm procedure. 

function UInt64CompareLT(i, j: Int64): Boolean;
asm
 ???
end;

function UInt64CompareGT(i, j: Int64): Boolean;
asm
 ???
end;

Solution

  • The Int64Rec type from SysUtils is designed for the task of picking out the parts of a 64 bit integer.

    If you happen to be using a Delphi that pre-dates this type, define it yourself:

    type
      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;
    

    What's more, you only need a single function that returns -1 for less than, 1 for greater than and 0 for equals. Something like this:

    function CompareUInt64(const i, j: Int64): Integer;
    begin
      if Int64Rec(i).Hi < Int64Rec(j).Hi then
        Result := -1
      else if Int64Rec(i).Hi > Int64Rec(j).Hi then
        Result := 1
      else if Int64Rec(i).Lo < Int64Rec(j).Lo then
        Result := -1
      else if Int64Rec(i).Lo > Int64Rec(j).Lo then
        Result := 1
      else
        Result := 0;
    end;
    

    The idea is that you first compare the high order part, and only if that is equal do you then go on to compare the low order part.

    This can be made simpler with a compare function for Cardinal.

    function CompareCardinal(const i, j: Cardinal): Integer;
    begin
      if i < j then
        Result := -1
      else if i > j then
        Result := 1
      else
        Result := 0;
    end;
    
    function CompareUInt64(const i, j: Int64): Integer;
    begin
      Result := CompareCardinal(Int64Rec(i).Hi, Int64Rec(j).Hi);
      if Result = 0 then
        Result := CompareCardinal(Int64Rec(i).Lo, Int64Rec(j).Lo);
    end;
    

    Finally, should you need the boolean functions of your question, they can be implemented on top of this more general function.