irplib_polynomial.c

00001 /* $Id: irplib_polynomial.c,v 1.29 2009/02/18 08:27:07 llundin 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  */
00020 
00021 /*
00022  * $Author: llundin $
00023  * $Date: 2009/02/18 08:27:07 $
00024  * $Revision: 1.29 $
00025  * $Name: visir-3_2_2 $
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, int *,
00097                                                    double *, double *,
00098                                                    double *, double *);
00099 
00100 static cpl_error_code irplib_polynomial_solve_1d_nonzero(cpl_polynomial *,
00101                                                          cpl_vector *,
00102                                                          int *);
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 
00116 /*----------------------------------------------------------------------------*/
00132 /*----------------------------------------------------------------------------*/
00133 cpl_error_code irplib_polynomial_shift_1d(cpl_polynomial * p, int i, double u)
00134 {
00135 
00136 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE > CPL_VERSION(4, 5, 0)
00137     cpl_ensure_code(!cpl_polynomial_shift_1d(p, i, u), cpl_error_get_code());
00138 #else
00139     const int ndim = cpl_polynomial_get_dimension(p);
00140 
00141     cpl_ensure_code(p != NULL, CPL_ERROR_NULL_INPUT);
00142     cpl_ensure_code(i >= 0,    CPL_ERROR_ILLEGAL_INPUT);
00143     cpl_ensure_code(i < ndim,  CPL_ERROR_ACCESS_OUT_OF_RANGE);
00144 
00145     if (ndim == 1) {
00146         /* Should not be able to fail now */
00147         cpl_ensure_code(!cpl_polynomial_shift_1d(p, u), cpl_error_get_code());
00148     } else if (ndim == 2) {
00149         const int        ndeg = cpl_polynomial_get_degree(p);
00150         cpl_polynomial * p1d  = cpl_polynomial_new(1);
00151         int              powers[2];
00152         int            * pi2  = powers + 1 - i; /* Other power */
00153 
00154         cpl_ensure_code(p1d != NULL, CPL_ERROR_NULL_INPUT);
00155         /* Should not be able to fail now */
00156 
00157         for (*pi2 = ndeg; *pi2 >=0; (*pi2)--) {
00158             int * pshift = powers + i;
00159 
00160             /* Copy to a 1D all coefficients with this power*/
00161             /* - *pi2 decreases so all coeffs in p1d are overwritten */
00162             /* - *pshift decreases to avoid realloc() in _set_coeff() */
00163             for (*pshift = ndeg - *pi2; *pshift >= 0; (*pshift)--) {
00164                 /* cx_assert(powers[i] == *pshift); */
00165                 cpl_polynomial_set_coeff(p1d, pshift,
00166                                          cpl_polynomial_get_coeff(p, powers));
00167             }
00168 
00169             cpl_polynomial_shift_1d(p1d, u);
00170 
00171             /* Copy back, overwriting any old coeffs */
00172             for (*pshift = ndeg - *pi2; *pshift >= 0; (*pshift)--) {
00173                 /* cx_assert(powers[i] == *pshift); */
00174                 cpl_polynomial_set_coeff(p, powers,
00175                                          cpl_polynomial_get_coeff(p1d, pshift));
00176             }
00177         }
00178 
00179         cpl_polynomial_delete(p1d);
00180     } else {
00181         cpl_ensure_code(0, CPL_ERROR_UNSUPPORTED_MODE);
00182     }
00183 
00184 #endif
00185     return CPL_ERROR_NONE;
00186 }
00187 
00188 /*----------------------------------------------------------------------------*/
00203 /*----------------------------------------------------------------------------*/
00204 cpl_error_code irplib_polynomial_add(cpl_polynomial * self,
00205                                      const cpl_polynomial * first,
00206                                      const cpl_polynomial * second)
00207 {
00208     int       degree0 = cpl_polynomial_get_degree(self);
00209     const int degree1 = cpl_polynomial_get_degree(first);
00210     const int degree2 = cpl_polynomial_get_degree(second);
00211     const int maxdeg  = degree1 > degree2 ? degree1 : degree2;
00212 
00213 
00214     cpl_ensure_code(self   != NULL, CPL_ERROR_NULL_INPUT);
00215     cpl_ensure_code(first  != NULL, CPL_ERROR_NULL_INPUT);
00216     cpl_ensure_code(second != NULL, CPL_ERROR_NULL_INPUT);
00217 
00218     cpl_ensure_code(cpl_polynomial_get_dimension(self) ==
00219                     cpl_polynomial_get_dimension(first),
00220                     CPL_ERROR_INCOMPATIBLE_INPUT);
00221     cpl_ensure_code(cpl_polynomial_get_dimension(self) ==
00222                     cpl_polynomial_get_dimension(second),
00223                     CPL_ERROR_INCOMPATIBLE_INPUT);
00224 
00225     /* FIXME: */
00226     cpl_ensure_code(cpl_polynomial_get_dimension(self) == 1,
00227                     CPL_ERROR_UNSUPPORTED_MODE);
00228 
00229     if (degree0 < maxdeg) {
00230         degree0 = maxdeg;
00231     } else {
00232         /* Reset coefficients in self as needed */
00233         for (; degree0 > maxdeg; degree0--) {
00234             cpl_polynomial_set_coeff(self, &degree0, 0.0);
00235         }
00236     }
00237 
00238     /* assert( degree0 == maxdeg ); */
00239 
00240     for (; degree0 >= 0; degree0--) {
00241         const double val1 = cpl_polynomial_get_coeff(first, &degree0);
00242         const double val2 = cpl_polynomial_get_coeff(second, &degree0);
00243         cpl_polynomial_set_coeff(self, &degree0, val1 + val2);
00244     }
00245 
00246     return CPL_ERROR_NONE;
00247 }
00248 
00249 /*----------------------------------------------------------------------------*/
00264 /*----------------------------------------------------------------------------*/
00265 cpl_error_code irplib_polynomial_subtract(cpl_polynomial * self,
00266                                           const cpl_polynomial * first,
00267                                           const cpl_polynomial * second)
00268 {
00269     int       degree0 = cpl_polynomial_get_degree(self);
00270     const int degree1 = cpl_polynomial_get_degree(first);
00271     const int degree2 = cpl_polynomial_get_degree(second);
00272     const int maxdeg  = degree1 > degree2 ? degree1 : degree2;
00273 
00274 
00275     cpl_ensure_code(self   != NULL, CPL_ERROR_NULL_INPUT);
00276     cpl_ensure_code(first  != NULL, CPL_ERROR_NULL_INPUT);
00277     cpl_ensure_code(second != NULL, CPL_ERROR_NULL_INPUT);
00278 
00279     cpl_ensure_code(cpl_polynomial_get_dimension(self) ==
00280                     cpl_polynomial_get_dimension(first),
00281                     CPL_ERROR_INCOMPATIBLE_INPUT);
00282     cpl_ensure_code(cpl_polynomial_get_dimension(self) ==
00283                     cpl_polynomial_get_dimension(second),
00284                     CPL_ERROR_INCOMPATIBLE_INPUT);
00285 
00286     /* FIXME: */
00287     cpl_ensure_code(cpl_polynomial_get_dimension(self) == 1,
00288                     CPL_ERROR_UNSUPPORTED_MODE);
00289 
00290     if (degree0 < maxdeg) {
00291         degree0 = maxdeg;
00292     } else {
00293         /* Reset coefficients in self as needed */
00294         for (; degree0 > maxdeg; degree0--) {
00295             cpl_polynomial_set_coeff(self, &degree0, 0.0);
00296         }
00297     }
00298 
00299     /* assert( degree0 == maxdeg ); */
00300 
00301     for (; degree0 >= 0; degree0--) {
00302         const double val1 = cpl_polynomial_get_coeff(first, &degree0);
00303         const double val2 = cpl_polynomial_get_coeff(second, &degree0);
00304         cpl_polynomial_set_coeff(self, &degree0, val1 - val2);
00305     }
00306 
00307     return CPL_ERROR_NONE;
00308 }
00309 
00310 /*----------------------------------------------------------------------------*/
00321 /*----------------------------------------------------------------------------*/
00322 cpl_error_code irplib_polynomial_multiply_scalar(cpl_polynomial * self,
00323                                                  double factor)
00324 {
00325 
00326     int degree0;
00327 
00328     cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
00329 
00330     cpl_ensure_code(cpl_polynomial_get_dimension(self) == 1,
00331                     CPL_ERROR_UNSUPPORTED_MODE);
00332 
00333     degree0 = cpl_polynomial_get_degree(self);
00334 
00335     for (; degree0 >=0; degree0--) {
00336         const double val = cpl_polynomial_get_coeff(self, &degree0);
00337         cpl_polynomial_set_coeff(self, &degree0, factor * val);
00338     }
00339 
00340     return CPL_ERROR_NONE;
00341 }
00342 
00343 /*----------------------------------------------------------------------------*/
00369 /*----------------------------------------------------------------------------*/
00370 cpl_error_code irplib_polynomial_solve_1d_all(const cpl_polynomial * self,
00371                                               cpl_vector * roots, int * preal)
00372 {
00373 
00374     cpl_error_code error = CPL_ERROR_NONE;
00375     cpl_polynomial * p;
00376 
00377     cpl_ensure_code(self  != NULL, CPL_ERROR_NULL_INPUT);
00378     cpl_ensure_code(roots != NULL, CPL_ERROR_NULL_INPUT);
00379     cpl_ensure_code(preal != NULL, CPL_ERROR_NULL_INPUT);
00380     cpl_ensure_code(cpl_polynomial_get_dimension(self) == 1,
00381                     CPL_ERROR_INVALID_TYPE);
00382     cpl_ensure_code(cpl_polynomial_get_degree(self) > 0,
00383                     CPL_ERROR_DATA_NOT_FOUND);
00384     cpl_ensure_code(cpl_polynomial_get_degree(self) ==
00385                     cpl_vector_get_size(roots), CPL_ERROR_INCOMPATIBLE_INPUT);
00386 
00387     *preal = 0;
00388 
00389     p = cpl_polynomial_duplicate(self);
00390 
00391     error = irplib_polynomial_solve_1d_nonzero(p, roots, preal);
00392 
00393     cpl_polynomial_delete(p);
00394 
00395     return error;
00396 
00397 }
00398 
00401 /*----------------------------------------------------------------------------*/
00427 /*----------------------------------------------------------------------------*/
00428 static cpl_error_code irplib_polynomial_solve_1d_nonzero(cpl_polynomial * self,
00429                                                          cpl_vector * roots,
00430                                                          int * preal)
00431 {
00432     cpl_error_code error = CPL_ERROR_NONE;
00433     const int ncoeffs = 1 + cpl_polynomial_get_degree(self);
00434 
00435     cpl_ensure_code(self  != NULL,  CPL_ERROR_NULL_INPUT);
00436     cpl_ensure_code(roots != NULL,  CPL_ERROR_NULL_INPUT);
00437     cpl_ensure_code(preal != NULL,  CPL_ERROR_NULL_INPUT);
00438     cpl_ensure_code(cpl_polynomial_get_dimension(self) == 1,
00439                     CPL_ERROR_INVALID_TYPE);
00440     cpl_ensure_code(ncoeffs   > 1,  CPL_ERROR_DATA_NOT_FOUND);
00441     cpl_ensure_code(*preal >= 0,    CPL_ERROR_ILLEGAL_INPUT);
00442     cpl_ensure_code(ncoeffs + *preal == 1+cpl_vector_get_size(roots),
00443                     CPL_ERROR_INCOMPATIBLE_INPUT);
00444 
00445     switch (ncoeffs) {
00446 
00447     case 2 : {
00448         const int i1 = 1;
00449         const double p1 = cpl_polynomial_get_coeff(self, &i1);
00450         const int i0 = 0;
00451         const double p0 = cpl_polynomial_get_coeff(self, &i0);
00452 
00453         cpl_vector_set(roots, (*preal)++, -p0/p1);
00454         break;
00455     }
00456     case 3 : {
00457         const int i2 = 2;
00458         const int i1 = 1;
00459         const int i0 = 0;
00460         const double p2 = cpl_polynomial_get_coeff(self, &i2);
00461         const double p1 = cpl_polynomial_get_coeff(self, &i1);
00462         const double p0 = cpl_polynomial_get_coeff(self, &i0);
00463         double x1, x2;
00464 
00465         if (irplib_polynomial_solve_1d_2(p2, p1, p0, &x1, &x2)) {
00466             /* This is the complex root in the upper imaginary half-plane */
00467             cpl_vector_set(roots, (*preal)  , x1);
00468             cpl_vector_set(roots, (*preal)+1, x2);
00469         } else {
00470             cpl_vector_set(roots, (*preal)++, x1);
00471             cpl_vector_set(roots, (*preal)++, x2);
00472         }
00473         break;
00474     }
00475     case 4 : {
00476         const int i3 = 3;
00477         const int i2 = 2;
00478         const int i1 = 1;
00479         const int i0 = 0;
00480         const double p3 = cpl_polynomial_get_coeff(self, &i3);
00481         const double p2 = cpl_polynomial_get_coeff(self, &i2);
00482         const double p1 = cpl_polynomial_get_coeff(self, &i1);
00483         const double p0 = cpl_polynomial_get_coeff(self, &i0);
00484         double x1, x2, x3;
00485 
00486         if (irplib_polynomial_solve_1d_3(p3, p2, p1, p0, &x1, &x2, &x3,
00487                                          NULL, NULL)) {
00488             cpl_vector_set(roots, (*preal)++, x1);
00489             /* This is the complex root in the upper imaginary half-plane */
00490             cpl_vector_set(roots, (*preal)  , x2);
00491             cpl_vector_set(roots, (*preal)+1, x3);
00492         } else {
00493             cpl_vector_set(roots, (*preal)++, x1);
00494             cpl_vector_set(roots, (*preal)++, x2);
00495             cpl_vector_set(roots, (*preal)++, x3);
00496         }
00497         break;
00498     }
00499     case 5 : {
00500         const int i4 = 4;
00501         const int i3 = 3;
00502         const int i2 = 2;
00503         const int i1 = 1;
00504         const int i0 = 0;
00505         const double p4 = cpl_polynomial_get_coeff(self, &i4);
00506         const double p3 = cpl_polynomial_get_coeff(self, &i3);
00507         const double p2 = cpl_polynomial_get_coeff(self, &i2);
00508         const double p1 = cpl_polynomial_get_coeff(self, &i1);
00509         const double p0 = cpl_polynomial_get_coeff(self, &i0);
00510         double x1, x2, x3, x4;
00511         int nreal;
00512 
00513         error = irplib_polynomial_solve_1d_4(p4, p3, p2, p1, p0, &nreal,
00514                                              &x1, &x2, &x3, &x4);
00515         if (!error) {
00516             cpl_vector_set(roots, (*preal)  , x1);
00517             cpl_vector_set(roots, (*preal)+1, x2);
00518             cpl_vector_set(roots, (*preal)+2, x3);
00519             cpl_vector_set(roots, (*preal)+3, x4);
00520 
00521             *preal += nreal;
00522         }
00523         break;
00524     }
00525 
00526     default: {
00527 
00528         /* Try to reduce the problem by finding a single root */
00529 #ifndef IPRLIB_POLYNOMIAL_USE_MONOMIAL_ROOT
00530         const int    n0 = ncoeffs-1;
00531         const double pn0 = cpl_polynomial_get_coeff(self, &n0);
00532         const int    n1 = ncoeffs-2;
00533         const double pn1 = cpl_polynomial_get_coeff(self, &n1);
00534         /* First guess of root is the root average.
00535            FIXME: May need refinement, e.g. via bisection */
00536         const double rmean = -pn1 / (pn0 * n0);
00537         double root = rmean;
00538 #else
00539         /* Try an analytical solution to a (shifted) monomial */
00540         cpl_polynomial * copy = cpl_polynomial_duplicate(self);
00541         const int    i0 = 0;
00542         const double rmean = irplib_polynomial_depress_1d(copy);
00543         const double c0 = cpl_polynomial_get_coeff(copy, &i0);
00544         double root = rmean + ((n0&1) && c0 < 0.0 ? -1.0 : 1.0)
00545             * pow(fabs(c0), 1.0/n0);
00546 
00547         cpl_polynomial_delete(copy);
00548 #endif
00549 
00550         error = cpl_polynomial_solve_1d(self, root, &root, 1);
00551 
00552         if (!error) {
00553 
00554             cpl_vector_set(roots, (*preal)++, root);
00555 
00556             irplib_polynomial_divide_1d_root(self, root, NULL);
00557 
00558             error = irplib_polynomial_solve_1d_nonzero(self, roots, preal);
00559 
00560             if (!error && *preal > 1) {
00561                 /* Sort the real roots */
00562 
00563                 /* FIXME: Assumes that all roots found so far are real */
00564 
00565                 cpl_vector * reals = cpl_vector_wrap(*preal,
00566                                                      cpl_vector_get_data(roots));
00567                 cpl_vector_sort(reals, 1);
00568                 (void)cpl_vector_unwrap(reals);
00569             }
00570         }
00571         break;
00572     }
00573     }
00574 
00575     return error;
00576 }
00577 
00578 /*----------------------------------------------------------------------------*/
00590 /*----------------------------------------------------------------------------*/
00591 static cpl_boolean irplib_polynomial_solve_1d_2(double p2, double p1, double p0,
00592                                                 double * px1,
00593                                                 double * px2) {
00594 
00595     const double sqrtD = sqrt(fabs(p1 * p1 - 4.0 * p2 * p0));
00596     cpl_boolean is_complex = CPL_FALSE;
00597     double x1 = -0.5 * p1 / p2; /* Double root */
00598     double x2;
00599 
00600     /* Compute residual, assuming D == 0 */
00601     double res0 = irplib_polynomial_eval_2_max(p2, p1, p0, CPL_FALSE, x1, x1);
00602     double res;
00603 
00604     assert(px1 != NULL );
00605     assert(px2 != NULL );
00606 
00607     *px2 = *px1 = x1;
00608 
00609     /* Compute residual, assuming D > 0 */
00610 
00611     /* x1 is the root with largest absolute value */
00612     if (p1 > 0.0) {
00613         x1 = -0.5 * (p1 + sqrtD);
00614         irplib_trace(); /* OK */
00615     } else {
00616         x1 = -0.5 * (p1 - sqrtD);
00617         irplib_trace(); /* OK */
00618     }
00619     /* Compute smaller root via division to avoid
00620        loss of precision due to cancellation */
00621     x2 = p0 / x1;
00622     x1 /= p2; /* Scale x1 with leading coefficient */
00623 
00624     res = irplib_polynomial_eval_2_max(p2, p1, p0, CPL_FALSE, x1, x2);
00625 
00626     if (res < res0) {
00627         res0 = res;
00628         if (x2 > x1) {
00629             *px1 = x1;
00630             *px2 = x2;
00631             irplib_trace(); /* OK */
00632         } else {
00633             *px1 = x2;
00634             *px2 = x1;
00635             irplib_trace(); /* OK */
00636         }
00637     }
00638 
00639     /* Compute residual, assuming D < 0 */
00640 
00641     x1 = -0.5 * p1 / p2;          /* Real part of complex root */
00642     x2 =  0.5 * sqrtD / fabs(p2); /* Positive, imaginary part of root */
00643 
00644     res  = irplib_polynomial_eval_2_max(p2, p1, p0, CPL_TRUE,  x1, x2);
00645 
00646     if (res < res0) {
00647         *px1 = x1;
00648         *px2 = x2;
00649         is_complex = CPL_TRUE;
00650         irplib_trace(); /* OK */
00651     }
00652 
00653     return is_complex;
00654 
00655 }
00656 
00657 
00658 /*----------------------------------------------------------------------------*/
00671 /*----------------------------------------------------------------------------*/
00672 static double irplib_polynomial_eval_2_max(double p2, double p1, double p0,
00673                                            cpl_boolean is_c,
00674                                            double x1, double x2)
00675 {
00676     double res;
00677 
00678     if (is_c) {
00679         res = fabs(p0 + x1 * (p1 + x1 * p2) - p2 * x2 * x2);
00680         irplib_trace(); /* OK */
00681     } else {
00682         const double r1 = fabs(p0 + x1 * (p1 + x1 * p2));
00683         const double r2 = fabs(p0 + x2 * (p1 + x2 * p2));
00684 
00685         res = r1 > r2 ? r1 : r2;
00686         irplib_trace(); /* OK */
00687     }
00688 
00689     return res;
00690 }
00691 
00692 
00693 /*----------------------------------------------------------------------------*/
00708 /*----------------------------------------------------------------------------*/
00709 static double irplib_polynomial_eval_3_max(double p3, double p2,
00710                                            double p1, double p0,
00711                                            cpl_boolean is_c,
00712                                            double x1, double x2, double x3)
00713 {
00714     const double r1 = fabs(p0 + x1 * (p1 + x1 * (p2 + x1 * p3)));
00715     double res;
00716 
00717     if (is_c) {
00718         const double r2 = fabs(p0 + x2 * (p1 + x2 * (p2 + x2 * p3))
00719                                - x3 * x3 * ( 3.0 * p3 * x2 + p2));
00720 
00721         res = r1 > r2 ? r1 : r2;
00722         irplib_trace(); /* OK */
00723     } else {
00724         const double r2 = fabs(p0 + x2 * (p1 + x2 * (p2 + x2 * p3)));
00725         const double r3 = fabs(p0 + x3 * (p1 + x3 * (p2 + x3 * p3)));
00726         res = r1 > r2 ? (r1 > r3 ? r1 : r3) : (r2 > r3 ? r2 : r3);
00727         irplib_trace(); /* OK */
00728     }
00729 
00730     /* cpl_msg_info(cpl_func, "%d: %g (%g)", __LINE__, res, r1); */
00731 
00732     return res;
00733 }
00734 
00735 
00736 /*----------------------------------------------------------------------------*/
00755 /*----------------------------------------------------------------------------*/
00756 static cpl_boolean irplib_polynomial_solve_1d_3(double p3, double p2, double p1,
00757                                                 double p0,
00758                                                 double * px1,
00759                                                 double * px2,
00760                                                 double * px3,
00761                                                 cpl_boolean * pdbl1,
00762                                                 cpl_boolean * pdbl2) {
00763     cpl_boolean is_complex = CPL_FALSE;
00764     const double a = p2/p3;
00765     const double b = p1/p3;
00766     const double c = p0/p3;
00767 
00768     const double q = (a * a - 3.0 * b);
00769     const double r = (a * (2.0 * a * a - 9.0 * b) + 27.0 * c);
00770 
00771     const double Q = q / 9.0;
00772     const double R = r / 54.0;
00773 
00774     const double Q3 = Q * Q * Q;
00775     const double R2 = R * R;
00776 
00777     double x1 = DBL_MAX; /* Fix (false) uninit warning */
00778     double x2 = DBL_MAX; /* Fix (false) uninit warning */
00779     double x3 = DBL_MAX; /* Fix (false) uninit warning */
00780     double xx1 = DBL_MAX; /* Fix (false) uninit warning */
00781     double xx2 = DBL_MAX; /* Fix (false) uninit warning */
00782     double xx3 = DBL_MAX; /* Fix (false) uninit warning */
00783 
00784     double resx = DBL_MAX;
00785     double res  = DBL_MAX;
00786     cpl_boolean is_first = CPL_TRUE;
00787 
00788     cpl_boolean dbl2;
00789 
00790 
00791     assert(px1 != NULL );
00792 
00793     if (pdbl1 != NULL) *pdbl1 = CPL_FALSE;
00794     if (pdbl2 != NULL) *pdbl2 = CPL_FALSE;
00795 
00796     dbl2 = CPL_FALSE;
00797 
00798     /*
00799       All branches (for which the roots are defined) are evaluated, and
00800       the branch with the smallest maximum-residual is chosen.
00801       When two maximum-residual are identical, preference is given to
00802       the purely real solution and if necessary to the solution with a
00803       double root.
00804     */
00805 
00806     if ((R2 >= Q3 && R != 0.0) || R2 > Q3) {
00807 
00808         cpl_boolean is_c = CPL_FALSE;
00809 
00810         irplib_polynomial_solve_1d_3c(a, c, Q, Q3, R, R2, &x1, &x2, &x3,
00811                                       &is_c, &dbl2);
00812 
00813 
00814         res = resx = irplib_polynomial_eval_3_max(p3, p2, p1, p0, is_c,
00815                                             x1, x2, x3);
00816 
00817         is_first = CPL_FALSE;
00818 
00819         if (pdbl1 != NULL) *pdbl1 = CPL_FALSE;
00820         if (!is_c && pdbl2 != NULL) *pdbl2 = dbl2;
00821         is_complex = is_c;
00822         irplib_trace(); /* OK */
00823    
00824     }
00825 
00826     if (Q > 0.0 && fabs(R / (Q * sqrt(Q))) <= 1.0) {
00827 
00828         /* this test is actually R2 < Q3, written in a form suitable
00829            for exact computation with integers */
00830 
00831         /* assert( Q > 0.0 ); */
00832 
00833         irplib_polynomial_solve_1d_3r(a, c, Q, R, &xx1, &xx2, &xx3);
00834 
00835         resx = irplib_polynomial_eval_3_max(p3, p2, p1, p0, CPL_FALSE,
00836                                             xx1, xx2, xx3);
00837 
00838         if (is_first || (dbl2 ? resx < res : resx <= res)) {
00839             is_first = CPL_FALSE;
00840             res = resx;
00841             x1 = xx1;
00842             x2 = xx2;
00843             x3 = xx3;
00844             if (pdbl1 != NULL) *pdbl1 = CPL_FALSE;
00845             if (pdbl2 != NULL) *pdbl2 = CPL_FALSE;
00846             is_complex = CPL_FALSE;
00847             irplib_trace(); /* OK */
00848         }
00849     }
00850 
00851     if (Q >= 0) {
00852         cpl_boolean dbl1 = CPL_FALSE;
00853 
00854 
00855         irplib_polynomial_solve_1d_32(a, c, Q, &xx1, &xx2, &xx3, &dbl2);
00856 
00857         resx = irplib_polynomial_eval_3_max(p3, p2, p1, p0, CPL_FALSE,
00858                                             xx1, xx2, xx3);
00859         /*
00860         cpl_msg_info(cpl_func, "%d: %g = %g - %g (%u)", __LINE__,
00861                      res - resx, res, resx, is_complex);
00862         */
00863 
00864         if (is_first || resx <= res) {
00865             is_first = CPL_FALSE;
00866             res = resx;
00867             x1 = xx1;
00868             x2 = xx2;
00869             x3 = xx3;
00870             if (pdbl1 != NULL) *pdbl1 = CPL_FALSE;
00871             if (pdbl2 != NULL) *pdbl2 = dbl2;
00872             is_complex = CPL_FALSE;
00873             irplib_trace(); /* OK */
00874         }
00875 
00876 
00877         /* This branch also covers the case where the depressed cubic
00878            polynomial has zero as triple root (i.e. Q == R == 0) */
00879 
00880         irplib_polynomial_solve_1d_31(a, Q, &xx1, &xx2, &xx3, &dbl1);
00881 
00882         resx = irplib_polynomial_eval_3_max(p3, p2, p1, p0, CPL_FALSE,
00883                                             xx1, xx2, xx3);
00884 
00885         if (resx <= res) {
00886             is_first = CPL_FALSE;
00887             res = resx;
00888             x1 = xx1;
00889             x2 = xx2;
00890             x3 = xx3;
00891             if (pdbl1 != NULL) *pdbl1 = dbl1;
00892             if (pdbl2 != NULL) *pdbl2 = CPL_FALSE;
00893             is_complex = CPL_FALSE;
00894             irplib_trace(); /* OK */
00895         }
00896 
00897     }
00898 
00899     if (px2 != NULL && px3 != NULL) {
00900         *px1 = x1;
00901         *px2 = x2;
00902         *px3 = x3;
00903         irplib_trace(); /* OK */
00904     } else if (is_complex) {
00905         *px1 = x1;
00906         irplib_trace(); /* OK */
00907     } else {
00908         *px1 = x3;
00909         irplib_trace(); /* OK */
00910     }
00911 
00912     return is_complex;
00913 }
00914 
00915 /*----------------------------------------------------------------------------*/
00929 /*----------------------------------------------------------------------------*/
00930 static void irplib_polynomial_solve_1d_31(double a, double Q,
00931                                           double * px1, double * px2,
00932                                           double * px3, cpl_boolean * pdbl1)
00933 {
00934 
00935     const double sqrtQ = sqrt (Q);
00936 
00937     double x1, x2, x3;
00938 
00939     x2 = x1 = -sqrtQ - a / 3.0;
00940     x3 = 2.0 * sqrtQ - a / 3.0;
00941     if (pdbl1 != NULL) *pdbl1 = CPL_TRUE;
00942 
00943     *px1 = x1;
00944     *px2 = x2;
00945     *px3 = x3;
00946 
00947     irplib_trace(); /* OK */
00948     return;
00949 }
00950 
00951 /*----------------------------------------------------------------------------*/
00966 /*----------------------------------------------------------------------------*/
00967 static void irplib_polynomial_solve_1d_32(double a, double c, double Q,
00968                                           double * px1, double * px2,
00969                                           double * px3, cpl_boolean * pdbl2)
00970 {
00971 
00972     const double sqrtQ = sqrt (Q);
00973 
00974     double x1 = DBL_MAX;
00975     double x2 = DBL_MAX;
00976     double x3 = DBL_MAX;
00977 
00978     if (a > 0.0) {
00979         /* a and sqrt(Q) have same sign - or Q is zero */
00980         x1 = -2.0 * sqrtQ - a / 3.0;
00981         /* FIXME: Two small roots with opposite signs may
00982            end up here, with the sign lost for one of them */
00983         x3 = x2 = -a < x1 ? -sqrt(fabs(c / x1)) : sqrt(fabs(c / x1));
00984         if (pdbl2 != NULL) *pdbl2 = CPL_TRUE;
00985         irplib_trace(); /* OK */
00986     } else if (a < 0.0) {
00987         /* a and sqrt(Q) have opposite signs - or Q is zero */
00988         x3 = x2 = sqrtQ - a / 3.0;
00989         x1 = -c / (x2 * x2);
00990         if (pdbl2 != NULL) *pdbl2 = CPL_TRUE;
00991         irplib_trace(); /* OK */
00992     } else {
00993         x1 = -2.0 * sqrtQ;
00994         x3 = x2 = sqrtQ;
00995         if (pdbl2 != NULL) *pdbl2 = CPL_TRUE;
00996         irplib_trace(); /* OK */
00997     }
00998 
00999     *px1 = x1;
01000     *px2 = x2;
01001     *px3 = x3;
01002 
01003     return;
01004 }
01005 
01006 /*----------------------------------------------------------------------------*/
01026 /*----------------------------------------------------------------------------*/
01027 static void irplib_polynomial_solve_1d_3c(double a, double c,
01028                                           double Q, double Q3,
01029                                           double R, double R2,
01030                                           double * px1,
01031                                           double * px2, double * px3,
01032                                           cpl_boolean * pis_c,
01033                                           cpl_boolean * pdbl2)
01034 {
01035 
01036     /* Due to finite precision some double roots may be missed, and
01037        will be considered to be a pair of complex roots z = x +/-
01038        epsilon i close to the real axis. */
01039 
01040     /* Another case: A double root, which is small relative to the
01041        last root, may cause this branch to be taken - with the
01042        imaginary part eventually being truncated to zero. */
01043 
01044     const double sgnR = (R >= 0 ? 1.0 : -1.0);
01045     const double A = -sgnR * pow (fabs (R) + sqrt (R2 - Q3), 1.0 / 3.0);
01046     const double B = Q / A;
01047 
01048     double x1 = DBL_MAX;
01049     double x2 = DBL_MAX;
01050     double x3 = DBL_MAX;
01051     cpl_boolean is_complex = CPL_FALSE;
01052 
01053     if (( A > -B && a > 0.0) || (A < -B && a < 0.0)) {
01054         /* A+B has same sign as a */
01055 
01056         /* Real part of complex conjugate */
01057         x2 = -0.5 * (A + B) - a / 3.0; /* No cancellation */
01058         /* Positive, imaginary part of complex conjugate */
01059         x3 = 0.5 * CPL_MATH_SQRT3 * fabs(A - B);
01060 
01061         x1 = -c / (x2 * x2 + x3 * x3);
01062         irplib_trace(); /* OK */
01063     } else {
01064         /* A+B and a have opposite signs - or exactly one is zero */
01065         x1 = A + B - a / 3.0;
01066         /* Positive, imaginary part of complex conjugate */
01067         x3 = 0.5 * CPL_MATH_SQRT3 * fabs(A - B);
01068 
01069         if (x3 > 0.0) {
01070             /* Real part of complex conjugate */
01071             x2 = -0.5 * (A + B) - a / 3.0; /* FIXME: Cancellation */
01072             irplib_trace(); /* OK */
01073         } else {
01074 
01075             x2 = -a < x1 ? -sqrt(fabs(c / x1)) : sqrt(fabs(c / x1));
01076             x2 = -0.5 * (A + B) - a / 3.0; /* FIXME: Cancellation */
01077             x3 = 0.0;
01078             irplib_trace(); /* OK */
01079         }
01080     }
01081 
01082     if (x3 > 0.0) {
01083         is_complex = CPL_TRUE;
01084         irplib_trace(); /* OK */
01085     } else {
01086         /* Whoaa, the imaginary part was truncated to zero
01087            - return a real, double root */
01088         x3 = x2;
01089         if (pdbl2 != NULL) *pdbl2 = CPL_TRUE;
01090         irplib_trace(); /* OK */
01091     }
01092 
01093     *px1 = x1;
01094     *px2 = x2;
01095     *px3 = x3;
01096     *pis_c = is_complex;
01097 
01098     return;
01099 }
01100 
01101 /*----------------------------------------------------------------------------*/
01116 /*----------------------------------------------------------------------------*/
01117 static void irplib_polynomial_solve_1d_3r(double a, double c,
01118                                           double Q, double R,
01119                                           double * px1,
01120                                           double * px2, double * px3)
01121 {
01122 
01123     const double sqrtQ = sqrt(Q);
01124     const double theta = acos (R / (Q * sqrtQ)); /* theta in range [0; pi] */
01125 
01126     /* -1.0 <= cos((theta + CPL_MATH_2PI) / 3.0) <= -0.5
01127        -0.5 <= cos((theta - CPL_MATH_2PI) / 3.0) <=  0.5
01128         0.5 <= cos((theta                  ) / 3.0) <=  1.0 */
01129 
01130 #define TR1 (-2.0 * sqrtQ * cos( theta                    / 3.0))
01131 #define TR2 (-2.0 * sqrtQ * cos((theta - CPL_MATH_2PI) / 3.0))
01132 #define TR3 (-2.0 * sqrtQ * cos((theta + CPL_MATH_2PI) / 3.0))
01133 
01134     /* TR1 < TR2 < TR3, except when theta == 0, then TR2 == TR3 */
01135 
01136     /* The three roots must be transformed back via subtraction with a/3.
01137        To prevent loss of precision due to cancellation, the root which
01138        is closest to a/3 is computed using the relation
01139        p3 * x1 * x2 * x3 = -p0 */
01140 
01141     double x1 = DBL_MAX;
01142     double x2 = DBL_MAX;
01143     double x3 = DBL_MAX;
01144 
01145     if (a > 0.0) {
01146         x1 = TR1 - a / 3.0;
01147         if (TR2 > 0.0 && (TR2 + TR3) > 2.0 * a) {
01148             /* FIXME: Cancellation may still effect x3 ? */
01149             x3 = TR3 - a / 3.0;
01150             x2 = -c / ( x1 * x3 );
01151             irplib_trace(); /* OK */
01152         } else {
01153             /* FIXME: Cancellation may still effect x2, especially
01154                if x2, x3 is (almost) a double root, i.e.
01155                if theta is close to zero. */
01156             x2 = TR2 - a / 3.0;
01157  
01158             x3 = -c / ( x1 * x2 );
01159             irplib_trace(); /* OK */
01160         }
01161     } else if (a < 0.0) {
01162         x3 = TR3 - a / 3.0;
01163         if (TR2 < 0.0 && (TR1 + TR2) > 2.0 * a) {
01164             x1 = TR1 - a / 3.0;
01165             x2 = -c / ( x1 * x3 );
01166             irplib_trace(); /* OK */
01167         } else {
01168             x2 = TR2 - a / 3.0;
01169             x1 = -c / ( x2 * x3 );
01170             irplib_trace(); /* OK */
01171         }
01172     } else {
01173         x1 = TR1;
01174         x2 = TR2;
01175         x3 = TR3;
01176         irplib_trace(); /* OK */
01177     }
01178 
01179     assert(x1 < x3);
01180 
01181     if (x1 > x2) {
01182         /* In absence of round-off:
01183            theta == PI: x1 == x2,
01184            theta  < PI: x1 <  x2,
01185 
01186            The only way x1 could exceed x2 would be due to round-off when
01187            theta is close to PI */
01188      
01189         x1 = x2 = 0.5 * ( x1 + x2 );
01190         irplib_trace(); /* OK, tested only for x1 == x2 */
01191     } else if (x2 > x3) {
01192         /* In absence of round-off:
01193            theta == 0: x2 == x3,
01194            theta  > 0: x2 <  x3,
01195 
01196            For small theta:
01197            Round-off can cause x2 to become greater than x3 */
01198      
01199         x3 = x2 = 0.5 * ( x2 + x3 );
01200         irplib_trace(); /* OK */
01201     }
01202 
01203     *px1 = x1;
01204     *px2 = x2;
01205     *px3 = x3;
01206 
01207     return;
01208 }
01209 
01210 /*----------------------------------------------------------------------------*/
01228 /*----------------------------------------------------------------------------*/
01229 static cpl_error_code irplib_polynomial_solve_1d_4(double p4, double p3,
01230                                                    double p2, double p1,
01231                                                    double p0, int * preal,
01232                                                    double * px1, double * px2,
01233                                                    double * px3, double * px4)
01234 {
01235 
01236     /* Construct the monic, depressed quartic using Horners scheme on 1 / p4 */
01237     const double a = (p2 - 0.375 * p3 * p3 / p4) / p4;
01238     const double b = (p1 - 0.5 * (p2 - 0.25 * p3 * p3 / p4 ) * p3 / p4 ) / p4;
01239     const double c =
01240         (p0 - 0.25 * (p1 - 0.25 * (p2 - 0.1875 * p3 * p3 / p4 ) * p3 / p4
01241                       ) * p3 / p4 ) / p4;
01242 
01243     double x1 = DBL_MAX; /* Fix (false) uninit warning */
01244     double x2 = DBL_MAX; /* Fix (false) uninit warning */
01245     double x3 = DBL_MAX; /* Fix (false) uninit warning */
01246     double x4 = DBL_MAX; /* Fix (false) uninit warning */
01247 
01248     assert(preal != NULL );
01249     assert(px1   != NULL );
01250     assert(px2   != NULL );
01251     assert(px3   != NULL );
01252     assert(px4   != NULL );
01253 
01254     *preal = 4;
01255 
01256     if (c == 0.0) {
01257         /* The depressed quartic has zero as root */
01258         /* Since the sum of the roots is zero, at least one is negative
01259            and at least one is positive - unless they are all zero */
01260         cpl_boolean dbl1, dbl2;
01261         const cpl_boolean is_real =
01262             !irplib_polynomial_solve_1d_3(1.0, 0.0, a, b, &x1, &x3, &x4,
01263                                           &dbl1, &dbl2);
01264 
01265         x1 -= 0.25 * p3 / p4;
01266         x2 = -0.25 * p3 / p4;
01267         x3 -= 0.25 * p3 / p4;
01268         if (is_real) {
01269 
01270             if (dbl2) {
01271                 x4 = x3;
01272                 assert( x1 <= x2);
01273                 assert( x2 <= x3);
01274             } else {
01275                 x4 -= 0.25 * p3 / p4;
01276                 /* Need (only) a guarded swap of x2, x3 */
01277                 if (x2 > x3) {
01278                     IRPLIB_SWAP(x2, x3);
01279                 }
01280                 if (dbl1) {
01281                     assert( x1 <= x2); /* The cubic may have 0 as triple root */
01282                     assert( x2 <= x3);
01283                     assert( x2 <= x4);
01284                 } else {
01285                     assert( x1 < x2);
01286                     assert( x2 < x4);
01287                 }
01288             }
01289         } else {
01290             *preal = 2;
01291 
01292             if (x1 > x2) {
01293                 assert( x3 <= x2 ); /* Don't swap a complex root */
01294 
01295                 IRPLIB_SWAP(x1, x2);
01296             } else {
01297                 assert( x3 >= x2 );
01298             }
01299         }
01300 
01301     } else if (b == 0.0) {
01302         /* The monic, depressed quartic is a monic, biquadratic equation */
01303         double u1, u2;
01304         const cpl_boolean is_complex = irplib_polynomial_solve_1d_2(1.0, a, c,
01305                                                                     &u1, &u2);
01306 
01307         if (is_complex) {
01308             /* All four roots are conjugate, complex */
01309             const double norm = sqrt(u1*u1 + u2*u2);
01310             const double   v1 = sqrt(0.5*(norm+u1));
01311             const double   v2 = u2 / sqrt(2.0*(norm+u1));
01312 
01313 
01314             x1 = -0.25 * p3 / p4 - v1;
01315             x3 = -0.25 * p3 / p4 + v1;
01316 
01317             x4 = x2 = v2;
01318 
01319             *preal = 0;
01320 
01321         } else if (u1 >= 0.0) {
01322             /* All four roots are real */
01323             const double sv1 = sqrt(u1);
01324             const double sv2 = sqrt(u2);
01325 
01326 
01327             *preal = 4;
01328 
01329             x1 = -0.25 * p3 / p4 - sv2;
01330             x2 = -0.25 * p3 / p4 - sv1;
01331             x3 = -0.25 * p3 / p4 + sv1;
01332             x4 = -0.25 * p3 / p4 + sv2;
01333         } else if (u2 < 0.0) {
01334             /* All four roots are conjugate, complex */
01335             const double sv1 = sqrt(-u2);
01336             const double sv2 = sqrt(-u1);
01337 
01338 
01339             *preal = 0;
01340 
01341             x1 = x3 = -0.25 * p3 / p4;
01342 
01343             x2 = sv1;
01344             x4 = sv2;
01345         } else {
01346             /* Two roots are real, two roots are conjugate, complex */
01347             const double sv1 = sqrt(-u1);
01348             const double sv2 = sqrt(u2);
01349 
01350 
01351             *preal = 2;
01352 
01353             x1 = -0.25 * p3 / p4 - sv2;
01354             x2 = -0.25 * p3 / p4 + sv2;
01355 
01356             x3 = -0.25 * p3 / p4;
01357             x4 = sv1;
01358         }
01359     } else {
01360         /* Need a root from the nested, monic cubic */
01361         const double q2 = -a;
01362         const double q1 = -4.0 * c;
01363         const double q0 = 4.0 * a * c - b * b;
01364         double u1, sqrtd, sqrtrd;
01365         double z1, z2, z3, z4;
01366 
01367         cpl_boolean is_complex1, is_complex2;
01368 
01369         /* Largest cubic root ensures real square roots when solving the
01370            quartic equation */
01371         (void)irplib_polynomial_solve_1d_3(1.0, q2, q1, q0, &u1, NULL, NULL,
01372                                            NULL, NULL);
01373 
01374 
01375         assert( u1 > a );
01376 
01377         sqrtd = sqrt(u1 - a);
01378 
01379         sqrtrd = 0.5 * b/sqrtd;
01380 
01381         is_complex1 = irplib_polynomial_solve_1d_2(1.0,  sqrtd, 0.5*u1 - sqrtrd,
01382                                                    &z1, &z2);
01383 
01384         is_complex2 = irplib_polynomial_solve_1d_2(1.0, -sqrtd, 0.5*u1 + sqrtrd,
01385                                                    &z3, &z4);
01386 
01387         z1 -= 0.25 * p3 / p4;
01388         z3 -= 0.25 * p3 / p4;
01389         if (!is_complex1) z2 -= 0.25 * p3 / p4;
01390         if (!is_complex2) z4 -= 0.25 * p3 / p4;
01391 
01392         if (!is_complex1 && is_complex2) {
01393             *preal = 2;
01394             x1 = z1;
01395             x2 = z2;
01396             x3 = z3;
01397             x4 = z4;
01398         } else if (is_complex1 && !is_complex2) {
01399             *preal = 2;
01400             x1 = z3;
01401             x2 = z4;
01402             x3 = z1;
01403             x4 = z2;
01404         } else if (is_complex1 && is_complex2) {
01405             *preal = 0;
01406 
01407             if (z1 < z3 || (z1 == z3 && z2 <= z4)) {
01408                 x1 = z1;
01409                 x2 = z2;
01410                 x3 = z3;
01411                 x4 = z4;
01412             } else {
01413                 x1 = z3;
01414                 x2 = z4;
01415                 x3 = z1;
01416                 x4 = z2;
01417             }
01418         } else {
01419             *preal = 4;
01420 
01421             if (z3 >= z2) {
01422                 x1 = z1;
01423                 x2 = z2;
01424                 x3 = z3;
01425                 x4 = z4;
01426             } else if (z4 <= z1) {
01427                 x1 = z3;
01428                 x2 = z4;
01429                 x3 = z1;
01430                 x4 = z2;
01431             } else if (z2 > z4) {
01432                 x1 = z3;
01433                 x2 = z1;
01434                 x3 = z4;
01435                 x4 = z2;
01436             } else {
01437                 x1 = z1;
01438                 x2 = z3;
01439                 x3 = z2;
01440                 x4 = z4;
01441             }
01442         }
01443     }
01444 
01445     *px1 = x1;
01446     *px2 = x2;
01447     *px3 = x3;
01448     *px4 = x4;
01449 
01450     return CPL_ERROR_NONE;
01451 }
01452 
01453 #ifdef IPRLIB_POLYNOMIAL_USE_MONOMIAL_ROOT
01454 /*----------------------------------------------------------------------------*/
01462 /*----------------------------------------------------------------------------*/
01463 static double irplib_polynomial_depress_1d(cpl_polynomial * self)
01464 {
01465 
01466     const int    degree = cpl_polynomial_get_degree(self);
01467     const int    nc1    = degree - 1;
01468     const double an     = cpl_polynomial_get_coeff(self, &degree);
01469     const double an1    = cpl_polynomial_get_coeff(self, &nc1);
01470     double       rmean;
01471     int          i;
01472 
01473 
01474     cpl_ensure(degree > 0,   CPL_ERROR_DATA_NOT_FOUND, 0.0);
01475 
01476     assert( an != 0.0 );
01477 
01478     rmean = -an1/(an * (double)degree);
01479 
01480     if (rmean != 0.0) {
01481 
01482         cpl_polynomial_shift_1d(self, rmean);
01483 
01484         cpl_polynomial_set_coeff(self, &nc1, 0.0); /* Round-off... */
01485 
01486     }
01487 
01488     /* Set leading coefficient to one. */
01489     for (i = 0; i < degree-1; i++) {
01490         const double ai = cpl_polynomial_get_coeff(self, &i) / an;
01491         cpl_polynomial_set_coeff(self, &i, ai);
01492     }
01493 
01494     cpl_polynomial_set_coeff(self, &degree, 1.0); /* Round-off... */
01495 
01496     return rmean;
01497 }
01498 #endif
01499 
01500 /*----------------------------------------------------------------------------*/
01515 /*----------------------------------------------------------------------------*/
01516 static
01517 cpl_error_code irplib_polynomial_divide_1d_root(cpl_polynomial * p, double r,
01518                                                 double * pres)
01519 {
01520 
01521     const int n = cpl_polynomial_get_degree(p);
01522     double    sum;
01523     int       i;
01524 
01525 
01526     cpl_ensure_code(p != NULL, CPL_ERROR_NULL_INPUT);
01527     cpl_ensure_code(cpl_polynomial_get_dimension(p) == 1,
01528                     CPL_ERROR_INVALID_TYPE);
01529     cpl_ensure_code(n > 0, CPL_ERROR_DATA_NOT_FOUND);
01530 
01531     sum = cpl_polynomial_get_coeff(p, &n);
01532     cpl_polynomial_set_coeff(p, &n, 0.0);
01533 
01534     for (i = n-1; i >= 0; i--) {
01535         const double coeff = cpl_polynomial_get_coeff(p, &i);
01536 
01537         cpl_polynomial_set_coeff(p, &i, sum);
01538 
01539         sum = coeff + r * sum;
01540 
01541     }
01542 
01543     if (pres != NULL) *pres = sum;
01544 
01545     return CPL_ERROR_NONE;
01546 }

Generated on Fri Jul 3 11:15:23 2009 for VISIR Pipeline Reference Manual by  doxygen 1.5.8