36 #include "irplib_polynomial.h"
55 #define IRPLIB_SWAP(a,b) { const double t=(a);(a)=(b);(b)=t; }
58 #define irplib_trace() cpl_msg_info(cpl_func, "%d: Trace", __LINE__)
60 #define irplib_trace()
67 static double irplib_polynomial_eval_2_max(
double,
double,
double, cpl_boolean,
70 static double irplib_polynomial_eval_3_max(
double,
double,
double,
double,
71 cpl_boolean,
double,
double,
double);
74 static cpl_boolean irplib_polynomial_solve_1d_2(
double,
double,
double,
76 static cpl_boolean irplib_polynomial_solve_1d_3(
double,
double,
double,
double,
77 double *,
double *,
double *,
81 static void irplib_polynomial_solve_1d_31(
double,
double,
double *,
double *,
82 double *, cpl_boolean *);
84 static void irplib_polynomial_solve_1d_32(
double,
double,
double,
double *,
85 double *,
double *, cpl_boolean *);
87 static void irplib_polynomial_solve_1d_3r(
double,
double,
double,
double,
88 double *,
double *,
double *);
90 static void irplib_polynomial_solve_1d_3c(
double,
double,
double,
91 double,
double,
double,
92 double *,
double *,
double *,
93 cpl_boolean *, cpl_boolean *);
95 static cpl_error_code irplib_polynomial_solve_1d_4(
double,
double,
double,
96 double,
double, cpl_size *,
100 static cpl_error_code irplib_polynomial_solve_1d_nonzero(cpl_polynomial *,
104 static cpl_error_code irplib_polynomial_divide_1d_root(cpl_polynomial *,
double,
107 #ifdef IPRLIB_POLYNOMIAL_USE_MONOMIAL_ROOT
108 static double irplib_polynomial_depress_1d(cpl_polynomial *);
115 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE > CPL_VERSION(5, 92, 0)
135 const cpl_polynomial * first,
136 const cpl_polynomial * second)
138 cpl_size degree0 = cpl_polynomial_get_degree(
self);
139 const cpl_size degree1 = cpl_polynomial_get_degree(first);
140 const cpl_size degree2 = cpl_polynomial_get_degree(second);
141 const cpl_size maxdeg = degree1 > degree2 ? degree1 : degree2;
144 cpl_ensure_code(
self != NULL, CPL_ERROR_NULL_INPUT);
145 cpl_ensure_code(first != NULL, CPL_ERROR_NULL_INPUT);
146 cpl_ensure_code(second != NULL, CPL_ERROR_NULL_INPUT);
148 cpl_ensure_code(cpl_polynomial_get_dimension(
self) ==
149 cpl_polynomial_get_dimension(first),
150 CPL_ERROR_INCOMPATIBLE_INPUT);
151 cpl_ensure_code(cpl_polynomial_get_dimension(
self) ==
152 cpl_polynomial_get_dimension(second),
153 CPL_ERROR_INCOMPATIBLE_INPUT);
156 cpl_ensure_code(cpl_polynomial_get_dimension(
self) == 1,
157 CPL_ERROR_UNSUPPORTED_MODE);
159 if (degree0 < maxdeg) {
163 for (; degree0 > maxdeg; degree0--) {
164 cpl_polynomial_set_coeff(
self, °ree0, 0.0);
170 for (; degree0 >= 0; degree0--) {
171 const double val1 = cpl_polynomial_get_coeff(first, °ree0);
172 const double val2 = cpl_polynomial_get_coeff(second, °ree0);
173 cpl_polynomial_set_coeff(
self, °ree0, val1 + val2);
176 return CPL_ERROR_NONE;
196 const cpl_polynomial * first,
197 const cpl_polynomial * second)
199 cpl_size degree0 = cpl_polynomial_get_degree(
self);
200 const cpl_size degree1 = cpl_polynomial_get_degree(first);
201 const cpl_size degree2 = cpl_polynomial_get_degree(second);
202 const cpl_size maxdeg = degree1 > degree2 ? degree1 : degree2;
205 cpl_ensure_code(
self != NULL, CPL_ERROR_NULL_INPUT);
206 cpl_ensure_code(first != NULL, CPL_ERROR_NULL_INPUT);
207 cpl_ensure_code(second != NULL, CPL_ERROR_NULL_INPUT);
209 cpl_ensure_code(cpl_polynomial_get_dimension(
self) ==
210 cpl_polynomial_get_dimension(first),
211 CPL_ERROR_INCOMPATIBLE_INPUT);
212 cpl_ensure_code(cpl_polynomial_get_dimension(
self) ==
213 cpl_polynomial_get_dimension(second),
214 CPL_ERROR_INCOMPATIBLE_INPUT);
217 cpl_ensure_code(cpl_polynomial_get_dimension(
self) == 1,
218 CPL_ERROR_UNSUPPORTED_MODE);
220 if (degree0 < maxdeg) {
224 for (; degree0 > maxdeg; degree0--) {
225 cpl_polynomial_set_coeff(
self, °ree0, 0.0);
231 for (; degree0 >= 0; degree0--) {
232 const double val1 = cpl_polynomial_get_coeff(first, °ree0);
233 const double val2 = cpl_polynomial_get_coeff(second, °ree0);
234 cpl_polynomial_set_coeff(
self, °ree0, val1 - val2);
237 return CPL_ERROR_NONE;
254 const cpl_polynomial * other,
258 const cpl_size maxdeg = cpl_polynomial_get_degree(other);
259 const cpl_size zerodeg = cpl_polynomial_get_degree(
self);
262 cpl_ensure_code(
self != NULL, CPL_ERROR_NULL_INPUT);
263 cpl_ensure_code(other != NULL, CPL_ERROR_NULL_INPUT);
265 cpl_ensure_code(cpl_polynomial_get_dimension(
self) == 1,
266 CPL_ERROR_UNSUPPORTED_MODE);
267 cpl_ensure_code(cpl_polynomial_get_dimension(other) == 1,
268 CPL_ERROR_UNSUPPORTED_MODE);
270 for (degree = 0; degree <= maxdeg; degree++) {
271 const double val = factor * cpl_polynomial_get_coeff(other, °ree);
272 cpl_polynomial_set_coeff(
self, °ree, val);
276 for (; degree <= zerodeg; degree++) {
277 cpl_polynomial_set_coeff(
self, &zerodeg, 0.0);
280 return CPL_ERROR_NONE;
315 cpl_error_code error = CPL_ERROR_NONE;
318 cpl_ensure_code(
self != NULL, CPL_ERROR_NULL_INPUT);
319 cpl_ensure_code(roots != NULL, CPL_ERROR_NULL_INPUT);
320 cpl_ensure_code(preal != NULL, CPL_ERROR_NULL_INPUT);
321 cpl_ensure_code(cpl_polynomial_get_dimension(
self) == 1,
322 CPL_ERROR_INVALID_TYPE);
323 cpl_ensure_code(cpl_polynomial_get_degree(
self) > 0,
324 CPL_ERROR_DATA_NOT_FOUND);
325 cpl_ensure_code(cpl_polynomial_get_degree(
self) ==
326 cpl_vector_get_size(roots), CPL_ERROR_INCOMPATIBLE_INPUT);
330 p = cpl_polynomial_duplicate(
self);
332 error = irplib_polynomial_solve_1d_nonzero(p, roots, preal);
334 cpl_polynomial_delete(p);
369 static cpl_error_code irplib_polynomial_solve_1d_nonzero(cpl_polynomial *
self,
373 cpl_error_code error = CPL_ERROR_NONE;
374 const cpl_size ncoeffs = 1 + cpl_polynomial_get_degree(
self);
376 cpl_ensure_code(
self != NULL, CPL_ERROR_NULL_INPUT);
377 cpl_ensure_code(roots != NULL, CPL_ERROR_NULL_INPUT);
378 cpl_ensure_code(preal != NULL, CPL_ERROR_NULL_INPUT);
379 cpl_ensure_code(cpl_polynomial_get_dimension(
self) == 1,
380 CPL_ERROR_INVALID_TYPE);
381 cpl_ensure_code(ncoeffs > 1, CPL_ERROR_DATA_NOT_FOUND);
382 cpl_ensure_code(*preal >= 0, CPL_ERROR_ILLEGAL_INPUT);
383 cpl_ensure_code(ncoeffs + *preal == 1+cpl_vector_get_size(roots),
384 CPL_ERROR_INCOMPATIBLE_INPUT);
389 const cpl_size i1 = 1;
390 const cpl_size i0 = 0;
391 const double p1 = cpl_polynomial_get_coeff(
self, &i1);
392 const double p0 = cpl_polynomial_get_coeff(
self, &i0);
394 cpl_vector_set(roots, (*preal)++, -p0/p1);
398 const cpl_size i2 = 2;
399 const cpl_size i1 = 1;
400 const cpl_size i0 = 0;
401 const double p2 = cpl_polynomial_get_coeff(
self, &i2);
402 const double p1 = cpl_polynomial_get_coeff(
self, &i1);
403 const double p0 = cpl_polynomial_get_coeff(
self, &i0);
406 if (irplib_polynomial_solve_1d_2(p2, p1, p0, &x1, &x2)) {
408 cpl_vector_set(roots, (*preal) , x1);
409 cpl_vector_set(roots, (*preal)+1, x2);
411 cpl_vector_set(roots, (*preal)++, x1);
412 cpl_vector_set(roots, (*preal)++, x2);
417 const cpl_size i3 = 3;
418 const cpl_size i2 = 2;
419 const cpl_size i1 = 1;
420 const cpl_size i0 = 0;
421 const double p3 = cpl_polynomial_get_coeff(
self, &i3);
422 const double p2 = cpl_polynomial_get_coeff(
self, &i2);
423 const double p1 = cpl_polynomial_get_coeff(
self, &i1);
424 const double p0 = cpl_polynomial_get_coeff(
self, &i0);
427 if (irplib_polynomial_solve_1d_3(p3, p2, p1, p0, &x1, &x2, &x3,
429 cpl_vector_set(roots, (*preal)++, x1);
431 cpl_vector_set(roots, (*preal) , x2);
432 cpl_vector_set(roots, (*preal)+1, x3);
434 cpl_vector_set(roots, (*preal)++, x1);
435 cpl_vector_set(roots, (*preal)++, x2);
436 cpl_vector_set(roots, (*preal)++, x3);
441 const cpl_size i4 = 4;
442 const cpl_size i3 = 3;
443 const cpl_size i2 = 2;
444 const cpl_size i1 = 1;
445 const cpl_size i0 = 0;
446 const double p4 = cpl_polynomial_get_coeff(
self, &i4);
447 const double p3 = cpl_polynomial_get_coeff(
self, &i3);
448 const double p2 = cpl_polynomial_get_coeff(
self, &i2);
449 const double p1 = cpl_polynomial_get_coeff(
self, &i1);
450 const double p0 = cpl_polynomial_get_coeff(
self, &i0);
451 double x1, x2, x3, x4;
454 error = irplib_polynomial_solve_1d_4(p4, p3, p2, p1, p0, &nreal,
457 cpl_vector_set(roots, (*preal) , x1);
458 cpl_vector_set(roots, (*preal)+1, x2);
459 cpl_vector_set(roots, (*preal)+2, x3);
460 cpl_vector_set(roots, (*preal)+3, x4);
470 #ifndef IPRLIB_POLYNOMIAL_USE_MONOMIAL_ROOT
471 const cpl_size n0 = ncoeffs-1;
472 const double pn0 = cpl_polynomial_get_coeff(
self, &n0);
473 const cpl_size n1 = ncoeffs-2;
474 const double pn1 = cpl_polynomial_get_coeff(
self, &n1);
477 const double rmean = -pn1 / (pn0 * n0);
481 cpl_polynomial * copy = cpl_polynomial_duplicate(
self);
482 const cpl_size i0 = 0;
483 const double rmean = irplib_polynomial_depress_1d(copy);
484 const double c0 = cpl_polynomial_get_coeff(copy, &i0);
485 double root = rmean + ((n0&1) && c0 < 0.0 ? -1.0 : 1.0)
486 * pow(fabs(c0), 1.0/n0);
488 cpl_polynomial_delete(copy);
491 error = cpl_polynomial_solve_1d(
self, root, &root, 1);
495 cpl_vector_set(roots, (*preal)++, root);
497 irplib_polynomial_divide_1d_root(
self, root, NULL);
499 error = irplib_polynomial_solve_1d_nonzero(
self, roots, preal);
501 if (!error && *preal > 1) {
506 cpl_vector * reals = cpl_vector_wrap(*preal,
507 cpl_vector_get_data(roots));
508 cpl_vector_sort(reals, 1);
509 (void)cpl_vector_unwrap(reals);
532 static cpl_boolean irplib_polynomial_solve_1d_2(
double p2,
double p1,
double p0,
536 const double sqrtD = sqrt(fabs(p1 * p1 - 4.0 * p2 * p0));
537 cpl_boolean is_complex = CPL_FALSE;
538 double x1 = -0.5 * p1 / p2;
542 double res0 = irplib_polynomial_eval_2_max(p2, p1, p0, CPL_FALSE, x1, x1);
545 assert(px1 != NULL );
546 assert(px2 != NULL );
554 x1 = -0.5 * (p1 + sqrtD);
557 x1 = -0.5 * (p1 - sqrtD);
565 res = irplib_polynomial_eval_2_max(p2, p1, p0, CPL_FALSE, x1, x2);
583 x2 = 0.5 * sqrtD / fabs(p2);
585 res = irplib_polynomial_eval_2_max(p2, p1, p0, CPL_TRUE, x1, x2);
590 is_complex = CPL_TRUE;
613 static double irplib_polynomial_eval_2_max(
double p2,
double p1,
double p0,
615 double x1,
double x2)
620 res = fabs(p0 + x1 * (p1 + x1 * p2) - p2 * x2 * x2);
623 const double r1 = fabs(p0 + x1 * (p1 + x1 * p2));
624 const double r2 = fabs(p0 + x2 * (p1 + x2 * p2));
626 res = r1 > r2 ? r1 : r2;
650 static double irplib_polynomial_eval_3_max(
double p3,
double p2,
651 double p1,
double p0,
653 double x1,
double x2,
double x3)
655 const double r1 = fabs(p0 + x1 * (p1 + x1 * (p2 + x1 * p3)));
659 const double r2 = fabs(p0 + x2 * (p1 + x2 * (p2 + x2 * p3))
660 - x3 * x3 * ( 3.0 * p3 * x2 + p2));
662 res = r1 > r2 ? r1 : r2;
665 const double r2 = fabs(p0 + x2 * (p1 + x2 * (p2 + x2 * p3)));
666 const double r3 = fabs(p0 + x3 * (p1 + x3 * (p2 + x3 * p3)));
667 res = r1 > r2 ? (r1 > r3 ? r1 : r3) : (r2 > r3 ? r2 : r3);
697 static cpl_boolean irplib_polynomial_solve_1d_3(
double p3,
double p2,
double p1,
703 cpl_boolean * pdbl2) {
704 cpl_boolean is_complex = CPL_FALSE;
705 const double a = p2/p3;
706 const double b = p1/p3;
707 const double c = p0/p3;
709 const double q = (a * a - 3.0 * b);
710 const double r = (a * (2.0 * a * a - 9.0 * b) + 27.0 * c);
712 const double Q = q / 9.0;
713 const double R = r / 54.0;
715 const double Q3 = Q * Q * Q;
716 const double R2 = R * R;
721 double xx1 = DBL_MAX;
722 double xx2 = DBL_MAX;
723 double xx3 = DBL_MAX;
725 double resx = DBL_MAX;
726 double res = DBL_MAX;
727 cpl_boolean is_first = CPL_TRUE;
732 assert(px1 != NULL );
734 if (pdbl1 != NULL) *pdbl1 = CPL_FALSE;
735 if (pdbl2 != NULL) *pdbl2 = CPL_FALSE;
747 if ((R2 >= Q3 && R != 0.0) || R2 > Q3) {
749 cpl_boolean is_c = CPL_FALSE;
751 irplib_polynomial_solve_1d_3c(a, c, Q, Q3, R, R2, &x1, &x2, &x3,
755 res = resx = irplib_polynomial_eval_3_max(p3, p2, p1, p0, is_c,
758 is_first = CPL_FALSE;
760 if (pdbl1 != NULL) *pdbl1 = CPL_FALSE;
761 if (!is_c && pdbl2 != NULL) *pdbl2 = dbl2;
767 if (Q > 0.0 && fabs(R / (Q * sqrt(Q))) <= 1.0) {
774 irplib_polynomial_solve_1d_3r(a, c, Q, R, &xx1, &xx2, &xx3);
776 resx = irplib_polynomial_eval_3_max(p3, p2, p1, p0, CPL_FALSE,
779 if (is_first || (dbl2 ? resx < res : resx <= res)) {
780 is_first = CPL_FALSE;
785 if (pdbl1 != NULL) *pdbl1 = CPL_FALSE;
786 if (pdbl2 != NULL) *pdbl2 = CPL_FALSE;
787 is_complex = CPL_FALSE;
793 cpl_boolean dbl1 = CPL_FALSE;
796 irplib_polynomial_solve_1d_32(a, c, Q, &xx1, &xx2, &xx3, &dbl2);
798 resx = irplib_polynomial_eval_3_max(p3, p2, p1, p0, CPL_FALSE,
805 if (is_first || resx <= res) {
806 is_first = CPL_FALSE;
811 if (pdbl1 != NULL) *pdbl1 = CPL_FALSE;
812 if (pdbl2 != NULL) *pdbl2 = dbl2;
813 is_complex = CPL_FALSE;
821 irplib_polynomial_solve_1d_31(a, Q, &xx1, &xx2, &xx3, &dbl1);
823 resx = irplib_polynomial_eval_3_max(p3, p2, p1, p0, CPL_FALSE,
827 is_first = CPL_FALSE;
832 if (pdbl1 != NULL) *pdbl1 = dbl1;
833 if (pdbl2 != NULL) *pdbl2 = CPL_FALSE;
834 is_complex = CPL_FALSE;
840 if (px2 != NULL && px3 != NULL) {
845 }
else if (is_complex) {
871 static void irplib_polynomial_solve_1d_31(
double a,
double Q,
872 double * px1,
double * px2,
873 double * px3, cpl_boolean * pdbl1)
876 const double sqrtQ = sqrt (Q);
880 x2 = x1 = -sqrtQ - a / 3.0;
881 x3 = 2.0 * sqrtQ - a / 3.0;
882 if (pdbl1 != NULL) *pdbl1 = CPL_TRUE;
908 static void irplib_polynomial_solve_1d_32(
double a,
double c,
double Q,
909 double * px1,
double * px2,
910 double * px3, cpl_boolean * pdbl2)
913 const double sqrtQ = sqrt (Q);
921 x1 = -2.0 * sqrtQ - a / 3.0;
924 x3 = x2 = -a < x1 ? -sqrt(fabs(c / x1)) : sqrt(fabs(c / x1));
925 if (pdbl2 != NULL) *pdbl2 = CPL_TRUE;
927 }
else if (a < 0.0) {
929 x3 = x2 = sqrtQ - a / 3.0;
931 if (pdbl2 != NULL) *pdbl2 = CPL_TRUE;
936 if (pdbl2 != NULL) *pdbl2 = CPL_TRUE;
968 static void irplib_polynomial_solve_1d_3c(
double a,
double c,
972 double * px2,
double * px3,
985 const double sgnR = (R >= 0 ? 1.0 : -1.0);
986 const double A = -sgnR * pow (fabs (R) + sqrt (R2 - Q3), 1.0 / 3.0);
987 const double B = Q / A;
992 cpl_boolean is_complex = CPL_FALSE;
994 if (( A > -B && a > 0.0) || (A < -B && a < 0.0)) {
998 x2 = -0.5 * (A + B) - a / 3.0;
1000 x3 = 0.5 * CPL_MATH_SQRT3 * fabs(A - B);
1002 x1 = -c / (x2 * x2 + x3 * x3);
1006 x1 = A + B - a / 3.0;
1008 x3 = 0.5 * CPL_MATH_SQRT3 * fabs(A - B);
1012 x2 = -0.5 * (A + B) - a / 3.0;
1016 x2 = -a < x1 ? -sqrt(fabs(c / x1)) : sqrt(fabs(c / x1));
1023 is_complex = CPL_TRUE;
1029 if (pdbl2 != NULL) *pdbl2 = CPL_TRUE;
1036 *pis_c = is_complex;
1057 static void irplib_polynomial_solve_1d_3r(
double a,
double c,
1060 double * px2,
double * px3)
1063 const double sqrtQ = sqrt(Q);
1064 const double theta = acos (R / (Q * sqrtQ));
1070 #define TR1 (-2.0 * sqrtQ * cos( theta / 3.0))
1071 #define TR2 (-2.0 * sqrtQ * cos((theta - CPL_MATH_2PI) / 3.0))
1072 #define TR3 (-2.0 * sqrtQ * cos((theta + CPL_MATH_2PI) / 3.0))
1081 double x1 = DBL_MAX;
1082 double x2 = DBL_MAX;
1083 double x3 = DBL_MAX;
1087 if (TR2 > 0.0 && (TR2 + TR3) > 2.0 * a) {
1090 x2 = -c / ( x1 * x3 );
1098 x3 = -c / ( x1 * x2 );
1101 }
else if (a < 0.0) {
1103 if (TR2 < 0.0 && (TR1 + TR2) > 2.0 * a) {
1105 x2 = -c / ( x1 * x3 );
1109 x1 = -c / ( x2 * x3 );
1129 x1 = x2 = 0.5 * ( x1 + x2 );
1131 }
else if (x2 > x3) {
1139 x3 = x2 = 0.5 * ( x2 + x3 );
1169 static cpl_error_code irplib_polynomial_solve_1d_4(
double p4,
double p3,
1170 double p2,
double p1,
1171 double p0, cpl_size * preal,
1172 double * px1,
double * px2,
1173 double * px3,
double * px4)
1177 const double a = (p2 - 0.375 * p3 * p3 / p4) / p4;
1178 const double b = (p1 - 0.5 * (p2 - 0.25 * p3 * p3 / p4 ) * p3 / p4 ) / p4;
1180 (p0 - 0.25 * (p1 - 0.25 * (p2 - 0.1875 * p3 * p3 / p4 ) * p3 / p4
1183 double x1 = DBL_MAX;
1184 double x2 = DBL_MAX;
1185 double x3 = DBL_MAX;
1186 double x4 = DBL_MAX;
1188 assert(preal != NULL );
1189 assert(px1 != NULL );
1190 assert(px2 != NULL );
1191 assert(px3 != NULL );
1192 assert(px4 != NULL );
1200 cpl_boolean dbl1, dbl2;
1201 const cpl_boolean is_real =
1202 !irplib_polynomial_solve_1d_3(1.0, 0.0, a, b, &x1, &x3, &x4,
1205 x1 -= 0.25 * p3 / p4;
1206 x2 = -0.25 * p3 / p4;
1207 x3 -= 0.25 * p3 / p4;
1215 x4 -= 0.25 * p3 / p4;
1218 IRPLIB_SWAP(x2, x3);
1235 IRPLIB_SWAP(x1, x2);
1241 }
else if (b == 0.0) {
1244 const cpl_boolean is_complex = irplib_polynomial_solve_1d_2(1.0, a, c,
1249 const double norm = sqrt(u1*u1 + u2*u2);
1250 const double v1 = sqrt(0.5*(norm+u1));
1251 const double v2 = u2 / sqrt(2.0*(norm+u1));
1254 x1 = -0.25 * p3 / p4 - v1;
1255 x3 = -0.25 * p3 / p4 + v1;
1261 }
else if (u1 >= 0.0) {
1263 const double sv1 = sqrt(u1);
1264 const double sv2 = sqrt(u2);
1269 x1 = -0.25 * p3 / p4 - sv2;
1270 x2 = -0.25 * p3 / p4 - sv1;
1271 x3 = -0.25 * p3 / p4 + sv1;
1272 x4 = -0.25 * p3 / p4 + sv2;
1273 }
else if (u2 < 0.0) {
1275 const double sv1 = sqrt(-u2);
1276 const double sv2 = sqrt(-u1);
1281 x1 = x3 = -0.25 * p3 / p4;
1287 const double sv1 = sqrt(-u1);
1288 const double sv2 = sqrt(u2);
1293 x1 = -0.25 * p3 / p4 - sv2;
1294 x2 = -0.25 * p3 / p4 + sv2;
1296 x3 = -0.25 * p3 / p4;
1301 const double q2 = -a;
1302 const double q1 = -4.0 * c;
1303 const double q0 = 4.0 * a * c - b * b;
1304 double u1, sqrtd, sqrtrd;
1305 double z1, z2, z3, z4;
1307 cpl_boolean is_complex1, is_complex2;
1311 (void)irplib_polynomial_solve_1d_3(1.0, q2, q1, q0, &u1, NULL, NULL,
1317 sqrtd = sqrt(u1 - a);
1319 sqrtrd = 0.5 * b/sqrtd;
1321 is_complex1 = irplib_polynomial_solve_1d_2(1.0, sqrtd, 0.5*u1 - sqrtrd,
1324 is_complex2 = irplib_polynomial_solve_1d_2(1.0, -sqrtd, 0.5*u1 + sqrtrd,
1327 z1 -= 0.25 * p3 / p4;
1328 z3 -= 0.25 * p3 / p4;
1329 if (!is_complex1) z2 -= 0.25 * p3 / p4;
1330 if (!is_complex2) z4 -= 0.25 * p3 / p4;
1332 if (!is_complex1 && is_complex2) {
1338 }
else if (is_complex1 && !is_complex2) {
1344 }
else if (is_complex1 && is_complex2) {
1347 if (z1 < z3 || (z1 == z3 && z2 <= z4)) {
1366 }
else if (z4 <= z1) {
1371 }
else if (z2 > z4) {
1390 return CPL_ERROR_NONE;
1393 #ifdef IPRLIB_POLYNOMIAL_USE_MONOMIAL_ROOT
1403 static double irplib_polynomial_depress_1d(cpl_polynomial *
self)
1406 const cpl_size degree = cpl_polynomial_get_degree(
self);
1407 const cpl_size nc1 = degree - 1;
1408 const double an = cpl_polynomial_get_coeff(
self, °ree);
1409 const double an1 = cpl_polynomial_get_coeff(
self, &nc1);
1414 cpl_ensure(degree > 0, CPL_ERROR_DATA_NOT_FOUND, 0.0);
1416 assert( an != 0.0 );
1418 rmean = -an1/(an * (double)degree);
1422 cpl_polynomial_shift_1d(
self, 0, rmean);
1424 cpl_polynomial_set_coeff(
self, &nc1, 0.0);
1429 for (i = 0; i < degree-1; i++) {
1430 const double ai = cpl_polynomial_get_coeff(
self, &i) / an;
1431 cpl_polynomial_set_coeff(
self, &i, ai);
1434 cpl_polynomial_set_coeff(
self, °ree, 1.0);
1457 cpl_error_code irplib_polynomial_divide_1d_root(cpl_polynomial * p,
double r,
1461 const cpl_size n = cpl_polynomial_get_degree(p);
1466 cpl_ensure_code(p != NULL, CPL_ERROR_NULL_INPUT);
1467 cpl_ensure_code(cpl_polynomial_get_dimension(p) == 1,
1468 CPL_ERROR_INVALID_TYPE);
1469 cpl_ensure_code(n > 0, CPL_ERROR_DATA_NOT_FOUND);
1471 sum = cpl_polynomial_get_coeff(p, &n);
1472 cpl_polynomial_set_coeff(p, &n, 0.0);
1474 for (i = n-1; i >= 0; i--) {
1475 const double coeff = cpl_polynomial_get_coeff(p, &i);
1477 cpl_polynomial_set_coeff(p, &i, sum);
1479 sum = coeff + r * sum;
1483 if (pres != NULL) *pres = sum;
1485 return CPL_ERROR_NONE;