Changeset 161


Ignore:
Timestamp:
Apr 26, 2018, 1:10:38 PM (6 years ago)
Author:
chronos
Message:
  • Modified: Further Int128 unit implementation.
Location:
branches/virtualcpu3
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • branches/virtualcpu3/UFormMain.lfm

    r160 r161  
    77  ClientHeight = 783
    88  ClientWidth = 1028
     9  DesignTimePPI = 120
    910  OnShow = FormShow
    10   LCLVersion = '1.8.0.4'
     11  LCLVersion = '1.8.2.0'
    1112  object Memo1: TMemo
    1213    Left = 48
  • branches/virtualcpu3/UFormMain.pas

    r160 r161  
    1919
    2020  public
    21     procedure TestInt128;
    2221  end;
    2322
     
    5453  Writer64: TInstWriter64;
    5554begin
    56   TestInt128;
    57 
    5855{  CPU8 := TCPU8.Create;
    5956  Writer8 := TInstWriter8.Create;
     
    9390end;
    9491
    95 procedure TForm1.TestInt128;
    96 var
    97   A, B, C: Int128;
    98 begin
    99   A := 2;
    100   B := 3;
    101   C := A + B;
    102   Memo1.Lines.Add(IntToStr(A) + ' + ' + IntToStr(B) + ' = ' + IntToStr(C));
    103   C := A * B;
    104   Memo1.Lines.Add(IntToStr(A) + ' * ' + IntToStr(B) + ' = ' + IntToStr(C));
    105 end;
    106 
    10792end.
    10893
  • branches/virtualcpu3/UInt128.pas

    r160 r161  
    99
    1010type
     11
     12  { UInt128 }
     13
     14  UInt128 = packed record
     15    procedure SetZero;
     16    procedure SetOne;
     17    procedure SetMinimum;
     18    procedure SetMaximum;
     19    function IsZero: Boolean;
     20    function IsOne: Boolean;
     21    function IsMinimum: Boolean;
     22    function IsMaximum: Boolean;
     23    class function Min(A, B: UInt128): UInt128; static;
     24    class function Max(A, B: UInt128): UInt128; static;
     25    class function Zero: UInt128; static;
     26    class function One: UInt128; static;
     27    class function Minimum: UInt128; static;
     28    class function Maximum: UInt128; static;
     29    class function Compare(A, B: UInt128): Int8; static;
     30    class procedure IntDivMod(A, B: UInt128; var Q, R: UInt128); static;
     31    class operator Inc(A: UInt128): UInt128;
     32    class operator Dec(A: UInt128): UInt128;
     33    class operator Implicit(A: ShortInt): UInt128;
     34    class operator Implicit(A: Byte): UInt128;
     35    class operator Implicit(A: UInt128): Byte;
     36    class operator Implicit(A: UInt128): LongWord;
     37    class operator Implicit(A: UInt128): ShortInt;
     38    class operator BitwiseXor(A, B: UInt128): UInt128;
     39    class operator BitwiseAnd(A, B: UInt128): UInt128;
     40    class operator BitwiseOr(A, B: UInt128): UInt128;
     41    class operator Add(A, B: UInt128): UInt128;
     42    class operator Subtract(A, B: UInt128): UInt128;
     43    class operator Equal(A, B: UInt128): Boolean;
     44    class operator LessThan(A, B: UInt128): Boolean;
     45    class operator LessThanOrEqual(A, B: UInt128): Boolean;
     46    class operator GreaterThan(A, B: UInt128): Boolean;
     47    class operator GreaterThanOrEqual(A, B: UInt128): Boolean;
     48    class operator Multiply(A, B: UInt128): UInt128;
     49    class operator IntDivide(A, B: UInt128): UInt128;
     50    class operator Modulus(A, B: UInt128): UInt128;
     51    class operator LeftShift(A, B: UInt128): UInt128;
     52    class operator RightShift(A, B: UInt128): UInt128;
     53    case Integer of
     54      0: (Bytes: array[0..15] of Byte);
     55      1: (Words: array[0..7] of Word);
     56      2: (LongWords: array[0..3] of LongWord);
     57      3: (QWords: array[0..1] of QWord);
     58  end;
     59  PUInt128 = ^UInt128;
    1160
    1261  { Int128 }
     
    2776    function Abs: Int128;
    2877    function Sign: Int8;
    29     function Min(A, B: Int128): Int128;
    30     function Max(A, B: Int128): Int128;
     78    class function Min(A, B: Int128): Int128; static;
     79    class function Max(A, B: Int128): Int128; static;
    3180    class function Zero: Int128; static;
    3281    class function One: Int128; static;
     
    3584    class function Maximum: Int128; static;
    3685    class function Compare(A, B: Int128): Int8; static;
     86    class procedure IntDivMod(A, B: Int128; var Q, R: Int128); static;
     87    class operator Inc(A: Int128): Int128;
     88    class operator Dec(A: Int128): Int128;
    3789    class operator Implicit(A: ShortInt): Int128;
    3890    class operator Implicit(A: Byte): Int128;
     91    class operator Implicit(A: Int64): Int128;
     92    class operator Implicit(A: UInt128): Int128;
     93    class operator Implicit(A: Int128): ShortInt;
    3994    class operator Implicit(A: Int128): Byte;
    4095    class operator Implicit(A: Int128): LongWord;
     96    class operator Implicit(A: Int128): UInt128;
    4197    class operator BitwiseXor(A, B: Int128): Int128;
    4298    class operator BitwiseAnd(A, B: Int128): Int128;
     
    67123  PInt128 = ^Int128;
    68124
    69 function IntToStr(Value: Int128): string;
     125function IntToStr(Value: Int128): string; overload;
     126function IntToStr(Value: UInt128): string; overload;
     127function IntToHex(Value: Int128; Digits: integer): string; overload;
     128function IntToHex(Value: UInt128; Digits: integer): string; overload;
    70129
    71130
    72131implementation
     132
     133
     134const
     135   HexDigits: array[0..15] of Char = '0123456789ABCDEF';
    73136
    74137// Raise errors using Error function in System.pas
     
    78141  Error(reIntOverflow);
    79142end;
     143{$ENDIF}
     144
     145{$IFOPT R+}
     146procedure RaiseRangeError;
     147begin
     148  Error(reRangeError);
     149end;
     150{$ENDIF}
     151procedure RaiseDivByZeroError;
     152begin
     153  Error(reDivByZero);
     154end;
     155
     156function IntToHex(Value: Int128; Digits: integer): string;
     157var
     158  I: Integer;
     159begin
     160  if Digits = 0 then
     161    Digits := 1;
     162  SetLength(Result, Digits);
     163  for I := 0 to Digits - 1 do
     164  begin
     165    Result[Digits - I] := HexDigits[Value and 15];
     166    Value := Value shr 4;
     167  end ;
     168  while Value <> 0 do begin
     169    Result := HexDigits[Value and 15] + Result;
     170    Value := Value shr 4;
     171  end;
     172end;
     173
     174function IntToHex(Value: UInt128; Digits: integer): string;
     175var
     176  I: Integer;
     177begin
     178  if Digits = 0 then
     179    Digits := 1;
     180  SetLength(Result, Digits);
     181  for I := 0 to Digits - 1 do
     182  begin
     183    Result[Digits - I] := HexDigits[Value and 15];
     184    Value := Value shr 4;
     185  end ;
     186  while Value <> 0 do begin
     187    Result := HexDigits[Value and 15] + Result;
     188    Value := Value shr 4;
     189  end;
     190end;
    80191
    81192function IntToStr(Value: Int128): string;
     
    83194  Result := '';
    84195  if Value < 0 then begin
    85     while Value < 9 do begin
     196    Value := -Value;
     197    while Value > 9 do begin
    86198      Result := Chr(Ord('0') + (Value mod 10)) + Result;
    87199      Value := Value div 10;
     
    90202  end else begin
    91203    while Value > 9 do begin
    92       Result := Result + Chr(Ord('0') + (Value mod 10));
     204      Result := Chr(Ord('0') + (Value mod 10)) + Result;
    93205      Value := Value div 10;
    94206    end;
     
    97209end;
    98210
    99 {$ENDIF}
    100 
    101 { Int128 }
    102 
    103 procedure Int128.SetZero;
     211function IntToStr(Value: UInt128): string;
     212begin
     213  Result := '';
     214  while Value < 9 do begin
     215    Result := Chr(Ord('0') + (Value mod 10)) + Result;
     216    Value := Value div 10;
     217  end;
     218  Result := Chr(Ord('0') + (Value mod 10)) + Result;
     219end;
     220
     221{ UInt128 }
     222
     223procedure UInt128.SetZero;
    104224begin
    105225  QWords[0] := 0;
     
    107227end;
    108228
    109 procedure Int128.SetOne;
     229procedure UInt128.SetOne;
    110230begin
    111231  QWords[0] := 1;
     
    113233end;
    114234
    115 procedure Int128.SetMinusOne;
     235procedure UInt128.SetMinimum;
     236begin
     237  SetZero;
     238end;
     239
     240procedure UInt128.SetMaximum;
    116241begin
    117242  LongWords[0] := $ffffffff;
     
    121246end;
    122247
     248function UInt128.IsZero: Boolean;
     249begin
     250  Result := Self = UInt128.Zero;
     251end;
     252
     253function UInt128.IsOne: Boolean;
     254begin
     255  Result := Self = UInt128.One;
     256end;
     257
     258function UInt128.IsMinimum: Boolean;
     259begin
     260  Result := Self = UInt128.Minimum;
     261end;
     262
     263function UInt128.IsMaximum: Boolean;
     264begin
     265  Result := Self = UInt128.Maximum;
     266end;
     267
     268class function UInt128.Min(A, B: UInt128): UInt128;
     269begin
     270  if A < B then Result := A else Result := B;
     271end;
     272
     273class function UInt128.Max(A, B: UInt128): UInt128;
     274begin
     275  if A > B then Result := A else Result := B;
     276end;
     277
     278class function UInt128.Zero: UInt128;
     279begin
     280  Result.SetZero;
     281end;
     282
     283class function UInt128.One: UInt128;
     284begin
     285  Result.SetOne;
     286end;
     287
     288class function UInt128.Minimum: UInt128;
     289begin
     290  Result.SetMinimum;
     291end;
     292
     293class function UInt128.Maximum: UInt128;
     294begin
     295  Result.SetMaximum;
     296end;
     297
     298class function UInt128.Compare(A, B: UInt128): Int8;
     299var
     300  C, D: LongWord;
     301begin
     302  C := A.LongWords[3];
     303  D := B.LongWords[3];
     304  if C = D then
     305    begin
     306      C := A.LongWords[2];
     307      D := B.LongWords[2];
     308      if C = D then
     309        begin
     310          C := A.LongWords[1];
     311          D := B.LongWords[1];
     312          if C = D then
     313            begin
     314              C := A.LongWords[0];
     315              D := B.LongWords[0];
     316            end;
     317        end;
     318    end;
     319  if C > D then
     320    Result := 1 else
     321  if C < D then
     322    Result := -1
     323  else
     324    Result := 0;
     325end;
     326
     327class operator UInt128.Implicit(A: ShortInt): UInt128;
     328begin
     329  {$IFOPT R+}
     330  if A < 0 then
     331    RaiseRangeError;
     332  {$ENDIF}
     333  Result.SetZero;
     334  Result.Bytes[0] := A;
     335end;
     336
     337class operator UInt128.Implicit(A: Byte): UInt128;
     338begin
     339  Result.SetZero;
     340  Result.Bytes[0] := A;
     341end;
     342
     343class operator UInt128.Implicit(A: UInt128): Byte;
     344begin
     345  Result := A.Bytes[0];
     346end;
     347
     348class operator UInt128.Implicit(A: UInt128): LongWord;
     349begin
     350  Result := A.LongWords[0];
     351end;
     352
     353class operator UInt128.Implicit(A: UInt128): ShortInt;
     354begin
     355  {$IFOPT R+}
     356  if not (A <= High(ShortInt)) then
     357    RaiseRangeError;
     358  {$ENDIF}
     359  Result := A.Bytes[0];
     360end;
     361
     362class operator UInt128.BitwiseXor(A, B: UInt128): UInt128;
     363begin
     364  Result.LongWords[0] := A.LongWords[0] xor B.LongWords[0];
     365  Result.LongWords[1] := A.LongWords[1] xor B.LongWords[1];
     366end;
     367
     368class operator UInt128.BitwiseAnd(A, B: UInt128): UInt128;
     369begin
     370  Result.LongWords[0] := A.LongWords[0] and B.LongWords[0];
     371  Result.LongWords[1] := A.LongWords[1] and B.LongWords[1];
     372end;
     373
     374class operator UInt128.BitwiseOr(A, B: UInt128): UInt128;
     375begin
     376  Result.LongWords[0] := A.LongWords[0] or B.LongWords[0];
     377  Result.LongWords[1] := A.LongWords[1] or B.LongWords[1];
     378end;
     379
     380class operator UInt128.Add(A, B: UInt128): UInt128;
     381var
     382  C: LongWord;
     383  D: Integer;
     384begin
     385  C := LongWord(A.Words[0]) + B.Words[0];
     386  Result.Words[0] := Word(C and $FFFF);
     387
     388  for D := 1 to 7 do begin
     389    C := C shr 16;
     390    Inc(C, A.Words[D]);
     391    Inc(C, B.Words[D]);
     392    Result.Words[D] := Word(C and $FFFF);
     393  end;
     394
     395  {$IFOPT Q+}
     396  C := C shr 16;
     397  if C > 0 then RaiseOverflowError;
     398  {$ENDIF}
     399end;
     400
     401class operator UInt128.Subtract(A, B: UInt128): UInt128;
     402var
     403  C, D: Integer;
     404begin
     405  C := A.Words[0];
     406  Dec(C, B.Words[0]);
     407  Result.Words[0] := Word(C);
     408
     409  for D := 1 to 7 do
     410    begin
     411      if C < 0 then C := -1 else C := 0;
     412      Inc(C, A.Words[D]);
     413      Dec(C, B.Words[D]);
     414      Result.Words[D] := Word(C);
     415    end;
     416
     417  {$IFOPT Q+}
     418  if C < 0 then RaiseOverflowError;
     419  {$ENDIF}
     420end;
     421
     422class operator UInt128.Equal(A, B: UInt128): Boolean;
     423begin
     424  Result := (A.LongWords[0] = B.LongWords[0]) and
     425    (A.LongWords[1] = B.LongWords[1]);
     426end;
     427
     428class operator UInt128.LessThan(A, B: UInt128): Boolean;
     429var
     430  G: Int8;
     431begin
     432  G := Compare(A, B);
     433  Result := G = -1;
     434end;
     435
     436class operator UInt128.LessThanOrEqual(A, B: UInt128): Boolean;
     437begin
     438  Result := not (A > B);
     439end;
     440
     441class operator UInt128.GreaterThan(A, B: UInt128): Boolean;
     442begin
     443  Result := Compare(A, B) = 1;
     444end;
     445
     446class operator UInt128.GreaterThanOrEqual(A, B: UInt128): Boolean;
     447begin
     448  Result := not (A < B);
     449end;
     450
     451class operator UInt128.Multiply(A, B: UInt128): UInt128;
     452var
     453  C : Int64;
     454begin
     455  C := LongWord(A.Words[0]) * B.Words[0];
     456  Result.Words[0] := Word(C);
     457
     458  C := C shr 16;
     459  Inc(C, LongWord(A.Words[0]) * B.Words[1]);
     460  Inc(C, LongWord(A.Words[1]) * B.Words[0]);
     461  Result.Words[1] := Word(C);
     462
     463  C := C shr 16;
     464  Inc(C, LongWord(A.Words[0]) * B.Words[2]);
     465  Inc(C, LongWord(A.Words[1]) * B.Words[1]);
     466  Inc(C, LongWord(A.Words[2]) * B.Words[0]);
     467  Result.Words[2] := Word(C);
     468
     469  C := C shr 16;
     470  Inc(C, LongWord(A.Words[0]) * B.Words[3]);
     471  Inc(C, LongWord(A.Words[1]) * B.Words[2]);
     472  Inc(C, LongWord(A.Words[2]) * B.Words[1]);
     473  Inc(C, LongWord(A.Words[3]) * B.Words[0]);
     474  Result.Words[3] := Word(C);
     475
     476  C := C shr 16;
     477  Inc(C, LongWord(A.Words[0]) * B.Words[4]);
     478  Inc(C, LongWord(A.Words[1]) * B.Words[3]);
     479  Inc(C, LongWord(A.Words[2]) * B.Words[2]);
     480  Inc(C, LongWord(A.Words[3]) * B.Words[1]);
     481  Inc(C, LongWord(A.Words[4]) * B.Words[0]);
     482  Result.Words[4] := Word(C);
     483
     484  C := C shr 16;
     485  Inc(C, LongWord(A.Words[0]) * B.Words[5]);
     486  Inc(C, LongWord(A.Words[1]) * B.Words[4]);
     487  Inc(C, LongWord(A.Words[2]) * B.Words[3]);
     488  Inc(C, LongWord(A.Words[3]) * B.Words[2]);
     489  Inc(C, LongWord(A.Words[4]) * B.Words[1]);
     490  Inc(C, LongWord(A.Words[5]) * B.Words[0]);
     491  Result.Words[5] := Word(C);
     492
     493  C := C shr 16;
     494  Inc(C, LongWord(A.Words[0]) * B.Words[6]);
     495  Inc(C, LongWord(A.Words[1]) * B.Words[5]);
     496  Inc(C, LongWord(A.Words[2]) * B.Words[4]);
     497  Inc(C, LongWord(A.Words[3]) * B.Words[3]);
     498  Inc(C, LongWord(A.Words[4]) * B.Words[2]);
     499  Inc(C, LongWord(A.Words[5]) * B.Words[1]);
     500  Inc(C, LongWord(A.Words[6]) * B.Words[0]);
     501  Result.Words[6] := Word(C);
     502
     503  C := C shr 16;
     504  Inc(C, LongWord(A.Words[0]) * B.Words[7]);
     505  Inc(C, LongWord(A.Words[1]) * B.Words[6]);
     506  Inc(C, LongWord(A.Words[2]) * B.Words[5]);
     507  Inc(C, LongWord(A.Words[3]) * B.Words[4]);
     508  Inc(C, LongWord(A.Words[4]) * B.Words[3]);
     509  Inc(C, LongWord(A.Words[5]) * B.Words[2]);
     510  Inc(C, LongWord(A.Words[6]) * B.Words[1]);
     511  Inc(C, LongWord(A.Words[7]) * B.Words[0]);
     512  Result.Words[7] := Word(C);
     513
     514  {$IFOPT Q+}
     515  C := C shr 16;
     516  Inc(C, LongWord(A.Words[1]) * B.Words[7]);
     517  Inc(C, LongWord(A.Words[2]) * B.Words[6]);
     518  Inc(C, LongWord(A.Words[3]) * B.Words[5]);
     519  Inc(C, LongWord(A.Words[4]) * B.Words[4]);
     520  Inc(C, LongWord(A.Words[5]) * B.Words[3]);
     521  Inc(C, LongWord(A.Words[6]) * B.Words[2]);
     522  Inc(C, LongWord(A.Words[7]) * B.Words[1]);
     523  if C > 0 then
     524    RaiseOverflowError;
     525
     526  C := C shr 16;
     527  Inc(C, LongWord(A.Words[2]) * B.Words[7]);
     528  Inc(C, LongWord(A.Words[3]) * B.Words[6]);
     529  Inc(C, LongWord(A.Words[4]) * B.Words[5]);
     530  Inc(C, LongWord(A.Words[5]) * B.Words[4]);
     531  Inc(C, LongWord(A.Words[6]) * B.Words[3]);
     532  Inc(C, LongWord(A.Words[7]) * B.Words[2]);
     533  if C > 0 then
     534    RaiseOverflowError;
     535
     536  C := C shr 16;
     537  Inc(C, LongWord(A.Words[3]) * B.Words[7]);
     538  Inc(C, LongWord(A.Words[4]) * B.Words[6]);
     539  Inc(C, LongWord(A.Words[5]) * B.Words[5]);
     540  Inc(C, LongWord(A.Words[6]) * B.Words[4]);
     541  Inc(C, LongWord(A.Words[7]) * B.Words[3]);
     542  if C > 0 then
     543    RaiseOverflowError;
     544
     545  C := C shr 16;
     546  Inc(C, LongWord(A.Words[4]) * B.Words[7]);
     547  Inc(C, LongWord(A.Words[5]) * B.Words[6]);
     548  Inc(C, LongWord(A.Words[6]) * B.Words[5]);
     549  Inc(C, LongWord(A.Words[7]) * B.Words[4]);
     550  if C > 0 then
     551    RaiseOverflowError;
     552
     553  C := C shr 16;
     554  Inc(C, LongWord(A.Words[5]) * B.Words[7]);
     555  Inc(C, LongWord(A.Words[6]) * B.Words[6]);
     556  Inc(C, LongWord(A.Words[7]) * B.Words[5]);
     557  if C > 0 then
     558    RaiseOverflowError;
     559
     560  C := C shr 16;
     561  Inc(C, LongWord(A.Words[6]) * B.Words[7]);
     562  Inc(C, LongWord(A.Words[7]) * B.Words[6]);
     563  if C > 0 then
     564    RaiseOverflowError;
     565
     566  C := C shr 16;
     567  Inc(C, LongWord(A.Words[7]) * B.Words[7]);
     568  if C > 0 then
     569    RaiseOverflowError;
     570  {$ENDIF}
     571end;
     572
     573class operator UInt128.IntDivide(A, B: UInt128): UInt128;
     574var
     575  M: UInt128;
     576begin
     577  IntDivMod(A, B, Result, M);
     578end;
     579
     580class procedure UInt128.IntDivMod(A, B: UInt128; var Q, R: UInt128);
     581var
     582  C: Integer;
     583  D: UInt128;
     584begin
     585  // Handle special cases
     586  if B.IsZero then begin // B = 0
     587    RaiseDivByZeroError;
     588  end else
     589  if B.IsOne then begin// B = 1
     590    Q := A;
     591    R.SetZero;
     592    Exit;
     593  end else
     594  if A.IsZero then begin // A = 0
     595    Q.SetZero;
     596    R.SetZero;
     597    Exit;
     598  end;
     599  C := UInt128.Compare(A, B);
     600  if C < 0 then begin // A < B
     601    R := A;
     602    Q.SetZero;
     603    Exit;
     604  end else
     605  if C = 0 then begin // A = B
     606    Q.SetOne;
     607    R.SetZero;
     608    Exit;
     609  end;
     610  // Divide using "restoring radix two" division
     611  D := A;
     612  R.SetZero; // remainder (128 bits)
     613  Q.SetZero; // quotient (128 bits)
     614  for C := 0 to 127 do begin
     615    // Shift high bit of dividend D into low bit of remainder R
     616    R := R shl 1;
     617    if D.LongWords[3] and $80000000 <> 0 then
     618      R.LongWords[0] := R.LongWords[0] or 1;
     619    D := D shl 1;
     620    // Shift quotient
     621    Q := Q shl 1;
     622    // Subtract divisor from remainder if large enough
     623    if UInt128.Compare(R, B) >= 0 then begin
     624      R := R - B;
     625      // Set result bit in quotient
     626      Q.LongWords[0] := Q.LongWords[0] or 1;
     627    end;
     628  end;
     629end;
     630
     631class operator UInt128.Inc(A: UInt128): UInt128;
     632var
     633  C: LongWord;
     634  D: Integer;
     635begin
     636  C := A.Words[0];
     637  Inc(C);
     638  Result.Words[0] := Word(C and $FFFF);
     639
     640  C := C shr 16;
     641  if C = 0 then Exit;
     642  Inc(C, A.Words[1]);
     643  Result.Words[1] := Word(C and $FFFF);
     644
     645  for D := 2 to 7 do begin
     646    C := C shr 16;
     647    if C = 0 then Exit;
     648    Inc(C, A.Words[D]);
     649    Result.Words[D] := Word(C and $FFFF);
     650  end;
     651
     652  {$IFOPT Q+}
     653  C := C shr 16;
     654  if C > 0 then RaiseOverflowError;
     655  {$ENDIF}
     656end;
     657
     658class operator UInt128.Dec(A: UInt128): UInt128;
     659begin
     660  Result := A - 1;
     661end;
     662
     663class operator UInt128.Modulus(A, B: UInt128): UInt128;
     664var
     665  D: UInt128;
     666begin
     667  IntDivMod(A, B, D, Result);
     668end;
     669
     670class operator UInt128.LeftShift(A, B: UInt128): UInt128;
     671var
     672  C, D : Byte;
     673begin
     674  if B = 0 then begin
     675    Exit;
     676  end else
     677  if B = 1 then begin
     678    Result.LongWords[3] := (A.LongWords[3] shl 1) or (A.LongWords[2] shr 31);
     679    Result.LongWords[2] := (A.LongWords[2] shl 1) or (A.LongWords[1] shr 31);
     680    Result.LongWords[1] := (A.LongWords[1] shl 1) or (A.LongWords[0] shr 31);
     681    Result.LongWords[0] := (A.LongWords[0] shl 1);
     682  end else
     683  if B >= 128 then begin
     684    A.SetZero;
     685  end else
     686  if B < 32 then begin // 1 <= B <= 31
     687    C := 32 - B;
     688    Result.LongWords[3] := (A.LongWords[3] shl B) or (A.LongWords[2] shr C);
     689    Result.LongWords[2] := (A.LongWords[2] shl B) or (A.LongWords[1] shr C);
     690    Result.LongWords[1] := (A.LongWords[1] shl B) or (A.LongWords[0] shr C);
     691    Result.LongWords[0] := (A.LongWords[0] shl B);
     692  end else
     693  if B < 64 then begin // 32 <= B <= 63
     694    D := B - 32;
     695    C := 32 - D;
     696    Result.LongWords[3] := (A.LongWords[2] shl D) or (A.LongWords[1] shr C);
     697    Result.LongWords[2] := (A.LongWords[1] shl D) or (A.LongWords[0] shr C);
     698    Result.LongWords[1] := (A.LongWords[0] shl D);
     699    Result.LongWords[0] := 0;
     700  end else
     701  if B < 96 then begin // 64 <= B <= 95
     702    D := B - 64;
     703    C := 32 - D;
     704    Result.LongWords[3] := (A.LongWords[1] shl D) or (A.LongWords[0] shr C);
     705    Result.LongWords[2] := (A.LongWords[0] shl D);
     706    Result.LongWords[1] := 0;
     707    Result.LongWords[0] := 0;
     708  end else begin          // 96 <= B <= 127
     709    D := B - 96;
     710    Result.LongWords[3] := (A.LongWords[0] shl D);
     711    Result.LongWords[2] := 0;
     712    Result.LongWords[1] := 0;
     713    Result.LongWords[0] := 0;
     714  end;
     715end;
     716
     717class operator UInt128.RightShift(A, B: UInt128): UInt128;
     718var
     719  C, D : Byte;
     720begin
     721  if B = 0 then begin
     722    Exit;
     723  end else
     724  if B = 1 then begin
     725    Result.LongWords[0] := (A.LongWords[0] shr 1) or (A.LongWords[1] shl 31);
     726    Result.LongWords[1] := (A.LongWords[1] shr 1) or (A.LongWords[2] shl 31);
     727    Result.LongWords[2] := (A.LongWords[2] shr 1) or (A.LongWords[3] shl 31);
     728    Result.LongWords[3] := (A.LongWords[3] shr 1);
     729  end else
     730  if B >= 128 then begin
     731    A.SetZero;
     732  end else
     733  if B < 32 then begin // 1 <= B <= 31
     734    C := 32 - B;
     735    Result.LongWords[0] := (A.LongWords[0] shr B) or (A.LongWords[1] shl C);
     736    Result.LongWords[1] := (A.LongWords[1] shr B) or (A.LongWords[2] shl C);
     737    Result.LongWords[2] := (A.LongWords[2] shr B) or (A.LongWords[3] shl C);
     738    Result.LongWords[3] := (A.LongWords[3] shr B);
     739  end else
     740  if B < 64 then begin // 32 <= B <= 63
     741    D := B - 32;
     742    C := 32 - D;
     743    Result.LongWords[0] := (A.LongWords[1] shr D) or (A.LongWords[2] shl C);
     744    Result.LongWords[1] := (A.LongWords[2] shr D) or (A.LongWords[3] shl C);
     745    Result.LongWords[2] := (A.LongWords[3] shr D);
     746    Result.LongWords[3] := 0;
     747  end else
     748  if B < 96 then begin // 64 <= B <= 95
     749    D := B - 64;
     750    C := 32 - D;
     751    Result.LongWords[0] := (A.LongWords[2] shr D) or (A.LongWords[3] shl C);
     752    Result.LongWords[1] := (A.LongWords[3] shr D);
     753    Result.LongWords[2] := 0;
     754    Result.LongWords[3] := 0;
     755  end else begin           // 96 <= B <= 127
     756    D := B - 96;
     757    Result.LongWords[0] := (A.LongWords[3] shr D);
     758    Result.LongWords[1] := 0;
     759    Result.LongWords[2] := 0;
     760    Result.LongWords[3] := 0;
     761  end;
     762end;
     763
     764{ Int128 }
     765
     766procedure Int128.SetZero;
     767begin
     768  QWords[0] := 0;
     769  QWords[1] := 0;
     770end;
     771
     772procedure Int128.SetOne;
     773begin
     774  QWords[0] := 1;
     775  QWords[1] := 0;
     776end;
     777
     778procedure Int128.SetMinusOne;
     779begin
     780  LongWords[0] := $ffffffff;
     781  LongWords[1] := $ffffffff;
     782  LongWords[2] := $ffffffff;
     783  LongWords[3] := $ffffffff;
     784end;
     785
    123786procedure Int128.SetMinimum;
    124787begin
     
    137800function Int128.IsNegative: Boolean;
    138801begin
    139   Result := Sign = -1;
     802  Result := (LongWords[3] and $80000000) <> 0;
    140803end;
    141804
    142805function Int128.IsPositive: Boolean;
    143806begin
    144   Result := Sign <> -1;
     807  Result := (LongWords[3] and $80000000) = 0;
    145808end;
    146809
     
    208871end;
    209872
    210 function Int128.Min(A, B: Int128): Int128;
     873class function Int128.Min(A, B: Int128): Int128;
    211874begin
    212875  if A < B then Result := A else Result := B;
    213876end;
    214877
    215 function Int128.Max(A, B: Int128): Int128;
     878class function Int128.Max(A, B: Int128): Int128;
    216879begin
    217880  if A > B then Result := A else Result := B;
     
    222885  if A < 0 then begin
    223886    Result.SetMinusOne;
    224     Result.Bytes[0] := A;
     887    Result.ShortInts[0] := A;
    225888  end else begin
    226889    Result.SetZero;
    227     Result.Bytes[0] := A;
     890    Result.ShortInts[0] := A;
    228891  end;
    229892end;
     
    235898end;
    236899
     900class operator Int128.Implicit(A: Int64): Int128;
     901begin
     902  Result.Int64s[0] := A;
     903  if A < 0 then Result.Int64s[1] := -1
     904    else Result.Int64s[1] := 0;
     905end;
     906
    237907class operator Int128.Implicit(A: Int128): Byte;
    238908begin
     909  {$IFOPT R+}
     910  if not ((A <= High(Byte)) and (A >= Low(Byte))) then
     911    RaiseRangeError;
     912  {$ENDIF}
    239913  Result := A.Bytes[0];
    240914end;
     
    243917begin
    244918  Result := A.LongWords[0];
     919end;
     920
     921class operator Int128.Implicit(A: Int128): UInt128;
     922begin
     923  {$IFOPT R+}
     924  if A.IsNegative then
     925    RaiseRangeError;
     926  {$ENDIF}
     927  Result.QWords[0] := A.QWords[0];
     928  Result.QWords[1] := A.QWords[1];
     929end;
     930
     931class operator Int128.Implicit(A: UInt128): Int128;
     932begin
     933  {$IFOPT R+}
     934  if A.LongWords[3] and $80000000 <> 0 then
     935    RaiseRangeError;
     936  {$ENDIF}
     937  Result.LongWords[0] := A.LongWords[0];
     938  Result.LongWords[1] := A.LongWords[1];
     939  Result.LongWords[2] := A.LongWords[2];
     940  Result.LongWords[3] := A.LongWords[3];
     941end;
     942
     943class operator Int128.Implicit(A: Int128): ShortInt;
     944begin
     945  {$IFOPT R+}
     946  if not ((A <= High(ShortInt)) and (A >= Low(ShortInt))) then
     947    RaiseRangeError;
     948  {$ENDIF}
     949  Result := A.ShortInts[0];
    245950end;
    246951
     
    2951000end;
    2961001
     1002class procedure Int128.IntDivMod(A, B: Int128; var Q, R: Int128);
     1003var
     1004  C, T: UInt128;
     1005  D, E: UInt128;
     1006begin
     1007  C := A.Abs;
     1008  D := B.Abs;
     1009  UInt128.IntDivMod(C, D, T, E);
     1010  if not (A.IsNegative xor B.IsNegative) then Q := T
     1011    else Q := -Int128(T);
     1012  R := E;
     1013end;
     1014
     1015class operator Int128.Inc(A: Int128): Int128;
     1016begin
     1017  Result := A + 1;
     1018end;
     1019
     1020class operator Int128.Dec(A: Int128): Int128;
     1021begin
     1022  Result := A - 1;
     1023end;
     1024
    2971025class operator Int128.Add(A, B: Int128): Int128;
    2981026var
     
    3681096class operator Int128.LessThanOrEqual(A, B: Int128): Boolean;
    3691097begin
    370   Result := A > B;
     1098  Result := not (A > B);
    3711099end;
    3721100
     
    3781106class operator Int128.GreaterThanOrEqual(A, B: Int128): Boolean;
    3791107begin
    380   Result := A < B;
     1108  Result := not (A < B);
    3811109end;
    3821110
    3831111class operator Int128.Negative(A: Int128): Int128;
    3841112begin
    385   Result := (A xor Int128.MinusOne) - 1;
     1113  Result := (A xor Int128.MinusOne) + 1;
    3861114end;
    3871115
     
    3971125
    3981126class operator Int128.IntDivide(A, B: Int128): Int128;
    399 begin
    400 
     1127var
     1128  M: Int128;
     1129begin
     1130  IntDivMod(A, B, Result, M);
    4011131end;
    4021132
    4031133class operator Int128.Modulus(A, B: Int128): Int128;
    404 begin
    405 
     1134var
     1135  D: Int128;
     1136begin
     1137  IntDivMod(A, B, D, Result);
    4061138end;
    4071139
     
    4711203  if B < 32 then begin // 1 <= B <= 31
    4721204    C := 32 - B;
    473     Result.LongWords[0] := (A.LongWords[0] shr B) or (A.LongWords[1] shl C);
    474     Result.LongWords[1] := (A.LongWords[1] shr B) or (A.LongWords[2] shl C);
    475     Result.LongWords[2] := (A.LongWords[2] shr B) or (A.LongWords[3] shl C);
    476     Result.LongWords[3] := (A.LongWords[3] shr B);
     1205    Result.LongWords[0] := (A.LongWords[0] shr Byte(B)) or (A.LongWords[1] shl C);
     1206    Result.LongWords[1] := (A.LongWords[1] shr Byte(B)) or (A.LongWords[2] shl C);
     1207    Result.LongWords[2] := (A.LongWords[2] shr Byte(B)) or (A.LongWords[3] shl C);
     1208    Result.LongWords[3] := (A.LongWords[3] shr Byte(B));
    4771209  end else
    4781210  if B < 64 then begin // 32 <= B <= 63
    4791211    D := B - 32;
    4801212    C := 32 - D;
    481     Result.LongWords[0] := (A.LongWords[1] shr D) or (A.LongWords[2] shl C);
    482     Result.LongWords[1] := (A.LongWords[2] shr D) or (A.LongWords[3] shl C);
    483     Result.LongWords[2] := (A.LongWords[3] shr D);
     1213    Result.LongWords[0] := (A.LongWords[1] shr Byte(D)) or (A.LongWords[2] shl C);
     1214    Result.LongWords[1] := (A.LongWords[2] shr Byte(D)) or (A.LongWords[3] shl C);
     1215    Result.LongWords[2] := (A.LongWords[3] shr Byte(D));
    4841216    Result.LongWords[3] := 0;
    4851217  end else
     
    4871219    D := B - 64;
    4881220    C := 32 - D;
    489     Result.LongWords[0] := (A.LongWords[2] shr D) or (A.LongWords[3] shl C);
    490     Result.LongWords[1] := (A.LongWords[3] shr D);
     1221    Result.LongWords[0] := (A.LongWords[2] shr Byte(D)) or (A.LongWords[3] shl C);
     1222    Result.LongWords[1] := (A.LongWords[3] shr Byte(D));
    4911223    Result.LongWords[2] := 0;
    4921224    Result.LongWords[3] := 0;
    4931225  end else begin           // 96 <= B <= 127
    4941226    D := B - 96;
    495     Result.LongWords[0] := (A.LongWords[3] shr D);
     1227    Result.LongWords[0] := (A.LongWords[3] shr Byte(D));
    4961228    Result.LongWords[1] := 0;
    4971229    Result.LongWords[2] := 0;
Note: See TracChangeset for help on using the changeset viewer.