36 #include <irplib_polynomial.h>
46 #define irplib_polynomial_test_root_all(A, B, C, D, E) \
47 irplib_polynomial_test_root_all_macro(A, B, C, D, E, __LINE__)
53 static cpl_error_code irplib_polynomial_multiply_1d_factor(cpl_polynomial *,
56 static void irplib_polynomial_solve_1d_all_test(
void);
58 static void irplib_polynomial_test_root_all_macro(
const cpl_vector *, cpl_size,
59 double,
double,
double,
68 cpl_test_init(PACKAGE_BUGREPORT, CPL_MSG_WARNING);
70 irplib_polynomial_solve_1d_all_test();
72 return cpl_test_end(0);
84 static void irplib_polynomial_solve_1d_all_test(
void)
87 cpl_polynomial * p2d = cpl_polynomial_new(2);
88 cpl_polynomial * p1d = cpl_polynomial_new(1);
89 cpl_vector * xtrue = cpl_vector_new(2);
90 const cpl_size maxdegree = 4;
95 CPL_ERROR_NULL_INPUT);
96 cpl_test_error(CPL_ERROR_NULL_INPUT);
99 CPL_ERROR_NULL_INPUT);
100 cpl_test_error(CPL_ERROR_NULL_INPUT);
103 CPL_ERROR_NULL_INPUT);
104 cpl_test_error(CPL_ERROR_NULL_INPUT);
107 CPL_ERROR_INVALID_TYPE);
108 cpl_test_error(CPL_ERROR_INVALID_TYPE);
111 CPL_ERROR_DATA_NOT_FOUND);
112 cpl_test_error(CPL_ERROR_DATA_NOT_FOUND);
116 cpl_test_eq(cpl_polynomial_set_coeff(p1d, &i, 1.0), CPL_ERROR_NONE);
118 CPL_ERROR_INCOMPATIBLE_INPUT);
119 cpl_test_error(CPL_ERROR_INCOMPATIBLE_INPUT);
121 cpl_polynomial_delete(p1d);
122 cpl_polynomial_delete(p2d);
124 for (nreal = 1; nreal <= maxdegree; nreal++) {
129 cpl_vector_set_size(xtrue, nreal);
131 (void)cpl_vector_fill(xtrue, xreal);
133 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
134 2.0 * DBL_EPSILON, 2.0 * DBL_EPSILON);
139 (void)cpl_vector_fill(xtrue, xreal);
141 irplib_polynomial_test_root_all(xtrue, nreal, 1.0,
142 2.0 * DBL_EPSILON, 2.0 * DBL_EPSILON);
145 for (i = 0; i < nreal; i++) {
146 (void)cpl_vector_set(xtrue, i, 2.0 * (
double)i - CPL_MATH_E);
149 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
151 300.0 * DBL_EPSILON);
154 for (i = 0; i < nreal-1; i++) {
155 (void)cpl_vector_set(xtrue, nreal-i-2, (
double)(-i));
157 (void)cpl_vector_set(xtrue, nreal-1, (
double)(nreal-1));
159 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
160 16.0*DBL_EPSILON, 600.0*DBL_EPSILON);
162 if (nreal < 2)
continue;
166 (void)cpl_vector_fill(xtrue, 2.0);
167 (void)cpl_vector_set(xtrue, nreal-2, -1.0);
168 (void)cpl_vector_set(xtrue, nreal-1, 1.0);
170 irplib_polynomial_test_root_all(xtrue, nreal-2, CPL_MATH_PI,
171 30.0*DBL_EPSILON, 25.0*DBL_EPSILON);
173 if (nreal < 3)
continue;
176 (void)cpl_vector_fill(xtrue, 1.0);
177 (void)cpl_vector_set(xtrue, nreal - 1 , 2.0);
179 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
180 DBL_EPSILON, DBL_EPSILON);
182 (void)cpl_vector_fill(xtrue, -1.0);
183 (void)cpl_vector_set(xtrue, 0 , -2.0);
185 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
186 DBL_EPSILON, DBL_EPSILON);
188 (void)cpl_vector_fill(xtrue, 2.0);
189 (void)cpl_vector_set(xtrue, 0, 1.0);
191 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
192 DBL_EPSILON, DBL_EPSILON);
195 if (nreal > 3)
continue;
198 (void)cpl_vector_fill(xtrue, -2.0 * FLT_EPSILON);
199 (void)cpl_vector_set(xtrue, 0, -1.0);
201 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
202 DBL_EPSILON, 2.0*DBL_EPSILON);
205 (void)cpl_vector_fill(xtrue, -0.2 * FLT_EPSILON);
206 (void)cpl_vector_set(xtrue, 0, -1.0);
208 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
209 FLT_EPSILON, 3.0*DBL_EPSILON);
213 (void)cpl_vector_fill(xtrue, -2.0 * DBL_EPSILON);
214 (void)cpl_vector_set(xtrue, 0, -1.0);
216 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
217 DBL_EPSILON, 2.0*DBL_EPSILON);
220 (void)cpl_vector_set(xtrue, 0, -1.0);
221 (void)cpl_vector_set(xtrue, 1, -2.0e-4 * FLT_EPSILON);
222 (void)cpl_vector_set(xtrue, 2, 2.0e-4 * FLT_EPSILON);
224 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
225 FLT_EPSILON, 2.0*DBL_EPSILON);
230 (void)cpl_vector_fill(xtrue, 2.0*DBL_EPSILON);
231 (void)cpl_vector_set(xtrue, nreal - 2 , 3.0);
232 (void)cpl_vector_set(xtrue, nreal - 1 , 2.0);
234 irplib_polynomial_test_root_all(xtrue, nreal - 2, CPL_MATH_PI,
235 4.0 * DBL_EPSILON, DBL_EPSILON);
239 (void)cpl_vector_fill(xtrue, 3.0);
240 (void)cpl_vector_set(xtrue, nreal - 2 , -1.0);
241 (void)cpl_vector_set(xtrue, nreal - 1 , 2.0);
243 irplib_polynomial_test_root_all(xtrue, nreal - 2, CPL_MATH_PI,
244 6.0*DBL_EPSILON, 220.0*DBL_EPSILON);
254 cpl_vector_set_size(xtrue, nreal);
257 (void)cpl_vector_set(xtrue, 0, -2.0);
258 (void)cpl_vector_set(xtrue, 1, 2.0 * DBL_EPSILON);
259 (void)cpl_vector_set(xtrue, 2, 1.5);
261 irplib_polynomial_test_root_all(xtrue, nreal, 1.0,
262 4.0*DBL_EPSILON, 30.0*DBL_EPSILON);
267 cpl_vector_set_size(xtrue, nreal);
270 (void)cpl_vector_set(xtrue, 0, -1.0);
271 (void)cpl_vector_set(xtrue, 1, 1.0);
272 (void)cpl_vector_set(xtrue, 2, 2.0);
273 (void)cpl_vector_set(xtrue, 3, 2.0);
275 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
276 2.0 * DBL_EPSILON, 2.0 * DBL_EPSILON);
279 irplib_polynomial_test_root_all(xtrue, 2, CPL_MATH_PI,
280 2.0 * DBL_EPSILON, 2.0 * DBL_EPSILON);
284 (void)cpl_vector_set(xtrue, 0, -2.0);
285 (void)cpl_vector_set(xtrue, 1, -1.0);
286 (void)cpl_vector_set(xtrue, 2, 1.0);
287 (void)cpl_vector_set(xtrue, 3, 2.0);
289 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
290 2.0 * DBL_EPSILON, 2.0 * DBL_EPSILON);
293 (void)cpl_vector_set(xtrue, 0, -1.0);
294 (void)cpl_vector_set(xtrue, 1, 1.0);
295 (void)cpl_vector_set(xtrue, 2, 0.0);
296 (void)cpl_vector_set(xtrue, 3, 2.0);
298 irplib_polynomial_test_root_all(xtrue, 2, CPL_MATH_PI,
299 2.0 * DBL_EPSILON, 2.0 * DBL_EPSILON);
303 (void)cpl_vector_set(xtrue, 0, 1.0);
304 (void)cpl_vector_set(xtrue, 1, 2.0);
305 (void)cpl_vector_set(xtrue, 2, 1.0);
306 (void)cpl_vector_set(xtrue, 3, 3.0);
308 irplib_polynomial_test_root_all(xtrue, 0, CPL_MATH_PI,
309 10.0 * DBL_EPSILON, 10.0 * DBL_EPSILON);
312 (void)cpl_vector_set(xtrue, 0, 0.0);
313 (void)cpl_vector_set(xtrue, 1, 0.0);
314 (void)cpl_vector_set(xtrue, 2, 0.0);
315 (void)cpl_vector_set(xtrue, 3, 2.0);
317 irplib_polynomial_test_root_all(xtrue, 2, CPL_MATH_PI,
318 2.0 * DBL_EPSILON, 2.0 * DBL_EPSILON);
320 p1d = cpl_polynomial_new(1);
323 cpl_polynomial_set_coeff(p1d, &i, -5.0);
325 cpl_polynomial_set_coeff(p1d, &i, -1.0);
327 cpl_polynomial_set_coeff(p1d, &i, -2.0);
329 cpl_polynomial_set_coeff(p1d, &i, 1.0);
334 cpl_msg_info(cpl_func,
"Computed roots (%" CPL_SIZE_FORMAT
" real): ",
336 if (cpl_msg_get_level() <= CPL_MSG_INFO)
337 cpl_vector_dump(xtrue, stderr);
338 cpl_msg_info(cpl_func,
"Residual: %g -> %g ", cpl_vector_get(xtrue, 0),
339 cpl_polynomial_eval_1d(p1d, cpl_vector_get(xtrue, 0), NULL) );
340 cpl_msg_info(cpl_func,
"Residual: %g -> %g ", cpl_vector_get(xtrue, 1),
341 cpl_polynomial_eval_1d(p1d, cpl_vector_get(xtrue, 1), NULL) );
343 cpl_polynomial_delete(p1d);
345 (void)cpl_vector_set(xtrue, 0, 0.0);
346 (void)cpl_vector_set(xtrue, 1, 2.0);
347 (void)cpl_vector_set(xtrue, 2, 1.0);
348 (void)cpl_vector_set(xtrue, 3, 1.0);
350 irplib_polynomial_test_root_all(xtrue, 0, CPL_MATH_PI,
351 2.0 * DBL_EPSILON, 2.0 * DBL_EPSILON);
353 (void)cpl_vector_set(xtrue, 0, -1.0);
354 (void)cpl_vector_set(xtrue, 1, 2.0);
355 (void)cpl_vector_set(xtrue, 2, 1.0);
356 (void)cpl_vector_set(xtrue, 3, 3.0);
358 irplib_polynomial_test_root_all(xtrue, 0, CPL_MATH_PI,
359 3.0 * DBL_EPSILON, 3.0 * DBL_EPSILON);
363 cpl_vector_set_size(xtrue, nreal);
366 (void)cpl_vector_set(xtrue, 0, -1.0);
367 (void)cpl_vector_set(xtrue, 1, 1.0);
368 (void)cpl_vector_set(xtrue, 2, 2.0);
369 (void)cpl_vector_set(xtrue, 3, 3.0);
370 (void)cpl_vector_set(xtrue, 4, 4.0);
372 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
373 48.0 * DBL_EPSILON, 2800.0 * DBL_EPSILON);
375 irplib_polynomial_test_root_all(xtrue, nreal-2, CPL_MATH_PI,
376 8.0 * DBL_EPSILON, 4000.0 * DBL_EPSILON);
378 irplib_polynomial_test_root_all(xtrue, nreal-4, CPL_MATH_PI,
379 4.0 * DBL_EPSILON, 600.0 * DBL_EPSILON);
384 cpl_vector_set_size(xtrue, nreal);
387 (void)cpl_vector_set(xtrue, 0, -1.0);
388 (void)cpl_vector_set(xtrue, 1, 1.0);
389 (void)cpl_vector_set(xtrue, 2, 2.0);
390 (void)cpl_vector_set(xtrue, 3, 3.0);
391 (void)cpl_vector_set(xtrue, 4, 4.0);
392 (void)cpl_vector_set(xtrue, 5, 5.0);
394 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
395 240.0 * DBL_EPSILON, 50.0e3 * DBL_EPSILON);
397 irplib_polynomial_test_root_all(xtrue, nreal-2, CPL_MATH_PI,
398 8.0 * DBL_EPSILON, 25.0e3 * DBL_EPSILON);
400 irplib_polynomial_test_root_all(xtrue, nreal-4, CPL_MATH_PI,
401 12.0 * DBL_EPSILON, 1600.0 * DBL_EPSILON);
408 cpl_vector_delete(xtrue);
426 cpl_error_code irplib_polynomial_multiply_1d_factor(cpl_polynomial *
self,
427 const cpl_vector * roots,
431 const cpl_size nroots = cpl_vector_get_size(roots);
434 cpl_ensure_code(
self != NULL, CPL_ERROR_NULL_INPUT);
435 cpl_ensure_code(roots != NULL, CPL_ERROR_NULL_INPUT);
436 cpl_ensure_code(cpl_polynomial_get_dimension(
self) == 1,
437 CPL_ERROR_ILLEGAL_INPUT);
439 cpl_ensure_code(nreal >= 0, CPL_ERROR_ILLEGAL_INPUT);
440 cpl_ensure_code(nreal <= nroots,
441 CPL_ERROR_ILLEGAL_INPUT);
442 cpl_ensure_code((cpl_vector_get_size(roots) - nreal) % 2 == 0,
443 CPL_ERROR_ILLEGAL_INPUT);
446 degree = cpl_polynomial_get_degree(
self);
447 cpl_ensure_code(degree > 0 || cpl_polynomial_get_coeff(
self, &i) != 0.0,
448 CPL_ERROR_DATA_NOT_FOUND);
450 for (i = 0; i < nreal; i++) {
451 const double root = cpl_vector_get(roots, i);
457 for (j = degree; j >= 0; j--) {
462 const cpl_size jj = j - 1;
463 newval = value = cpl_polynomial_get_coeff(
self, &jj);
469 newval -= root * prev;
472 cpl_polynomial_set_coeff(
self, &j, newval);
481 for (; i < nroots; i += 2) {
482 const double a = cpl_vector_get(roots, i);
483 const double b = cpl_vector_get(roots, i+1);
484 cpl_vector * aroot = cpl_vector_new(2);
485 cpl_polynomial * copy = cpl_polynomial_duplicate(
self);
487 cpl_vector_fill(aroot, a);
489 irplib_polynomial_multiply_1d_factor(
self, aroot, 2);
491 cpl_polynomial_multiply_scalar(copy, copy, b * b);
493 cpl_polynomial_add(
self,
self, copy);
495 cpl_vector_delete(aroot);
496 cpl_polynomial_delete(copy);
500 return CPL_ERROR_NONE;
519 irplib_polynomial_test_root_all_macro(
const cpl_vector *
self, cpl_size nreal,
520 double factor,
double tolerance,
521 double resitol,
unsigned line)
524 const cpl_size degree = cpl_vector_get_size(
self);
525 cpl_polynomial * p1d = cpl_polynomial_new(1);
526 cpl_vector * roots = cpl_vector_new(degree);
530 cpl_test_eq(cpl_polynomial_set_coeff(p1d, &i, factor), CPL_ERROR_NONE);
532 cpl_test_eq(irplib_polynomial_multiply_1d_factor(p1d,
self, nreal),
538 cpl_test_eq(jreal, nreal);
539 if (jreal != nreal) {
540 cpl_msg_info(cpl_func,
"1D-polynomial:");
541 cpl_polynomial_dump(p1d, stderr);
542 cpl_msg_error(cpl_func,
"True roots (%" CPL_SIZE_FORMAT
543 " real): (line=%u)", nreal, line);
544 cpl_vector_dump(
self, stderr);
545 cpl_msg_error(cpl_func,
"Computed roots (%" CPL_SIZE_FORMAT
" real): ",
547 cpl_vector_dump(roots, stderr);
548 }
else if (cpl_msg_get_level() < CPL_MSG_WARNING) {
549 cpl_bivector * dump =
550 cpl_bivector_wrap_vectors((cpl_vector*)
self, roots);
552 cpl_msg_warning(cpl_func,
"Comparing %" CPL_SIZE_FORMAT
" roots (%"
553 CPL_SIZE_FORMAT
" real): (line=%u)",
554 degree, nreal, line);
555 cpl_bivector_dump(dump, stderr);
556 cpl_bivector_unwrap_vectors(dump);
559 for (i = 0; i < jreal; i++) {
560 const double root = cpl_vector_get(roots, i);
561 const double residual = cpl_polynomial_eval_1d(p1d, root, NULL);
563 cpl_test_abs(root, cpl_vector_get(
self, i), tolerance);
565 cpl_test_abs(residual, 0.0, resitol);
569 for (i = nreal; i < degree; i++) {
570 const double root = cpl_vector_get(roots, i);
572 cpl_test_abs(root, cpl_vector_get(
self, i), tolerance);
578 cpl_vector_delete(roots);
579 cpl_polynomial_delete(p1d);