1 package org.djutils.polynomialroots;
2
3 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
4 import static org.junit.jupiter.api.Assertions.assertEquals;
5
6 import org.djutils.complex.Complex;
7 import org.junit.jupiter.api.Test;
8
9
10
11
12
13
14
15
16
17
18 public class TestPolynomialRoots2
19 {
20
21
22
23
24
25 @Test
26 public void quadraticTest()
27 {
28 double[] paramValues = new double[] {0, 1, 2, 3, 4, Math.PI, -Math.E, 0.0001, 10000};
29 for (double a : paramValues)
30 {
31 for (double b : paramValues)
32 {
33 for (double c : paramValues)
34 {
35
36 Complex[] roots = PolynomialRoots2.quadraticRoots(a, b, c);
37 int expectedNumber = a != 0 ? 2 : b != 0 ? 1 : 0;
38 assertEquals(expectedNumber, roots.length, "number of roots");
39
40
41 for (Complex root : roots)
42 {
43
44 Complex result = root.times(root).times(a).plus(root.times(b)).plus(c);
45 double margin = Math.max(root.norm() / 1e6, 1E-300);
46 assertEquals(0, result.re, margin, "root is a root of the equation; re");
47 assertEquals(0, result.im, margin, "root is a root of the equation; im");
48 }
49
50 Complex[] alternate = PolynomialRoots2.cubicRootsDurandKerner(0, a, b, c);
51 assertArrayEquals(roots, alternate, "cubic solver returns same results as quadratic solver if a is 0");
52 }
53 }
54 }
55 double q1 = 3 * Math.sqrt(Double.MAX_VALUE);
56 Complex[] roots = PolynomialRoots2.quadraticRoots(q1, 1);
57 assertEquals(2, roots.length, "two roots");
58 assertEquals(0, roots[0].re, 0.0001, "first root is 0: re");
59 assertEquals(0, roots[0].im, 0.0001, "first root is 0: im");
60
61 assertEquals(-q1, roots[1].re, q1 / 1e7, "second root is 0: re");
62 assertEquals(0, roots[1].im, 0.0001, "second root is 0: im");
63 }
64
65
66
67
68 @Test
69 public void cubicTestDurandKerner()
70 {
71 double[] paramValues = new double[] {0, 1, 2, 3, 4, Math.PI, -Math.E, 0.001, 1000};
72 for (double a : paramValues)
73 {
74 for (double b : paramValues)
75 {
76 for (double c : paramValues)
77 {
78 for (double d : paramValues)
79 {
80
81 Complex[] roots = PolynomialRoots2.cubicRootsDurandKerner(a, b, c, d);
82 int expectedNumber = a != 0 ? 3 : b != 0 ? 2 : c != 0 ? 1 : 0;
83 assertEquals(expectedNumber, roots.length, "number of roots");
84
85
86 for (Complex root : roots)
87 {
88
89 Complex result = root.times(root).times(root).times(a).plus(root.times(root).times(b))
90 .plus(root.times(c)).plus(d);
91 double margin = Math.max(root.norm() / 1e6, 1E-300);
92 assertEquals(0, result.re, margin, "root is a root of the equation; re");
93 assertEquals(0, result.im, margin, "root is a root of the equation; im");
94 }
95
96 }
97 }
98 }
99 }
100 }
101
102
103
104
105 @Test
106 public void quarticTestDurandKerner()
107 {
108 double[] paramValues = new double[] {0, 1, 2, 3, 4, Math.PI, -Math.E, 0.01, 100};
109 for (double a : paramValues)
110 {
111 for (double b : paramValues)
112 {
113 for (double c : paramValues)
114 {
115 for (double d : paramValues)
116 {
117 for (double e : paramValues)
118 {
119
120 Complex[] roots = PolynomialRoots2.quarticRootsDurandKerner(a, b, c, d, e);
121 int expectedNumber = a != 0 ? 4 : b != 0 ? 3 : c != 0 ? 2 : d != 0 ? 1 : 0;
122 assertEquals(expectedNumber, roots.length, "number of roots");
123
124
125 for (Complex root : roots)
126 {
127
128
129 Complex result = root.times(root).times(root).times(root).times(a)
130 .plus(root.times(root).times(root).times(b)).plus(root.times(root).times(c))
131 .plus(root.times(d)).plus(e);
132 double margin = Math.max(root.norm() / 2e5, 1E-300);
133 assertEquals(0, result.re, margin, a + " x^4 + " + b + " x^3 + " + c + " x^2 + " + d + " x + " + e
134 + " = 0 : root is a root of the equation; re");
135 assertEquals(0, result.im, margin, a + " x^4 + " + b + " x^3 + " + c + " x^2 + " + d + " x + " + e
136 + " = 0 : root is a root of the equation; im");
137 }
138
139 }
140 }
141 }
142 }
143 }
144 }
145
146
147
148
149 @Test
150 public void cubicTestAberthEhrlich()
151 {
152 double[] paramValues = new double[] {0, 1, 2, 3, 4, Math.PI, -Math.E, 0.001, 1000};
153 for (double a : paramValues)
154 {
155 for (double b : paramValues)
156 {
157 for (double c : paramValues)
158 {
159 for (double d : paramValues)
160 {
161
162 Complex[] roots = PolynomialRoots2.cubicRootsAberthEhrlich(a, b, c, d);
163 int expectedNumber = a != 0 ? 3 : b != 0 ? 2 : c != 0 ? 1 : 0;
164 assertEquals(expectedNumber, roots.length, "number of roots");
165
166
167 for (Complex root : roots)
168 {
169
170 Complex result = root.times(root).times(root).times(a).plus(root.times(root).times(b))
171 .plus(root.times(c)).plus(d);
172 double margin = Math.max(root.norm() / 1e6, 1E-300);
173 assertEquals(0, result.re, margin, "root is a root of the equation; re");
174 assertEquals(0, result.im, margin, "root is a root of the equation; im");
175 }
176
177 }
178 }
179 }
180 }
181 }
182
183
184
185
186 @Test
187 public void quarticTestAberthEhrlich()
188 {
189 double[] paramValues = new double[] {0, 1, 2, 3, 4, Math.PI, -Math.E, 0.01, 100};
190 for (double a : paramValues)
191 {
192 for (double b : paramValues)
193 {
194 for (double c : paramValues)
195 {
196 for (double d : paramValues)
197 {
198 for (double e : paramValues)
199 {
200
201 Complex[] roots = PolynomialRoots2.quarticRootsAberthEhrlich(a, b, c, d, e);
202 int expectedNumber = a != 0 ? 4 : b != 0 ? 3 : c != 0 ? 2 : d != 0 ? 1 : 0;
203 assertEquals(expectedNumber, roots.length, "number of roots");
204
205
206 for (Complex root : roots)
207 {
208
209
210 Complex result = root.times(root).times(root).times(root).times(a)
211 .plus(root.times(root).times(root).times(b)).plus(root.times(root).times(c))
212 .plus(root.times(d)).plus(e);
213 double margin = Math.max(root.norm() / 2e5, 1E-300);
214 assertEquals(0, result.re, margin, a + " x^4 + " + b + " x^3 + " + c + " x^2 + " + d + " x + " + e
215 + " = 0 : root is a root of the equation; re");
216 assertEquals(0, result.im, margin, a + " x^4 + " + b + " x^3 + " + c + " x^2 + " + d + " x + " + e
217 + " = 0 : root is a root of the equation; im");
218 }
219
220 }
221 }
222 }
223 }
224 }
225 }
226
227
228
229
230
231 public void cubicTestNewtonFactor()
232 {
233 double[] paramValues = new double[] {0, 1, 2, 3, 4, Math.PI, -Math.E, 0.001, 1000};
234 for (double a : paramValues)
235 {
236 for (double b : paramValues)
237 {
238 for (double c : paramValues)
239 {
240 for (double d : paramValues)
241 {
242
243 Complex[] roots = PolynomialRoots2.cubicRootsNewtonFactor(a, b, c, d);
244 int expectedNumber = a != 0 ? 3 : b != 0 ? 2 : c != 0 ? 1 : 0;
245 assertEquals(expectedNumber, roots.length, "number of roots");
246
247
248 for (Complex root : roots)
249 {
250
251 Complex result = root.times(root).times(root).times(a).plus(root.times(root).times(b))
252 .plus(root.times(c)).plus(d);
253 double margin = Math.max(root.norm() / 1e4, 1E-3);
254 String eq = a + " x^3 + " + b + " x^2 + " + c + " x + " + d + " = 0";
255 assertEquals(0, result.re, margin, eq + ", root=" + root + ", result=" + result + "; re");
256 assertEquals(0, result.im, margin, eq + ", root=" + root + ", result=" + result + "; im");
257 }
258
259 }
260 }
261 }
262 }
263 }
264
265 }