Added TBigIntPolynomial methods needed for bisection algorithm
This commit is contained in:
parent
aef4f28f46
commit
cbaffbf55e
116
UPolynomial.pas
116
UPolynomial.pas
|
@ -38,7 +38,29 @@ type
|
||||||
property Degree: Integer read GetDegree;
|
property Degree: Integer read GetDegree;
|
||||||
property Coefficient[const AIndex: Integer]: TBigInt read GetCoefficient;
|
property Coefficient[const AIndex: Integer]: TBigInt read GetCoefficient;
|
||||||
function CalcValueAt(const AX: Int64): TBigInt;
|
function CalcValueAt(const AX: Int64): TBigInt;
|
||||||
|
function CalcSignVariations: Integer;
|
||||||
|
|
||||||
|
// Returns 2^n * f(x), given a polynomial f(x) and exponent n.
|
||||||
|
function ScaleByPowerOfTwo(const AExponent: Cardinal): TBigIntPolynomial;
|
||||||
|
|
||||||
|
// Returns f(s * x), given a polynomial f(x) and scale factor s.
|
||||||
function ScaleVariable(const AScaleFactor: TBigInt): TBigIntPolynomial;
|
function ScaleVariable(const AScaleFactor: TBigInt): TBigIntPolynomial;
|
||||||
|
|
||||||
|
// Returns f(x / 2), given a polynomial f(x).
|
||||||
|
function ScaleVariableByHalf: TBigIntPolynomial;
|
||||||
|
|
||||||
|
// Returns f(x + 1), given a polynomial f(x).
|
||||||
|
function TranslateVariableByOne: TBigIntPolynomial;
|
||||||
|
|
||||||
|
// Returns a polynomial with the reverse order of coefficients, i.e. the polynomial
|
||||||
|
// a_0 * x^n + a_1 * x^(n - 1) + ... + a_(n - 1) * x + a_n,
|
||||||
|
// given a polynomial
|
||||||
|
// a_n * x^n + a_(n - 1) * x^(n - 1) + ... + a_1 * x + a_0.
|
||||||
|
function RevertOrderOfCoefficients: TBigIntPolynomial;
|
||||||
|
|
||||||
|
// Returns a polynomial with all coefficents shifted down one position, and the constant term removed. This should
|
||||||
|
// only be used when the constant term is zero and is then equivalent to a division of polynomial f(x) by x.
|
||||||
|
function DivideByVariable: TBigIntPolynomial;
|
||||||
function IsEqualTo(const AOther: TBigIntPolynomial): Boolean;
|
function IsEqualTo(const AOther: TBigIntPolynomial): Boolean;
|
||||||
function ToString: string;
|
function ToString: string;
|
||||||
class function Create(const ACoefficients: array of TBigInt): TBigIntPolynomial; static;
|
class function Create(const ACoefficients: array of TBigInt): TBigIntPolynomial; static;
|
||||||
|
@ -72,6 +94,34 @@ begin
|
||||||
Result := Result * AX + FCoefficients[i];
|
Result := Result * AX + FCoefficients[i];
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TBigIntPolynomial.CalcSignVariations: Integer;
|
||||||
|
var
|
||||||
|
current, last, i: Integer;
|
||||||
|
begin
|
||||||
|
Result := 0;
|
||||||
|
last := 0;
|
||||||
|
for i := 0 to Length(FCoefficients) - 1 do
|
||||||
|
begin
|
||||||
|
current := FCoefficients[i].Sign;
|
||||||
|
if (current <> 0) and (last <> current) then
|
||||||
|
begin
|
||||||
|
if last <> 0 then
|
||||||
|
Inc(Result);
|
||||||
|
last := current
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TBigIntPolynomial.ScaleByPowerOfTwo(const AExponent: Cardinal): TBigIntPolynomial;
|
||||||
|
var
|
||||||
|
len, i: Integer;
|
||||||
|
begin
|
||||||
|
len := Length(FCoefficients);
|
||||||
|
SetLength(Result.FCoefficients, len);
|
||||||
|
for i := 0 to len - 1 do
|
||||||
|
Result.FCoefficients[i] := FCoefficients[i] << AExponent;
|
||||||
|
end;
|
||||||
|
|
||||||
function TBigIntPolynomial.ScaleVariable(const AScaleFactor: TBigInt): TBigIntPolynomial;
|
function TBigIntPolynomial.ScaleVariable(const AScaleFactor: TBigInt): TBigIntPolynomial;
|
||||||
var
|
var
|
||||||
len, i: Integer;
|
len, i: Integer;
|
||||||
|
@ -94,6 +144,72 @@ begin
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TBigIntPolynomial.ScaleVariableByHalf: TBigIntPolynomial;
|
||||||
|
var
|
||||||
|
len, i: Integer;
|
||||||
|
begin
|
||||||
|
len := Length(FCoefficients);
|
||||||
|
SetLength(Result.FCoefficients, len);
|
||||||
|
Result.FCoefficients[0] := FCoefficients[0];
|
||||||
|
for i := 1 to len - 1 do
|
||||||
|
Result.FCoefficients[i] := FCoefficients[i] >> i;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TBigIntPolynomial.TranslateVariableByOne: TBigIntPolynomial;
|
||||||
|
var
|
||||||
|
len, i, j: Integer;
|
||||||
|
factors: array of Cardinal;
|
||||||
|
begin
|
||||||
|
len := Length(FCoefficients);
|
||||||
|
SetLength(Result.FCoefficients, len);
|
||||||
|
SetLength(factors, len);
|
||||||
|
for i := 0 to len - 1 do
|
||||||
|
begin
|
||||||
|
Result.FCoefficients[i] := TBigInt.Zero;
|
||||||
|
factors[i] := 1;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Calculates new coefficients.
|
||||||
|
for i := 0 to len - 1 do
|
||||||
|
begin
|
||||||
|
for j := 0 to len - i - 1 do
|
||||||
|
begin
|
||||||
|
if (i <> 0) and (j <> 0) then
|
||||||
|
factors[j] := factors[j] + factors[j - 1];
|
||||||
|
Result.FCoefficients[i] := Result.FCoefficients[i] + factors[j] * FCoefficients[j + i];
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TBigIntPolynomial.RevertOrderOfCoefficients: TBigIntPolynomial;
|
||||||
|
var
|
||||||
|
len, skip, i: Integer;
|
||||||
|
begin
|
||||||
|
// Counts the trailing zeros to skip.
|
||||||
|
len := Length(FCoefficients);
|
||||||
|
skip := 0;
|
||||||
|
while (skip < len) and (FCoefficients[skip] = 0) do
|
||||||
|
Inc(skip);
|
||||||
|
|
||||||
|
// Copies the other coefficients in reverse order.
|
||||||
|
SetLength(Result.FCoefficients, len - skip);
|
||||||
|
for i := skip to len - 1 do
|
||||||
|
Result.FCoefficients[len - i - 1] := FCoefficients[i];
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TBigIntPolynomial.DivideByVariable: TBigIntPolynomial;
|
||||||
|
var
|
||||||
|
len: Integer;
|
||||||
|
begin
|
||||||
|
len := Length(FCoefficients);
|
||||||
|
if len > 1 then
|
||||||
|
Result.FCoefficients := Copy(FCoefficients, 1, len - 1)
|
||||||
|
else begin
|
||||||
|
SetLength(Result.FCoefficients, 1);
|
||||||
|
Result.FCoefficients[0] := TBigInt.Zero;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
function TBigIntPolynomial.IsEqualTo(const AOther: TBigIntPolynomial): Boolean;
|
function TBigIntPolynomial.IsEqualTo(const AOther: TBigIntPolynomial): Boolean;
|
||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
|
|
|
@ -40,6 +40,13 @@ type
|
||||||
procedure TestUnequalSameLength;
|
procedure TestUnequalSameLength;
|
||||||
procedure TestUnequalDifferentLength;
|
procedure TestUnequalDifferentLength;
|
||||||
procedure TestTrimLeadingZeros;
|
procedure TestTrimLeadingZeros;
|
||||||
|
procedure TestCalcValueAt;
|
||||||
|
procedure TestSignVariations;
|
||||||
|
procedure TestScaleByPowerOfTwo;
|
||||||
|
procedure TestScaleVariable;
|
||||||
|
procedure TestTranslateVariableByOne;
|
||||||
|
procedure TestRevertOrderOfCoefficients;
|
||||||
|
procedure TestDivideByVariable;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
@ -110,6 +117,69 @@ begin
|
||||||
AssertTrue('Polynomials are not equal.', a = b);
|
AssertTrue('Polynomials are not equal.', a = b);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntPolynomialTestCase.TestCalcValueAt;
|
||||||
|
var
|
||||||
|
a: TBigIntPolynomial;
|
||||||
|
exp: TBigInt;
|
||||||
|
begin
|
||||||
|
a := TBigIntPolynomial.Create([80, 892477222, 0, 921556, 7303]);
|
||||||
|
exp:= TBigInt.FromInt64(16867124285);
|
||||||
|
AssertTrue('Polynomial evaluation unexpected.', a.CalcValueAt(15) = exp);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntPolynomialTestCase.TestSignVariations;
|
||||||
|
var
|
||||||
|
a: TBigIntPolynomial;
|
||||||
|
begin
|
||||||
|
a := TBigIntPolynomial.Create([-10, 15, 0, 10, -20, -15, 0, 0, 5, 10, -10]);
|
||||||
|
AssertEquals(4, a.CalcSignVariations);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntPolynomialTestCase.TestScaleByPowerOfTwo;
|
||||||
|
var
|
||||||
|
a, b: TBigIntPolynomial;
|
||||||
|
begin
|
||||||
|
a := TBigIntPolynomial.Create([10, 7, 5, 1034]).ScaleByPowerOfTwo(7);
|
||||||
|
b := TBigIntPolynomial.Create([128 * 10, 128 * 7, 128 * 5, 128 * 1034]);
|
||||||
|
AssertTrue('Polynomials are not equal.', a = b);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntPolynomialTestCase.TestScaleVariable;
|
||||||
|
var
|
||||||
|
a, b: TBigIntPolynomial;
|
||||||
|
begin
|
||||||
|
a := TBigIntPolynomial.Create([10, 7, 5, 1034]).ScaleVariable(TBigInt.FromInt64(10));
|
||||||
|
b := TBigIntPolynomial.Create([10, 70, 500, 1034000]);
|
||||||
|
AssertTrue('Polynomials are not equal.', a = b);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntPolynomialTestCase.TestTranslateVariableByOne;
|
||||||
|
var
|
||||||
|
a, b: TBigIntPolynomial;
|
||||||
|
begin
|
||||||
|
a := TBigIntPolynomial.Create([10, 7, 5, 1034]).TranslateVariableByOne;
|
||||||
|
b := TBigIntPolynomial.Create([1056, 3119, 3107, 1034]);
|
||||||
|
AssertTrue('Polynomials are not equal.', a = b);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntPolynomialTestCase.TestRevertOrderOfCoefficients;
|
||||||
|
var
|
||||||
|
a, b: TBigIntPolynomial;
|
||||||
|
begin
|
||||||
|
a := TBigIntPolynomial.Create([0, 10, 7, 5, 1034]).RevertOrderOfCoefficients;
|
||||||
|
b := TBigIntPolynomial.Create([1034, 5, 7, 10]);
|
||||||
|
AssertTrue('Polynomials are not equal.', a = b);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBigIntPolynomialTestCase.TestDivideByVariable;
|
||||||
|
var
|
||||||
|
a, b: TBigIntPolynomial;
|
||||||
|
begin
|
||||||
|
a := TBigIntPolynomial.Create([0, 10, 7, 5, 1034]).DivideByVariable;
|
||||||
|
b := TBigIntPolynomial.Create([10, 7, 5, 1034]);
|
||||||
|
AssertTrue('Polynomials are not equal.', a = b);
|
||||||
|
end;
|
||||||
|
|
||||||
initialization
|
initialization
|
||||||
|
|
||||||
RegisterTest(TBigIntPolynomialTestCase);
|
RegisterTest(TBigIntPolynomialTestCase);
|
||||||
|
|
Loading…
Reference in New Issue