36 #include <irplib_polynomial.h>
47 #define irplib_polynomial_test_root_all(A, B, C, D, E) \
48 irplib_polynomial_test_root_all_macro(A, B, C, D, E, __LINE__)
54 static cpl_error_code irplib_polynomial_multiply_1d_factor(cpl_polynomial *,
57 static void irplib_polynomial_solve_1d_all_test(
void);
59 static void irplib_polynomial_test_root_all_macro(
const cpl_vector *, cpl_size,
60 double,
double,
double,
69 cpl_test_init(PACKAGE_BUGREPORT, CPL_MSG_WARNING);
71 irplib_polynomial_solve_1d_all_test();
73 return cpl_test_end(0);
85 static void irplib_polynomial_solve_1d_all_test(
void)
88 cpl_polynomial * p2d = cpl_polynomial_new(2);
89 cpl_polynomial * p1d = cpl_polynomial_new(1);
90 cpl_vector * xtrue = cpl_vector_new(2);
91 const cpl_size maxdegree = 4;
96 CPL_ERROR_NULL_INPUT);
97 cpl_test_error(CPL_ERROR_NULL_INPUT);
100 CPL_ERROR_NULL_INPUT);
101 cpl_test_error(CPL_ERROR_NULL_INPUT);
104 CPL_ERROR_NULL_INPUT);
105 cpl_test_error(CPL_ERROR_NULL_INPUT);
108 CPL_ERROR_INVALID_TYPE);
109 cpl_test_error(CPL_ERROR_INVALID_TYPE);
112 CPL_ERROR_DATA_NOT_FOUND);
113 cpl_test_error(CPL_ERROR_DATA_NOT_FOUND);
117 cpl_test_eq(cpl_polynomial_set_coeff(p1d, &i, 1.0), CPL_ERROR_NONE);
119 CPL_ERROR_INCOMPATIBLE_INPUT);
120 cpl_test_error(CPL_ERROR_INCOMPATIBLE_INPUT);
122 cpl_polynomial_delete(p1d);
123 cpl_polynomial_delete(p2d);
125 for (nreal = 1; nreal <= maxdegree; nreal++) {
130 cpl_vector_set_size(xtrue, nreal);
132 (void)cpl_vector_fill(xtrue, xreal);
134 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
135 2.0 * DBL_EPSILON, 2.0 * DBL_EPSILON);
140 (void)cpl_vector_fill(xtrue, xreal);
142 irplib_polynomial_test_root_all(xtrue, nreal, 1.0,
143 2.0 * DBL_EPSILON, 2.0 * DBL_EPSILON);
146 for (i = 0; i < nreal; i++) {
147 (void)cpl_vector_set(xtrue, i, 2.0 * (
double)i - CPL_MATH_E);
150 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
152 300.0 * DBL_EPSILON);
155 for (i = 0; i < nreal-1; i++) {
156 (void)cpl_vector_set(xtrue, nreal-i-2, (
double)(-i));
158 (void)cpl_vector_set(xtrue, nreal-1, (
double)(nreal-1));
160 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
161 16.0*DBL_EPSILON, 600.0*DBL_EPSILON);
163 if (nreal < 2)
continue;
167 (void)cpl_vector_fill(xtrue, 2.0);
168 (void)cpl_vector_set(xtrue, nreal-2, -1.0);
169 (void)cpl_vector_set(xtrue, nreal-1, 1.0);
171 irplib_polynomial_test_root_all(xtrue, nreal-2, CPL_MATH_PI,
172 30.0*DBL_EPSILON, 25.0*DBL_EPSILON);
174 if (nreal < 3)
continue;
177 (void)cpl_vector_fill(xtrue, 1.0);
178 (void)cpl_vector_set(xtrue, nreal - 1 , 2.0);
180 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
181 DBL_EPSILON, DBL_EPSILON);
183 (void)cpl_vector_fill(xtrue, -1.0);
184 (void)cpl_vector_set(xtrue, 0 , -2.0);
186 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
187 DBL_EPSILON, DBL_EPSILON);
189 (void)cpl_vector_fill(xtrue, 2.0);
190 (void)cpl_vector_set(xtrue, 0, 1.0);
192 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
193 DBL_EPSILON, DBL_EPSILON);
196 if (nreal > 3)
continue;
199 (void)cpl_vector_fill(xtrue, -2.0 * FLT_EPSILON);
200 (void)cpl_vector_set(xtrue, 0, -1.0);
202 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
203 DBL_EPSILON, 2.0*DBL_EPSILON);
206 #if defined SIZE_MAX && SIZE_MAX <= 4294967295
207 (void)cpl_vector_fill(xtrue, -0.1 * FLT_EPSILON);
209 (void)cpl_vector_fill(xtrue, -0.2 * FLT_EPSILON);
212 (void)cpl_vector_set(xtrue, 0, -1.0);
214 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
215 FLT_EPSILON, 3.0*DBL_EPSILON);
219 (void)cpl_vector_fill(xtrue, -2.0 * DBL_EPSILON);
220 (void)cpl_vector_set(xtrue, 0, -1.0);
222 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
223 DBL_EPSILON, 2.0*DBL_EPSILON);
226 (void)cpl_vector_set(xtrue, 0, -1.0);
227 (void)cpl_vector_set(xtrue, 1, -2.0e-4 * FLT_EPSILON);
228 (void)cpl_vector_set(xtrue, 2, 2.0e-4 * FLT_EPSILON);
230 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
231 FLT_EPSILON, 2.0*DBL_EPSILON);
236 (void)cpl_vector_fill(xtrue, 2.0*DBL_EPSILON);
237 (void)cpl_vector_set(xtrue, nreal - 2 , 3.0);
238 (void)cpl_vector_set(xtrue, nreal - 1 , 2.0);
240 irplib_polynomial_test_root_all(xtrue, nreal - 2, CPL_MATH_PI,
241 4.0 * DBL_EPSILON, DBL_EPSILON);
245 (void)cpl_vector_fill(xtrue, 3.0);
246 (void)cpl_vector_set(xtrue, nreal - 2 , -1.0);
247 (void)cpl_vector_set(xtrue, nreal - 1 , 2.0);
249 irplib_polynomial_test_root_all(xtrue, nreal - 2, CPL_MATH_PI,
250 6.0*DBL_EPSILON, 220.0*DBL_EPSILON);
260 cpl_vector_set_size(xtrue, nreal);
263 (void)cpl_vector_set(xtrue, 0, -2.0);
264 (void)cpl_vector_set(xtrue, 1, 2.0 * DBL_EPSILON);
265 (void)cpl_vector_set(xtrue, 2, 1.5);
267 irplib_polynomial_test_root_all(xtrue, nreal, 1.0,
268 4.0*DBL_EPSILON, 30.0*DBL_EPSILON);
273 cpl_vector_set_size(xtrue, nreal);
276 (void)cpl_vector_set(xtrue, 0, -1.0);
277 (void)cpl_vector_set(xtrue, 1, 1.0);
278 (void)cpl_vector_set(xtrue, 2, 2.0);
279 (void)cpl_vector_set(xtrue, 3, 2.0);
281 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
282 2.0 * DBL_EPSILON, 2.0 * DBL_EPSILON);
285 irplib_polynomial_test_root_all(xtrue, 2, CPL_MATH_PI,
286 2.0 * DBL_EPSILON, 2.0 * DBL_EPSILON);
290 (void)cpl_vector_set(xtrue, 0, -2.0);
291 (void)cpl_vector_set(xtrue, 1, -1.0);
292 (void)cpl_vector_set(xtrue, 2, 1.0);
293 (void)cpl_vector_set(xtrue, 3, 2.0);
295 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
296 2.0 * DBL_EPSILON, 2.0 * DBL_EPSILON);
299 (void)cpl_vector_set(xtrue, 0, -1.0);
300 (void)cpl_vector_set(xtrue, 1, 1.0);
301 (void)cpl_vector_set(xtrue, 2, 0.0);
302 (void)cpl_vector_set(xtrue, 3, 2.0);
304 irplib_polynomial_test_root_all(xtrue, 2, CPL_MATH_PI,
305 2.0 * DBL_EPSILON, 2.0 * DBL_EPSILON);
309 (void)cpl_vector_set(xtrue, 0, 1.0);
310 (void)cpl_vector_set(xtrue, 1, 2.0);
311 (void)cpl_vector_set(xtrue, 2, 1.0);
312 (void)cpl_vector_set(xtrue, 3, 3.0);
314 irplib_polynomial_test_root_all(xtrue, 0, CPL_MATH_PI,
315 10.0 * DBL_EPSILON, 10.0 * DBL_EPSILON);
318 (void)cpl_vector_set(xtrue, 0, 0.0);
319 (void)cpl_vector_set(xtrue, 1, 0.0);
320 (void)cpl_vector_set(xtrue, 2, 0.0);
321 (void)cpl_vector_set(xtrue, 3, 2.0);
323 irplib_polynomial_test_root_all(xtrue, 2, CPL_MATH_PI,
324 2.0 * DBL_EPSILON, 2.0 * DBL_EPSILON);
326 p1d = cpl_polynomial_new(1);
329 cpl_polynomial_set_coeff(p1d, &i, -5.0);
331 cpl_polynomial_set_coeff(p1d, &i, -1.0);
333 cpl_polynomial_set_coeff(p1d, &i, -2.0);
335 cpl_polynomial_set_coeff(p1d, &i, 1.0);
340 cpl_msg_info(cpl_func,
"Computed roots (%" CPL_SIZE_FORMAT
" real): ",
342 if (cpl_msg_get_level() <= CPL_MSG_INFO)
343 cpl_vector_dump(xtrue, stderr);
344 cpl_msg_info(cpl_func,
"Residual: %g -> %g ", cpl_vector_get(xtrue, 0),
345 cpl_polynomial_eval_1d(p1d, cpl_vector_get(xtrue, 0), NULL) );
346 cpl_msg_info(cpl_func,
"Residual: %g -> %g ", cpl_vector_get(xtrue, 1),
347 cpl_polynomial_eval_1d(p1d, cpl_vector_get(xtrue, 1), NULL) );
349 cpl_polynomial_delete(p1d);
351 (void)cpl_vector_set(xtrue, 0, 0.0);
352 (void)cpl_vector_set(xtrue, 1, 2.0);
353 (void)cpl_vector_set(xtrue, 2, 1.0);
354 (void)cpl_vector_set(xtrue, 3, 1.0);
356 irplib_polynomial_test_root_all(xtrue, 0, CPL_MATH_PI,
357 2.0 * DBL_EPSILON, 2.0 * DBL_EPSILON);
359 (void)cpl_vector_set(xtrue, 0, -1.0);
360 (void)cpl_vector_set(xtrue, 1, 2.0);
361 (void)cpl_vector_set(xtrue, 2, 1.0);
362 (void)cpl_vector_set(xtrue, 3, 3.0);
364 irplib_polynomial_test_root_all(xtrue, 0, CPL_MATH_PI,
365 3.0 * DBL_EPSILON, 3.0 * DBL_EPSILON);
369 cpl_vector_set_size(xtrue, nreal);
372 (void)cpl_vector_set(xtrue, 0, -1.0);
373 (void)cpl_vector_set(xtrue, 1, 1.0);
374 (void)cpl_vector_set(xtrue, 2, 2.0);
375 (void)cpl_vector_set(xtrue, 3, 3.0);
376 (void)cpl_vector_set(xtrue, 4, 4.0);
378 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
379 48.0 * DBL_EPSILON, 2800.0 * DBL_EPSILON);
381 irplib_polynomial_test_root_all(xtrue, nreal-2, CPL_MATH_PI,
382 8.0 * DBL_EPSILON, 4000.0 * DBL_EPSILON);
384 irplib_polynomial_test_root_all(xtrue, nreal-4, CPL_MATH_PI,
385 4.0 * DBL_EPSILON, 600.0 * DBL_EPSILON);
390 cpl_vector_set_size(xtrue, nreal);
393 (void)cpl_vector_set(xtrue, 0, -1.0);
394 (void)cpl_vector_set(xtrue, 1, 1.0);
395 (void)cpl_vector_set(xtrue, 2, 2.0);
396 (void)cpl_vector_set(xtrue, 3, 3.0);
397 (void)cpl_vector_set(xtrue, 4, 4.0);
398 (void)cpl_vector_set(xtrue, 5, 5.0);
400 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
401 240.0 * DBL_EPSILON, 50.0e3 * DBL_EPSILON);
403 irplib_polynomial_test_root_all(xtrue, nreal-2, CPL_MATH_PI,
404 8.0 * DBL_EPSILON, 25.0e3 * DBL_EPSILON);
406 irplib_polynomial_test_root_all(xtrue, nreal-4, CPL_MATH_PI,
407 12.0 * DBL_EPSILON, 1600.0 * DBL_EPSILON);
414 cpl_vector_delete(xtrue);
432 cpl_error_code irplib_polynomial_multiply_1d_factor(cpl_polynomial *
self,
433 const cpl_vector * roots,
437 const cpl_size nroots = cpl_vector_get_size(roots);
440 cpl_ensure_code(
self != NULL, CPL_ERROR_NULL_INPUT);
441 cpl_ensure_code(roots != NULL, CPL_ERROR_NULL_INPUT);
442 cpl_ensure_code(cpl_polynomial_get_dimension(
self) == 1,
443 CPL_ERROR_ILLEGAL_INPUT);
445 cpl_ensure_code(nreal >= 0, CPL_ERROR_ILLEGAL_INPUT);
446 cpl_ensure_code(nreal <= nroots,
447 CPL_ERROR_ILLEGAL_INPUT);
448 cpl_ensure_code((cpl_vector_get_size(roots) - nreal) % 2 == 0,
449 CPL_ERROR_ILLEGAL_INPUT);
452 degree = cpl_polynomial_get_degree(
self);
453 cpl_ensure_code(degree > 0 || cpl_polynomial_get_coeff(
self, &i) != 0.0,
454 CPL_ERROR_DATA_NOT_FOUND);
456 for (i = 0; i < nreal; i++) {
457 const double root = cpl_vector_get(roots, i);
463 for (j = degree; j >= 0; j--) {
468 const cpl_size jj = j - 1;
469 newval = value = cpl_polynomial_get_coeff(
self, &jj);
475 newval -= root * prev;
478 cpl_polynomial_set_coeff(
self, &j, newval);
487 for (; i < nroots; i += 2) {
488 const double a = cpl_vector_get(roots, i);
489 const double b = cpl_vector_get(roots, i+1);
490 cpl_vector * aroot = cpl_vector_new(2);
491 cpl_polynomial * copy = cpl_polynomial_duplicate(
self);
493 cpl_vector_fill(aroot, a);
495 irplib_polynomial_multiply_1d_factor(
self, aroot, 2);
497 cpl_polynomial_multiply_scalar(copy, copy, b * b);
499 cpl_polynomial_add(
self,
self, copy);
501 cpl_vector_delete(aroot);
502 cpl_polynomial_delete(copy);
506 return CPL_ERROR_NONE;
525 irplib_polynomial_test_root_all_macro(
const cpl_vector *
self, cpl_size nreal,
526 double factor,
double tolerance,
527 double resitol,
unsigned line)
530 const cpl_size degree = cpl_vector_get_size(
self);
531 cpl_polynomial * p1d = cpl_polynomial_new(1);
532 cpl_vector * roots = cpl_vector_new(degree);
536 cpl_test_eq(cpl_polynomial_set_coeff(p1d, &i, factor), CPL_ERROR_NONE);
538 cpl_test_eq(irplib_polynomial_multiply_1d_factor(p1d,
self, nreal),
544 cpl_test_eq(jreal, nreal);
545 if (jreal != nreal) {
546 cpl_msg_info(cpl_func,
"1D-polynomial:");
547 cpl_polynomial_dump(p1d, stderr);
548 cpl_msg_error(cpl_func,
"True roots (%" CPL_SIZE_FORMAT
549 " real): (line=%u)", nreal, line);
550 cpl_vector_dump(
self, stderr);
551 cpl_msg_error(cpl_func,
"Computed roots (%" CPL_SIZE_FORMAT
" real): ",
553 cpl_vector_dump(roots, stderr);
554 }
else if (cpl_msg_get_level() < CPL_MSG_WARNING) {
555 cpl_bivector * dump =
556 cpl_bivector_wrap_vectors((cpl_vector*)
self, roots);
558 cpl_msg_warning(cpl_func,
"Comparing %" CPL_SIZE_FORMAT
" roots (%"
559 CPL_SIZE_FORMAT
" real): (line=%u)",
560 degree, nreal, line);
561 cpl_bivector_dump(dump, stderr);
562 cpl_bivector_unwrap_vectors(dump);
565 for (i = 0; i < jreal; i++) {
566 const double root = cpl_vector_get(roots, i);
567 const double residual = cpl_polynomial_eval_1d(p1d, root, NULL);
569 cpl_test_abs(root, cpl_vector_get(
self, i), tolerance);
571 cpl_test_abs(residual, 0.0, resitol);
575 for (i = nreal; i < degree; i++) {
576 const double root = cpl_vector_get(roots, i);
578 cpl_test_abs(root, cpl_vector_get(
self, i), tolerance);
584 cpl_vector_delete(roots);
585 cpl_polynomial_delete(p1d);