fcl-hash: fixed freeing TBigIntContext.BIRadix and migrated to mode objfpc

This commit is contained in:
mattias 2022-04-28 23:10:01 +02:00
parent 67905957cb
commit 864b2ad3f3
3 changed files with 121 additions and 147 deletions

View File

@ -335,7 +335,7 @@ begin
begin
Line:=sl[i];
if not PemLineIsBase64(Line) then
exit;
raise Exception.Create('20220428220523');
TxtBase64:=TxtBase64+Line;
end;
Result:=basenenc.Base64.Decode(TxtBase64,True);

View File

@ -159,10 +159,9 @@ begin
try
ASNParse(PublicKeyDER,List);
//for i:=0 to List.Count-1 do begin
// ASNParse_GetItem(List,i,ASNType,ASNSize);
// writeln('X509RsaPublicKeyInitFromDER ',i,'/',List.Count,' ASNType=',hexstr(ASNType,2),' ASNSize=',ASNSize,' S="',List[i],'"');
//end;
{$IFDEF TLS_DEBUG}
ASNDebugList('X509RsaPublicKeyInitFromDER',List);
{$ENDIF}
if List.Count<7 then
raise Exception.Create('20220428180055');
@ -186,7 +185,6 @@ begin
// check null
ASNParse_GetItem(List,3,ASNType,ASNSize);
writeln('X509RsaPublicKeyInitFromDER ',ASNType,' ',ASNSize);
if ASNType<>ASN1_NULL then
raise Exception.Create('20220428181659');
@ -206,8 +204,8 @@ begin
{$IFDEF TLS_DEBUG}
writeln('X509RsaPublicKeyInitFromDER: ');
writeln(' Modulus=',BytesToHexStr(RSA.Modulus));
writeln(' Exponent=',BytesToHexStr(RSA.Exponent));
writeln(' Modulus=$',BytesToHexStr(RSA.Modulus));
writeln(' Exponent=$',BytesToHexStr(RSA.Exponent));
{$ENDIF}
finally
List.Free;
@ -330,12 +328,12 @@ begin
if Len > Size-11 then
Exit;
{$IFDEF CRYPTO_DEBUG}
writeln('RSAEncryptSign - Len = ' + IntToStr(Len) + ' Size = ' + IntToStr(Size) + ' Padding = ' + IntToStr(Padding)); //To Do
writeln('RSAEncryptSign - Len = ' + IntToStr(Len) + ' Size = ' + IntToStr(Size) + ' Padding = ' + IntToStr(Padding)); //To Do
{$ENDIF}
if Size > RSA_MODULUS_BYTES_MAX then
Imported := GetMem(Size)
else
Imported := @Block;
Imported := @Block[0];
try
// Leading zero to ensure encryption block is less than modulus (when converted to an integer)
Imported[0]:=0;
@ -373,14 +371,14 @@ begin
if Sign then
begin
// Sign with Private Key
Encrypted:=BICRT(RSA.Context,Decrypted,RSA.DP,RSA.DQ,RSA.P,RSA.Q,RSA.QInv);
Encrypted:=BICRT(RSA.Context,Decrypted,RSA.DP,RSA.DQ,RSA.P,RSA.Q,RSA.QInv); // this releases Decrypted
end else
begin
// Encrypt with Public Key
RSA.Context.ModOffset:=BIGINT_M_OFFSET;
Encrypted:=BIModPower(RSA.Context,Decrypted,RSA.E);
Encrypted:=BIModPower(RSA.Context,Decrypted,RSA.E); // this releases Decrypted
end;
BIExport(RSA.Context,Encrypted,Output,Size);
BIExport(RSA.Context,Encrypted,Output,Size); // this releases Encrypted
{$IFDEF CRYPTO_DEBUG}
writeln('RSAEncryptSign - Output Size = ' + IntToStr(Size) + ' Output = ',Output,Size);

View File

