00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #ifdef HAVE_CONFIG_H
00033 #include <config.h>
00034 #endif
00035
00036 #include <irplib_polynomial.h>
00037 #include <math.h>
00038 #include <float.h>
00039
00040
00041
00042
00043
00044 #define MAXDEGREE 6
00045
00046 #define irplib_polynomial_test_root_all(A, B, C, D, E) \
00047 irplib_polynomial_test_root_all_macro(A, B, C, D, E, __LINE__)
00048
00049
00050
00051
00052
00053 static cpl_error_code irplib_polynomial_multiply_1d_factor(cpl_polynomial *,
00054 const cpl_vector *,
00055 int);
00056 static void irplib_polynomial_solve_1d_all_test(void);
00057
00058 static void irplib_polynomial_test_root_all_macro(const cpl_vector *, int,
00059 double, double, double,
00060 unsigned);
00061
00062
00063
00064
00065 int main(void)
00066 {
00067
00068 cpl_test_init(PACKAGE_BUGREPORT, CPL_MSG_WARNING);
00069
00070 irplib_polynomial_solve_1d_all_test();
00071
00072 return cpl_test_end(0);
00073 }
00074
00075
00076
00083
00084 static void irplib_polynomial_solve_1d_all_test(void)
00085 {
00086
00087 cpl_polynomial * p2d = cpl_polynomial_new(2);
00088 cpl_polynomial * p1d = cpl_polynomial_new(1);
00089 cpl_vector * xtrue = cpl_vector_new(2);
00090 const int maxdegree = 4;
00091 int nreal = 0;
00092 int i;
00093
00094 cpl_test_eq(irplib_polynomial_solve_1d_all(NULL, xtrue, &nreal),
00095 CPL_ERROR_NULL_INPUT);
00096 cpl_test_error(CPL_ERROR_NULL_INPUT);
00097
00098 cpl_test_eq(irplib_polynomial_solve_1d_all(p1d, NULL, &nreal),
00099 CPL_ERROR_NULL_INPUT);
00100 cpl_test_error(CPL_ERROR_NULL_INPUT);
00101
00102 cpl_test_eq(irplib_polynomial_solve_1d_all(p1d, xtrue, NULL),
00103 CPL_ERROR_NULL_INPUT);
00104 cpl_test_error(CPL_ERROR_NULL_INPUT);
00105
00106 cpl_test_eq(irplib_polynomial_solve_1d_all(p2d, xtrue, &nreal),
00107 CPL_ERROR_INVALID_TYPE);
00108 cpl_test_error(CPL_ERROR_INVALID_TYPE);
00109
00110 cpl_test_eq(irplib_polynomial_solve_1d_all(p1d, xtrue, &nreal),
00111 CPL_ERROR_DATA_NOT_FOUND);
00112 cpl_test_error(CPL_ERROR_DATA_NOT_FOUND);
00113
00114
00115 i = 1;
00116 cpl_test_eq(cpl_polynomial_set_coeff(p1d, &i, 1.0), CPL_ERROR_NONE);
00117 cpl_test_eq(irplib_polynomial_solve_1d_all(p1d, xtrue, &nreal),
00118 CPL_ERROR_INCOMPATIBLE_INPUT);
00119 cpl_test_error(CPL_ERROR_INCOMPATIBLE_INPUT);
00120
00121 cpl_polynomial_delete(p1d);
00122 cpl_polynomial_delete(p2d);
00123
00124 for (nreal = 1; nreal <= maxdegree; nreal++) {
00125
00126 double xreal = 0.0;
00127
00128
00129 cpl_vector_set_size(xtrue, nreal);
00130
00131 (void)cpl_vector_fill(xtrue, xreal);
00132
00133 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
00134 2.0 * DBL_EPSILON, 2.0 * DBL_EPSILON);
00135
00136
00137 xreal = 1.0;
00138
00139 (void)cpl_vector_fill(xtrue, xreal);
00140
00141 irplib_polynomial_test_root_all(xtrue, nreal, 1.0,
00142 2.0 * DBL_EPSILON, 2.0 * DBL_EPSILON);
00143
00144
00145 for (i = 0; i < nreal; i++) {
00146 (void)cpl_vector_set(xtrue, i, 2.0 * (double)i - CPL_MATH_E);
00147 }
00148
00149 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
00150 20.0 * DBL_EPSILON,
00151 300.0 * DBL_EPSILON);
00152
00153
00154 for (i = 0; i < nreal-1; i++) {
00155 (void)cpl_vector_set(xtrue, nreal-i-2, (double)(-i));
00156 }
00157 (void)cpl_vector_set(xtrue, nreal-1, (double)(nreal-1));
00158
00159 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
00160 16.0*DBL_EPSILON, 400.0*DBL_EPSILON);
00161
00162 if (nreal < 2) continue;
00163
00164
00165
00166 (void)cpl_vector_fill(xtrue, 2.0);
00167 (void)cpl_vector_set(xtrue, nreal-2, -1.0);
00168 (void)cpl_vector_set(xtrue, nreal-1, 1.0);
00169
00170 irplib_polynomial_test_root_all(xtrue, nreal-2, CPL_MATH_PI,
00171 30.0*DBL_EPSILON, 25.0*DBL_EPSILON);
00172
00173 if (nreal < 3) continue;
00174 if (nreal > 4) {
00175
00176 (void)cpl_vector_fill(xtrue, 1.0);
00177 (void)cpl_vector_set(xtrue, nreal - 1 , 2.0);
00178
00179 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
00180 DBL_EPSILON, DBL_EPSILON);
00181
00182 (void)cpl_vector_fill(xtrue, -1.0);
00183 (void)cpl_vector_set(xtrue, 0 , -2.0);
00184
00185 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
00186 DBL_EPSILON, DBL_EPSILON);
00187
00188 (void)cpl_vector_fill(xtrue, 2.0);
00189 (void)cpl_vector_set(xtrue, 0, 1.0);
00190
00191 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
00192 DBL_EPSILON, DBL_EPSILON);
00193 }
00194
00195 if (nreal > 3) continue;
00196
00197
00198 (void)cpl_vector_fill(xtrue, -2.0 * FLT_EPSILON);
00199 (void)cpl_vector_set(xtrue, 0, -1.0);
00200
00201 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
00202 DBL_EPSILON, 2.0*DBL_EPSILON);
00203
00204
00205 (void)cpl_vector_fill(xtrue, -2.0e-4 * FLT_EPSILON);
00206 (void)cpl_vector_set(xtrue, 0, -1.0);
00207
00208 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
00209 FLT_EPSILON, 2.0*DBL_EPSILON);
00210
00211 if (nreal != 3) {
00212
00213 (void)cpl_vector_fill(xtrue, -2.0 * DBL_EPSILON);
00214 (void)cpl_vector_set(xtrue, 0, -1.0);
00215
00216 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
00217 DBL_EPSILON, 2.0*DBL_EPSILON);
00218
00219
00220 (void)cpl_vector_set(xtrue, 0, -1.0);
00221 (void)cpl_vector_set(xtrue, 1, -2.0e-4 * FLT_EPSILON);
00222 (void)cpl_vector_set(xtrue, 2, 2.0e-4 * FLT_EPSILON);
00223
00224 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
00225 FLT_EPSILON, 2.0*DBL_EPSILON);
00226 }
00227
00228
00229
00230 (void)cpl_vector_fill(xtrue, 2.0*DBL_EPSILON);
00231 (void)cpl_vector_set(xtrue, nreal - 2 , 3.0);
00232 (void)cpl_vector_set(xtrue, nreal - 1 , 2.0);
00233
00234 irplib_polynomial_test_root_all(xtrue, nreal - 2, CPL_MATH_PI,
00235 4.0 * DBL_EPSILON, DBL_EPSILON);
00236
00237
00238
00239 (void)cpl_vector_fill(xtrue, 3.0);
00240 (void)cpl_vector_set(xtrue, nreal - 2 , -1.0);
00241 (void)cpl_vector_set(xtrue, nreal - 1 , 2.0);
00242
00243 irplib_polynomial_test_root_all(xtrue, nreal - 2, CPL_MATH_PI,
00244 6.0*DBL_EPSILON, 220.0*DBL_EPSILON);
00245
00246
00247 }
00248
00249 #if MAXDEGREE > 2
00250
00251
00252 nreal = 3;
00253
00254 cpl_vector_set_size(xtrue, nreal);
00255
00256
00257 (void)cpl_vector_set(xtrue, 0, -2.0);
00258 (void)cpl_vector_set(xtrue, 1, 2.0 * DBL_EPSILON);
00259 (void)cpl_vector_set(xtrue, 2, 1.5);
00260
00261 irplib_polynomial_test_root_all(xtrue, nreal, 1.0,
00262 4.0*DBL_EPSILON, 30.0*DBL_EPSILON);
00263
00264 #if MAXDEGREE > 3
00265 nreal = 4;
00266
00267 cpl_vector_set_size(xtrue, nreal);
00268
00269
00270 (void)cpl_vector_set(xtrue, 0, -1.0);
00271 (void)cpl_vector_set(xtrue, 1, 1.0);
00272 (void)cpl_vector_set(xtrue, 2, 2.0);
00273 (void)cpl_vector_set(xtrue, 3, 2.0);
00274
00275 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
00276 2.0 * DBL_EPSILON, 2.0 * DBL_EPSILON);
00277
00278
00279 irplib_polynomial_test_root_all(xtrue, 2, CPL_MATH_PI,
00280 2.0 * DBL_EPSILON, 2.0 * DBL_EPSILON);
00281
00282
00283
00284 (void)cpl_vector_set(xtrue, 0, -2.0);
00285 (void)cpl_vector_set(xtrue, 1, -1.0);
00286 (void)cpl_vector_set(xtrue, 2, 1.0);
00287 (void)cpl_vector_set(xtrue, 3, 2.0);
00288
00289 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
00290 2.0 * DBL_EPSILON, 2.0 * DBL_EPSILON);
00291
00292
00293 (void)cpl_vector_set(xtrue, 0, -1.0);
00294 (void)cpl_vector_set(xtrue, 1, 1.0);
00295 (void)cpl_vector_set(xtrue, 2, 0.0);
00296 (void)cpl_vector_set(xtrue, 3, 2.0);
00297
00298 irplib_polynomial_test_root_all(xtrue, 2, CPL_MATH_PI,
00299 2.0 * DBL_EPSILON, 2.0 * DBL_EPSILON);
00300
00301
00302
00303 (void)cpl_vector_set(xtrue, 0, 1.0);
00304 (void)cpl_vector_set(xtrue, 1, 2.0);
00305 (void)cpl_vector_set(xtrue, 2, 1.0);
00306 (void)cpl_vector_set(xtrue, 3, 3.0);
00307
00308 irplib_polynomial_test_root_all(xtrue, 0, CPL_MATH_PI,
00309 10.0 * DBL_EPSILON, 10.0 * DBL_EPSILON);
00310
00311
00312 (void)cpl_vector_set(xtrue, 0, 0.0);
00313 (void)cpl_vector_set(xtrue, 1, 0.0);
00314 (void)cpl_vector_set(xtrue, 2, 0.0);
00315 (void)cpl_vector_set(xtrue, 3, 2.0);
00316
00317 irplib_polynomial_test_root_all(xtrue, 2, CPL_MATH_PI,
00318 2.0 * DBL_EPSILON, 2.0 * DBL_EPSILON);
00319
00320 p1d = cpl_polynomial_new(1);
00321
00322 i = 0;
00323 cpl_polynomial_set_coeff(p1d, &i, -5.0);
00324 i = 1;
00325 cpl_polynomial_set_coeff(p1d, &i, -1.0);
00326 i = 2;
00327 cpl_polynomial_set_coeff(p1d, &i, -2.0);
00328 i = 4;
00329 cpl_polynomial_set_coeff(p1d, &i, 1.0);
00330
00331 cpl_test_eq(irplib_polynomial_solve_1d_all(p1d, xtrue, &nreal),
00332 CPL_ERROR_NONE);
00333
00334 cpl_msg_info(cpl_func, "Computed roots (%d real): ", nreal);
00335 if (cpl_msg_get_level() <= CPL_MSG_INFO)
00336 cpl_vector_dump(xtrue, stderr);
00337 cpl_msg_info(cpl_func, "Residual: %g -> %g ", cpl_vector_get(xtrue, 0),
00338 cpl_polynomial_eval_1d(p1d, cpl_vector_get(xtrue, 0), NULL) );
00339 cpl_msg_info(cpl_func, "Residual: %g -> %g ", cpl_vector_get(xtrue, 1),
00340 cpl_polynomial_eval_1d(p1d, cpl_vector_get(xtrue, 1), NULL) );
00341
00342 cpl_polynomial_delete(p1d);
00343
00344 (void)cpl_vector_set(xtrue, 0, 0.0);
00345 (void)cpl_vector_set(xtrue, 1, 2.0);
00346 (void)cpl_vector_set(xtrue, 2, 1.0);
00347 (void)cpl_vector_set(xtrue, 3, 1.0);
00348
00349 irplib_polynomial_test_root_all(xtrue, 0, CPL_MATH_PI,
00350 2.0 * DBL_EPSILON, 2.0 * DBL_EPSILON);
00351
00352 (void)cpl_vector_set(xtrue, 0, -1.0);
00353 (void)cpl_vector_set(xtrue, 1, 2.0);
00354 (void)cpl_vector_set(xtrue, 2, 1.0);
00355 (void)cpl_vector_set(xtrue, 3, 3.0);
00356
00357 irplib_polynomial_test_root_all(xtrue, 0, CPL_MATH_PI,
00358 3.0 * DBL_EPSILON, 3.0 * DBL_EPSILON);
00359 #if MAXDEGREE > 4
00360 nreal = 5;
00361
00362 cpl_vector_set_size(xtrue, nreal);
00363
00364
00365 (void)cpl_vector_set(xtrue, 0, -1.0);
00366 (void)cpl_vector_set(xtrue, 1, 1.0);
00367 (void)cpl_vector_set(xtrue, 2, 2.0);
00368 (void)cpl_vector_set(xtrue, 3, 3.0);
00369 (void)cpl_vector_set(xtrue, 4, 4.0);
00370
00371 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
00372 48.0 * DBL_EPSILON, 2800.0 * DBL_EPSILON);
00373
00374 irplib_polynomial_test_root_all(xtrue, nreal-2, CPL_MATH_PI,
00375 8.0 * DBL_EPSILON, 4000.0 * DBL_EPSILON);
00376
00377 irplib_polynomial_test_root_all(xtrue, nreal-4, CPL_MATH_PI,
00378 2.0 * DBL_EPSILON, 160.0 * DBL_EPSILON);
00379
00380 #if MAXDEGREE > 5
00381 nreal = 6;
00382
00383 cpl_vector_set_size(xtrue, nreal);
00384
00385
00386 (void)cpl_vector_set(xtrue, 0, -1.0);
00387 (void)cpl_vector_set(xtrue, 1, 1.0);
00388 (void)cpl_vector_set(xtrue, 2, 2.0);
00389 (void)cpl_vector_set(xtrue, 3, 3.0);
00390 (void)cpl_vector_set(xtrue, 4, 4.0);
00391 (void)cpl_vector_set(xtrue, 5, 5.0);
00392
00393 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
00394 160.0 * DBL_EPSILON, 28.0e3 * DBL_EPSILON);
00395
00396 irplib_polynomial_test_root_all(xtrue, nreal-2, CPL_MATH_PI,
00397 8.0 * DBL_EPSILON, 25.0e3 * DBL_EPSILON);
00398
00399 irplib_polynomial_test_root_all(xtrue, nreal-4, CPL_MATH_PI,
00400 12.0 * DBL_EPSILON, 1600.0 * DBL_EPSILON);
00401
00402 #endif
00403 #endif
00404 #endif
00405 #endif
00406
00407 cpl_vector_delete(xtrue);
00408
00409 return;
00410 }
00411
00412
00423
00424 static
00425 cpl_error_code irplib_polynomial_multiply_1d_factor(cpl_polynomial * self,
00426 const cpl_vector * roots,
00427 int nreal)
00428 {
00429
00430 int i, degree;
00431 const int nroots = cpl_vector_get_size(roots);
00432
00433 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
00434 cpl_ensure_code(roots != NULL, CPL_ERROR_NULL_INPUT);
00435 cpl_ensure_code(cpl_polynomial_get_dimension(self) == 1,
00436 CPL_ERROR_ILLEGAL_INPUT);
00437
00438 cpl_ensure_code(nreal >= 0, CPL_ERROR_ILLEGAL_INPUT);
00439 cpl_ensure_code(nreal <= nroots,
00440 CPL_ERROR_ILLEGAL_INPUT);
00441 cpl_ensure_code((cpl_vector_get_size(roots) - nreal) % 2 == 0,
00442 CPL_ERROR_ILLEGAL_INPUT);
00443
00444 i = 0;
00445 degree = cpl_polynomial_get_degree(self);
00446 cpl_ensure_code(degree > 0 || cpl_polynomial_get_coeff(self, &i) != 0.0,
00447 CPL_ERROR_DATA_NOT_FOUND);
00448
00449 for (i = 0; i < nreal; i++) {
00450 const double root = cpl_vector_get(roots, i);
00451 double prev = 0.0;
00452 int j;
00453
00454 degree++;
00455
00456 for (j = degree; j >= 0; j--) {
00457 double value = 0.0;
00458 double newval;
00459
00460 if (j > 0) {
00461 const int jj = j - 1;
00462 newval = value = cpl_polynomial_get_coeff(self, &jj);
00463 } else {
00464 newval = 0.0;
00465 }
00466
00467 if (j < degree) {
00468 newval -= root * prev;
00469 }
00470
00471 cpl_polynomial_set_coeff(self, &j, newval);
00472
00473 prev = value;
00474
00475 }
00476 }
00477
00478
00479
00480 for (; i < nroots; i += 2) {
00481 const double a = cpl_vector_get(roots, i);
00482 const double b = cpl_vector_get(roots, i+1);
00483 cpl_vector * aroot = cpl_vector_new(2);
00484 cpl_polynomial * copy = cpl_polynomial_duplicate(self);
00485
00486 cpl_vector_fill(aroot, a);
00487
00488 irplib_polynomial_multiply_1d_factor(self, aroot, 2);
00489
00490 irplib_polynomial_multiply_scalar(copy, b * b);
00491
00492 irplib_polynomial_add(self, self, copy);
00493
00494 cpl_vector_delete(aroot);
00495 cpl_polynomial_delete(copy);
00496
00497 }
00498
00499 return CPL_ERROR_NONE;
00500
00501 }
00502
00503
00516
00517 static void
00518 irplib_polynomial_test_root_all_macro(const cpl_vector * self, int nreal,
00519 double factor, double tolerance,
00520 double resitol, unsigned line)
00521 {
00522
00523 const int degree = cpl_vector_get_size(self);
00524 cpl_polynomial * p1d = cpl_polynomial_new(1);
00525 cpl_vector * roots = cpl_vector_new(degree);
00526 int i = 0;
00527 int jreal;
00528
00529 cpl_test_eq(cpl_polynomial_set_coeff(p1d, &i, factor), CPL_ERROR_NONE);
00530
00531 cpl_test_eq(irplib_polynomial_multiply_1d_factor(p1d, self, nreal),
00532 CPL_ERROR_NONE);
00533
00534 cpl_test_eq(irplib_polynomial_solve_1d_all(p1d, roots, &jreal),
00535 CPL_ERROR_NONE);
00536
00537 cpl_test_eq(jreal, nreal);
00538 if (jreal != nreal) {
00539 cpl_msg_info(cpl_func, "1D-polynomial:");
00540 cpl_polynomial_dump(p1d, stderr);
00541 cpl_msg_error(cpl_func, "True roots (%d real): (line=%u)", nreal, line);
00542 cpl_vector_dump(self, stderr);
00543 cpl_msg_error(cpl_func, "Computed roots (%d real): ", jreal);
00544 cpl_vector_dump(roots, stderr);
00545 } else if (cpl_msg_get_level() < CPL_MSG_WARNING) {
00546 cpl_bivector * dump =
00547 cpl_bivector_wrap_vectors((cpl_vector*)self, roots);
00548
00549 cpl_msg_warning(cpl_func, "Comparing %d roots (%d real):",
00550 degree, nreal);
00551 cpl_bivector_dump(dump, stderr);
00552 cpl_bivector_unwrap_vectors(dump);
00553 }
00554
00555 for (i = 0; i < jreal; i++) {
00556 const double root = cpl_vector_get(roots, i);
00557 const double residual = cpl_polynomial_eval_1d(p1d, root, NULL);
00558
00559 cpl_test_abs(root, cpl_vector_get(self, i), tolerance);
00560
00561 cpl_test_abs(residual, 0.0, resitol);
00562
00563 }
00564
00565 for (i = nreal; i < degree; i++) {
00566 const double root = cpl_vector_get(roots, i);
00567
00568 cpl_test_abs(root, cpl_vector_get(self, i), tolerance);
00569
00570
00571
00572 }
00573
00574 cpl_vector_delete(roots);
00575 cpl_polynomial_delete(p1d);
00576
00577 return;
00578 }