Pastebin launched a little side project called HostCabi.net, check it out ;-)Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on Dec 9th, 2009  |  syntax: Delphi  |  size: 3.68 KB  |  hits: 770  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. unit LargeInt;
  2.  
  3. interface
  4.  
  5. type
  6.   PInt128 = ^UInt128;
  7.   UInt128 = packed record
  8.   private
  9.     function GetQuadPart(AIndex: Integer): LongWord;
  10.     procedure SetQuadPart(AIndex: Integer; const Value: LongWord);
  11.   public
  12.     Hi: UInt64;
  13.     Lo: UInt64;
  14.  
  15.     function IsZero: Boolean;
  16.  
  17.     procedure Inc(const AValue: UInt128);
  18.  
  19.     function Multiply(const AValue: LongWord): UInt128;
  20.     function Divide(const AValue: LongWord; out ARemainder: LongWord): UInt128;
  21.  
  22.     property QuadPart[AIndex: Integer]: LongWord read GetQuadPart write SetQuadPart;
  23.   end;
  24.  
  25. function ToUInt128(AHi, ALo: UInt64): UInt128;
  26.  
  27. implementation
  28.  
  29. function ToUInt128(AHi, ALo: UInt64): UInt128;
  30. begin
  31.   Result.Hi := AHi;
  32.   Result.Lo := ALo;
  33. end;
  34.  
  35. function AddWithCarry(const A, B: LongWord; var Carry: LongWord): LongWord;
  36. var
  37.   R: UInt64;
  38. begin
  39.   R := UInt64(A) + UInt64(B) + UInt64(Carry);
  40.   Carry := (R shr 32) and $1;
  41.  
  42.   Result := LongWord(R);
  43. end;
  44.  
  45. function MultiplyWithCarry(const A, B: LongWord; var Carry: LongWord): LongWord;
  46. var
  47.   R: UInt64;
  48. begin
  49.   // "Carry" here is a misnomer. A multiplication never generates a carry, since
  50.   //   the product of two 32-bit values is a 64-bit value. But here we return
  51.   //   only the lowest 32 bits, leaving the higher 32-bit in the "Carry".
  52.  
  53.   R := UInt64(A) * UInt64(B) + UInt64(Carry);
  54.   Carry := (R shr 32);
  55.  
  56.   Result := LongWord(R);
  57. end;
  58.  
  59. function DivideWithRemainder(const A, B: LongWord; var Remainder: LongWord): LongWord;
  60. var
  61.   A64: UInt64;
  62. begin
  63.   A64 := (UInt64(Remainder) shl 32 or A);
  64.  
  65.   Remainder := A64 mod B;
  66.   Result := A64 div B;
  67. end;
  68.  
  69. // --- UInt128 -----------------------------------------------------------
  70.  
  71. function UInt128.GetQuadPart(AIndex: Integer): LongWord;
  72. begin
  73.   Result := 0;
  74.   case AIndex of
  75.     3: Result := Self.Hi shr 32;
  76.     2: Result := Self.Hi;
  77.     1: Result := Self.Lo shr 32;
  78.     0: Result := Self.Lo;
  79.   end;
  80. end;
  81.  
  82. procedure UInt128.SetQuadPart(AIndex: Integer; const Value: LongWord);
  83. begin
  84.   case AIndex of
  85.     3: Self.Hi := (Self.Hi and $00000000FFFFFFFF) or (UInt64(Value) shl 32);
  86.     2: Self.Hi := (Self.Hi and $FFFFFFFF00000000) or Value;
  87.     1: Self.Lo := (Self.Lo and $00000000FFFFFFFF) or (UInt64(Value) shl 32);
  88.     0: Self.Lo := (Self.Lo and $FFFFFFFF00000000) or Value;
  89.   end;
  90. end;
  91.  
  92. function UInt128.IsZero: Boolean;
  93. begin
  94.   Result := (Self.Hi = 0) and (Self.Lo = 0);
  95. end;
  96.  
  97. procedure UInt128.Inc(const AValue: UInt128);
  98. var
  99.   LCarry: LongWord;
  100. begin
  101.   LCarry := 0;
  102.   Self.QuadPart[0] := AddWithCarry(Self.QuadPart[0], AValue.QuadPart[0], LCarry);
  103.   Self.QuadPart[1] := AddWithCarry(Self.QuadPart[1], AValue.QuadPart[1], LCarry);
  104.   Self.QuadPart[2] := AddWithCarry(Self.QuadPart[2], AValue.QuadPart[2], LCarry);
  105.   Self.QuadPart[3] := AddWithCarry(Self.QuadPart[3], AValue.QuadPart[3], LCarry);
  106. end;
  107.  
  108. function UInt128.Multiply(const AValue: LongWord): UInt128;
  109. var
  110.   LCarry: LongWord;
  111. begin
  112.   LCarry := 0;
  113.   Result.QuadPart[0] := MultiplyWithCarry(Self.QuadPart[0], AValue, LCarry);
  114.   Result.QuadPart[1] := MultiplyWithCarry(Self.QuadPart[1], AValue, LCarry);
  115.   Result.QuadPart[2] := MultiplyWithCarry(Self.QuadPart[2], AValue, LCarry);
  116.   Result.QuadPart[3] := MultiplyWithCarry(Self.QuadPart[3], AValue, LCarry);
  117. end;
  118.  
  119. function UInt128.Divide(const AValue: LongWord; out ARemainder: LongWord): UInt128;
  120. begin
  121.   ARemainder := 0;
  122.   Result.QuadPart[3] := DivideWithRemainder(Self.QuadPart[3], AValue, ARemainder);
  123.   Result.QuadPart[2] := DivideWithRemainder(Self.QuadPart[2], AValue, ARemainder);
  124.   Result.QuadPart[1] := DivideWithRemainder(Self.QuadPart[1], AValue, ARemainder);
  125.   Result.QuadPart[0] := DivideWithRemainder(Self.QuadPart[0], AValue, ARemainder);
  126. end;
  127.  
  128. end.