From 2df8266d42dcb2364268ed479d36127e2665383f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20M=C3=BCller?= Date: Thu, 23 May 2024 22:01:25 +0200 Subject: [PATCH] Added some improvements for TBigInt shift left operator --- UBigInt.pas | 78 +++++++++++++++++++------------------- tests/UBigIntTestCases.pas | 3 +- 2 files changed, 42 insertions(+), 39 deletions(-) diff --git a/UBigInt.pas b/UBigInt.pas index 907ec6b..421368d 100644 --- a/UBigInt.pas +++ b/UBigInt.pas @@ -626,49 +626,51 @@ var begin // Handles shift of zero. if A = 0 then - Result := TBigInt.Zero - else begin - // Determines full digit shifts and bit shifts. - DivMod(B, CBitsPerDigit, digitShifts, bitShifts); + begin + Result := TBigInt.Zero; + Exit; + end; - if bitShifts > 0 then + // Determines full digit shifts and bit shifts. + DivMod(B, CBitsPerDigit, digitShifts, bitShifts); + + if bitShifts > 0 then + begin + reverseShift := CBitsPerDigit - bitShifts; + len := Length(A.FDigits); + lastDigit := A.FDigits[len - 1] >> reverseShift; + newLength := len + digitShifts; + + if lastDigit = 0 then + SetLength(Result.FDigits, newLength) + else + SetLength(Result.FDigits, newLength + 1); + + // Performs full digit shifts by shifting the access index j for A.FDigits. + Result.FDigits[digitShifts] := A.FDigits[0] << bitShifts; + j := 0; + for i := digitShifts + 1 to newLength - 1 do begin - reverseShift := CBitsPerDigit - bitShifts; - len := Length(A.FDigits); - lastDigit := A.FDigits[len - 1] >> reverseShift; - newLength := len + digitShifts; - - if lastDigit = 0 then - SetLength(Result.FDigits, newLength) - else - SetLength(Result.FDigits, newLength + 1); - - // Performs full digit shifts by shifting the access index j for A.FDigits. - Result.FDigits[digitShifts] := A.FDigits[0] << bitShifts; - j := 0; - for i := digitShifts + 1 to newLength - 1 do - begin - // Performs bit shifts. - Result.FDigits[i] := A.FDigits[j] >> reverseShift; - Inc(j); - Result.FDigits[i] := Result.FDigits[i] or (A.FDigits[j] << bitShifts); - end; - - if Length(Result.FDigits) > newLength then - Result.FDigits[newLength] := lastDigit; - end - else begin - // Performs full digit shifts by copy if there are no bit shifts. - len := Length(A.FDigits); - SetLength(Result.FDigits, len + digitShifts); - for i := 0 to digitShifts - 1 do - Result.FDigits[i] := 0; - for i := 0 to len - 1 do - Result.FDigits[i + digitShifts] := A.FDigits[i]; + // Performs bit shifts. + Result.FDigits[i] := A.FDigits[j] >> reverseShift; + Inc(j); + Result.FDigits[i] := Result.FDigits[i] or (A.FDigits[j] << bitShifts); end; - Result.FIsNegative := A.IsNegative; + if lastDigit > 0 then + Result.FDigits[newLength] := lastDigit; + end + else begin + // Performs full digit shifts by copy if there are no bit shifts. + len := Length(A.FDigits); + SetLength(Result.FDigits, len + digitShifts); + for i := 0 to digitShifts - 1 do + Result.FDigits[i] := 0; + for i := 0 to len - 1 do + Result.FDigits[i + digitShifts] := A.FDigits[i]; end; + + Result.FIsNegative := A.IsNegative; end; operator shr(const A: TBigInt; const B: Integer): TBigInt; diff --git a/tests/UBigIntTestCases.pas b/tests/UBigIntTestCases.pas index 06019b1..9639ac6 100644 --- a/tests/UBigIntTestCases.pas +++ b/tests/UBigIntTestCases.pas @@ -732,7 +732,8 @@ end; { TBigIntShiftLeftTestCase } -procedure TBigIntShiftLeftTestCase.Test(const AHexValueOperand: string; const AShift: Integer; const AHexValueResult: string); +procedure TBigIntShiftLeftTestCase.Test(const AHexValueOperand: string; const AShift: Integer; const AHexValueResult: + string); var a, s: TBigInt; begin