irplib_polynomial.c

00001 /* $Id: irplib_polynomial.c,v 1.35 2013/01/29 08:43:33 jtaylor Exp $
00002  *
00003  * This file is part of the ESO Common Pipeline Library
00004  * Copyright (C) 2001-2004 European Southern Observatory
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA
00019  */
00020 
00021 /*
00022  * $Author: jtaylor $
00023  * $Date: 2013/01/29 08:43:33 $
00024  * $Revision: 1.35 $
00025  * $Name: HEAD $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 /*-----------------------------------------------------------------------------
00033                                    Includes
00034  -----------------------------------------------------------------------------*/
00035 
00036 #include "irplib_polynomial.h"
00037 #include <assert.h>
00038 #include <math.h>
00039 /* DBL_MAX: */
00040 #include <float.h>
00041 
00042 /*----------------------------------------------------------------------------*/
00048 /*----------------------------------------------------------------------------*/
00051 /*-----------------------------------------------------------------------------
00052                                    Macro definitions
00053  -----------------------------------------------------------------------------*/
00054 
00055 #define IRPLIB_SWAP(a,b) { const double t=(a);(a)=(b);(b)=t; }
00056 
00057 #if 0
00058 #define irplib_trace() cpl_msg_info(cpl_func, "%d: Trace", __LINE__)
00059 #else
00060 #define irplib_trace() /* Trace */
00061 #endif
00062 
00063 /*-----------------------------------------------------------------------------
00064                                    Static functions
00065  -----------------------------------------------------------------------------*/
00066 
00067 static double irplib_polynomial_eval_2_max(double, double, double, cpl_boolean,
00068                                            double, double);
00069 
00070 static double irplib_polynomial_eval_3_max(double, double, double, double,
00071                                            cpl_boolean, double, double, double);
00072 
00073 
00074 static cpl_boolean irplib_polynomial_solve_1d_2(double, double, double,
00075                                                 double *, double *);
00076 static cpl_boolean irplib_polynomial_solve_1d_3(double, double, double, double,
00077                                                 double *, double *, double *,
00078                                                 cpl_boolean *,
00079                                                 cpl_boolean *);
00080 
00081 static void irplib_polynomial_solve_1d_31(double, double, double *, double *,
00082                                           double *, cpl_boolean *);
00083 
00084 static void irplib_polynomial_solve_1d_32(double, double, double, double *,
00085                                           double *, double *, cpl_boolean *);
00086 
00087 static void irplib_polynomial_solve_1d_3r(double, double, double, double,
00088                                           double *, double *, double *);
00089 
00090 static void irplib_polynomial_solve_1d_3c(double, double, double,
00091                                           double, double, double,
00092                                           double *, double *, double *,
00093                                           cpl_boolean *, cpl_boolean *);
00094 
00095 static cpl_error_code irplib_polynomial_solve_1d_4(double, double, double,
00096                                                    double, double, cpl_size *,
00097                                                    double *, double *,
00098                                                    double *, double *);
00099 
00100 static cpl_error_code irplib_polynomial_solve_1d_nonzero(cpl_polynomial *,
00101                                                          cpl_vector *,
00102                                                          cpl_size *);
00103 
00104 static cpl_error_code irplib_polynomial_divide_1d_root(cpl_polynomial *, double,
00105                                                        double *);
00106 
00107 #ifdef IPRLIB_POLYNOMIAL_USE_MONOMIAL_ROOT
00108 static double irplib_polynomial_depress_1d(cpl_polynomial *);
00109 #endif
00110 
00111 /*-----------------------------------------------------------------------------
00112                               Function codes
00113  -----------------------------------------------------------------------------*/
00114 
00115 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE > CPL_VERSION(5, 92, 0)
00116 #else
00117 
00118 /*----------------------------------------------------------------------------*/
00133 /*----------------------------------------------------------------------------*/
00134 cpl_error_code irplib_polynomial_add(cpl_polynomial * self,
00135                                      const cpl_polynomial * first,
00136                                      const cpl_polynomial * second)
00137 {
00138     cpl_size       degree0 = cpl_polynomial_get_degree(self);
00139     const cpl_size degree1 = cpl_polynomial_get_degree(first);
00140     const cpl_size degree2 = cpl_polynomial_get_degree(second);
00141     const cpl_size maxdeg  = degree1 > degree2 ? degree1 : degree2;
00142 
00143 
00144     cpl_ensure_code(self   != NULL, CPL_ERROR_NULL_INPUT);
00145     cpl_ensure_code(first  != NULL, CPL_ERROR_NULL_INPUT);
00146     cpl_ensure_code(second != NULL, CPL_ERROR_NULL_INPUT);
00147 
00148     cpl_ensure_code(cpl_polynomial_get_dimension(self) ==
00149                     cpl_polynomial_get_dimension(first),
00150                     CPL_ERROR_INCOMPATIBLE_INPUT);
00151     cpl_ensure_code(cpl_polynomial_get_dimension(self) ==
00152                     cpl_polynomial_get_dimension(second),
00153                     CPL_ERROR_INCOMPATIBLE_INPUT);
00154 
00155     /* FIXME: */
00156     cpl_ensure_code(cpl_polynomial_get_dimension(self) == 1,
00157                     CPL_ERROR_UNSUPPORTED_MODE);
00158 
00159     if (degree0 < maxdeg) {
00160         degree0 = maxdeg;
00161     } else {
00162         /* Reset coefficients in self as needed */
00163         for (; degree0 > maxdeg; degree0--) {
00164             cpl_polynomial_set_coeff(self, &degree0, 0.0);
00165         }
00166     }
00167 
00168     /* assert( degree0 == maxdeg ); */
00169 
00170     for (; degree0 >= 0; degree0--) {
00171         const double val1 = cpl_polynomial_get_coeff(first, &degree0);
00172         const double val2 = cpl_polynomial_get_coeff(second, &degree0);
00173         cpl_polynomial_set_coeff(self, &degree0, val1 + val2);
00174     }
00175 
00176     return CPL_ERROR_NONE;
00177 }
00178 
00179 /*----------------------------------------------------------------------------*/
00194 /*----------------------------------------------------------------------------*/
00195 cpl_error_code irplib_polynomial_subtract(cpl_polynomial * self,
00196                                           const cpl_polynomial * first,
00197                                           const cpl_polynomial * second)
00198 {
00199     cpl_size       degree0 = cpl_polynomial_get_degree(self);
00200     const cpl_size degree1 = cpl_polynomial_get_degree(first);
00201     const cpl_size degree2 = cpl_polynomial_get_degree(second);
00202     const cpl_size maxdeg  = degree1 > degree2 ? degree1 : degree2;
00203 
00204 
00205     cpl_ensure_code(self   != NULL, CPL_ERROR_NULL_INPUT);
00206     cpl_ensure_code(first  != NULL, CPL_ERROR_NULL_INPUT);
00207     cpl_ensure_code(second != NULL, CPL_ERROR_NULL_INPUT);
00208 
00209     cpl_ensure_code(cpl_polynomial_get_dimension(self) ==
00210                     cpl_polynomial_get_dimension(first),
00211                     CPL_ERROR_INCOMPATIBLE_INPUT);
00212     cpl_ensure_code(cpl_polynomial_get_dimension(self) ==
00213                     cpl_polynomial_get_dimension(second),
00214                     CPL_ERROR_INCOMPATIBLE_INPUT);
00215 
00216     /* FIXME: */
00217     cpl_ensure_code(cpl_polynomial_get_dimension(self) == 1,
00218                     CPL_ERROR_UNSUPPORTED_MODE);
00219 
00220     if (degree0 < maxdeg) {
00221         degree0 = maxdeg;
00222     } else {
00223         /* Reset coefficients in self as needed */
00224         for (; degree0 > maxdeg; degree0--) {
00225             cpl_polynomial_set_coeff(self, &degree0, 0.0);
00226         }
00227     }
00228 
00229     /* assert( degree0 == maxdeg ); */
00230 
00231     for (; degree0 >= 0; degree0--) {
00232         const double val1 = cpl_polynomial_get_coeff(first, &degree0);
00233         const double val2 = cpl_polynomial_get_coeff(second, &degree0);
00234         cpl_polynomial_set_coeff(self, &degree0, val1 - val2);
00235     }
00236 
00237     return CPL_ERROR_NONE;
00238 }
00239 
00240 /*----------------------------------------------------------------------------*/
00252 /*----------------------------------------------------------------------------*/
00253 cpl_error_code irplib_polynomial_multiply_scalar(cpl_polynomial * self,
00254                                                  const cpl_polynomial * other,
00255                                                  double factor)
00256 {
00257 
00258     const cpl_size maxdeg  = cpl_polynomial_get_degree(other);
00259     const cpl_size zerodeg = cpl_polynomial_get_degree(self);
00260     cpl_size       degree;
00261 
00262     cpl_ensure_code(self  != NULL, CPL_ERROR_NULL_INPUT);
00263     cpl_ensure_code(other != NULL, CPL_ERROR_NULL_INPUT);
00264 
00265     cpl_ensure_code(cpl_polynomial_get_dimension(self) == 1,
00266                     CPL_ERROR_UNSUPPORTED_MODE);
00267     cpl_ensure_code(cpl_polynomial_get_dimension(other) == 1,
00268                     CPL_ERROR_UNSUPPORTED_MODE);
00269 
00270     for (degree = 0; degree <= maxdeg; degree++) {
00271         const double val = factor * cpl_polynomial_get_coeff(other, &degree);
00272         cpl_polynomial_set_coeff(self, &degree, val);
00273     }
00274 
00275     /* Reset coefficients in self as needed */
00276     for (; degree <= zerodeg; degree++) {
00277         cpl_polynomial_set_coeff(self, &zerodeg, 0.0);
00278     }
00279 
00280     return CPL_ERROR_NONE;
00281 }
00282 #endif
00283 /*----------------------------------------------------------------------------*/
00309 /*----------------------------------------------------------------------------*/
00310 cpl_error_code irplib_polynomial_solve_1d_all(const cpl_polynomial * self,
00311                                               cpl_vector * roots,
00312                                               cpl_size * preal)
00313 {
00314 
00315     cpl_error_code error = CPL_ERROR_NONE;
00316     cpl_polynomial * p;
00317 
00318     cpl_ensure_code(self  != NULL, CPL_ERROR_NULL_INPUT);
00319     cpl_ensure_code(roots != NULL, CPL_ERROR_NULL_INPUT);
00320     cpl_ensure_code(preal != NULL, CPL_ERROR_NULL_INPUT);
00321     cpl_ensure_code(cpl_polynomial_get_dimension(self) == 1,
00322                     CPL_ERROR_INVALID_TYPE);
00323     cpl_ensure_code(cpl_polynomial_get_degree(self) > 0,
00324                     CPL_ERROR_DATA_NOT_FOUND);
00325     cpl_ensure_code(cpl_polynomial_get_degree(self) ==
00326                     cpl_vector_get_size(roots), CPL_ERROR_INCOMPATIBLE_INPUT);
00327 
00328     *preal = 0;
00329 
00330     p = cpl_polynomial_duplicate(self);
00331 
00332     error = irplib_polynomial_solve_1d_nonzero(p, roots, preal);
00333 
00334     cpl_polynomial_delete(p);
00335 
00336     return error;
00337 
00338 }
00339 
00342 /*----------------------------------------------------------------------------*/
00368 /*----------------------------------------------------------------------------*/
00369 static cpl_error_code irplib_polynomial_solve_1d_nonzero(cpl_polynomial * self,
00370                                                          cpl_vector * roots,
00371                                                          cpl_size * preal)
00372 {
00373     cpl_error_code error   = CPL_ERROR_NONE;
00374     const cpl_size ncoeffs = 1 + cpl_polynomial_get_degree(self);
00375 
00376     cpl_ensure_code(self  != NULL,  CPL_ERROR_NULL_INPUT);
00377     cpl_ensure_code(roots != NULL,  CPL_ERROR_NULL_INPUT);
00378     cpl_ensure_code(preal != NULL,  CPL_ERROR_NULL_INPUT);
00379     cpl_ensure_code(cpl_polynomial_get_dimension(self) == 1,
00380                     CPL_ERROR_INVALID_TYPE);
00381     cpl_ensure_code(ncoeffs   > 1,  CPL_ERROR_DATA_NOT_FOUND);
00382     cpl_ensure_code(*preal >= 0,    CPL_ERROR_ILLEGAL_INPUT);
00383     cpl_ensure_code(ncoeffs + *preal == 1+cpl_vector_get_size(roots),
00384                     CPL_ERROR_INCOMPATIBLE_INPUT);
00385 
00386     switch (ncoeffs) {
00387 
00388     case 2 : {
00389         const cpl_size i1 = 1;
00390         const cpl_size i0 = 0;
00391         const double   p1 = cpl_polynomial_get_coeff(self, &i1);
00392         const double   p0 = cpl_polynomial_get_coeff(self, &i0);
00393 
00394         cpl_vector_set(roots, (*preal)++, -p0/p1);
00395         break;
00396     }
00397     case 3 : {
00398         const cpl_size i2 = 2;
00399         const cpl_size i1 = 1;
00400         const cpl_size i0 = 0;
00401         const double   p2 = cpl_polynomial_get_coeff(self, &i2);
00402         const double   p1 = cpl_polynomial_get_coeff(self, &i1);
00403         const double   p0 = cpl_polynomial_get_coeff(self, &i0);
00404         double         x1, x2;
00405 
00406         if (irplib_polynomial_solve_1d_2(p2, p1, p0, &x1, &x2)) {
00407             /* This is the complex root in the upper imaginary half-plane */
00408             cpl_vector_set(roots, (*preal)  , x1);
00409             cpl_vector_set(roots, (*preal)+1, x2);
00410         } else {
00411             cpl_vector_set(roots, (*preal)++, x1);
00412             cpl_vector_set(roots, (*preal)++, x2);
00413         }
00414         break;
00415     }
00416     case 4 : {
00417         const cpl_size i3 = 3;
00418         const cpl_size i2 = 2;
00419         const cpl_size i1 = 1;
00420         const cpl_size i0 = 0;
00421         const double   p3 = cpl_polynomial_get_coeff(self, &i3);
00422         const double   p2 = cpl_polynomial_get_coeff(self, &i2);
00423         const double   p1 = cpl_polynomial_get_coeff(self, &i1);
00424         const double   p0 = cpl_polynomial_get_coeff(self, &i0);
00425         double         x1, x2, x3;
00426 
00427         if (irplib_polynomial_solve_1d_3(p3, p2, p1, p0, &x1, &x2, &x3,
00428                                          NULL, NULL)) {
00429             cpl_vector_set(roots, (*preal)++, x1);
00430             /* This is the complex root in the upper imaginary half-plane */
00431             cpl_vector_set(roots, (*preal)  , x2);
00432             cpl_vector_set(roots, (*preal)+1, x3);
00433         } else {
00434             cpl_vector_set(roots, (*preal)++, x1);
00435             cpl_vector_set(roots, (*preal)++, x2);
00436             cpl_vector_set(roots, (*preal)++, x3);
00437         }
00438         break;
00439     }
00440     case 5 : {
00441         const cpl_size i4 = 4;
00442         const cpl_size i3 = 3;
00443         const cpl_size i2 = 2;
00444         const cpl_size i1 = 1;
00445         const cpl_size i0 = 0;
00446         const double   p4 = cpl_polynomial_get_coeff(self, &i4);
00447         const double   p3 = cpl_polynomial_get_coeff(self, &i3);
00448         const double   p2 = cpl_polynomial_get_coeff(self, &i2);
00449         const double   p1 = cpl_polynomial_get_coeff(self, &i1);
00450         const double   p0 = cpl_polynomial_get_coeff(self, &i0);
00451         double         x1, x2, x3, x4;
00452         cpl_size       nreal;
00453 
00454         error = irplib_polynomial_solve_1d_4(p4, p3, p2, p1, p0, &nreal,
00455                                              &x1, &x2, &x3, &x4);
00456         if (!error) {
00457             cpl_vector_set(roots, (*preal)  , x1);
00458             cpl_vector_set(roots, (*preal)+1, x2);
00459             cpl_vector_set(roots, (*preal)+2, x3);
00460             cpl_vector_set(roots, (*preal)+3, x4);
00461 
00462             *preal += nreal;
00463         }
00464         break;
00465     }
00466 
00467     default: {
00468 
00469         /* Try to reduce the problem by finding a single root */
00470 #ifndef IPRLIB_POLYNOMIAL_USE_MONOMIAL_ROOT
00471         const cpl_size    n0 = ncoeffs-1;
00472         const double pn0 = cpl_polynomial_get_coeff(self, &n0);
00473         const cpl_size    n1 = ncoeffs-2;
00474         const double pn1 = cpl_polynomial_get_coeff(self, &n1);
00475         /* First guess of root is the root average.
00476            FIXME: May need refinement, e.g. via bisection */
00477         const double rmean = -pn1 / (pn0 * n0);
00478         double root = rmean;
00479 #else
00480         /* Try an analytical solution to a (shifted) monomial */
00481         cpl_polynomial * copy = cpl_polynomial_duplicate(self);
00482         const cpl_size    i0 = 0;
00483         const double rmean = irplib_polynomial_depress_1d(copy);
00484         const double c0 = cpl_polynomial_get_coeff(copy, &i0);
00485         double root = rmean + ((n0&1) && c0 < 0.0 ? -1.0 : 1.0)
00486             * pow(fabs(c0), 1.0/n0);
00487 
00488         cpl_polynomial_delete(copy);
00489 #endif
00490 
00491         error = cpl_polynomial_solve_1d(self, root, &root, 1);
00492 
00493         if (!error) {
00494 
00495             cpl_vector_set(roots, (*preal)++, root);
00496 
00497             irplib_polynomial_divide_1d_root(self, root, NULL);
00498 
00499             error = irplib_polynomial_solve_1d_nonzero(self, roots, preal);
00500 
00501             if (!error && *preal > 1) {
00502                 /* Sort the real roots */
00503 
00504                 /* FIXME: Assumes that all roots found so far are real */
00505 
00506                 cpl_vector * reals = cpl_vector_wrap(*preal,
00507                                                      cpl_vector_get_data(roots));
00508                 cpl_vector_sort(reals, 1);
00509                 (void)cpl_vector_unwrap(reals);
00510             }
00511         }
00512         break;
00513     }
00514     }
00515 
00516     return error;
00517 }
00518 
00519 /*----------------------------------------------------------------------------*/
00531 /*----------------------------------------------------------------------------*/
00532 static cpl_boolean irplib_polynomial_solve_1d_2(double p2, double p1, double p0,
00533                                                 double * px1,
00534                                                 double * px2) {
00535 
00536     const double sqrtD = sqrt(fabs(p1 * p1 - 4.0 * p2 * p0));
00537     cpl_boolean is_complex = CPL_FALSE;
00538     double x1 = -0.5 * p1 / p2; /* Double root */
00539     double x2;
00540 
00541     /* Compute residual, assuming D == 0 */
00542     double res0 = irplib_polynomial_eval_2_max(p2, p1, p0, CPL_FALSE, x1, x1);
00543     double res;
00544 
00545     assert(px1 != NULL );
00546     assert(px2 != NULL );
00547 
00548     *px2 = *px1 = x1;
00549 
00550     /* Compute residual, assuming D > 0 */
00551 
00552     /* x1 is the root with largest absolute value */
00553     if (p1 > 0.0) {
00554         x1 = -0.5 * (p1 + sqrtD);
00555         irplib_trace(); /* OK */
00556     } else {
00557         x1 = -0.5 * (p1 - sqrtD);
00558         irplib_trace(); /* OK */
00559     }
00560     /* Compute smaller root via division to avoid
00561        loss of precision due to cancellation */
00562     x2 = p0 / x1;
00563     x1 /= p2; /* Scale x1 with leading coefficient */
00564 
00565     res = irplib_polynomial_eval_2_max(p2, p1, p0, CPL_FALSE, x1, x2);
00566 
00567     if (res < res0) {
00568         res0 = res;
00569         if (x2 > x1) {
00570             *px1 = x1;
00571             *px2 = x2;
00572             irplib_trace(); /* OK */
00573         } else {
00574             *px1 = x2;
00575             *px2 = x1;
00576             irplib_trace(); /* OK */
00577         }
00578     }
00579 
00580     /* Compute residual, assuming D < 0 */
00581 
00582     x1 = -0.5 * p1 / p2;          /* Real part of complex root */
00583     x2 =  0.5 * sqrtD / fabs(p2); /* Positive, imaginary part of root */
00584 
00585     res  = irplib_polynomial_eval_2_max(p2, p1, p0, CPL_TRUE,  x1, x2);
00586 
00587     if (res < res0) {
00588         *px1 = x1;
00589         *px2 = x2;
00590         is_complex = CPL_TRUE;
00591         irplib_trace(); /* OK */
00592     }
00593 
00594     return is_complex;
00595 
00596 }
00597 
00598 
00599 /*----------------------------------------------------------------------------*/
00612 /*----------------------------------------------------------------------------*/
00613 static double irplib_polynomial_eval_2_max(double p2, double p1, double p0,
00614                                            cpl_boolean is_c,
00615                                            double x1, double x2)
00616 {
00617     double res;
00618 
00619     if (is_c) {
00620         res = fabs(p0 + x1 * (p1 + x1 * p2) - p2 * x2 * x2);
00621         irplib_trace(); /* OK */
00622     } else {
00623         const double r1 = fabs(p0 + x1 * (p1 + x1 * p2));
00624         const double r2 = fabs(p0 + x2 * (p1 + x2 * p2));
00625 
00626         res = r1 > r2 ? r1 : r2;
00627         irplib_trace(); /* OK */
00628     }
00629 
00630     return res;
00631 }
00632 
00633 
00634 /*----------------------------------------------------------------------------*/
00649 /*----------------------------------------------------------------------------*/
00650 static double irplib_polynomial_eval_3_max(double p3, double p2,
00651                                            double p1, double p0,
00652                                            cpl_boolean is_c,
00653                                            double x1, double x2, double x3)
00654 {
00655     const double r1 = fabs(p0 + x1 * (p1 + x1 * (p2 + x1 * p3)));
00656     double res;
00657 
00658     if (is_c) {
00659         const double r2 = fabs(p0 + x2 * (p1 + x2 * (p2 + x2 * p3))
00660                                - x3 * x3 * ( 3.0 * p3 * x2 + p2));
00661 
00662         res = r1 > r2 ? r1 : r2;
00663         irplib_trace(); /* OK */
00664     } else {
00665         const double r2 = fabs(p0 + x2 * (p1 + x2 * (p2 + x2 * p3)));
00666         const double r3 = fabs(p0 + x3 * (p1 + x3 * (p2 + x3 * p3)));
00667         res = r1 > r2 ? (r1 > r3 ? r1 : r3) : (r2 > r3 ? r2 : r3);
00668         irplib_trace(); /* OK */
00669     }
00670 
00671     /* cpl_msg_info(cpl_func, "%d: %g (%g)", __LINE__, res, r1); */
00672 
00673     return res;
00674 }
00675 
00676 
00677 /*----------------------------------------------------------------------------*/
00696 /*----------------------------------------------------------------------------*/
00697 static cpl_boolean irplib_polynomial_solve_1d_3(double p3, double p2, double p1,
00698                                                 double p0,
00699                                                 double * px1,
00700                                                 double * px2,
00701                                                 double * px3,
00702                                                 cpl_boolean * pdbl1,
00703                                                 cpl_boolean * pdbl2) {
00704     cpl_boolean is_complex = CPL_FALSE;
00705     const double a = p2/p3;
00706     const double b = p1/p3;
00707     const double c = p0/p3;
00708 
00709     const double q = (a * a - 3.0 * b);
00710     const double r = (a * (2.0 * a * a - 9.0 * b) + 27.0 * c);
00711 
00712     const double Q = q / 9.0;
00713     const double R = r / 54.0;
00714 
00715     const double Q3 = Q * Q * Q;
00716     const double R2 = R * R;
00717 
00718     double x1 = DBL_MAX; /* Fix (false) uninit warning */
00719     double x2 = DBL_MAX; /* Fix (false) uninit warning */
00720     double x3 = DBL_MAX; /* Fix (false) uninit warning */
00721     double xx1 = DBL_MAX; /* Fix (false) uninit warning */
00722     double xx2 = DBL_MAX; /* Fix (false) uninit warning */
00723     double xx3 = DBL_MAX; /* Fix (false) uninit warning */
00724 
00725     double resx = DBL_MAX;
00726     double res  = DBL_MAX;
00727     cpl_boolean is_first = CPL_TRUE;
00728 
00729     cpl_boolean dbl2;
00730 
00731 
00732     assert(px1 != NULL );
00733 
00734     if (pdbl1 != NULL) *pdbl1 = CPL_FALSE;
00735     if (pdbl2 != NULL) *pdbl2 = CPL_FALSE;
00736 
00737     dbl2 = CPL_FALSE;
00738 
00739     /*
00740       All branches (for which the roots are defined) are evaluated, and
00741       the branch with the smallest maximum-residual is chosen.
00742       When two maximum-residual are identical, preference is given to
00743       the purely real solution and if necessary to the solution with a
00744       double root.
00745     */
00746 
00747     if ((R2 >= Q3 && R != 0.0) || R2 > Q3) {
00748 
00749         cpl_boolean is_c = CPL_FALSE;
00750 
00751         irplib_polynomial_solve_1d_3c(a, c, Q, Q3, R, R2, &x1, &x2, &x3,
00752                                       &is_c, &dbl2);
00753 
00754 
00755         res = resx = irplib_polynomial_eval_3_max(p3, p2, p1, p0, is_c,
00756                                             x1, x2, x3);
00757 
00758         is_first = CPL_FALSE;
00759 
00760         if (pdbl1 != NULL) *pdbl1 = CPL_FALSE;
00761         if (!is_c && pdbl2 != NULL) *pdbl2 = dbl2;
00762         is_complex = is_c;
00763         irplib_trace(); /* OK */
00764    
00765     }
00766 
00767     if (Q > 0.0 && fabs(R / (Q * sqrt(Q))) <= 1.0) {
00768 
00769         /* this test is actually R2 < Q3, written in a form suitable
00770            for exact computation with integers */
00771 
00772         /* assert( Q > 0.0 ); */
00773 
00774         irplib_polynomial_solve_1d_3r(a, c, Q, R, &xx1, &xx2, &xx3);
00775 
00776         resx = irplib_polynomial_eval_3_max(p3, p2, p1, p0, CPL_FALSE,
00777                                             xx1, xx2, xx3);
00778 
00779         if (is_first || (dbl2 ? resx < res : resx <= res)) {
00780             is_first = CPL_FALSE;
00781             res = resx;
00782             x1 = xx1;
00783             x2 = xx2;
00784             x3 = xx3;
00785             if (pdbl1 != NULL) *pdbl1 = CPL_FALSE;
00786             if (pdbl2 != NULL) *pdbl2 = CPL_FALSE;
00787             is_complex = CPL_FALSE;
00788             irplib_trace(); /* OK */
00789         }
00790     }
00791 
00792     if (Q >= 0) {
00793         cpl_boolean dbl1 = CPL_FALSE;
00794 
00795 
00796         irplib_polynomial_solve_1d_32(a, c, Q, &xx1, &xx2, &xx3, &dbl2);
00797 
00798         resx = irplib_polynomial_eval_3_max(p3, p2, p1, p0, CPL_FALSE,
00799                                             xx1, xx2, xx3);
00800         /*
00801         cpl_msg_info(cpl_func, "%d: %g = %g - %g (%u)", __LINE__,
00802                      res - resx, res, resx, is_complex);
00803         */
00804 
00805         if (is_first || resx <= res) {
00806             is_first = CPL_FALSE;
00807             res = resx;
00808             x1 = xx1;
00809             x2 = xx2;
00810             x3 = xx3;
00811             if (pdbl1 != NULL) *pdbl1 = CPL_FALSE;
00812             if (pdbl2 != NULL) *pdbl2 = dbl2;
00813             is_complex = CPL_FALSE;
00814             irplib_trace(); /* OK */
00815         }
00816 
00817 
00818         /* This branch also covers the case where the depressed cubic
00819            polynomial has zero as triple root (i.e. Q == R == 0) */
00820 
00821         irplib_polynomial_solve_1d_31(a, Q, &xx1, &xx2, &xx3, &dbl1);
00822 
00823         resx = irplib_polynomial_eval_3_max(p3, p2, p1, p0, CPL_FALSE,
00824                                             xx1, xx2, xx3);
00825 
00826         if (resx <= res) {
00827             is_first = CPL_FALSE;
00828             res = resx;
00829             x1 = xx1;
00830             x2 = xx2;
00831             x3 = xx3;
00832             if (pdbl1 != NULL) *pdbl1 = dbl1;
00833             if (pdbl2 != NULL) *pdbl2 = CPL_FALSE;
00834             is_complex = CPL_FALSE;
00835             irplib_trace(); /* OK */
00836         }
00837 
00838     }
00839 
00840     if (px2 != NULL && px3 != NULL) {
00841         *px1 = x1;
00842         *px2 = x2;
00843         *px3 = x3;
00844         irplib_trace(); /* OK */
00845     } else if (is_complex) {
00846         *px1 = x1;
00847         irplib_trace(); /* OK */
00848     } else {
00849         *px1 = x3;
00850         irplib_trace(); /* OK */
00851     }
00852 
00853     return is_complex;
00854 }
00855 
00856 /*----------------------------------------------------------------------------*/
00870 /*----------------------------------------------------------------------------*/
00871 static void irplib_polynomial_solve_1d_31(double a, double Q,
00872                                           double * px1, double * px2,
00873                                           double * px3, cpl_boolean * pdbl1)
00874 {
00875 
00876     const double sqrtQ = sqrt (Q);
00877 
00878     double x1, x2, x3;
00879 
00880     x2 = x1 = -sqrtQ - a / 3.0;
00881     x3 = 2.0 * sqrtQ - a / 3.0;
00882     if (pdbl1 != NULL) *pdbl1 = CPL_TRUE;
00883 
00884     *px1 = x1;
00885     *px2 = x2;
00886     *px3 = x3;
00887 
00888     irplib_trace(); /* OK */
00889     return;
00890 }
00891 
00892 /*----------------------------------------------------------------------------*/
00907 /*----------------------------------------------------------------------------*/
00908 static void irplib_polynomial_solve_1d_32(double a, double c, double Q,
00909                                           double * px1, double * px2,
00910                                           double * px3, cpl_boolean * pdbl2)
00911 {
00912 
00913     const double sqrtQ = sqrt (Q);
00914 
00915     double x1 = DBL_MAX;
00916     double x2 = DBL_MAX;
00917     double x3 = DBL_MAX;
00918 
00919     if (a > 0.0) {
00920         /* a and sqrt(Q) have same sign - or Q is zero */
00921         x1 = -2.0 * sqrtQ - a / 3.0;
00922         /* FIXME: Two small roots with opposite signs may
00923            end up here, with the sign lost for one of them */
00924         x3 = x2 = -a < x1 ? -sqrt(fabs(c / x1)) : sqrt(fabs(c / x1));
00925         if (pdbl2 != NULL) *pdbl2 = CPL_TRUE;
00926         irplib_trace(); /* OK */
00927     } else if (a < 0.0) {
00928         /* a and sqrt(Q) have opposite signs - or Q is zero */
00929         x3 = x2 = sqrtQ - a / 3.0;
00930         x1 = -c / (x2 * x2);
00931         if (pdbl2 != NULL) *pdbl2 = CPL_TRUE;
00932         irplib_trace(); /* OK */
00933     } else {
00934         x1 = -2.0 * sqrtQ;
00935         x3 = x2 = sqrtQ;
00936         if (pdbl2 != NULL) *pdbl2 = CPL_TRUE;
00937         irplib_trace(); /* OK */
00938     }
00939 
00940     *px1 = x1;
00941     *px2 = x2;
00942     *px3 = x3;
00943 
00944     return;
00945 }
00946 
00947 /*----------------------------------------------------------------------------*/
00967 /*----------------------------------------------------------------------------*/
00968 static void irplib_polynomial_solve_1d_3c(double a, double c,
00969                                           double Q, double Q3,
00970                                           double R, double R2,
00971                                           double * px1,
00972                                           double * px2, double * px3,
00973                                           cpl_boolean * pis_c,
00974                                           cpl_boolean * pdbl2)
00975 {
00976 
00977     /* Due to finite precision some double roots may be missed, and
00978        will be considered to be a pair of complex roots z = x +/-
00979        epsilon i close to the real axis. */
00980 
00981     /* Another case: A double root, which is small relative to the
00982        last root, may cause this branch to be taken - with the
00983        imaginary part eventually being truncated to zero. */
00984 
00985     const double sgnR = (R >= 0 ? 1.0 : -1.0);
00986     const double A = -sgnR * pow (fabs (R) + sqrt (R2 - Q3), 1.0 / 3.0);
00987     const double B = Q / A;
00988 
00989     double x1 = DBL_MAX;
00990     double x2 = DBL_MAX;
00991     double x3 = DBL_MAX;
00992     cpl_boolean is_complex = CPL_FALSE;
00993 
00994     if (( A > -B && a > 0.0) || (A < -B && a < 0.0)) {
00995         /* A+B has same sign as a */
00996 
00997         /* Real part of complex conjugate */
00998         x2 = -0.5 * (A + B) - a / 3.0; /* No cancellation */
00999         /* Positive, imaginary part of complex conjugate */
01000         x3 = 0.5 * CPL_MATH_SQRT3 * fabs(A - B);
01001 
01002         x1 = -c / (x2 * x2 + x3 * x3);
01003         irplib_trace(); /* OK */
01004     } else {
01005         /* A+B and a have opposite signs - or exactly one is zero */
01006         x1 = A + B - a / 3.0;
01007         /* Positive, imaginary part of complex conjugate */
01008         x3 = 0.5 * CPL_MATH_SQRT3 * fabs(A - B);
01009 
01010         if (x3 > 0.0) {
01011             /* Real part of complex conjugate */
01012             x2 = -0.5 * (A + B) - a / 3.0; /* FIXME: Cancellation */
01013             irplib_trace(); /* OK */
01014         } else {
01015 
01016             x2 = -a < x1 ? -sqrt(fabs(c / x1)) : sqrt(fabs(c / x1));
01017             x3 = 0.0;
01018             irplib_trace(); /* OK */
01019         }
01020     }
01021 
01022     if (x3 > 0.0) {
01023         is_complex = CPL_TRUE;
01024         irplib_trace(); /* OK */
01025     } else {
01026         /* Whoaa, the imaginary part was truncated to zero
01027            - return a real, double root */
01028         x3 = x2;
01029         if (pdbl2 != NULL) *pdbl2 = CPL_TRUE;
01030         irplib_trace(); /* OK */
01031     }
01032 
01033     *px1 = x1;
01034     *px2 = x2;
01035     *px3 = x3;
01036     *pis_c = is_complex;
01037 
01038     return;
01039 }
01040 
01041 /*----------------------------------------------------------------------------*/
01056 /*----------------------------------------------------------------------------*/
01057 static void irplib_polynomial_solve_1d_3r(double a, double c,
01058                                           double Q, double R,
01059                                           double * px1,
01060                                           double * px2, double * px3)
01061 {
01062 
01063     const double sqrtQ = sqrt(Q);
01064     const double theta = acos (R / (Q * sqrtQ)); /* theta in range [0; pi] */
01065 
01066     /* -1.0 <= cos((theta + CPL_MATH_2PI) / 3.0) <= -0.5
01067        -0.5 <= cos((theta - CPL_MATH_2PI) / 3.0) <=  0.5
01068         0.5 <= cos((theta                  ) / 3.0) <=  1.0 */
01069 
01070 #define TR1 (-2.0 * sqrtQ * cos( theta                    / 3.0))
01071 #define TR2 (-2.0 * sqrtQ * cos((theta - CPL_MATH_2PI) / 3.0))
01072 #define TR3 (-2.0 * sqrtQ * cos((theta + CPL_MATH_2PI) / 3.0))
01073 
01074     /* TR1 < TR2 < TR3, except when theta == 0, then TR2 == TR3 */
01075 
01076     /* The three roots must be transformed back via subtraction with a/3.
01077        To prevent loss of precision due to cancellation, the root which
01078        is closest to a/3 is computed using the relation
01079        p3 * x1 * x2 * x3 = -p0 */
01080 
01081     double x1 = DBL_MAX;
01082     double x2 = DBL_MAX;
01083     double x3 = DBL_MAX;
01084 
01085     if (a > 0.0) {
01086         x1 = TR1 - a / 3.0;
01087         if (TR2 > 0.0 && (TR2 + TR3) > 2.0 * a) {
01088             /* FIXME: Cancellation may still effect x3 ? */
01089             x3 = TR3 - a / 3.0;
01090             x2 = -c / ( x1 * x3 );
01091             irplib_trace(); /* OK */
01092         } else {
01093             /* FIXME: Cancellation may still effect x2, especially
01094                if x2, x3 is (almost) a double root, i.e.
01095                if theta is close to zero. */
01096             x2 = TR2 - a / 3.0;
01097  
01098             x3 = -c / ( x1 * x2 );
01099             irplib_trace(); /* OK */
01100         }
01101     } else if (a < 0.0) {
01102         x3 = TR3 - a / 3.0;
01103         if (TR2 < 0.0 && (TR1 + TR2) > 2.0 * a) {
01104             x1 = TR1 - a / 3.0;
01105             x2 = -c / ( x1 * x3 );
01106             irplib_trace(); /* OK */
01107         } else {
01108             x2 = TR2 - a / 3.0;
01109             x1 = -c / ( x2 * x3 );
01110             irplib_trace(); /* OK */
01111         }
01112     } else {
01113         x1 = TR1;
01114         x2 = TR2;
01115         x3 = TR3;
01116         irplib_trace(); /* OK */
01117     }
01118 
01119     assert(x1 < x3);
01120 
01121     if (x1 > x2) {
01122         /* In absence of round-off:
01123            theta == PI: x1 == x2,
01124            theta  < PI: x1 <  x2,
01125 
01126            The only way x1 could exceed x2 would be due to round-off when
01127            theta is close to PI */
01128      
01129         x1 = x2 = 0.5 * ( x1 + x2 );
01130         irplib_trace(); /* OK, tested only for x1 == x2 */
01131     } else if (x2 > x3) {
01132         /* In absence of round-off:
01133            theta == 0: x2 == x3,
01134            theta  > 0: x2 <  x3,
01135 
01136            For small theta:
01137            Round-off can cause x2 to become greater than x3 */
01138      
01139         x3 = x2 = 0.5 * ( x2 + x3 );
01140         irplib_trace(); /* OK */
01141     }
01142 
01143     *px1 = x1;
01144     *px2 = x2;
01145     *px3 = x3;
01146 
01147     return;
01148 }
01149 
01150 /*----------------------------------------------------------------------------*/
01168 /*----------------------------------------------------------------------------*/
01169 static cpl_error_code irplib_polynomial_solve_1d_4(double p4, double p3,
01170                                                    double p2, double p1,
01171                                                    double p0, cpl_size * preal,
01172                                                    double * px1, double * px2,
01173                                                    double * px3, double * px4)
01174 {
01175 
01176     /* Construct the monic, depressed quartic using Horners scheme on 1 / p4 */
01177     const double a = (p2 - 0.375 * p3 * p3 / p4) / p4;
01178     const double b = (p1 - 0.5 * (p2 - 0.25 * p3 * p3 / p4 ) * p3 / p4 ) / p4;
01179     const double c =
01180         (p0 - 0.25 * (p1 - 0.25 * (p2 - 0.1875 * p3 * p3 / p4 ) * p3 / p4
01181                       ) * p3 / p4 ) / p4;
01182 
01183     double x1 = DBL_MAX; /* Fix (false) uninit warning */
01184     double x2 = DBL_MAX; /* Fix (false) uninit warning */
01185     double x3 = DBL_MAX; /* Fix (false) uninit warning */
01186     double x4 = DBL_MAX; /* Fix (false) uninit warning */
01187 
01188     assert(preal != NULL );
01189     assert(px1   != NULL );
01190     assert(px2   != NULL );
01191     assert(px3   != NULL );
01192     assert(px4   != NULL );
01193 
01194     *preal = 4;
01195 
01196     if (c == 0.0) {
01197         /* The depressed quartic has zero as root */
01198         /* Since the sum of the roots is zero, at least one is negative
01199            and at least one is positive - unless they are all zero */
01200         cpl_boolean dbl1, dbl2;
01201         const cpl_boolean is_real =
01202             !irplib_polynomial_solve_1d_3(1.0, 0.0, a, b, &x1, &x3, &x4,
01203                                           &dbl1, &dbl2);
01204 
01205         x1 -= 0.25 * p3 / p4;
01206         x2 = -0.25 * p3 / p4;
01207         x3 -= 0.25 * p3 / p4;
01208         if (is_real) {
01209 
01210             if (dbl2) {
01211                 x4 = x3;
01212                 assert( x1 <= x2);
01213                 assert( x2 <= x3);
01214             } else {
01215                 x4 -= 0.25 * p3 / p4;
01216                 /* Need (only) a guarded swap of x2, x3 */
01217                 if (x2 > x3) {
01218                     IRPLIB_SWAP(x2, x3);
01219                 }
01220                 if (dbl1) {
01221                     assert( x1 <= x2); /* The cubic may have 0 as triple root */
01222                     assert( x2 <= x3);
01223                     assert( x2 <= x4);
01224                 } else {
01225                     assert( x1 < x2);
01226                     assert( x2 < x4);
01227                 }
01228             }
01229         } else {
01230             *preal = 2;
01231 
01232             if (x1 > x2) {
01233                 assert( x3 <= x2 ); /* Don't swap a complex root */
01234 
01235                 IRPLIB_SWAP(x1, x2);
01236             } else {
01237                 assert( x3 >= x2 );
01238             }
01239         }
01240 
01241     } else if (b == 0.0) {
01242         /* The monic, depressed quartic is a monic, biquadratic equation */
01243         double u1, u2;
01244         const cpl_boolean is_complex = irplib_polynomial_solve_1d_2(1.0, a, c,
01245                                                                     &u1, &u2);
01246 
01247         if (is_complex) {
01248             /* All four roots are conjugate, complex */
01249             const double norm = sqrt(u1*u1 + u2*u2);
01250             const double   v1 = sqrt(0.5*(norm+u1));
01251             const double   v2 = u2 / sqrt(2.0*(norm+u1));
01252 
01253 
01254             x1 = -0.25 * p3 / p4 - v1;
01255             x3 = -0.25 * p3 / p4 + v1;
01256 
01257             x4 = x2 = v2;
01258 
01259             *preal = 0;
01260 
01261         } else if (u1 >= 0.0) {
01262             /* All four roots are real */
01263             const double sv1 = sqrt(u1);
01264             const double sv2 = sqrt(u2);
01265 
01266 
01267             *preal = 4;
01268 
01269             x1 = -0.25 * p3 / p4 - sv2;
01270             x2 = -0.25 * p3 / p4 - sv1;
01271             x3 = -0.25 * p3 / p4 + sv1;
01272             x4 = -0.25 * p3 / p4 + sv2;
01273         } else if (u2 < 0.0) {
01274             /* All four roots are conjugate, complex */
01275             const double sv1 = sqrt(-u2);
01276             const double sv2 = sqrt(-u1);
01277 
01278 
01279             *preal = 0;
01280 
01281             x1 = x3 = -0.25 * p3 / p4;
01282 
01283             x2 = sv1;
01284             x4 = sv2;
01285         } else {
01286             /* Two roots are real, two roots are conjugate, complex */
01287             const double sv1 = sqrt(-u1);
01288             const double sv2 = sqrt(u2);
01289 
01290 
01291             *preal = 2;
01292 
01293             x1 = -0.25 * p3 / p4 - sv2;
01294             x2 = -0.25 * p3 / p4 + sv2;
01295 
01296             x3 = -0.25 * p3 / p4;
01297             x4 = sv1;
01298         }
01299     } else {
01300         /* Need a root from the nested, monic cubic */
01301         const double q2 = -a;
01302         const double q1 = -4.0 * c;
01303         const double q0 = 4.0 * a * c - b * b;
01304         double u1, sqrtd, sqrtrd;
01305         double z1, z2, z3, z4;
01306 
01307         cpl_boolean is_complex1, is_complex2;
01308 
01309         /* Largest cubic root ensures real square roots when solving the
01310            quartic equation */
01311         (void)irplib_polynomial_solve_1d_3(1.0, q2, q1, q0, &u1, NULL, NULL,
01312                                            NULL, NULL);
01313 
01314 
01315         assert( u1 > a );
01316 
01317         sqrtd = sqrt(u1 - a);
01318 
01319         sqrtrd = 0.5 * b/sqrtd;
01320 
01321         is_complex1 = irplib_polynomial_solve_1d_2(1.0,  sqrtd, 0.5*u1 - sqrtrd,
01322                                                    &z1, &z2);
01323 
01324         is_complex2 = irplib_polynomial_solve_1d_2(1.0, -sqrtd, 0.5*u1 + sqrtrd,
01325                                                    &z3, &z4);
01326 
01327         z1 -= 0.25 * p3 / p4;
01328         z3 -= 0.25 * p3 / p4;
01329         if (!is_complex1) z2 -= 0.25 * p3 / p4;
01330         if (!is_complex2) z4 -= 0.25 * p3 / p4;
01331 
01332         if (!is_complex1 && is_complex2) {
01333             *preal = 2;
01334             x1 = z1;
01335             x2 = z2;
01336             x3 = z3;
01337             x4 = z4;
01338         } else if (is_complex1 && !is_complex2) {
01339             *preal = 2;
01340             x1 = z3;
01341             x2 = z4;
01342             x3 = z1;
01343             x4 = z2;
01344         } else if (is_complex1 && is_complex2) {
01345             *preal = 0;
01346 
01347             if (z1 < z3 || (z1 == z3 && z2 <= z4)) {
01348                 x1 = z1;
01349                 x2 = z2;
01350                 x3 = z3;
01351                 x4 = z4;
01352             } else {
01353                 x1 = z3;
01354                 x2 = z4;
01355                 x3 = z1;
01356                 x4 = z2;
01357             }
01358         } else {
01359             *preal = 4;
01360 
01361             if (z3 >= z2) {
01362                 x1 = z1;
01363                 x2 = z2;
01364                 x3 = z3;
01365                 x4 = z4;
01366             } else if (z4 <= z1) {
01367                 x1 = z3;
01368                 x2 = z4;
01369                 x3 = z1;
01370                 x4 = z2;
01371             } else if (z2 > z4) {
01372                 x1 = z3;
01373                 x2 = z1;
01374                 x3 = z4;
01375                 x4 = z2;
01376             } else {
01377                 x1 = z1;
01378                 x2 = z3;
01379                 x3 = z2;
01380                 x4 = z4;
01381             }
01382         }
01383     }
01384 
01385     *px1 = x1;
01386     *px2 = x2;
01387     *px3 = x3;
01388     *px4 = x4;
01389 
01390     return CPL_ERROR_NONE;
01391 }
01392 
01393 #ifdef IPRLIB_POLYNOMIAL_USE_MONOMIAL_ROOT
01394 /*----------------------------------------------------------------------------*/
01402 /*----------------------------------------------------------------------------*/
01403 static double irplib_polynomial_depress_1d(cpl_polynomial * self)
01404 {
01405 
01406     const cpl_size degree = cpl_polynomial_get_degree(self);
01407     const cpl_size nc1    = degree - 1;
01408     const double   an     = cpl_polynomial_get_coeff(self, &degree);
01409     const double   an1    = cpl_polynomial_get_coeff(self, &nc1);
01410     double         rmean;
01411     cpl_size       i;
01412 
01413 
01414     cpl_ensure(degree > 0,   CPL_ERROR_DATA_NOT_FOUND, 0.0);
01415 
01416     assert( an != 0.0 );
01417 
01418     rmean = -an1/(an * (double)degree);
01419 
01420     if (rmean != 0.0) {
01421 
01422         cpl_polynomial_shift_1d(self, 0, rmean);
01423 
01424         cpl_polynomial_set_coeff(self, &nc1, 0.0); /* Round-off... */
01425 
01426     }
01427 
01428     /* Set leading coefficient to one. */
01429     for (i = 0; i < degree-1; i++) {
01430         const double ai = cpl_polynomial_get_coeff(self, &i) / an;
01431         cpl_polynomial_set_coeff(self, &i, ai);
01432     }
01433 
01434     cpl_polynomial_set_coeff(self, &degree, 1.0); /* Round-off... */
01435 
01436     return rmean;
01437 }
01438 #endif
01439 
01440 /*----------------------------------------------------------------------------*/
01455 /*----------------------------------------------------------------------------*/
01456 static
01457 cpl_error_code irplib_polynomial_divide_1d_root(cpl_polynomial * p, double r,
01458                                                 double * pres)
01459 {
01460 
01461     const cpl_size n = cpl_polynomial_get_degree(p);
01462     double         sum;
01463     cpl_size       i;
01464 
01465 
01466     cpl_ensure_code(p != NULL, CPL_ERROR_NULL_INPUT);
01467     cpl_ensure_code(cpl_polynomial_get_dimension(p) == 1,
01468                     CPL_ERROR_INVALID_TYPE);
01469     cpl_ensure_code(n > 0, CPL_ERROR_DATA_NOT_FOUND);
01470 
01471     sum = cpl_polynomial_get_coeff(p, &n);
01472     cpl_polynomial_set_coeff(p, &n, 0.0);
01473 
01474     for (i = n-1; i >= 0; i--) {
01475         const double coeff = cpl_polynomial_get_coeff(p, &i);
01476 
01477         cpl_polynomial_set_coeff(p, &i, sum);
01478 
01479         sum = coeff + r * sum;
01480 
01481     }
01482 
01483     if (pres != NULL) *pres = sum;
01484 
01485     return CPL_ERROR_NONE;
01486 }

Generated on 3 Mar 2013 for SINFONI Pipeline Reference Manual by  doxygen 1.6.1