diff --git a/UPolynomialRoots.pas b/UPolynomialRoots.pas index 6853b80..fa1280c 100644 --- a/UPolynomialRoots.pas +++ b/UPolynomialRoots.pas @@ -37,6 +37,8 @@ type TIsolatingIntervals = specialize TList; + TIsolatingIntervalArray = array of TIsolatingInterval; + { TPolynomialRoots } TPolynomialRoots = class @@ -48,10 +50,10 @@ type TIsolatingInterval; public // Returns root-isolating intervals for non-negative, non-multiple roots. - class function BisectIsolation(constref APolynomial: TBigIntPolynomial): TIsolatingIntervals; + class function BisectIsolation(constref APolynomial: TBigIntPolynomial): TIsolatingIntervalArray; // Returns root-isolating intervals for non-multiple roots in the interval [0, 2^boundexp]. class function BisectIsolation(constref APolynomial: TBigIntPolynomial; constref ABoundExp: Cardinal): - TIsolatingIntervals; + TIsolatingIntervalArray; end; implementation @@ -100,7 +102,7 @@ begin end; end; -class function TPolynomialRoots.BisectIsolation(constref APolynomial: TBigIntPolynomial): TIsolatingIntervals; +class function TPolynomialRoots.BisectIsolation(constref APolynomial: TBigIntPolynomial): TIsolatingIntervalArray; var boundExp: Cardinal; begin @@ -111,7 +113,7 @@ end; // This is adapted from // https://en.wikipedia.org/wiki/Real-root_isolation#Bisection_method class function TPolynomialRoots.BisectIsolation(constref APolynomial: TBigIntPolynomial; constref ABoundExp: Cardinal): - TIsolatingIntervals; + TIsolatingIntervalArray; type TWorkItem = record C, K: Cardinal; @@ -123,8 +125,9 @@ var stack: TWorkStack; n, v: Integer; varq: TBigIntPolynomial; + iso: TIsolatingIntervals; begin - Result := TIsolatingIntervals.Create; + iso := TIsolatingIntervals.Create; stack := TWorkStack.Create; item.C := 0; @@ -141,7 +144,7 @@ begin // Found an integer root at 0. item.P := item.P.DivideByVariable; Dec(n); - Result.Add(CreateIsolatingInterval(item.C, item.K, 0, ABoundExp)); + iso.Add(CreateIsolatingInterval(item.C, item.K, 0, ABoundExp)); end; varq := item.P.RevertOrderOfCoefficients.TranslateVariableByOne; @@ -149,7 +152,7 @@ begin if v = 1 then begin // Found isolating interval. - Result.Add(CreateIsolatingInterval(item.C, item.K, 1, ABoundExp)); + iso.Add(CreateIsolatingInterval(item.C, item.K, 1, ABoundExp)); end else if v > 1 then begin @@ -164,6 +167,8 @@ begin stack.Push(item); end; end; + Result := iso.ToArray; + iso.Free; stack.Free; end; diff --git a/tests/UPolynomialRootsTestCases.pas b/tests/UPolynomialRootsTestCases.pas index cfd9e47..91c29d3 100644 --- a/tests/UPolynomialRootsTestCases.pas +++ b/tests/UPolynomialRootsTestCases.pas @@ -30,7 +30,7 @@ type TPolynomialRootsTestCase = class(TTestCase) private - procedure AssertBisectResult(constref AIsolatingIntervals: TIsolatingIntervals; constref AExpectedRoots: + procedure AssertBisectIntervals(AIsolatingIntervals: TIsolatingIntervalArray; constref AExpectedRoots: array of Cardinal); published procedure TestBisectNoBound; @@ -41,18 +41,18 @@ implementation { TPolynomialRootsTestCase } -procedure TPolynomialRootsTestCase.AssertBisectResult(constref AIsolatingIntervals: TIsolatingIntervals; constref - AExpectedRoots: array of Cardinal); +procedure TPolynomialRootsTestCase.AssertBisectIntervals(AIsolatingIntervals: TIsolatingIntervalArray; + constref AExpectedRoots: array of Cardinal); var exp: Cardinal; found: Boolean; i, foundIndex: Integer; begin - AssertEquals('Unexpected number of isolating intervals.', Length(AExpectedRoots), AIsolatingIntervals.Count); + AssertEquals('Unexpected number of isolating intervals.', Length(AExpectedRoots), Length(AIsolatingIntervals)); for exp in AExpectedRoots do begin found := False; - for i := 0 to AIsolatingIntervals.Count - 1 do + for i := 0 to Length(AIsolatingIntervals) - 1 do if (AIsolatingIntervals[i].A <= exp) and (exp <= AIsolatingIntervals[i].B) then begin found := True; @@ -60,7 +60,7 @@ begin Break; end; AssertTrue('No isolating interval for expected root ' + IntToStr(exp) + ' found.', found); - AIsolatingIntervals.Delete(foundIndex); + Delete(AIsolatingIntervals, foundIndex, 1); end; end; @@ -69,14 +69,13 @@ const expRoots: array of Cardinal = (34000, 23017, 5); var a: TBigIntPolynomial; - r: TIsolatingIntervals; + r: TIsolatingIntervalArray; 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 := TPolynomialRoots.BisectIsolation(a); - AssertBisectResult(r, expRoots); - r.Free; + AssertBisectIntervals(r, expRoots); end; procedure TPolynomialRootsTestCase.TestBisectWithBound; @@ -84,14 +83,13 @@ const expRoots: array of Cardinal = (23017, 5); var a: TBigIntPolynomial; - r: TIsolatingIntervals; + r: TIsolatingIntervalArray; 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 := TPolynomialRoots.BisectIsolation(a, 15); - AssertBisectResult(r, expRoots); - r.Free; + AssertBisectIntervals(r, expRoots); end; initialization