@ -13,7 +13,7 @@ interface
uses SysUtils;
{ $DEFINE BIGINT_DEBUG} // Enable debug output/functions for BitInt unit
{$DEFINE BIGINT_DEBUG} // Enable debug output/functions for BitInt unit
const
// Maintain a number of precomputed variables when doing reduction
@ -43,9 +43,6 @@ type
PBISignedLongComponent = ^TBISignedLongComponent;
TBISignedLongComponent = Int64; // A signed double precision component
PBIComponents = ^TBIComponents;
TBIComponents = array[0..(MaxInt div SizeOf(TBIComponent))-1] of TBIComponent;
type
PPBigInt = ^PBigInt;
PBigInt = ^TBigInt;
@ -57,8 +54,6 @@ type
Components: PBIComponent; // A ptr to the actual component data
procedure ToString(out S: AnsiString);
end;
PBigInts = ^TBigInts;
TBigInts = array[0..(MaxInt div SizeOf(PBigInt)) - 1] of PBigInt;
{Maintains the state of the cache, and a number of variables used in reduction}
PBigIntContext = ^TBigIntContext;
@ -80,12 +75,12 @@ procedure BIInitialize(out Context: TBigIntContext);
procedure BITerminate(var Context: TBigIntContext);
procedure BIPermanent(BI: PBigInt);
procedure BIDepermanent(BI: PBigInt);
procedure BIRelease(var Context: TBigIntContext; BI:PBigInt);
procedure BIRelease(var Context: TBigIntContext; BI: PBigInt);
function BICopy(BI: PBigInt): PBigInt;
function BIClone(var Context: TBigIntContext; const BI: TBigInt): PBigInt;
procedure BIExport(var Context: TBigIntContext; BI: PBigInt; Data: PByte; Size: Integer);
procedure BIExport(var Context: TBigIntContext; BI: PBigInt; Data: PByte; Size: Integer; Release: boolean = true);
function BIImport(var Context: TBigIntContext; Data: PByte; const Size: Integer): PBigInt; overload;
function BIImport(var Context: TBigIntContext; const Data: TBytes): PBigInt; overload;
function BIImport(var Context: TBigIntContext; const Data: AnsiString): PBigInt; overload;
@ -142,23 +137,19 @@ end;
{Perform a sanity check on bi}
function BICheck(const BI: TBigInt): Boolean; inline;
begin
{$IFDEF BIGINT_DEBUG}
{$IFDEF BIGINT_DEBUG}
if BI.References <= 0 then
begin
XLog(tlDebug, 'TLS', 'BICheck - Zero or negative References in TBigInt');
Result := False;
Exit;
writeln('BICheck - Zero or negative References in TBigInt');
raise Exception.Create('20220428201452');
end;
if BI.Next <> nil then
begin
XLog(tlDebug, 'TLS', 'BICheck - Attempt to use a TBigInt from the free list');
Result := False;
Exit;
writeln('BICheck - Attempt to use a TBigInt from the free list');
raise Exception.Create('20220428201508');
end;
{$ENDIF}
Result:=True;
{$ELSE}
Result:=True;
{$ENDIF}
end;
// Delete any leading 0's (and allow for 0)
@ -166,14 +157,11 @@ procedure BITrim(BI: PBigInt);
begin
if not BICheck(BI^) then
Exit;
while (PBIComponents(BI^.Components)^[BI^.Size-1] = 0) and (BI^.Size > 1) do
while (BI^.Components[BI^.Size-1] = 0) and (BI^.Size > 1) do
Dec(BI^.Size);
end;
procedure BIAddComponents(var Context: TBigIntContext; BI: PBigInt; N: Integer);
var
OldComponents: PBIComponent;
OldMaxComponents: Int32;
procedure BIResizeComponents(BI: PBigInt; N: Integer);
begin
if N > BI^.MaxComponents then
begin
@ -181,7 +169,7 @@ begin
ReAllocMem(BI^.Components, BI^.MaxComponents*BIGINT_COMP_BYTE_SIZE);
end;
if N > BI^.Size then
FillChar(PBIComponents(BI^.Components)^[BI^.Size], (N-BI^.Size)*BIGINT_COMP_BYTE_SIZE, 0);
FillByte(BI^.Components[BI^.Size], (N-BI^.Size)*BIGINT_COMP_BYTE_SIZE, 0);
BI^.Size := N;
end;
@ -190,21 +178,18 @@ begin
if Context.FreeList <> nil then
begin
Result := Context.FreeList;
if Result^.References <> 0 then
raise Exception.Create('20220428200026');
Context.FreeList := Result^.Next;
Dec(Context.FreeCount);
if Result^.References <> 0 then
begin
Result := nil;
Exit;
end;
BIAddComponents(Context, Result, Size);
BIResizeComponents(Result, Size);
end else
begin
Result := AllocMem(SizeOf(TBigint));
Result^.Components := AllocMem((Size*2)*BIGINT_COMP_BYTE_SIZE);
Result^.MaxComponents := Size*2; // Allow space to expand
Result^.Size := Size;
end;
Result^.Size := Size;
Result^.References := 1;
Result^.Next := nil;
Inc(Context.ActiveCount);
@ -218,7 +203,7 @@ var
begin
I := BIGINT_COMP_BIT_SIZE-1;
Shift:=BIGINT_COMP_RADIX div 2;
Test:=PBIComponents(BIExp^.Components)^[BIExp^.Size - 1]; {Assume no leading zeroes}
Test:=BIExp^.Components[BIExp^.Size - 1]; {Assume no leading zeroes}
if not BICheck(BIExp^) then
begin
Result:=-1;
@ -242,12 +227,12 @@ var
NumShifts: Integer;
Shift, Test: TBIComponent;
begin
Test := PBIComponents(BIExp^.Components)^[Offset div BIGINT_COMP_BIT_SIZE];
Test := BIExp^.Components[Offset div BIGINT_COMP_BIT_SIZE];
NumShifts := Offset mod BIGINT_COMP_BIT_SIZE;
if not BICheck(BIExp^) then
begin
Result := False;
Exit;
Result := False;
Exit;
end;
Shift := 1 shl NumShifts;
Result := (Test and Shift) <> 0;
@ -274,7 +259,7 @@ begin
A := BIA^.Components;
FillChar(R^, (N+1) * BIGINT_COMP_BYTE_SIZE, 0);
repeat
Tmp := R^ + TBILongComponent(PBIComponents(A)^[J]) * B + Carry; // Avoid overflow
Tmp := R^ + TBILongComponent(A[J]) * B + Carry; // Avoid overflow
R^ := Tmp; // Downsize
Inc(R);
Carry := Tmp shr BIGINT_COMP_BIT_SIZE;
@ -285,7 +270,7 @@ begin
BITrim(Result);
end;
function BIIntDivide(var Context: TBigIntContext; BIR: PBigInt; Denom: TBIComponent): PBigInt;
function BIIntDivide(BIR: PBigInt; Denom: TBIComponent): PBigInt;
var
I: Integer;
R: TBILongComponent;
@ -298,8 +283,8 @@ begin
I := BIR^.Size-1;
R := 0;
repeat
R := (R shl BIGINT_COMP_BIT_SIZE) + PBIComponents(BIR^.Components)^[I];
PBIComponents(BIR^.Components)^[I] := R div Denom;
R := (R shl BIGINT_COMP_BIT_SIZE) + BIR^.Components[I];
BIR^.Components[I] := R div Denom;
R := R mod Denom;
Dec(I);
until I < 0;
@ -320,10 +305,10 @@ begin
end;
I := BIR^.Size-NumShifts;
X := BIR^.Components;
Y := @PBIComponents(BIR^.Components)^[NumShifts];
Y := @BIR^.Components[NumShifts];
if I <= 0 then // Have we completely right shifted?
begin
PBIComponents(BIR^.Components)^[0]:=0; {Return 0}
BIR^.Components[0]:=0; {Return 0}
BIR^.Size:=1;
Result:=BIR;
Exit;
@ -339,7 +324,7 @@ begin
end;
// Take each component and shift it up (in terms of components)
function BICompLeftShift(var Context: TBigIntContext; BIR: PBigInt; NumShifts: Integer): PBigInt;
function BICompLeftShift(BIR: PBigInt; NumShifts: Integer): PBigInt;
var
I: Integer;
X: PBIComponent;
@ -356,16 +341,16 @@ begin
Result:=BIR;
Exit;
end;
BIAddComponents(Context, BIR, BIR^.Size+NumShifts);
X := @(PBIComponents(BIR^.Components)^[I + NumShifts]);
Y := @(PBIComponents(BIR^.Components)^[I]);
BIResizeComponents(BIR, BIR^.Size+NumShifts);
X := @(BIR^.Components[I + NumShifts]);
Y := @(BIR^.Components[I]);
repeat
X^ := Y^;
Dec(X);
Dec(Y);
Dec(I);
until I < 0;
FillChar(BIR^.Components^, NumShifts*BIGINT_COMP_BYTE_SIZE, 0); // Zero least significant components
FillByte(BIR^.Components^, NumShifts*BIGINT_COMP_BYTE_SIZE, 0); // Zero least significant components
Result := BIR;
end;
@ -390,7 +375,7 @@ begin
SR := BIR^.Components;
SA := BIA^.Components;
SB := BIB^.Components;
FillChar(BIR^.Components^, (N+T) * BIGINT_COMP_BYTE_SIZE, 0);
FillByte(BIR^.Components^, (N+T) * BIGINT_COMP_BYTE_SIZE, 0);
repeat
Carry := 0;
RIndex := I;
@ -403,13 +388,13 @@ begin
repeat
if (InnerPartial > 0) and (RIndex >= InnerPartial) then
Break;
Tmp := PBIComponents(SR)^[RIndex] + TBILongComponent(PBIComponents(SA)^[J]) * PBIComponents(SB)^[I] + Carry; // Avoid overflow
PBIComponents(SR)^[RIndex] := Tmp; // Downsize
Tmp := SR[RIndex] + TBILongComponent(SA[J]) * SB[I] + Carry; // Avoid overflow
SR[RIndex] := Tmp; // Downsize
Inc(RIndex);
Carry := Tmp shr BIGINT_COMP_BIT_SIZE;
Inc(J);
until J >= N;
PBIComponents(SR)^[RIndex] := Carry;
SR[RIndex] := Carry;
Inc(I);
until I >= T;
BIRelease(Context,BIA);
@ -435,32 +420,32 @@ begin
X := BI^.Components;
FillChar(W^,BIR^.Size * BIGINT_COMP_BYTE_SIZE,0);
repeat
Tmp := PBIComponents(W)^[2*I] + TBILongComponent(PBIComponents(X)^[I]) * PBIComponents(X)^[I]; // Avoid overflow
PBIComponents(W)^[2 * I] := Tmp;
Tmp := W[2*I] + TBILongComponent(X[I]) * X[I]; // Avoid overflow
W[2 * I] := Tmp;
Carry := Tmp shr BIGINT_COMP_BIT_SIZE;
J := I+1;
while J < T do
begin
C := 0;
XX := TBILongComponent(PBIComponents(X)^[I]) * PBIComponents(X)^[J]; // Avoid overflow
XX := TBILongComponent(X[I]) * X[J]; // Avoid overflow
if BIGINT_COMP_MAX-XX < XX then
C := 1;
Tmp := XX shl 1;
if BIGINT_COMP_MAX-Tmp < PBIComponents(W)^[I + J] then
if BIGINT_COMP_MAX-Tmp < W[I + J] then
C := 1;
Tmp := Tmp + PBIComponents(W)^[I + J];
Tmp := Tmp + W[I + J];
if BIGINT_COMP_MAX-Tmp < Carry then
C := 1;
Tmp := Tmp + Carry;
PBIComponents(W)^[I + J] := Tmp;
W[I + J] := Tmp;
Carry := Tmp shr BIGINT_COMP_BIT_SIZE;
if C > 0 then
Carry := Carry + BIGINT_COMP_RADIX;
Inc(J);
end;
Tmp := PBIComponents(W)^[I+T]+Carry;
PBIComponents(W)^[I+T] := Tmp;
PBIComponents(W)^[I+T+1] := Tmp shr BIGINT_COMP_BIT_SIZE;
Tmp := W[I+T]+Carry;
W[I+T] := Tmp;
W[I+T+1] := Tmp shr BIGINT_COMP_BIT_SIZE;
Inc(I);
until I >= T;
BIRelease(Context, BI);
@ -495,44 +480,49 @@ begin
Inc(I);
end;
Context.G := AllocMem(K*SizeOf(PBigInt));
PBigInts(Context.G)^[0] := BIClone(Context, G1^);
BIPermanent(PBigInts(Context.G)^[0]);
G2 := BIResidue(Context, BISquare(Context, PBigInts(Context.G)^[0])); {g^2}
Context.G[0] := BIClone(Context, G1^);
BIPermanent(Context.G[0]);
G2 := BIResidue(Context, BISquare(Context, Context.G[0])); {g^2}
for I := 1 to K-1 do
begin
PBigInts(Context.G)^[I] := BIResidue(Context, BIMultiply(Context, PBigInts(Context.G)^[I-1], BICopy(G2)));
BIPermanent(PBigInts(Context.G)^[I]);
Context.G[I] := BIResidue(Context, BIMultiply(Context, Context.G[I-1], BICopy(G2)));
BIPermanent(Context.G[I]);
end;
BIRelease(Context, G2);
Context.Window := K;
end;
procedure BIInitialize(out Context: TBigIntContext);
var
BIRadix: PBigInt;
begin
Context:=Default(TBigIntContext);
Context.BIRadix := BIAllocate(Context, 2);
PBIComponents(Context.BIRadix^.Components)^[0] := 0;
PBIComponents(Context.BIRadix^.Components)^[1] := 1;
BIPermanent(Context.BIRadix);
BIRadix:=BIAllocate(Context, 2);
Context.BIRadix := BIRadix;
BIRadix^.Components[0] := 0;
BIRadix^.Components[1] := 1;
BIPermanent(BIRadix);
end;
// Close the bigint context and free any resources
procedure BITerminate(var Context: TBigIntContext);
Var
BI,BN : PBigInt;
BI,BNext : PBigInt;
begin
FreeMem(Context.BIRadix);
BIRelease(Context, Context.BIRadix);
Context.BIRadix := nil;
BI:=Context.FreeList;
While BI<>Nil do
begin
BN:=BI^.Next;
BNext:=BI^.Next;
if BI^.Components<>Nil then
FreeMem(BI^.Components);
FreeMem(BI);
BI:=BN;
BI:=BNext;
end;
Context.FreeList:=nil;
end;
// Make a bigint object "unfreeable" if BIFree() is called on it
@ -541,24 +531,17 @@ begin
if not BICheck(BI^) then
Exit;
if BI^.References <> 1 then
begin
//XLog(tlDebug, 'TLS', 'BIPermanent - References not equal to one');
//To Do //Log Error /Raise Exception
Exit;
end;
raise Exception.Create('20220428195735');
BI^.References := BIGINT_PERMANENT;
end;
// Take a permanent object and make it freeable
procedure BIDepermanent(BI: PBigInt);
begin
if not BICHeck(BI^) then
if not BICheck(BI^) then
Exit;
if BI^.References <> BIGINT_PERMANENT then
begin
// XLog(tlDebug, 'TLS', 'BIDepermanent - References not equal to BIGINT_PERMANENT');
Exit;
end;
raise Exception.Create('20220428203636');
BI^.References := 1;
end;
@ -576,8 +559,10 @@ begin
Context.FreeList := BI;
Inc(Context.FreeCount);
Dec(Context.ActiveCount);
// if Context.ActiveCount < 0 then
// XLog(tlWarning, 'TLS', 'BIFree - ActiveCount less than zero');
{$IFDEF BIGINT_DEBUG}
if Context.ActiveCount < 0 then
raise Exception.Create('20220428203546');
{$ENDIF}
end;
{==============================================================================}
@ -606,7 +591,8 @@ begin
System.Move(BI.Components^, Result^.Components^, BI.Size*BIGINT_COMP_BYTE_SIZE);
end;
procedure BIExport(var Context: TBigIntContext; BI: PBigInt; Data: PByte; Size: Integer);
procedure BIExport(var Context: TBigIntContext; BI: PBigInt; Data: PByte;
Size: Integer; Release: boolean);
{Take a bigint and convert it into a byte sequence}
{Context: The bigint session context}
{BI: The bigint to be converted}
@ -616,28 +602,25 @@ var
I: Integer;
J: Integer;
K: Integer;
Mask: TBIComponent;
Num: Integer;
begin
if not BICheck(BI^) then
Exit;
FillChar(Data^,Size,0);
FillByte(Data^,Size,0);
K := Size-1;
try
for I := 0 to BI^.Size - 1 do
begin
for J := 0 to BIGINT_COMP_BYTE_SIZE - 1 do
begin
Mask := $FF shl (J * 8);
Num := (PBIComponents(BI^.Components)^[I] and Mask) shr (J * 8);
PByteArray(Data)^[K]:=Num;
Data[K]:=(BI^.Components[I] shr (J * 8)) and $ff;
Dec(K);
if K < 0 then
Exit;
end;
end;
finally
BIRelease(Context,BI);
if Release then
BIRelease(Context,BI);
end;
end;
@ -651,10 +634,10 @@ begin
J := 0;
Offset := 0;
Result := BIAllocate(Context, (Size+BIGINT_COMP_BYTE_SIZE-1) div BIGINT_COMP_BYTE_SIZE);
FillChar(Result^.Components^, Result^.Size*BIGINT_COMP_BYTE_SIZE, 0);
FillByte(Result^.Components^, Result^.Size*BIGINT_COMP_BYTE_SIZE, 0);
for I := Size-1 downto 0 do
begin
PBIComponents(Result^.Components)^[Offset] := PBIComponents(Result^.Components)^[Offset] + (PByteArray(Data)^[I] shl (J * 8));
Result^.Components[Offset] := Result^.Components[Offset] + (TBIComponent(Data[I]) shl (J * 8));
Inc(J);
if J = BIGINT_COMP_BYTE_SIZE then
begin
@ -666,7 +649,7 @@ end;
function BIImport(var Context: TBigIntContext; const Data: TBytes): PBigInt;
begin
Result := BIImport(Context, PByte(Data), Length(Data));
Result := BIImport(Context, @Data[0], Length(Data));
end;
function BIImport(var Context: TBigIntContext; const Data: AnsiString): PBigInt; overload;
@ -681,7 +664,7 @@ end;
function IntToBI(var Context: TBigIntContext; I: TBIComponent): PBigInt;
begin
Result := BIAllocate(Context,1);
PBIComponents(Result^.Components)^[0] := I;
Result^.Components[0] := I;
end;
function BIAdd(var Context: TBigIntContext; BIA, BIB: PBigInt): PBigInt;
@ -701,8 +684,8 @@ begin
Exit;
end;
N := Max(BIA^.Size, BIB^.Size);
BIAddComponents(Context, BIA, N+1);
BIAddComponents(Context, BIB, N);
BIResizeComponents(BIA, N+1);
BIResizeComponents(BIB, N);
PA := BIA^.Components;
PB := BIB^.Components;
repeat
@ -746,7 +729,7 @@ begin
Exit;
end;
N := BIA^.Size;
BIAddComponents(Context, BIB, N);
BIResizeComponents(BIB, N);
PA := BIA^.Components;
PB := BIB^.Components;
repeat
@ -780,17 +763,17 @@ function BIDivide(var Context: TBigIntContext; U, V: PBigInt; IsMod: Boolean): P
function BIDivide_V1(V:PBigInt):TBIComponent; inline;
begin // V1 for division
Result := PBIComponents(V^.Components)^[V^.Size-1];
Result := V^.Components[V^.Size-1];
end;
function BIDivide_V2(V: PBigInt): TBIComponent; inline;
begin // V2 for division
Result := PBIComponents(V^.Components)^[V^.Size-2];
Result := V^.Components[V^.Size-2];
end;
function BIDivide_U(TmpU: PBigInt; J: Integer): TBIComponent; inline;
begin // U(J) for division
Result := PBIComponents(TmpU^.Components)^[TmpU^.Size-J-1];
Result := TmpU^.Components[TmpU^.Size-J-1];
end;
var
@ -833,10 +816,10 @@ begin
V:=BIIntMultiply(Context,V,D);
end;
if OrigUSize = U^.Size then
BIAddComponents(Context, U, OrigUSize+1); // New digit position u0
BIResizeComponents(U, OrigUSize+1); // New digit position u0
repeat
// Get a temporary short version of u
System.Move(PBIComponents(U^.Components)^[U^.Size-N-1-J], TmpU^.Components^, (N+1) * BIGINT_COMP_BYTE_SIZE);
System.Move(U^.Components[U^.Size-N-1-J], TmpU^.Components^, (N+1) * BIGINT_COMP_BYTE_SIZE);
// Calculate q'
if BIDivide_U(TmpU, 0) = BIDivide_V1(V) then
begin
@ -855,11 +838,11 @@ begin
if QDash > 0 then
begin // Multiply and subtract
TmpU := BISubtract(Context, TmpU, BIIntMultiply(Context, BICopy(V), QDash), IsNegative);
BIAddComponents(Context, TmpU, N+1);
PBIComponents(Quotient^.Components)^[Quotient^.Size-J-1] := QDash;
BIResizeComponents(TmpU, N+1);
Quotient^.Components[Quotient^.Size-J-1] := QDash;
if IsNegative then
begin // Add back
Dec(PBIComponents(Quotient^.Components)^[Quotient^.Size-J-1]);
Dec(Quotient^.Components[Quotient^.Size-J-1]);
TmpU := BIAdd(Context, TmpU, BICopy(V));
// Lop off the carry
Dec(TmpU^.Size);
@ -867,10 +850,10 @@ begin
end;
end else
begin
PBIComponents(Quotient^.Components)^[Quotient^.Size-J-1] := 0;
Quotient^.Components[Quotient^.Size-J-1] := 0;
end;
// Copy back to U
System.Move(TmpU^.Components^, PBIComponents(U^.Components)^[U^.Size-N-1-J], (N+1) * BIGINT_COMP_BYTE_SIZE);
System.Move(TmpU^.Components^, U^.Components[U^.Size-N-1-J], (N+1) * BIGINT_COMP_BYTE_SIZE);
Inc(J);
until J > M;
BIRelease(Context, TmpU);
@ -879,7 +862,7 @@ begin
begin // Get the remainder
BIRelease(Context, Quotient);;
BITrim(U);
Result := BIIntDivide(Context, U, D);
Result := BIIntDivide(U, D);
end else
begin // Get the quotient
BIRelease(Context, U);
@ -950,7 +933,7 @@ begin
Dec(J);
end;
PartExp := (PartExp-1) div 2; // Adjust for array
BIR := BIResidue(Context, BIMultiply(Context, BIR, PBigInts(Context.G)^[PartExp]));
BIR := BIResidue(Context, BIMultiply(Context, BIR, Context.G[PartExp]));
I := L-1;
end else
begin // Square it
@ -960,8 +943,8 @@ begin
until I < 0;
for I := 0 to Context.Window-1 do
begin // Cleanup
BIDepermanent(PBigInts(Context.G)^[I]);
BIRelease(Context, PBigInts(Context.G)^[I]);
BIDepermanent(Context.G[I]);
BIRelease(Context, Context.G[I]);
end;
BIRelease(Context, BI);
BIRelease(Context, BIExp);
@ -1016,24 +999,17 @@ begin
Result := -1;
Exit;
end;
// Same number of components. Compare starting from the high end and working down
A := BIA^.Components;
B := BIB^.Components;
// Same number of components. Compare starting from the high end and working down
for I := BIA^.Size-1 downto 0 do
begin
if A[I] > B[I] then
Exit(1)
else if A[I] < B[I] then
Exit(-1);
end;
Result := 0;
I := BIA^.Size-1;
repeat
if PBIComponents(A)^[I] > PBIComponents(B)^[I] then
begin
Result := 1;
Exit;
end;
if PBIComponents(A)^[I] < PBIComponents(B)^[I] then
begin
Result := -1;
Exit;
end;
Dec(I);
until I < 0;
end;
// Pre-compute some of the expensive steps in reduction
@ -1047,14 +1023,14 @@ var
K: Integer;
begin
K := BIM^.Size;
D := BIGINT_COMP_RADIX div (TBILongComponent(PBIComponents(BIM^.Components)^[K-1]) + 1);
D := BIGINT_COMP_RADIX div (TBILongComponent(BIM^.Components[K-1]) + 1);
Context.BIMod[ModOffset] := BIM;
BIPermanent(Context.BIMod[ModOffset]);
Context.BINormalisedMod[ModOffset] := BIIntMultiply(Context, BIM, D);
BIPermanent(Context.BINormalisedMod[ModOffset]);
Context.BImu[ModOffset] := BIDivide(Context, BICompLeftShift(Context, BIClone(Context, Context.BIRadix^), K*2-1), Context.BIMod[ModOffset], False);
Context.BImu[ModOffset] := BIDivide(Context, BICompLeftShift(BIClone(Context, Context.BIRadix^), K*2-1), Context.BIMod[ModOffset], False);
BIPermanent(Context.BImu[ModOffset]);
Context.BIbk1[ModOffset] := BICompLeftShift(Context, IntToBI(Context,1), K+1);
Context.BIbk1[ModOffset] := BICompLeftShift(IntToBI(Context,1), K+1);
BIPermanent(Context.BIbk1[ModOffset]);
end;
@ -1144,7 +1120,7 @@ begin
end;
Result := BIRegularSquare(Context, BI);
{$ELSE}
Result := BIMultiply(Context, BICopy(BI), BI)
Result := BIMultiply(Context, BICopy(BI), BI);
{$ENDIF}
end;
@ -1187,7 +1163,7 @@ begin
for J := BIGINT_COMP_NUM_NIBBLES-1 downto 0 do
begin
Mask := $0F shl (J*4);
Num := (PBIComponents(BI^.Components)^[I] and Mask) shr (J*4);
Num := (BI^.Components[I] and Mask) shr (J*4);
S[K]:=Digits[Num and $F];
inc(K);
end;
@ -1220,7 +1196,7 @@ begin
Result := nil;
Exit;
end;
PBIComponents(BIR^.Components)^[Offset] := PBIComponents(BIR^.Components)^[Offset] + LongWord(Num shl (J * 4));
BIR^.Components[Offset] := BIR^.Components[Offset] + (LongWord(Num) shl (J * 4));
Inc(J);
if J = BIGINT_COMP_NUM_NIBBLES then
begin