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 cpl_size);
00056 static void irplib_polynomial_solve_1d_all_test(void);
00057
00058 static void irplib_polynomial_test_root_all_macro(const cpl_vector *, cpl_size,
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 cpl_size maxdegree = 4;
00091 cpl_size nreal = 0;
00092 cpl_size 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, 600.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-3 * 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, 3.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 (%" CPL_SIZE_FORMAT " real): ",
00335 nreal);
00336 if (cpl_msg_get_level() <= CPL_MSG_INFO)
00337 cpl_vector_dump(xtrue, stderr);
00338 cpl_msg_info(cpl_func, "Residual: %g -> %g ", cpl_vector_get(xtrue, 0),
00339 cpl_polynomial_eval_1d(p1d, cpl_vector_get(xtrue, 0), NULL) );
00340 cpl_msg_info(cpl_func, "Residual: %g -> %g ", cpl_vector_get(xtrue, 1),
00341 cpl_polynomial_eval_1d(p1d, cpl_vector_get(xtrue, 1), NULL) );
00342
00343 cpl_polynomial_delete(p1d);
00344
00345 (void)cpl_vector_set(xtrue, 0, 0.0);
00346 (void)cpl_vector_set(xtrue, 1, 2.0);
00347 (void)cpl_vector_set(xtrue, 2, 1.0);
00348 (void)cpl_vector_set(xtrue, 3, 1.0);
00349
00350 irplib_polynomial_test_root_all(xtrue, 0, CPL_MATH_PI,
00351 2.0 * DBL_EPSILON, 2.0 * DBL_EPSILON);
00352
00353 (void)cpl_vector_set(xtrue, 0, -1.0);
00354 (void)cpl_vector_set(xtrue, 1, 2.0);
00355 (void)cpl_vector_set(xtrue, 2, 1.0);
00356 (void)cpl_vector_set(xtrue, 3, 3.0);
00357
00358 irplib_polynomial_test_root_all(xtrue, 0, CPL_MATH_PI,
00359 3.0 * DBL_EPSILON, 3.0 * DBL_EPSILON);
00360 #if MAXDEGREE > 4
00361 nreal = 5;
00362
00363 cpl_vector_set_size(xtrue, nreal);
00364
00365
00366 (void)cpl_vector_set(xtrue, 0, -1.0);
00367 (void)cpl_vector_set(xtrue, 1, 1.0);
00368 (void)cpl_vector_set(xtrue, 2, 2.0);
00369 (void)cpl_vector_set(xtrue, 3, 3.0);
00370 (void)cpl_vector_set(xtrue, 4, 4.0);
00371
00372 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
00373 48.0 * DBL_EPSILON, 2800.0 * DBL_EPSILON);
00374
00375 irplib_polynomial_test_root_all(xtrue, nreal-2, CPL_MATH_PI,
00376 8.0 * DBL_EPSILON, 4000.0 * DBL_EPSILON);
00377
00378 irplib_polynomial_test_root_all(xtrue, nreal-4, CPL_MATH_PI,
00379 4.0 * DBL_EPSILON, 600.0 * DBL_EPSILON);
00380
00381 #if MAXDEGREE > 5
00382 nreal = 6;
00383
00384 cpl_vector_set_size(xtrue, nreal);
00385
00386
00387 (void)cpl_vector_set(xtrue, 0, -1.0);
00388 (void)cpl_vector_set(xtrue, 1, 1.0);
00389 (void)cpl_vector_set(xtrue, 2, 2.0);
00390 (void)cpl_vector_set(xtrue, 3, 3.0);
00391 (void)cpl_vector_set(xtrue, 4, 4.0);
00392 (void)cpl_vector_set(xtrue, 5, 5.0);
00393
00394 irplib_polynomial_test_root_all(xtrue, nreal, CPL_MATH_PI,
00395 240.0 * DBL_EPSILON, 50.0e3 * DBL_EPSILON);
00396
00397 irplib_polynomial_test_root_all(xtrue, nreal-2, CPL_MATH_PI,
00398 8.0 * DBL_EPSILON, 25.0e3 * DBL_EPSILON);
00399
00400 irplib_polynomial_test_root_all(xtrue, nreal-4, CPL_MATH_PI,
00401 12.0 * DBL_EPSILON, 1600.0 * DBL_EPSILON);
00402
00403 #endif
00404 #endif
00405 #endif
00406 #endif
00407
00408 cpl_vector_delete(xtrue);
00409
00410 return;
00411 }
00412
00413
00424
00425 static
00426 cpl_error_code irplib_polynomial_multiply_1d_factor(cpl_polynomial * self,
00427 const cpl_vector * roots,
00428 cpl_size nreal)
00429 {
00430
00431 const cpl_size nroots = cpl_vector_get_size(roots);
00432 cpl_size i, degree;
00433
00434 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
00435 cpl_ensure_code(roots != NULL, CPL_ERROR_NULL_INPUT);
00436 cpl_ensure_code(cpl_polynomial_get_dimension(self) == 1,
00437 CPL_ERROR_ILLEGAL_INPUT);
00438
00439 cpl_ensure_code(nreal >= 0, CPL_ERROR_ILLEGAL_INPUT);
00440 cpl_ensure_code(nreal <= nroots,
00441 CPL_ERROR_ILLEGAL_INPUT);
00442 cpl_ensure_code((cpl_vector_get_size(roots) - nreal) % 2 == 0,
00443 CPL_ERROR_ILLEGAL_INPUT);
00444
00445 i = 0;
00446 degree = cpl_polynomial_get_degree(self);
00447 cpl_ensure_code(degree > 0 || cpl_polynomial_get_coeff(self, &i) != 0.0,
00448 CPL_ERROR_DATA_NOT_FOUND);
00449
00450 for (i = 0; i < nreal; i++) {
00451 const double root = cpl_vector_get(roots, i);
00452 double prev = 0.0;
00453 cpl_size j;
00454
00455 degree++;
00456
00457 for (j = degree; j >= 0; j--) {
00458 double value = 0.0;
00459 double newval;
00460
00461 if (j > 0) {
00462 const cpl_size jj = j - 1;
00463 newval = value = cpl_polynomial_get_coeff(self, &jj);
00464 } else {
00465 newval = 0.0;
00466 }
00467
00468 if (j < degree) {
00469 newval -= root * prev;
00470 }
00471
00472 cpl_polynomial_set_coeff(self, &j, newval);
00473
00474 prev = value;
00475
00476 }
00477 }
00478
00479
00480
00481 for (; i < nroots; i += 2) {
00482 const double a = cpl_vector_get(roots, i);
00483 const double b = cpl_vector_get(roots, i+1);
00484 cpl_vector * aroot = cpl_vector_new(2);
00485 cpl_polynomial * copy = cpl_polynomial_duplicate(self);
00486
00487 cpl_vector_fill(aroot, a);
00488
00489 irplib_polynomial_multiply_1d_factor(self, aroot, 2);
00490
00491 irplib_polynomial_multiply_scalar(copy, copy, b * b);
00492
00493 irplib_polynomial_add(self, self, copy);
00494
00495 cpl_vector_delete(aroot);
00496 cpl_polynomial_delete(copy);
00497
00498 }
00499
00500 return CPL_ERROR_NONE;
00501
00502 }
00503
00504
00517
00518 static void
00519 irplib_polynomial_test_root_all_macro(const cpl_vector * self, cpl_size nreal,
00520 double factor, double tolerance,
00521 double resitol, unsigned line)
00522 {
00523
00524 const cpl_size degree = cpl_vector_get_size(self);
00525 cpl_polynomial * p1d = cpl_polynomial_new(1);
00526 cpl_vector * roots = cpl_vector_new(degree);
00527 cpl_size i = 0;
00528 cpl_size jreal;
00529
00530 cpl_test_eq(cpl_polynomial_set_coeff(p1d, &i, factor), CPL_ERROR_NONE);
00531
00532 cpl_test_eq(irplib_polynomial_multiply_1d_factor(p1d, self, nreal),
00533 CPL_ERROR_NONE);
00534
00535 cpl_test_eq(irplib_polynomial_solve_1d_all(p1d, roots, &jreal),
00536 CPL_ERROR_NONE);
00537
00538 cpl_test_eq(jreal, nreal);
00539 if (jreal != nreal) {
00540 cpl_msg_info(cpl_func, "1D-polynomial:");
00541 cpl_polynomial_dump(p1d, stderr);
00542 cpl_msg_error(cpl_func, "True roots (%" CPL_SIZE_FORMAT
00543 " real): (line=%u)", nreal, line);
00544 cpl_vector_dump(self, stderr);
00545 cpl_msg_error(cpl_func, "Computed roots (%" CPL_SIZE_FORMAT " real): ",
00546 jreal);
00547 cpl_vector_dump(roots, stderr);
00548 } else if (cpl_msg_get_level() < CPL_MSG_WARNING) {
00549 cpl_bivector * dump =
00550 cpl_bivector_wrap_vectors((cpl_vector*)self, roots);
00551
00552 cpl_msg_warning(cpl_func, "Comparing %" CPL_SIZE_FORMAT " roots (%"
00553 CPL_SIZE_FORMAT " real): (line=%u)",
00554 degree, nreal, line);
00555 cpl_bivector_dump(dump, stderr);
00556 cpl_bivector_unwrap_vectors(dump);
00557 }
00558
00559 for (i = 0; i < jreal; i++) {
00560 const double root = cpl_vector_get(roots, i);
00561 const double residual = cpl_polynomial_eval_1d(p1d, root, NULL);
00562
00563 cpl_test_abs(root, cpl_vector_get(self, i), tolerance);
00564
00565 cpl_test_abs(residual, 0.0, resitol);
00566
00567 }
00568
00569 for (i = nreal; i < degree; i++) {
00570 const double root = cpl_vector_get(roots, i);
00571
00572 cpl_test_abs(root, cpl_vector_get(self, i), tolerance);
00573
00574
00575
00576 }
00577
00578 cpl_vector_delete(roots);
00579 cpl_polynomial_delete(p1d);
00580
00581 return;
00582 }