36#include "irplib_polynomial.h"
39#include "irplib_utils.h"
59static double irplib_polynomial_eval_2_max(
double,
double,
double, cpl_boolean,
62static double irplib_polynomial_eval_3_max(
double,
double,
double,
double,
63 cpl_boolean,
double,
double,
double);
66static cpl_boolean irplib_polynomial_solve_1d_2(
double,
double,
double,
68static cpl_boolean irplib_polynomial_solve_1d_3(
double,
double,
double,
double,
69 double *,
double *,
double *,
73static void irplib_polynomial_solve_1d_31(
double,
double,
double *,
double *,
74 double *, cpl_boolean *);
76static void irplib_polynomial_solve_1d_32(
double,
double,
double,
double *,
77 double *,
double *, cpl_boolean *);
79static void irplib_polynomial_solve_1d_3r(
double,
double,
double,
double,
80 double *,
double *,
double *);
82static void irplib_polynomial_solve_1d_3c(
double,
double,
double,
83 double,
double,
double,
84 double *,
double *,
double *,
85 cpl_boolean *, cpl_boolean *);
87static cpl_error_code irplib_polynomial_solve_1d_4(
double,
double,
double,
88 double,
double, cpl_size *,
92static cpl_error_code irplib_polynomial_solve_1d_zero(cpl_polynomial *,
97static cpl_error_code irplib_polynomial_solve_1d_nonzero(cpl_polynomial *,
102static cpl_error_code irplib_polynomial_divide_1d_root(cpl_polynomial *,
double,
105static cpl_error_code irplib_polynomial_solve_1d_guess(
const cpl_polynomial *,
109#ifdef IRPLIB_POLYNOMIAL_GUESS_ANASOL
110static double irplib_polynomial_depress_1d(cpl_polynomial *);
144cpl_error_code irplib_polynomial_solve_1d_all(
const cpl_polynomial * self,
149 cpl_error_code error;
150 const cpl_size degree = cpl_polynomial_get_degree(self);
153 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
154 cpl_ensure_code(roots != NULL, CPL_ERROR_NULL_INPUT);
155 cpl_ensure_code(preal != NULL, CPL_ERROR_NULL_INPUT);
156 cpl_ensure_code(cpl_polynomial_get_dimension(self) == 1,
157 CPL_ERROR_INVALID_TYPE);
158 cpl_ensure_code(degree > 0, CPL_ERROR_DATA_NOT_FOUND);
159 cpl_ensure_code(degree == cpl_vector_get_size(roots),
160 CPL_ERROR_INCOMPATIBLE_INPUT);
164 p = cpl_polynomial_duplicate(self);
166 error = irplib_polynomial_solve_1d_zero(p, roots, preal);
168 if (!error && *preal < degree) {
172 const cpl_boolean dosort = *preal > 0 || degree - *preal > 4;
174 assert(cpl_polynomial_get_degree(p) + *preal == degree);
176 error = irplib_polynomial_solve_1d_nonzero(p, roots, preal);
178 if (!error && dosort) {
179 cpl_vector * reals = cpl_vector_wrap(*preal,
180 cpl_vector_get_data(roots));
181 cpl_vector_sort(reals, CPL_SORT_ASCENDING);
182 (void)cpl_vector_unwrap(reals);
186 cpl_polynomial_delete(p);
188 return error ? cpl_error_set_where(cpl_func) : CPL_ERROR_NONE;
206static cpl_error_code irplib_polynomial_solve_1d_zero(cpl_polynomial * self,
211 const cpl_size degree = cpl_polynomial_get_degree(self);
214 for (nzero = 0; nzero < degree; nzero++) {
215 if (cpl_polynomial_get_coeff(self, &nzero) != 0.0)
break;
220 for (; i <= degree - nzero; i++) {
221 const cpl_size icopy = i + nzero;
222 const double value = cpl_polynomial_get_coeff(self, &icopy);
224 if (cpl_polynomial_set_coeff(self, &i, value))
225 return cpl_error_set_where(cpl_func);
227 for (; i <= degree; i++) {
228 if (cpl_polynomial_set_coeff(self, &i, 0.0))
229 return cpl_error_set_where(cpl_func);
230 cpl_vector_set(roots, (*preal)++, 0.0);
234 return CPL_ERROR_NONE;
254static cpl_error_code irplib_polynomial_solve_1d_nonzero(cpl_polynomial * self,
258 cpl_error_code error = CPL_ERROR_NONE;
259 const cpl_size ncoeffs = 1 + cpl_polynomial_get_degree(self);
262 cpl_ensure_code(ncoeffs > 1, CPL_ERROR_DATA_NOT_FOUND);
263 cpl_ensure_code(*preal >= 0, CPL_ERROR_ILLEGAL_INPUT);
264 cpl_ensure_code(ncoeffs + *preal == 1+cpl_vector_get_size(roots),
265 CPL_ERROR_INCOMPATIBLE_INPUT);
270 const cpl_size i1 = 1;
271 const cpl_size i0 = 0;
272 const double p1 = cpl_polynomial_get_coeff(self, &i1);
273 const double p0 = cpl_polynomial_get_coeff(self, &i0);
277 cpl_vector_set(roots, (*preal)++, -p0/p1);
281 const cpl_size i2 = 2;
282 const cpl_size i1 = 1;
283 const cpl_size i0 = 0;
284 const double p2 = cpl_polynomial_get_coeff(self, &i2);
285 const double p1 = cpl_polynomial_get_coeff(self, &i1);
286 const double p0 = cpl_polynomial_get_coeff(self, &i0);
291 if (irplib_polynomial_solve_1d_2(p2, p1, p0, &x1, &x2)) {
293 cpl_vector_set(roots, (*preal) , x1);
294 cpl_vector_set(roots, (*preal)+1, x2);
296 cpl_vector_set(roots, (*preal)++, x1);
297 cpl_vector_set(roots, (*preal)++, x2);
302 const cpl_size i3 = 3;
303 const cpl_size i2 = 2;
304 const cpl_size i1 = 1;
305 const cpl_size i0 = 0;
306 const double p3 = cpl_polynomial_get_coeff(self, &i3);
307 const double p2 = cpl_polynomial_get_coeff(self, &i2);
308 const double p1 = cpl_polynomial_get_coeff(self, &i1);
309 const double p0 = cpl_polynomial_get_coeff(self, &i0);
314 if (irplib_polynomial_solve_1d_3(p3, p2, p1, p0, &x1, &x2, &x3,
316 cpl_vector_set(roots, (*preal)++, x1);
318 cpl_vector_set(roots, (*preal) , x2);
319 cpl_vector_set(roots, (*preal)+1, x3);
321 cpl_vector_set(roots, (*preal)++, x1);
322 cpl_vector_set(roots, (*preal)++, x2);
323 cpl_vector_set(roots, (*preal)++, x3);
328 const cpl_size i4 = 4;
329 const cpl_size i3 = 3;
330 const cpl_size i2 = 2;
331 const cpl_size i1 = 1;
332 const cpl_size i0 = 0;
333 const double p4 = cpl_polynomial_get_coeff(self, &i4);
334 const double p3 = cpl_polynomial_get_coeff(self, &i3);
335 const double p2 = cpl_polynomial_get_coeff(self, &i2);
336 const double p1 = cpl_polynomial_get_coeff(self, &i1);
337 const double p0 = cpl_polynomial_get_coeff(self, &i0);
338 double x1, x2, x3, x4;
343 error = irplib_polynomial_solve_1d_4(p4, p3, p2, p1, p0, &nreal,
346 cpl_vector_set(roots, (*preal) , x1);
347 cpl_vector_set(roots, (*preal)+1, x2);
348 cpl_vector_set(roots, (*preal)+2, x3);
349 cpl_vector_set(roots, (*preal)+3, x4);
361 error = irplib_polynomial_solve_1d_guess(self, &root);
365 cpl_vector_set(roots, (*preal)++, root);
367 irplib_polynomial_divide_1d_root(self, root, NULL);
369 error = irplib_polynomial_solve_1d_nonzero(self, roots, preal);
377 return error ? cpl_error_set_where(cpl_func) : CPL_ERROR_NONE;
392cpl_error_code irplib_polynomial_solve_1d_guess(
const cpl_polynomial * self,
395 cpl_errorstate prestate = cpl_errorstate_get();
396 cpl_error_code error = CPL_ERROR_NONE;
397 const cpl_size degree = cpl_polynomial_get_degree(self);
398 const cpl_size ncand = 5;
401 size_t ipos = 0, ineg = 0;
402 double rpos[1], rneg[1];
403 cpl_boolean do_bisect = CPL_FALSE;
410 for (itry = 0; ; itry++) {
414 const double pn0 = cpl_polynomial_get_coeff(self, °ree);
415 const cpl_size n1 = degree-1;
416 const double pn1 = cpl_polynomial_get_coeff(self, &n1);
419 assert( pn0 != 0.0 );
421 rmean = -pn1 / (pn0 * (double)degree);
423 rcand[icand++] = rmean;
430 const cpl_size i0 = 0;
431 const double c0 = cpl_polynomial_get_coeff(self, &i0);
436 rmean = pow(fabs(c0), 1.0/(
double)degree);
438 rcand[icand++] = rmean;
445 const cpl_size i0 = 0;
446 const double c0 = cpl_polynomial_get_coeff(self, &i0);
447 const double pn0 = cpl_polynomial_get_coeff(self, °ree);
448 const cpl_size n1 = degree-1;
449 const double pn1 = cpl_polynomial_get_coeff(self, &n1);
452 assert( pn0 != 0.0 );
454 rmean = -pn1 / (pn0 * (double)degree);
456 rcand[icand++] = rmean + c0;
457 rcand[icand++] = rmean - c0;
462#ifdef IRPLIB_POLYNOMIAL_GUESS_ANASOL
466 cpl_polynomial * copy = cpl_polynomial_duplicate(self);
467 const cpl_size i0 = 0;
468 const double rmean = irplib_polynomial_depress_1d(copy);
469 const double c0 = cpl_polynomial_get_coeff(copy, &i0);
470 const double radius = pow(fabs(c0), 1.0/(
double)degree);
472 rcand[icand++] = rmean + radius;
474 rcand[icand++] = rmean - radius;
476 cpl_polynomial_delete(copy);
485 if (ipos > 0 && ineg > 0) {
486 rcand[icand++] = 0.5 * (rpos[0] + rneg[0]);
487 do_bisect = CPL_TRUE;
494 double root = rcand[--icand];
495 const double resid = cpl_polynomial_eval_1d(self, root, &grad);
497#ifdef IRPLIB_POLYNOMIAL_DEBUG
499 cpl_msg_warning(cpl_func,
"RETRY(%d)=%g, degree=%d, r=%g, d=%g",
500 (
int)itry, root, (
int)degree, resid, grad);
503 error = cpl_polynomial_solve_1d(self, root, proot, 1);
505 cpl_errorstate_set(prestate);
510 *(resid > 0.0 ? rpos : rneg) = root;
514 if (ipos == 0) rpos[ipos++] = root;
515 }
else if (ineg == 0) {
519 if (ipos == 0 || ineg == 0) {
520 const double resid2 = cpl_polynomial_eval_1d(self, *proot,
523 if (ipos == 0) rpos[ipos++] = *proot;
524 }
else if (ineg == 0) {
525 rneg[ineg++] = *proot;
535 return error ? cpl_error_set_where(cpl_func) : CPL_ERROR_NONE;
553static cpl_boolean irplib_polynomial_solve_1d_2(
double p2,
double p1,
double p0,
557 const double sqrtD = sqrt(p1 * p1 < 4.0 * p2 * p0
558 ? 4.0 * p2 * p0 - p1 * p1
559 : p1 * p1 - 4.0 * p2 * p0);
560 cpl_boolean is_complex = CPL_FALSE;
561 double x1 = -0.5 * p1 / p2;
565 double res0 = irplib_polynomial_eval_2_max(p2, p1, p0, CPL_FALSE, x1, x1);
568 assert(px1 != NULL );
569 assert(px2 != NULL );
577 x1 = -0.5 * (p1 + sqrtD);
579 x1 = -0.5 * (p1 - sqrtD);
586 res = irplib_polynomial_eval_2_max(p2, p1, p0, CPL_FALSE, x1, x2);
602 x2 = 0.5 * sqrtD / fabs(p2);
604 res = irplib_polynomial_eval_2_max(p2, p1, p0, CPL_TRUE, x1, x2);
609 is_complex = CPL_TRUE;
631static double irplib_polynomial_eval_2_max(
double p2,
double p1,
double p0,
633 double x1,
double x2)
638 res = fabs(p0 + x1 * (p1 + x1 * p2) - p2 * x2 * x2);
640 const double r1 = fabs(p0 + x1 * (p1 + x1 * p2));
641 const double r2 = fabs(p0 + x2 * (p1 + x2 * p2));
643 res = r1 > r2 ? r1 : r2;
666static double irplib_polynomial_eval_3_max(
double p3,
double p2,
667 double p1,
double p0,
669 double x1,
double x2,
double x3)
671 const double r1 = fabs(p0 + x1 * (p1 + x1 * (p2 + x1 * p3)));
675 const double r2 = fabs(p0 + x2 * (p1 + x2 * (p2 + x2 * p3))
676 - x3 * x3 * ( 3.0 * p3 * x2 + p2));
678 res = r1 > r2 ? r1 : r2;
680 const double r2 = fabs(p0 + x2 * (p1 + x2 * (p2 + x2 * p3)));
681 const double r3 = fabs(p0 + x3 * (p1 + x3 * (p2 + x3 * p3)));
682 res = r1 > r2 ? (r1 > r3 ? r1 : r3) : (r2 > r3 ? r2 : r3);
711static cpl_boolean irplib_polynomial_solve_1d_3(
double p3,
double p2,
double p1,
717 cpl_boolean * pdbl2) {
718 cpl_boolean is_complex = CPL_FALSE;
719 const double a = p2/p3;
720 const double b = p1/p3;
721 const double c = p0/p3;
723 const double q = (a * a - 3.0 * b);
724 const double r = (a * (2.0 * a * a - 9.0 * b) + 27.0 * c);
726 const double Q = q / 9.0;
727 const double R = r / 54.0;
729 const double Q3 = Q * Q * Q;
730 const double R2 = R * R;
735 double xx1 = DBL_MAX;
736 double xx2 = DBL_MAX;
737 double xx3 = DBL_MAX;
739 double res = DBL_MAX;
740 cpl_boolean is_first = CPL_TRUE;
745 assert(px1 != NULL );
747 if (pdbl1 != NULL) *pdbl1 = CPL_FALSE;
748 if (pdbl2 != NULL) *pdbl2 = CPL_FALSE;
760 if ((R2 >= Q3 && R != 0.0) || R2 > Q3) {
762 cpl_boolean is_c = CPL_FALSE;
765 irplib_polynomial_solve_1d_3c(a, c, Q, Q3, R, R2, &x1, &x2, &x3,
769 res = resx = irplib_polynomial_eval_3_max(p3, p2, p1, p0, is_c,
772 is_first = CPL_FALSE;
774 if (pdbl1 != NULL) *pdbl1 = CPL_FALSE;
775 if (!is_c && pdbl2 != NULL) *pdbl2 = dbl2;
780 if (Q > 0.0 && fabs(R / (Q * sqrt(Q))) <= 1.0) {
788 irplib_polynomial_solve_1d_3r(a, c, Q, R, &xx1, &xx2, &xx3);
790 resx = irplib_polynomial_eval_3_max(p3, p2, p1, p0, CPL_FALSE,
793 if (is_first || (dbl2 ? resx < res : resx <= res)) {
794 is_first = CPL_FALSE;
799 if (pdbl1 != NULL) *pdbl1 = CPL_FALSE;
800 if (pdbl2 != NULL) *pdbl2 = CPL_FALSE;
801 is_complex = CPL_FALSE;
806 cpl_boolean dbl1 = CPL_FALSE;
810 irplib_polynomial_solve_1d_32(a, c, Q, &xx1, &xx2, &xx3, &dbl2);
812 resx = irplib_polynomial_eval_3_max(p3, p2, p1, p0, CPL_FALSE,
819 if (is_first || resx <= res) {
825 if (pdbl1 != NULL) *pdbl1 = CPL_FALSE;
826 if (pdbl2 != NULL) *pdbl2 = dbl2;
827 is_complex = CPL_FALSE;
834 irplib_polynomial_solve_1d_31(a, Q, &xx1, &xx2, &xx3, &dbl1);
836 resx = irplib_polynomial_eval_3_max(p3, p2, p1, p0, CPL_FALSE,
845 if (pdbl1 != NULL) *pdbl1 = dbl1;
846 if (pdbl2 != NULL) *pdbl2 = CPL_FALSE;
847 is_complex = CPL_FALSE;
852 if (px2 != NULL && px3 != NULL) {
856 }
else if (is_complex) {
880static void irplib_polynomial_solve_1d_31(
double a,
double Q,
881 double * px1,
double * px2,
882 double * px3, cpl_boolean * pdbl1)
885 const double sqrtQ = sqrt (Q);
889 x2 = x1 = -sqrtQ - a / 3.0;
890 x3 = 2.0 * sqrtQ - a / 3.0;
891 if (pdbl1 != NULL) *pdbl1 = CPL_TRUE;
916static void irplib_polynomial_solve_1d_32(
double a,
double c,
double Q,
917 double * px1,
double * px2,
918 double * px3, cpl_boolean * pdbl2)
921 const double sqrtQ = sqrt (Q);
929 x1 = -2.0 * sqrtQ - a / 3.0;
932 x3 = x2 = -a < x1 ? -sqrt(fabs(c / x1)) : sqrt(fabs(c / x1));
933 if (pdbl2 != NULL) *pdbl2 = CPL_TRUE;
934 }
else if (a < 0.0) {
936 x3 = x2 = sqrtQ - a / 3.0;
938 if (pdbl2 != NULL) *pdbl2 = CPL_TRUE;
942 if (pdbl2 != NULL) *pdbl2 = CPL_TRUE;
973static void irplib_polynomial_solve_1d_3c(
double a,
double c,
977 double * px2,
double * px3,
990 const double sgnR = (R >= 0 ? 1.0 : -1.0);
991 const double A = -sgnR * pow (fabs (R) + sqrt (R2 - Q3), 1.0 / 3.0);
992 const double B = Q / A;
997 cpl_boolean is_complex = CPL_FALSE;
999 if (( A > -B && a > 0.0) || (A < -B && a < 0.0)) {
1003 x2 = -0.5 * (A + B) - a / 3.0;
1005 x3 = 0.5 * CPL_MATH_SQRT3 * fabs(A - B);
1007 x1 = -c / (x2 * x2 + x3 * x3);
1010 x1 = A + B - a / 3.0;
1012 x3 = 0.5 * CPL_MATH_SQRT3 * fabs(A - B);
1016 x2 = -0.5 * (A + B) - a / 3.0;
1019 x2 = -a < x1 ? -sqrt(fabs(c / x1)) : sqrt(fabs(c / x1));
1025 is_complex = CPL_TRUE;
1030 if (pdbl2 != NULL) *pdbl2 = CPL_TRUE;
1036 *pis_c = is_complex;
1057static 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 );
1097 x3 = -c / ( x1 * x2 );
1099 }
else if (a < 0.0) {
1101 if (TR2 < 0.0 && (TR1 + TR2) > 2.0 * a) {
1103 x2 = -c / ( x1 * x3 );
1106 x1 = -c / ( x2 * x3 );
1124 x1 = x2 = 0.5 * ( x1 + x2 );
1125 }
else if (x2 > x3) {
1133 x3 = x2 = 0.5 * ( x2 + x3 );
1162static cpl_error_code irplib_polynomial_solve_1d_4(
double p4,
double p3,
1163 double p2,
double p1,
1164 double p0, cpl_size * preal,
1165 double * px1,
double * px2,
1166 double * px3,
double * px4)
1170 const double a = (p2 - 0.375 * p3 * p3 / p4) / p4;
1171 const double b = (p1 - 0.5 * (p2 - 0.25 * p3 * p3 / p4 ) * p3 / p4 ) / p4;
1173 (p0 - 0.25 * (p1 - 0.25 * (p2 - 0.1875 * p3 * p3 / p4 ) * p3 / p4
1176 double x1 = DBL_MAX;
1177 double x2 = DBL_MAX;
1178 double x3 = DBL_MAX;
1179 double x4 = DBL_MAX;
1181 assert(preal != NULL );
1182 assert(px1 != NULL );
1183 assert(px2 != NULL );
1184 assert(px3 != NULL );
1185 assert(px4 != NULL );
1193 cpl_boolean dbl1, dbl2;
1194 const cpl_boolean is_real =
1195 !irplib_polynomial_solve_1d_3(1.0, 0.0, a, b, &x1, &x3, &x4,
1198 x1 -= 0.25 * p3 / p4;
1199 x2 = -0.25 * p3 / p4;
1200 x3 -= 0.25 * p3 / p4;
1208 x4 -= 0.25 * p3 / p4;
1211 IRPLIB_SWAP_DOUBLE(x2, x3);
1228 IRPLIB_SWAP_DOUBLE(x1, x2);
1234 }
else if (b == 0.0) {
1237 const cpl_boolean is_complex = irplib_polynomial_solve_1d_2(1.0, a, c,
1242 const double norm = sqrt(u1*u1 + u2*u2);
1243 const double v1 = sqrt(0.5*(norm+u1));
1244 const double v2 = u2 / sqrt(2.0*(norm+u1));
1247 x1 = -0.25 * p3 / p4 - v1;
1248 x3 = -0.25 * p3 / p4 + v1;
1254 }
else if (u1 >= 0.0) {
1256 const double sv1 = sqrt(u1);
1257 const double sv2 = sqrt(u2);
1262 x1 = -0.25 * p3 / p4 - sv2;
1263 x2 = -0.25 * p3 / p4 - sv1;
1264 x3 = -0.25 * p3 / p4 + sv1;
1265 x4 = -0.25 * p3 / p4 + sv2;
1266 }
else if (u2 < 0.0) {
1268 const double sv1 = sqrt(-u2);
1269 const double sv2 = sqrt(-u1);
1274 x1 = x3 = -0.25 * p3 / p4;
1280 const double sv1 = sqrt(-u1);
1281 const double sv2 = sqrt(u2);
1286 x1 = -0.25 * p3 / p4 - sv2;
1287 x2 = -0.25 * p3 / p4 + sv2;
1289 x3 = -0.25 * p3 / p4;
1294 const double q2 = -a;
1295 const double q1 = -4.0 * c;
1296 const double q0 = 4.0 * a * c - b * b;
1297 double u1, sqrtd, sqrtrd;
1298 double z1, z2, z3, z4;
1300 cpl_boolean is_complex1, is_complex2;
1304 (void)irplib_polynomial_solve_1d_3(1.0, q2, q1, q0, &u1, NULL, NULL,
1310 sqrtd = sqrt(u1 - a);
1312 sqrtrd = 0.5 * b/sqrtd;
1314 is_complex1 = irplib_polynomial_solve_1d_2(1.0, sqrtd, 0.5*u1 - sqrtrd,
1317 is_complex2 = irplib_polynomial_solve_1d_2(1.0, -sqrtd, 0.5*u1 + sqrtrd,
1320 z1 -= 0.25 * p3 / p4;
1321 z3 -= 0.25 * p3 / p4;
1322 if (!is_complex1) z2 -= 0.25 * p3 / p4;
1323 if (!is_complex2) z4 -= 0.25 * p3 / p4;
1325 if (!is_complex1 && is_complex2) {
1331 }
else if (is_complex1 && !is_complex2) {
1337 }
else if (is_complex1 && is_complex2) {
1340 if (z1 < z3 || (z1 == z3 && z2 <= z4)) {
1359 }
else if (z4 <= z1) {
1364 }
else if (z2 > z4) {
1383 return CPL_ERROR_NONE;
1386#ifdef IRPLIB_POLYNOMIAL_GUESS_ANASOL
1396static double irplib_polynomial_depress_1d(cpl_polynomial * self)
1399 const cpl_size degree = cpl_polynomial_get_degree(self);
1400 const cpl_size nc1 = degree - 1;
1401 const double an = cpl_polynomial_get_coeff(self, °ree);
1402 const double an1 = cpl_polynomial_get_coeff(self, &nc1);
1403 const double rmean = an != 0.0 ? -an1/(an * (double)degree) : 0.0;
1406 cpl_ensure(degree > 0, CPL_ERROR_DATA_NOT_FOUND, 0.0);
1408 assert( an != 0.0 );
1412 cpl_polynomial_shift_1d(self, 0, rmean);
1417 for (cpl_size i = 0; i < nc1; i++) {
1418 const double ai = cpl_polynomial_get_coeff(self, &i) / an;
1419 cpl_polynomial_set_coeff(self, &i, ai);
1422 cpl_polynomial_set_coeff(self, &nc1, 0.0);
1423 cpl_polynomial_set_coeff(self, °ree, 1.0);
1446cpl_error_code irplib_polynomial_divide_1d_root(cpl_polynomial * p,
double r,
1450 const cpl_size n = cpl_polynomial_get_degree(p);
1455 cpl_ensure_code(p != NULL, CPL_ERROR_NULL_INPUT);
1456 cpl_ensure_code(n > 0, CPL_ERROR_DATA_NOT_FOUND);
1458 sum = cpl_polynomial_get_coeff(p, &n);
1459 cpl_polynomial_set_coeff(p, &n, 0.0);
1461 for (i = n-1; i >= 0; i--) {
1462 const double coeff = cpl_polynomial_get_coeff(p, &i);
1464 cpl_polynomial_set_coeff(p, &i, sum);
1466 sum = coeff + r * sum;
1470 if (pres != NULL) *pres = sum;
1472 return CPL_ERROR_NONE;