fors_polynomial.c

00001 /* $Id: fors_polynomial.c,v 1.7 2010/09/14 07:49:30 cizzo Exp $
00002  *
00003  * This file is part of the FORS Library
00004  * Copyright (C) 2002-2010 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  02110-1301 USA
00019  */
00020 
00021 /*
00022  * $Author: cizzo $
00023  * $Date: 2010/09/14 07:49:30 $
00024  * $Revision: 1.7 $
00025  * $Name: fors-4_8_6 $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 #include "fors_polynomial.h"
00033 
00034 #include "fors_utils.h"
00035 
00036 #include <cpl.h>
00037 #include <math.h>
00038 #include <string.h>
00039 
00040 /*----------------------------------------------------------------------------*/
00044 /*----------------------------------------------------------------------------*/
00045 
00047 /*-----------------------------------------------------------------------------
00048     Prototypes
00049  -----------------------------------------------------------------------------*/
00050 
00051 static bool
00052 fors_polynomial_is_coeff_set(               const cpl_polynomial    *p,
00053                                             const int               *powers);
00054 
00055 static bool
00056 fors_polynomial_powers_next(                const cpl_polynomial    *p,
00057                                             int                     *powers);
00058 
00059 /*-----------------------------------------------------------------------------
00060     Private Implementation
00061  -----------------------------------------------------------------------------*/
00062 
00063 /*----------------------------------------------------------------------------*/
00064 #undef cleanup
00065 #define cleanup
00066 
00072 /*----------------------------------------------------------------------------*/
00073 static bool
00074 fors_polynomial_is_coeff_set(               const cpl_polynomial    *p,
00075                                             const int               *powers)
00076 {
00077     cassure_automsg(                        p != NULL,
00078                                             CPL_ERROR_NULL_INPUT,
00079                                             return false);
00080     cassure_automsg(                        powers != NULL,
00081                                             CPL_ERROR_NULL_INPUT,
00082                                             return false);
00083     
00084     return (fabs(cpl_polynomial_get_coeff(p, powers)) > DBL_EPSILON);
00085 }
00086 
00087 /*----------------------------------------------------------------------------*/
00088 #undef cleanup
00089 #define cleanup
00090 
00096 /*----------------------------------------------------------------------------*/
00097 static bool
00098 fors_polynomial_powers_next(                const cpl_polynomial    *p,
00099                                             int                     *powers)
00100 {
00101     int             dim = 0,
00102                     ndims,
00103                     ndegs;
00104     bool            overflow = false;
00105     cpl_errorstate  errstat = cpl_errorstate_get();
00106     
00107     cassure_automsg(                        p != NULL,
00108                                             CPL_ERROR_NULL_INPUT,
00109                                             return true);
00110     cassure_automsg(                        powers != NULL,
00111                                             CPL_ERROR_NULL_INPUT,
00112                                             return true);
00113     
00114     ndims = cpl_polynomial_get_dimension(p);
00115     ndegs = cpl_polynomial_get_degree(p);
00116     passure(cpl_errorstate_is_equal(errstat), return true);
00117     
00118     powers[dim]++;
00119     while(dim < ndims && powers[dim] > ndegs) /* carry over */
00120     {
00121         powers[dim] = 0;
00122         dim++;
00123         overflow = (!(dim < ndims));
00124         if (!overflow)
00125             powers[dim]++;
00126     }
00127     
00128     return overflow;
00129 }
00130 
00131 /*-----------------------------------------------------------------------------
00132     Public Implementation
00133  -----------------------------------------------------------------------------*/
00134 
00135 /*----------------------------------------------------------------------------*/
00136 #undef cleanup
00137 #define cleanup \
00138 do { \
00139     if (pows != NULL) \
00140         cpl_free(pows); \
00141     pows = NULL; \
00142 } while (0)
00143 
00148 /*----------------------------------------------------------------------------*/
00149 int
00150 fors_polynomial_count_coeff(                const cpl_polynomial    *p)
00151 {
00152     int             ndims,
00153                     Ncoeff = 0;
00154     int             *pows = NULL;
00155     bool            overflow = false;
00156     cpl_errorstate  errstat = cpl_errorstate_get();
00157     
00158     cassure_automsg(                        p != NULL,
00159                                             CPL_ERROR_NULL_INPUT,
00160                                             return 0);
00161     
00162     ndims = cpl_polynomial_get_dimension(p);
00163     passure(cpl_errorstate_is_equal(errstat), return 0);
00164     
00165     pows = cpl_calloc(ndims, sizeof(*pows));
00166     
00167     while (!overflow) 
00168     {
00169         if (fors_polynomial_is_coeff_set(p, pows))
00170             Ncoeff++;
00171         
00172         overflow = fors_polynomial_powers_next(p, pows);
00173     }
00174     
00175     passure(cpl_errorstate_is_equal(errstat), return 0);
00176     cleanup;
00177     
00178     return Ncoeff;
00179 }
00180 
00181 /*----------------------------------------------------------------------------*/
00182 #undef cleanup
00183 #define cleanup
00184 
00190 /*----------------------------------------------------------------------------*/
00191 int
00192 fors_polynomial_powers_find_first_coeff(    const cpl_polynomial    *p,
00193                                             int                     *powers)
00194 {
00195     int             ndims,
00196                     dim;
00197     bool            overflow;
00198     cpl_errorstate  errstat = cpl_errorstate_get();
00199     
00200     cassure_automsg(                        p != NULL,
00201                                             CPL_ERROR_NULL_INPUT,
00202                                             return true);
00203     cassure_automsg(                        powers != NULL,
00204                                             CPL_ERROR_NULL_INPUT,
00205                                             return true);
00206     
00207     ndims = cpl_polynomial_get_dimension(p);
00208     for (dim = 0; dim < ndims; dim++)
00209         powers[dim] = 0;
00210     
00211     if (fors_polynomial_is_coeff_set(p, powers))
00212         return false;
00213     
00214     overflow = fors_polynomial_powers_find_next_coeff(p, powers);
00215     passure(cpl_errorstate_is_equal(errstat), return true);
00216     cleanup;
00217     
00218     return overflow;
00219 }
00220 
00221 /*----------------------------------------------------------------------------*/
00222 #undef cleanup
00223 #define cleanup
00224 
00230 /*----------------------------------------------------------------------------*/
00231 int
00232 fors_polynomial_powers_find_next_coeff(     const cpl_polynomial    *p,
00233                                             int                     *powers)
00234 {
00235     bool            overflow;
00236     cpl_errorstate  errstat = cpl_errorstate_get();
00237     
00238     cassure_automsg(                        p != NULL,
00239                                             CPL_ERROR_NULL_INPUT,
00240                                             return true);
00241     cassure_automsg(                        powers != NULL,
00242                                             CPL_ERROR_NULL_INPUT,
00243                                             return true);
00244     
00245     overflow = fors_polynomial_powers_next(p, powers);
00246     while (!overflow)
00247     {
00248         if (fors_polynomial_is_coeff_set(p, powers))
00249             break;
00250         
00251         overflow = fors_polynomial_powers_next(p, powers);
00252     }
00253     
00254     passure(cpl_errorstate_is_equal(errstat), return true);
00255     cleanup;
00256     
00257     return overflow;
00258 }
00259 
00260 /*----------------------------------------------------------------------------*/
00261 #undef cleanup
00262 #define cleanup \
00263 do { \
00264     if (pows != NULL) \
00265         cpl_free(pows); \
00266     pows = NULL; \
00267 } while (0)
00268 
00275 /*----------------------------------------------------------------------------*/
00276 cpl_error_code
00277 fors_polynomial_set_existing_coeff(         cpl_polynomial  *p,
00278                                             const double    *coeffs,
00279                                             int             n_coeffs)
00280 {
00281     int             n,
00282                     ndims;
00283     int             *pows = NULL;
00284     bool            overflow = false;
00285     cpl_errorstate  errstat = cpl_errorstate_get();
00286     
00287     if (p == NULL)
00288         return 0;
00289     
00290     /* check input */
00291     cassure_automsg(                        p != NULL,
00292                                             CPL_ERROR_NULL_INPUT,
00293                                             return cpl_error_get_code());
00294     cassure_automsg(                        coeffs != NULL,
00295                                             CPL_ERROR_NULL_INPUT,
00296                                             return cpl_error_get_code());
00297     cassure_automsg(                        n_coeffs > 0,
00298                                             CPL_ERROR_ILLEGAL_INPUT,
00299                                             return cpl_error_get_code());
00300     
00301     /* start */
00302     ndims = cpl_polynomial_get_dimension(p);
00303     pows = cpl_calloc(ndims, sizeof(*pows));
00304     
00305     overflow = fors_polynomial_powers_find_first_coeff(p, pows);
00306     n = 0;
00307     while (!overflow)
00308     {
00309         cassure(                            n < n_coeffs,
00310                                             CPL_ERROR_ACCESS_OUT_OF_RANGE,
00311                                             return cpl_error_get_code(),
00312                                             "p contains more coefficients "
00313                                             "than coeffs");
00314         cpl_polynomial_set_coeff(p, pows, coeffs[n]);
00315         n++;
00316         
00317         overflow = fors_polynomial_powers_find_next_coeff(p, pows);
00318     }
00319     
00320     cleanup;
00321     
00322     return  cpl_errorstate_is_equal(errstat) ?
00323                 CPL_ERROR_NONE :
00324                 cpl_error_get_code();
00325 }
00326 
00327 /*----------------------------------------------------------------------------*/
00328 #undef cleanup
00329 #define cleanup \
00330 do { \
00331     if (powersA != NULL) { cpl_free(powersA); powersA = NULL;} \
00332     if (powersB != NULL) { cpl_free(powersB); powersB = NULL;} \
00333     if (powersE != NULL) { cpl_free(powersE); powersE = NULL;} \
00334     cpl_polynomial_delete(ep); ep = NULL; \
00335 } while (0)
00336 
00354 /*----------------------------------------------------------------------------*/
00355 cpl_polynomial*
00356 fors_polynomial_create_variance_polynomial( const cpl_polynomial    *p_def,
00357                                             const cpl_matrix        *cov_coeff)
00358 {
00359     int             n_dims,
00360                     n_coeffs,
00361                     n_col,
00362                     ia = 0;
00363     int             *powersA = NULL,
00364                     *powersB = NULL,
00365                     *powersE = NULL;
00366     cpl_polynomial  *ep = NULL;
00367     bool            overflowa = false;
00368     cpl_errorstate  errstat = cpl_errorstate_get();
00369     
00370     /* check input */
00371     cassure_automsg(                        p_def != NULL,
00372                                             CPL_ERROR_NULL_INPUT,
00373                                             return ep);
00374     cassure_automsg(                        cov_coeff != NULL,
00375                                             CPL_ERROR_NULL_INPUT,
00376                                             return ep);
00377     
00378     n_coeffs = fors_polynomial_count_coeff(p_def);
00379     n_dims = cpl_polynomial_get_dimension(p_def);
00380     n_col = cpl_matrix_get_ncol(cov_coeff);
00381     passure(cpl_errorstate_is_equal(errstat), return ep);
00382     
00383     cassure(                                n_coeffs == n_col,
00384                                             CPL_ERROR_INCOMPATIBLE_INPUT,
00385                                             return ep,
00386                                             "number of p_def coefficients "
00387                                             "!= nr of columns");
00388     cassure(                                n_col == cpl_matrix_get_nrow(
00389                                                         cov_coeff),
00390                                             CPL_ERROR_ILLEGAL_INPUT,
00391                                             return ep,
00392                                             "cov_coeff is not square");
00393     
00394     ep = cpl_polynomial_new(n_dims);
00395     powersA = cpl_calloc(n_dims, sizeof(*powersA));
00396     powersB = cpl_calloc(n_dims, sizeof(*powersB));
00397     powersE = cpl_calloc(n_dims, sizeof(*powersE));
00398     passure(cpl_errorstate_is_equal(errstat), return ep);
00399     
00400     overflowa = fors_polynomial_powers_find_first_coeff(p_def, powersA);
00401     while (!overflowa)
00402     {
00403         bool    overflowb = false;
00404         int     ib = 0;
00405         
00406         overflowb = fors_polynomial_powers_find_first_coeff(p_def, powersB);
00407         while (!overflowb)
00408         {
00409             double  coeff;
00410             int     d;
00411             passure(cpl_errorstate_is_equal(errstat), return ep);
00412             /* Add cov_ij to the proper coeff:
00413              * cov_ij * dp/d(ai) * dp/d(aj) =
00414              * cov_ij * (x^degx[i] * y^degy[i]) * (x^degx[i] * y^degy[i]) =
00415              * cov_ij * x^(degx[i]+degx[j]) * y^(degy[i] + degy[j]),
00416              * 
00417              * i.e. add cov_ij to
00418              * coeff (degx[i]+degx[j], degy[i]+degy[j]) 
00419              */
00420             for (d = 0; d < n_dims; d++)
00421                 powersE[d] = powersA[d] + powersB[d];
00422             
00423             coeff = cpl_polynomial_get_coeff(ep, powersE);
00424             cpl_polynomial_set_coeff(ep, powersE,
00425                                      coeff
00426                                      + cpl_matrix_get(
00427                                         cov_coeff, ia, ib));
00428             
00429             ib++;
00430             overflowb = fors_polynomial_powers_find_next_coeff(p_def, powersB);
00431         }
00432         ia++;
00433         overflowa = fors_polynomial_powers_find_next_coeff(p_def, powersA);
00434     }
00435     passure(cpl_errorstate_is_equal(errstat), return ep);
00436     
00437     cpl_polynomial  *ret_ep = ep; ep = NULL;
00438     cleanup;
00439     
00440     return ret_ep;
00441 }
00442 
00443 /*----------------------------------------------------------------------------*/
00444 #undef cleanup
00445 #define cleanup \
00446 do { \
00447     if (pows != NULL) \
00448         cpl_free(pows); \
00449     pows = NULL; \
00450     if (ndxstr != NULL) \
00451         cpl_free(ndxstr); \
00452     ndxstr = NULL; \
00453 } while (0)
00454 
00463 /*----------------------------------------------------------------------------*/
00464 cpl_error_code
00465 fors_polynomial_dump(                       const cpl_polynomial    *p,
00466                                             const char              *name,
00467                                             cpl_msg_severity        level,
00468                                             const cpl_polynomial    *p_def)
00469 {
00470     int             ndims,
00471                     ndegs,
00472                     dim;
00473     int             *pows = NULL;
00474     char            *ndxstr = NULL;
00475     char            max_ndx_str[15];
00476     cpl_errorstate  errstat = cpl_errorstate_get();
00477     
00478     /* check input */
00479     cassure_automsg(                        p != NULL,
00480                                             CPL_ERROR_NULL_INPUT,
00481                                             return cpl_error_get_code());
00482     
00483     if (p_def != NULL)
00484     {
00485         ndims = cpl_polynomial_get_dimension(p_def);
00486         cassure_automsg(                    ndims
00487                                             = cpl_polynomial_get_dimension(p),
00488                                             CPL_ERROR_INCOMPATIBLE_INPUT,
00489                                             return cpl_error_get_code());
00490     }
00491     else
00492     {
00493         ndims = cpl_polynomial_get_dimension(p);
00494         p_def = p;
00495     }
00496     
00497     ndegs = cpl_polynomial_get_degree(p_def);
00498     
00499     pows = cpl_calloc(ndims, sizeof(*pows));
00500     /* allocate a string that can contain "%d,%d,...,%d" */
00501     sprintf(max_ndx_str, "%d", ndegs);
00502     ndxstr = cpl_calloc(ndims*(strlen(max_ndx_str)+1), sizeof(*ndxstr));
00503     
00504     /* ATTENTION: below, the last dimension is the fastest index (for nicer
00505      * printing). This differs from the strategy in all other polynomial
00506      * handling functions above, so be careful when doing copy & paste!
00507      */
00508     while (pows[0] <= ndegs) 
00509     {
00510         if (fors_polynomial_is_coeff_set(p_def, pows))
00511         {
00512             double  coeff;
00513             coeff = cpl_polynomial_get_coeff(p, pows);
00514             /* create the index string */
00515             sprintf(ndxstr, "%d", pows[0]);
00516             for (dim = 1; dim < ndims; dim++)
00517                 sprintf(ndxstr+strlen(ndxstr), ",%d", pows[dim]);
00518             fors_msg(                       level,
00519                                             "%s_%s = %e",
00520                                             (name != NULL) ? name : "p",
00521                                             ndxstr,
00522                                             coeff);
00523         }
00524         
00525         dim = ndims-1;
00526         pows[dim]++;
00527         while(dim > 0 && pows[dim] > ndegs) /* carry over */
00528         {
00529             pows[dim] = 0;
00530             dim--;
00531             pows[dim]++;
00532         }
00533     }
00534     
00535     cleanup;
00536     
00537     return  cpl_errorstate_is_equal(errstat) ?
00538                 CPL_ERROR_NONE :
00539                 cpl_error_get_code();
00540 }
00541 
00542 /*----------------------------------------------------------------------------*/
00543 #undef cleanup
00544 #define cleanup \
00545 do { \
00546     if (ndxstr != NULL) \
00547         cpl_free(ndxstr); \
00548     ndxstr = NULL; \
00549 } while (0)
00550 
00561 /*----------------------------------------------------------------------------*/
00562 char*
00563 fors_polynomial_sprint_coeff(               const cpl_polynomial    *p,
00564                                             int                     *powers,
00565                                             const char              *prefix)
00566 {
00567     int             ndims,
00568                     ndegs,
00569                     dim,
00570                     max_nr,
00571                     max_nr_strlen;
00572     char            *ndxstr = NULL;
00573     char            max_ndx_str[15];
00574     
00575     /* check input */
00576     cassure_automsg(                        p != NULL,
00577                                             CPL_ERROR_NULL_INPUT,
00578                                             return ndxstr);
00579     cassure_automsg(                        powers != NULL,
00580                                             CPL_ERROR_NULL_INPUT,
00581                                             return ndxstr);
00582     
00583     ndims = cpl_polynomial_get_dimension(p);
00584     ndegs = cpl_polynomial_get_degree(p);
00585     
00586     /* be safe to cover maximum required str length */
00587     /* FIXME: catch negative numbers */
00588     max_nr = ndegs;
00589     for (dim = 0; dim < ndims; dim++)
00590         if (powers[dim] > max_nr)
00591             max_nr = powers[dim];
00592     
00593     sprintf(max_ndx_str, "%d", max_nr);
00594     max_nr_strlen = strlen(max_ndx_str);
00595     if (prefix != NULL && prefix[0] != '\0')
00596     {
00597         int len = strlen(prefix) + 1 + ndims*(max_nr_strlen+1);
00598         ndxstr = cpl_calloc(len, sizeof(*ndxstr));
00599         sprintf(ndxstr, "%s_", prefix);
00600     }
00601     else
00602     {
00603         ndxstr = cpl_calloc(ndims*(max_nr_strlen+1), sizeof(*ndxstr));
00604     }
00605     /* specify max length for snprintf including nul char */
00606     snprintf(ndxstr+strlen(ndxstr),         max_nr_strlen+1,
00607                                             (powers[0] >= 0) ? "%d" : "?",
00608                                             powers[0]);
00609     for (dim = 1; dim < ndims; dim++)
00610         snprintf(ndxstr+strlen(ndxstr),     max_nr_strlen+2,
00611                                             (powers[dim] >= 0) ? ",%d" : "?",
00612                                             powers[dim]);
00613     
00614     return ndxstr;
00615 }
00616 

Generated on Fri Mar 4 09:46:00 2011 for FORS Pipeline Reference Manual by  doxygen 1.4.7