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
209 (void)cpl_vector_fill(xtrue, -0.2 * FLT_EPSILON);
211 (void)cpl_vector_set(xtrue, 0, -1.0);
213 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
214 FLT_EPSILON, 3.0*DBL_EPSILON);
220 (void)cpl_vector_fill(xtrue, -2.0 * DBL_EPSILON);
221 (void)cpl_vector_set(xtrue, 0, -1.0);
223 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
224 DBL_EPSILON, 2.0*DBL_EPSILON);
227 (void)cpl_vector_set(xtrue, 0, -1.0);
228 (void)cpl_vector_set(xtrue, 1, -2.0e-4 * FLT_EPSILON);
229 (void)cpl_vector_set(xtrue, 2, 2.0e-4 * FLT_EPSILON);
231 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
232 FLT_EPSILON, 2.0*DBL_EPSILON);
237 (void)cpl_vector_fill(xtrue, 2.0*DBL_EPSILON);
238 (void)cpl_vector_set(xtrue, nreal - 2 , 3.0);
239 (void)cpl_vector_set(xtrue, nreal - 1 , 2.0);
241 irplib_polynomial_test_root_all(xtrue, nreal - 2, CPL_MATH_PI,
242 4.0 * DBL_EPSILON, DBL_EPSILON);
246 (void)cpl_vector_fill(xtrue, 3.0);
247 (void)cpl_vector_set(xtrue, nreal - 2 , -1.0);
248 (void)cpl_vector_set(xtrue, nreal - 1 , 2.0);
250 irplib_polynomial_test_root_all(xtrue, nreal - 2, CPL_MATH_PI,
251 6.0*DBL_EPSILON, 220.0*DBL_EPSILON);
261 cpl_vector_set_size(xtrue, nreal);
264 (void)cpl_vector_set(xtrue, 0, -2.0);
265 (void)cpl_vector_set(xtrue, 1, 2.0 * DBL_EPSILON);
266 (void)cpl_vector_set(xtrue, 2, 1.5);
268 irplib_polynomial_test_root_all(xtrue, nreal, 1.0,
269 4.0*DBL_EPSILON, 30.0*DBL_EPSILON);
274 cpl_vector_set_size(xtrue, nreal);
277 (void)cpl_vector_set(xtrue, 0, -1.0);
278 (void)cpl_vector_set(xtrue, 1, 1.0);
279 (void)cpl_vector_set(xtrue, 2, 2.0);
280 (void)cpl_vector_set(xtrue, 3, 2.0);
282 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
283 2.0 * DBL_EPSILON, 2.0 * DBL_EPSILON);
286 irplib_polynomial_test_root_all(xtrue, 2, CPL_MATH_PI,
287 2.0 * DBL_EPSILON, 2.0 * DBL_EPSILON);
291 (void)cpl_vector_set(xtrue, 0, -2.0);
292 (void)cpl_vector_set(xtrue, 1, -1.0);
293 (void)cpl_vector_set(xtrue, 2, 1.0);
294 (void)cpl_vector_set(xtrue, 3, 2.0);
296 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
297 2.0 * DBL_EPSILON, 2.0 * DBL_EPSILON);
300 (void)cpl_vector_set(xtrue, 0, -1.0);
301 (void)cpl_vector_set(xtrue, 1, 1.0);
302 (void)cpl_vector_set(xtrue, 2, 0.0);
303 (void)cpl_vector_set(xtrue, 3, 2.0);
305 irplib_polynomial_test_root_all(xtrue, 2, CPL_MATH_PI,
306 2.0 * DBL_EPSILON, 2.0 * DBL_EPSILON);
310 (void)cpl_vector_set(xtrue, 0, 1.0);
311 (void)cpl_vector_set(xtrue, 1, 2.0);
312 (void)cpl_vector_set(xtrue, 2, 1.0);
313 (void)cpl_vector_set(xtrue, 3, 3.0);
315 irplib_polynomial_test_root_all(xtrue, 0, CPL_MATH_PI,
316 10.0 * DBL_EPSILON, 10.0 * DBL_EPSILON);
319 (void)cpl_vector_set(xtrue, 0, 0.0);
320 (void)cpl_vector_set(xtrue, 1, 0.0);
321 (void)cpl_vector_set(xtrue, 2, 0.0);
322 (void)cpl_vector_set(xtrue, 3, 2.0);
324 irplib_polynomial_test_root_all(xtrue, 2, CPL_MATH_PI,
325 2.0 * DBL_EPSILON, 2.0 * DBL_EPSILON);
327 p1d = cpl_polynomial_new(1);
330 cpl_polynomial_set_coeff(p1d, &i, -5.0);
332 cpl_polynomial_set_coeff(p1d, &i, -1.0);
334 cpl_polynomial_set_coeff(p1d, &i, -2.0);
336 cpl_polynomial_set_coeff(p1d, &i, 1.0);
341 cpl_msg_info(cpl_func,
"Computed roots (%" CPL_SIZE_FORMAT
" real): ",
343 if (cpl_msg_get_level() <= CPL_MSG_INFO)
344 cpl_vector_dump(xtrue, stderr);
345 cpl_msg_info(cpl_func,
"Residual: %g -> %g ", cpl_vector_get(xtrue, 0),
346 cpl_polynomial_eval_1d(p1d, cpl_vector_get(xtrue, 0), NULL) );
347 cpl_msg_info(cpl_func,
"Residual: %g -> %g ", cpl_vector_get(xtrue, 1),
348 cpl_polynomial_eval_1d(p1d, cpl_vector_get(xtrue, 1), NULL) );
350 cpl_polynomial_delete(p1d);
352 (void)cpl_vector_set(xtrue, 0, 0.0);
353 (void)cpl_vector_set(xtrue, 1, 2.0);
354 (void)cpl_vector_set(xtrue, 2, 1.0);
355 (void)cpl_vector_set(xtrue, 3, 1.0);
357 irplib_polynomial_test_root_all(xtrue, 0, CPL_MATH_PI,
358 2.0 * DBL_EPSILON, 2.0 * DBL_EPSILON);
360 (void)cpl_vector_set(xtrue, 0, -1.0);
361 (void)cpl_vector_set(xtrue, 1, 2.0);
362 (void)cpl_vector_set(xtrue, 2, 1.0);
363 (void)cpl_vector_set(xtrue, 3, 3.0);
365 irplib_polynomial_test_root_all(xtrue, 0, CPL_MATH_PI,
366 3.0 * DBL_EPSILON, 3.0 * DBL_EPSILON);
370 cpl_vector_set_size(xtrue, nreal);
373 (void)cpl_vector_set(xtrue, 0, -1.0);
374 (void)cpl_vector_set(xtrue, 1, 1.0);
375 (void)cpl_vector_set(xtrue, 2, 2.0);
376 (void)cpl_vector_set(xtrue, 3, 3.0);
377 (void)cpl_vector_set(xtrue, 4, 4.0);
379 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
380 48.0 * DBL_EPSILON, 2800.0 * DBL_EPSILON);
382 irplib_polynomial_test_root_all(xtrue, nreal-2, CPL_MATH_PI,
383 8.0 * DBL_EPSILON, 4000.0 * DBL_EPSILON);
385 irplib_polynomial_test_root_all(xtrue, nreal-4, CPL_MATH_PI,
386 4.0 * DBL_EPSILON, 600.0 * DBL_EPSILON);
391 cpl_vector_set_size(xtrue, nreal);
394 (void)cpl_vector_set(xtrue, 0, -1.0);
395 (void)cpl_vector_set(xtrue, 1, 1.0);
396 (void)cpl_vector_set(xtrue, 2, 2.0);
397 (void)cpl_vector_set(xtrue, 3, 3.0);
398 (void)cpl_vector_set(xtrue, 4, 4.0);
399 (void)cpl_vector_set(xtrue, 5, 5.0);
401 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
402 240.0 * DBL_EPSILON, 50.0e3 * DBL_EPSILON);
404 irplib_polynomial_test_root_all(xtrue, nreal-2, CPL_MATH_PI,
405 10.0 * DBL_EPSILON, 25.0e3 * DBL_EPSILON);
407 irplib_polynomial_test_root_all(xtrue, nreal-4, CPL_MATH_PI,
408 12.0 * DBL_EPSILON, 1600.0 * DBL_EPSILON);
415 cpl_vector_delete(xtrue);
433 cpl_error_code irplib_polynomial_multiply_1d_factor(cpl_polynomial *
self,
434 const cpl_vector * roots,
438 const cpl_size nroots = cpl_vector_get_size(roots);
441 cpl_ensure_code(
self != NULL, CPL_ERROR_NULL_INPUT);
442 cpl_ensure_code(roots != NULL, CPL_ERROR_NULL_INPUT);
443 cpl_ensure_code(cpl_polynomial_get_dimension(
self) == 1,
444 CPL_ERROR_ILLEGAL_INPUT);
446 cpl_ensure_code(nreal >= 0, CPL_ERROR_ILLEGAL_INPUT);
447 cpl_ensure_code(nreal <= nroots,
448 CPL_ERROR_ILLEGAL_INPUT);
449 cpl_ensure_code((cpl_vector_get_size(roots) - nreal) % 2 == 0,
450 CPL_ERROR_ILLEGAL_INPUT);
453 degree = cpl_polynomial_get_degree(
self);
454 cpl_ensure_code(degree > 0 || cpl_polynomial_get_coeff(
self, &i) != 0.0,
455 CPL_ERROR_DATA_NOT_FOUND);
457 for (i = 0; i < nreal; i++) {
458 const double root = cpl_vector_get(roots, i);
464 for (j = degree; j >= 0; j--) {
469 const cpl_size jj = j - 1;
470 newval = value = cpl_polynomial_get_coeff(
self, &jj);
476 newval -= root * prev;
479 cpl_polynomial_set_coeff(
self, &j, newval);
488 for (; i < nroots; i += 2) {
489 const double a = cpl_vector_get(roots, i);
490 const double b = cpl_vector_get(roots, i+1);
491 cpl_vector * aroot = cpl_vector_new(2);
492 cpl_polynomial * copy = cpl_polynomial_duplicate(
self);
494 cpl_vector_fill(aroot, a);
496 irplib_polynomial_multiply_1d_factor(
self, aroot, 2);
498 cpl_polynomial_multiply_scalar(copy, copy, b * b);
500 cpl_polynomial_add(
self,
self, copy);
502 cpl_vector_delete(aroot);
503 cpl_polynomial_delete(copy);
507 return CPL_ERROR_NONE;
526 irplib_polynomial_test_root_all_macro(
const cpl_vector *
self, cpl_size nreal,
527 double factor,
double tolerance,
528 double resitol,
unsigned line)
531 const cpl_size degree = cpl_vector_get_size(
self);
532 cpl_polynomial * p1d = cpl_polynomial_new(1);
533 cpl_vector * roots = cpl_vector_new(degree);
537 cpl_test_eq(cpl_polynomial_set_coeff(p1d, &i, factor), CPL_ERROR_NONE);
539 cpl_test_eq(irplib_polynomial_multiply_1d_factor(p1d,
self, nreal),
545 cpl_test_eq(jreal, nreal);
546 if (jreal != nreal) {
547 cpl_msg_info(cpl_func,
"1D-polynomial:");
548 cpl_polynomial_dump(p1d, stderr);
549 cpl_msg_error(cpl_func,
"True roots (%" CPL_SIZE_FORMAT
550 " real): (line=%u)", nreal, line);
551 cpl_vector_dump(
self, stderr);
552 cpl_msg_error(cpl_func,
"Computed roots (%" CPL_SIZE_FORMAT
" real): ",
554 cpl_vector_dump(roots, stderr);
555 }
else if (cpl_msg_get_level() < CPL_MSG_WARNING) {
556 cpl_bivector * dump =
557 cpl_bivector_wrap_vectors((cpl_vector*)
self, roots);
559 cpl_msg_warning(cpl_func,
"Comparing %" CPL_SIZE_FORMAT
" roots (%"
560 CPL_SIZE_FORMAT
" real): (line=%u)",
561 degree, nreal, line);
562 cpl_bivector_dump(dump, stderr);
563 cpl_bivector_unwrap_vectors(dump);
566 for (i = 0; i < jreal; i++) {
567 const double root = cpl_vector_get(roots, i);
568 const double residual = cpl_polynomial_eval_1d(p1d, root, NULL);
570 cpl_test_abs(root, cpl_vector_get(
self, i), tolerance);
572 cpl_test_abs(residual, 0.0, resitol);
576 for (i = nreal; i < degree; i++) {
577 const double root = cpl_vector_get(roots, i);
579 cpl_test_abs(root, cpl_vector_get(
self, i), tolerance);
585 cpl_vector_delete(roots);
586 cpl_polynomial_delete(p1d);
cpl_error_code irplib_polynomial_solve_1d_all(const cpl_polynomial *self, cpl_vector *roots, cpl_size *preal)
Compute all n roots of p(x) = 0, where p(x) is of degree n, n > 0.
int main(void)
Various tests of low-level library functions.