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 Coefficient[const AIndex: Integer]: TBigInt read GetCoefficient;
|
||||
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;
|
||||
|
||||
// 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 ToString: string;
|
||||
class function Create(const ACoefficients: array of TBigInt): TBigIntPolynomial; static;
|
||||
|
@ -72,6 +94,34 @@ begin
|
|||
Result := Result * AX + FCoefficients[i];
|
||||
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;
|
||||
var
|
||||
len, i: Integer;
|
||||
|
@ -94,6 +144,72 @@ begin
|
|||
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;
|
||||
var
|
||||
i: Integer;
|
||||
|
|
|
@ -40,6 +40,13 @@ type
|
|||
procedure TestUnequalSameLength;
|
||||
procedure TestUnequalDifferentLength;
|
||||
procedure TestTrimLeadingZeros;
|
||||
procedure TestCalcValueAt;
|
||||
procedure TestSignVariations;
|
||||
procedure TestScaleByPowerOfTwo;
|
||||
procedure TestScaleVariable;
|
||||
procedure TestTranslateVariableByOne;
|
||||
procedure TestRevertOrderOfCoefficients;
|
||||
procedure TestDivideByVariable;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
@ -110,6 +117,69 @@ begin
|
|||
AssertTrue('Polynomials are not equal.', a = b);
|
||||
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
|
||||
|
||||
RegisterTest(TBigIntPolynomialTestCase);
|
||||
|
|
Loading…
Reference in New Issue