diff --git a/UPolynomialRoots.pas b/UPolynomialRoots.pas index 3d9fafa..2a522f0 100644 --- a/UPolynomialRoots.pas +++ b/UPolynomialRoots.pas @@ -37,22 +37,23 @@ type TIsolatingIntervals = specialize TList; - { TRootIsolation } + { TPolynomialRoots } - TRootIsolation = class + TPolynomialRoots = class private - function CalcSimpleRootBound(constref APolynomial: TBigIntPolynomial): TBigInt; - function GetIsolatingInterval(const AC, AK, AH: Cardinal; constref ABound: TBigInt): TIsolatingInterval; + class function CalcUpperRootBound(constref APolynomial: TBigIntPolynomial): TBigInt; + class function CreateIsolatingInterval(const AC, AK, AH: Cardinal; constref ABound: TBigInt): TIsolatingInterval; public - function Bisect(constref APolynomial: TBigIntPolynomial): TIsolatingIntervals; - function Bisect(constref APolynomial: TBigIntPolynomial; constref ABound: TBigInt): TIsolatingIntervals; + class function BisectIsolation(constref APolynomial: TBigIntPolynomial): TIsolatingIntervals; + class function BisectIsolation(constref APolynomial: TBigIntPolynomial; constref ABound: TBigInt): + TIsolatingIntervals; end; implementation -{ TRootIsolation } +{ TPolynomialRoots } -function TRootIsolation.CalcSimpleRootBound(constref APolynomial: TBigIntPolynomial): TBigInt; +class function TPolynomialRoots.CalcUpperRootBound(constref APolynomial: TBigIntPolynomial): TBigInt; var i, sign: Integer; an, ai, max: TBigInt; @@ -76,7 +77,8 @@ begin Result := TBigInt.One << (numeratorBit - denominatorBit); end; -function TRootIsolation.GetIsolatingInterval(const AC, AK, AH: Cardinal; constref ABound: TBigInt): TIsolatingInterval; +class function TPolynomialRoots.CreateIsolatingInterval(const AC, AK, AH: Cardinal; constref ABound: TBigInt): + TIsolatingInterval; begin Result.C := AC; Result.K := AK; @@ -86,17 +88,18 @@ begin Result.B := ((AC + AH) * ABound) >> AK; end; -function TRootIsolation.Bisect(constref APolynomial: TBigIntPolynomial): TIsolatingIntervals; +class function TPolynomialRoots.BisectIsolation(constref APolynomial: TBigIntPolynomial): TIsolatingIntervals; var bound: TBigInt; begin - bound := CalcSimpleRootBound(APolynomial); - Result := Bisect(APolynomial, bound); + bound := CalcUpperRootBound(APolynomial); + Result := BisectIsolation(APolynomial, bound); end; // This is adapted from // https://en.wikipedia.org/wiki/Real-root_isolation#Bisection_method -function TRootIsolation.Bisect(constref APolynomial: TBigIntPolynomial; constref ABound: TBigInt): TIsolatingIntervals; +class function TPolynomialRoots.BisectIsolation(constref APolynomial: TBigIntPolynomial; constref ABound: TBigInt): + TIsolatingIntervals; type TWorkItem = record C, K: Cardinal; @@ -126,7 +129,7 @@ begin // Found an integer root at 0. item.P := item.P.DivideByVariable; Dec(n); - Result.Add(GetIsolatingInterval(item.C, item.K, 0, ABound)); + Result.Add(CreateIsolatingInterval(item.C, item.K, 0, ABound)); end; varq := item.P.RevertOrderOfCoefficients.TranslateVariableByOne; @@ -134,7 +137,7 @@ begin if v = 1 then begin // Found isolating interval. - Result.Add(GetIsolatingInterval(item.C, item.K, 1, ABound)); + Result.Add(CreateIsolatingInterval(item.C, item.K, 1, ABound)); end else if v > 1 then begin diff --git a/tests/UPolynomialRootsTestCases.pas b/tests/UPolynomialRootsTestCases.pas index e1d765d..03faa50 100644 --- a/tests/UPolynomialRootsTestCases.pas +++ b/tests/UPolynomialRootsTestCases.pas @@ -32,10 +32,6 @@ type private procedure AssertBisectResult(constref AIsolatingIntervals: TIsolatingIntervals; constref AExpectedRoots: array of Cardinal); - protected - FRootIsolation: TRootIsolation; - procedure SetUp; override; - procedure TearDown; override; published procedure TestBisectNoBound; procedure TestBisectWithBound; @@ -68,18 +64,6 @@ begin end; end; -procedure TPolynomialRootsTestCase.SetUp; -begin - inherited SetUp; - FRootIsolation := TRootIsolation.Create; -end; - -procedure TPolynomialRootsTestCase.TearDown; -begin - FRootIsolation.Free; - inherited TearDown; -end; - procedure TPolynomialRootsTestCase.TestBisectNoBound; const expRoots: array of Cardinal = (34000, 23017, 5); @@ -90,7 +74,7 @@ begin // y = 3 * (x - 34000) * (x - 23017) * (x - 5) * (x^2 - 19) * (x + 112) // = 3 * x^6 - 170730 * x^5 + 2329429920 * x^4 + 251300082690 * x^3 - 1270471872603 * x^2 + 4774763204640 * x - 24979889760000 a := TBigIntPolynomial.Create([-24979889760000, 4774763204640, -1270471872603, 251300082690, 2329429920, -170730, 3]); - r := FRootIsolation.Bisect(a); + r := TPolynomialRoots.BisectIsolation(a); AssertBisectResult(r, expRoots); r.Free; end; @@ -105,7 +89,7 @@ begin // y = 3 * (x - 34000) * (x - 23017) * (x - 5) * (x^2 - 19) * (x + 112) // = 3 * x^6 - 170730 * x^5 + 2329429920 * x^4 + 251300082690 * x^3 - 1270471872603 * x^2 + 4774763204640 * x - 24979889760000 a := TBigIntPolynomial.Create([-24979889760000, 4774763204640, -1270471872603, 251300082690, 2329429920, -170730, 3]); - r := FRootIsolation.Bisect(a, TBigInt.One << 15); + r := TPolynomialRoots.BisectIsolation(a, TBigInt.One << 15); AssertBisectResult(r, expRoots); r.Free; end;