Skip to content

Commit 5bc6160

Browse files
committed
Added 'limits of the real roots'
1 parent ed335f9 commit 5bc6160

3 files changed

Lines changed: 91 additions & 0 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ python3 main.py
5757

5858
- Briot-Ruffini method
5959
- Newton's Divided-Difference method
60+
- Limits of the real roots
6061

6162
### Numerical differentiation
6263

main.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,20 @@ def run_example_neville():
252252
print(f"\tq =\n{q}")
253253

254254

255+
@print_docstring
256+
def run_example_root_limits():
257+
"""Run an example 'Polynomials: Root limits'."""
258+
c = np.array([1, 2, -13, -14, 24])
259+
260+
print("Input:")
261+
print(f"\tc = {c}")
262+
263+
limits = polynomials.root_limits(c)
264+
265+
print("Output:")
266+
print(f"\tlimits = {limits}")
267+
268+
255269
@print_docstring
256270
def run_example_briot_ruffini():
257271
"""Run an example 'Polynomials: Briot-Ruffini'."""
@@ -656,6 +670,7 @@ def main():
656670
run_example_newton()
657671
run_example_lagrange()
658672
run_example_neville()
673+
run_example_root_limits()
659674
run_example_briot_ruffini()
660675
run_example_newton_divided_difference()
661676
run_example_derivative_backward_difference()

polynomials.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
"""Methods for polynomials."""
22

3+
import math
4+
35
import numpy as np
46

57

@@ -66,3 +68,76 @@ def newton_divided_difference(x, y):
6668
print("")
6769

6870
return [f]
71+
72+
73+
def root_limits(c):
74+
"""Find the limits of the real roots of a polynomial equation.
75+
76+
Using Lagrange's Theorem, whose proof is given by Demidovich and Maron.
77+
78+
Args:
79+
c: polynomial coefficients.
80+
81+
Returns:
82+
lim: lower and upper limits of positive and negative roots.
83+
"""
84+
lim = np.zeros(4)
85+
n = len(c) - 1
86+
c = np.concatenate(([0], c))
87+
c = np.concatenate((c, [0]))
88+
89+
if c[1] == 0:
90+
raise ValueError("The coefficient c[1] is null.")
91+
92+
t = n + 1
93+
c[t + 1] = 0
94+
95+
# If c[t+1] is null, then the polynomial is deflated.
96+
while True:
97+
if c[t] != 0:
98+
break
99+
t -= 1
100+
101+
# Compute the four limits of real roots.
102+
for i in range(0, 4):
103+
if i in (1, 3):
104+
# Inversion of the order of the coefficients.
105+
for j in range(1, t // 2 + 1):
106+
c[j], c[t - j + 1] = c[t - j + 1], c[j]
107+
else:
108+
if i == 2:
109+
# Reinversion of the order and exchange
110+
# of signs of the coefficients.
111+
for j in range(1, t // 2 + 1):
112+
c[j], c[t - j + 1] = c[t - j + 1], c[j]
113+
for j in range(t - 1, 0, -2):
114+
c[j] = -c[j]
115+
116+
# If c[1] is negative, then all coefficients are swapped.
117+
if c[1] < 0:
118+
for j in range(1, t + 1):
119+
c[j] = -c[j]
120+
121+
# Calculation of 'k', the largest index of the negative coefficients.
122+
k = 2
123+
while True:
124+
if c[k] < 0 or k > t:
125+
break
126+
k += 1
127+
128+
# Calculation of 'b', the largest negative coefficient in modulus.
129+
if k <= t:
130+
b = 0
131+
for j in range(2, t + 1):
132+
if c[j] < 0 and math.fabs(c[j]) > b:
133+
b = math.fabs(c[j])
134+
135+
# Limit of positive roots of 'P(x) = 0' and auxiliary equations.
136+
lim[i] = 1 + (b / c[1]) ** (1 / (k - 1))
137+
else:
138+
lim[i] = 10 ** 100
139+
140+
# Limit of positive and negative roots of 'P(x) = 0'.
141+
lim[0], lim[1], lim[2], lim[3] = 1 / lim[1], lim[0], -lim[2], -1 / lim[3]
142+
143+
return lim

0 commit comments

Comments
 (0)