IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 4991


Ignore:
Timestamp:
Sep 11, 2005, 12:18:40 PM (21 years ago)
Author:
gusciora
Message:

....

Location:
trunk/psLib/src
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/psLib/src/astro/psCoord.c

    r4957 r4991  
    1010*  @author GLG, MHPCC
    1111*
    12 *  @version $Revision: 1.85 $ $Name: not supported by cvs2svn $
    13 *  @date $Date: 2005-09-07 21:33:48 $
     12*  @version $Revision: 1.86 $ $Name: not supported by cvs2svn $
     13*  @date $Date: 2005-09-11 22:18:40 $
    1414*
    1515*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     
    545545        int nSamples)
    546546{
    547 
    548     // XXX: This does not yet use region and nSamples:  need to modify -rdd
    549 
    550547    PS_ASSERT_PTR_NON_NULL(trans1, NULL);
    551548    PS_ASSERT_PTR_NON_NULL(trans2, NULL);
     
    905902)
    906903{
    907     /*
    908         PS_ASSERT_PTR_NON_NULL(transformation, NULL);
    909         PS_ASSERT_POLY_NON_NULL(transformation->x, NULL);
    910         PS_ASSERT_POLY_NON_NULL(transformation->y, NULL);
    911         PS_ASSERT_PTR_NON_NULL(coord, NULL);
    912      
    913         if (out == NULL) {
    914             out = psPlaneAlloc();
    915         }
    916      
    917         out->x = 0.0;
    918         out->y = 0.0;
    919         out->xErr = 0.0;
    920         out->yErr = 0.0;
    921      
    922         psPolynomial2D *xPoly = transformation->x;
    923         psPolynomial2D *yPoly = transformation->y;
    924      
    925         //
    926         // Calculate the derivative with respect to x.
    927         //
    928         psF32 xSum = 1.0;
    929         psF32 ySum = 1.0;
    930      
    931         // This loop starts at loop_x=1 since the derivative of the loop_x=0 terms are all 0.0
    932         for (psS32 loop_x = 1; loop_x < xPoly->nX; loop_x++) {
    933             ySum = 1.0;
    934             for (psS32 loop_y = 0; loop_y < xPoly->nY; loop_y++) {
    935                 //
    936                 // For each iteration of the loop, we multiple the (x, y) coefficient
    937                 // by (coord->x^(loop_x-1) * coord->y^loop_y)
    938                 //
    939      
    940                 out->x+= xPoly->coeff[loop_x][loop_y] * xSum * ySum;
    941                 ySum*= coord->y;
    942             }
    943             xSum*= coord->x;
    944         }
    945      
    946         //
    947         // Calculate the derivative with respect to x.
    948         //
    949         xSum = 1.0;
    950      
    951         // This loop starts at loop_y=1 since the derivative of the loop_y=0 terms are all 0.0
    952         for (psS32 loop_x = 0; loop_x < yPoly->nX; loop_x++) {
    953             ySum = 1.0;
    954             for (psS32 loop_y = 1; loop_y < yPoly->nY; loop_y++) {
    955                 //
    956                 // For each iteration of the loop, we multiple the (x, y) coefficient
    957                 // by (coord->x^(loop_x-1) * coord->y^loop_y)
    958                 //
    959      
    960                 out->y+= yPoly->coeff[loop_x][loop_y] * xSum * ySum;
    961                 ySum*= coord->y;
    962             }
    963             xSum*= coord->x;
    964         }
    965     */
     904    PS_ASSERT_PTR_NON_NULL(transformation, NULL);
     905    PS_ASSERT_POLY_NON_NULL(transformation->x, NULL);
     906    PS_ASSERT_POLY_NON_NULL(transformation->y, NULL);
     907    PS_ASSERT_PTR_NON_NULL(coord, NULL);
     908
     909    if (out == NULL) {
     910        out = psPlaneAlloc();
     911    }
     912
     913    out->x = 0.0;
     914    out->y = 0.0;
     915    out->xErr = 0.0;
     916    out->yErr = 0.0;
     917
     918    psPolynomial2D *xPoly = transformation->x;
     919    psPolynomial2D *yPoly = transformation->y;
     920
     921    //
     922    // Calculate the derivative with respect to x.
     923    //
     924    psF32 xSum = 1.0;
     925    psF32 ySum = 1.0;
     926
     927    // This loop starts at loop_x=1 since the derivative of the loop_x=0 terms are all 0.0
     928    for (psS32 loop_x = 1; loop_x < xPoly->nX; loop_x++) {
     929        ySum = 1.0;
     930        for (psS32 loop_y = 0; loop_y < xPoly->nY; loop_y++) {
     931            //
     932            // For each iteration of the loop, we multiple the (x, y) coefficient
     933            // by (coord->x^(loop_x-1) * coord->y^loop_y)
     934            //
     935
     936            out->x+= xPoly->coeff[loop_x][loop_y] * xSum * ySum;
     937            ySum*= coord->y;
     938        }
     939        xSum*= coord->x;
     940    }
     941
     942    //
     943    // Calculate the derivative with respect to x.
     944    //
     945    xSum = 1.0;
     946
     947    // This loop starts at loop_y=1 since the derivative of the loop_y=0 terms are all 0.0
     948    for (psS32 loop_x = 0; loop_x < yPoly->nX; loop_x++) {
     949        ySum = 1.0;
     950        for (psS32 loop_y = 1; loop_y < yPoly->nY; loop_y++) {
     951            //
     952            // For each iteration of the loop, we multiple the (x, y) coefficient
     953            // by (coord->x^(loop_x-1) * coord->y^loop_y)
     954            //
     955
     956            out->y+= yPoly->coeff[loop_x][loop_y] * xSum * ySum;
     957            ySum*= coord->y;
     958        }
     959        xSum*= coord->x;
     960    }
    966961    return(out);
    967962}
     
    970965{
    971966    if(sphere == NULL) {
    972         //        psError();
     967        psError( PS_ERR_UNKNOWN, true, "psSphere argument is NULL.  Returning NULL.\n");
    973968        return NULL;
    974969    }
     
    990985{
    991986    if(cube == NULL) {
    992         //        psError();
     987        psError( PS_ERR_UNKNOWN, true, "psCube argument is NULL.  Returning NULL.\n");
    993988        return NULL;
    994989    }
  • trunk/psLib/src/math/psConstants.h

    r4581 r4991  
    66 *  @author GLG, MHPCC
    77 *
    8  *  @version $Revision: 1.75 $ $Name: not supported by cvs2svn $
    9  *  @date $Date: 2005-07-20 01:21:13 $
     8 *  @version $Revision: 1.76 $ $Name: not supported by cvs2svn $
     9 *  @date $Date: 2005-09-11 22:18:40 $
    1010 *
    1111 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     
    357357
    358358#define PS_VECTOR_PRINT_F32(NAME) \
    359 for (int my_i=0;my_i<(NAME)->n;my_i++) { \
    360     printf("%s->data.F32[%d] is %f\n", #NAME, my_i, (NAME)->data.F32[my_i]); \
    361 } \
    362 printf("\n"); \
     359if (NAME != NULL) { \
     360    for (int my_i=0;my_i<(NAME)->n;my_i++) { \
     361        printf("%s->data.F32[%d] is %f\n", #NAME, my_i, (NAME)->data.F32[my_i]); \
     362    } \
     363    printf("\n"); \
     364} else {\
     365    printf("MACRO WARNING: vector %s is NULL.\n", #NAME); \
     366}\
    363367
    364368#define PS_VECTOR_PRINT_F64(NAME) \
    365 for (int my_i=0;my_i<(NAME)->n;my_i++) { \
    366     printf("%s->data.F64[%d] is %f\n", #NAME, my_i, (NAME)->data.F64[my_i]); \
    367 } \
    368 printf("\n"); \
    369 
     369if (NAME != NULL) { \
     370    for (int my_i=0;my_i<(NAME)->n;my_i++) { \
     371        printf("%s->data.F64[%d] is %f\n", #NAME, my_i, (NAME)->data.F64[my_i]); \
     372    } \
     373    printf("\n"); \
     374} else {\
     375    printf("MACRO WARNING: vector %s is NULL.\n", #NAME); \
     376}\
    370377
    371378#define PS_VECTOR_CONVERT_F64_TO_F32_STATIC(OLD, NEW_PTR32, NEW_STATIC32) \
     
    742749#define PS_SQR(A) \
    743750((A) * (A))
     751
     752# define PS_SWAP(X,Y) {double tmp=(X); (X) = (Y); (Y) = tmp;}
  • trunk/psLib/src/math/psMinimize.c

    r4958 r4991  
    88 *
    99 *  @author GLG, MHPCC
     10 *  @author EAM, IfA
    1011 *
    11  *  @version $Revision: 1.134 $ $Name: not supported by cvs2svn $
    12  *  @date $Date: 2005-09-07 21:35:50 $
     12 *  @version $Revision: 1.135 $ $Name: not supported by cvs2svn $
     13 *  @date $Date: 2005-09-11 22:18:40 $
    1314 *
    1415 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     
    3233/*****************************************************************************/
    3334/* DEFINE STATEMENTS                                                         */
     35/* What are the following macros for?                                        */
    3436/*****************************************************************************/
    3537#define PS_SEG psLib
     
    5759/*****************************************************************************/
    5860
     61/******************************************************************************
     62 ******************************************************************************
     63 Levenberg-Marquadt routines.
     64 ******************************************************************************
     65 *****************************************************************************/
    5966// measure the distance to the minimum assuming a linear model
     67// XXX: Move this to the pub area.
    6068bool psMinimizeGaussNewtonDelta (psVector *delta,
    6169                                 const psVector *params,
     
    112120}
    113121
    114 /******************************************************************************
    115 buildSums1D(x, polyOrder, sums): this routine calculates the powers of input
    116 parameter "x" between 0 and input parameter polyOrder.  The result is returned
    117 as a psVector sums.
    118  
    119 XXX: Use a static vector.
    120  
    121 XXX: should the argument be polyOrder or numTerms?
    122  *****************************************************************************/
    123 static void buildSums1D(psF64 x,
    124                         psS32 polyOrder,
    125                         psVector* sums)
    126 {
    127     psS32 i = 0;
    128     psF64 xSum = 0.0;
    129     psS32 numTerms = polyOrder + 1;
    130 
    131     if (sums == NULL) {
    132         sums = psVectorAlloc(numTerms, PS_TYPE_F64);
    133     } else if (numTerms > sums->n) {
    134         sums = psVectorRealloc(sums, numTerms);
    135     }
    136 
    137     xSum = 1.0;
    138     for (i = 0; i < numTerms; i++) {
    139         sums->data.F64[i] = xSum;
    140         xSum *= x;
    141     }
    142 }
    143 
    144 /*****************************************************************************
    145 CalculateSecondDerivs(): Given a set of x/y vectors corresponding to a
    146 tabulated function at n points, this routine calculates the second
    147 derivatives of the interpolating cubic splines at those n points.
    148  
    149 The first and second derivatives at the endpoints, undefined in the SDR, are
    150 here defined to be 0.0.  They can be modified via ypo and yp1.
    151  
    152 This routine assumes that vectors x and y are of the appropriate types/sizes
    153 (F32).
    154  
    155 XXX: This algorithm is derived from the Numerical Recipes.
    156 XXX: use recycled vectors for internal data.
    157 XXX: do an F64 version?
    158  *****************************************************************************/
    159 static psF32 *calculateSecondDerivs(const psVector* x,        ///< Ordinates (or NULL to just use the indices)
    160                                     const psVector* y)        ///< Coordinates
    161 {
    162     psTrace(".psLib.dataManip.calculateSecondDerivs", 4,
    163             "---- calculateSecondDerivs() begin ----\n");
    164 
    165     psS32 i;
    166     psS32 k;
    167     psF32 sig;
    168     psF32 p;
    169     psS32 n = y->n;
    170     psF32 *u = (psF32 *) psAlloc(n * sizeof(psF32));
    171     psF32 *derivs2 = (psF32 *) psAlloc(n * sizeof(psF32));
    172     psF32 *X = (psF32 *) & (x->data.F32[0]);
    173     psF32 *Y = (psF32 *) & (y->data.F32[0]);
    174     psF32 qn;
    175 
    176     // XXX: The second derivatives at the endpoints, undefined in the SDR,
    177     // are set in psConstants.h: PS_LEFT_SPLINE_DERIV, PS_RIGHT_SPLINE_DERIV.
    178     derivs2[0] = -0.5;
    179     u[0]= (3.0/(X[1]-X[0])) * ((Y[1]-Y[0])/(X[1]-X[0]) - PS_LEFT_SPLINE_DERIV);
    180 
    181     for (i=1;i<=(n-2);i++) {
    182         sig = (X[i] - X[i-1]) / (X[i+1] - X[i-1]);
    183         p = sig * derivs2[i-1] + 2.0;
    184         derivs2[i] = (sig - 1.0) / p;
    185         u[i] = ((Y[i+1] - Y[i])/(X[i+1]-X[i])) - ((Y[i]-Y[i-1])/(X[i]-X[i-1]));
    186         u[i] = ((6.0 * u[i] / (X[i+1] - X[i-1])) - (sig * u[i-1])) / p;
    187 
    188         psTrace(".psLib.dataManip.calculateSecondDerivs", 6,
    189                 "X[%d] is %f\n", i, X[i]);
    190         psTrace(".psLib.dataManip.calculateSecondDerivs", 6,
    191                 "Y[%d] is %f\n", i, Y[i]);
    192         psTrace(".psLib.dataManip.calculateSecondDerivs", 6,
    193                 "u[%d] is %f\n", i, u[i]);
    194     }
    195 
    196     qn = 0.5;
    197     u[n-1] = (3.0/(X[n-1]-X[n-2])) * (PS_RIGHT_SPLINE_DERIV - (Y[n-1]-Y[n-2])/(X[n-1]-X[n-2]));
    198     derivs2[n-1] = (u[n-1] - (qn * u[n-2])) / ((qn * derivs2[n-2]) + 1.0);
    199 
    200     for (k=(n-2);k>=0;k--) {
    201         derivs2[k] = derivs2[k] * derivs2[k+1] + u[k];
    202 
    203         psTrace(".psLib.dataManip.calculateSecondDerivs", 6,
    204                 "derivs2[%d] is %f\n", k, derivs2[k]);
    205     }
    206 
    207     psFree(u);
    208     psTrace(".psLib.dataManip.calculateSecondDerivs", 4,
    209             "---- calculateSecondDerivs() end ----\n");
    210     return(derivs2);
    211 }
    212 
    213 /******************************************************************************
    214 p_psNRSpline1DEval(): This routine does NR-style evaluation of cubic splines.
    215 It takes advantage of the 2nd derivatives of the cubic splines, which are
    216 stored in the psSPline1D data structure, and computes the interpolated value
    217 directly, without computing (or using) the interpolating cubic spline
    218 polynomial.
    219  
    220 This routine is here mostly for a sanity check on the psLib function
    221 evalSpline() which computes the interpolated value based on the cubic spline
    222 polynomials which are stored in psSpline1D.
    223  
    224 XXX: This is F32 only
    225  
    226 XXX: spline->knots must be psF32
    227  
    228 XXXX: Remove this for next code shipment.
    229  *****************************************************************************/
    230 /*
    231 psF32 p_psNRSpline1DEval(psSpline1D *spline,
    232                          const psVector* x,
    233                          const psVector* y,
    234                          psF32 X)
    235 {
    236     PS_ASSERT_PTR_NON_NULL(spline, NAN);
    237     PS_ASSERT_INT_NONNEGATIVE(spline->n, NAN);
    238     PS_ASSERT_VECTOR_NON_NULL(spline->domains, NAN);
    239     PS_ASSERT_PTR_NON_NULL(spline->p_psDeriv2, NAN);
    240     PS_ASSERT_VECTOR_NON_NULL(x, NAN);
    241     PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F32, NAN);
    242     PS_ASSERT_VECTOR_NON_NULL(y, NAN);
    243     PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F32, NAN);
    244     PS_ASSERT_VECTOR_TYPE(spline->knots, PS_TYPE_F32, NULL);
    245  
    246     psS32 n;
    247     psS32 klo;
    248     psS32 khi;
    249     psF32 H;
    250     psF32 A;
    251     psF32 B;
    252     psF32 C;
    253     psF32 D;
    254     psF32 Y;
    255  
    256     n = spline->n;
    257     klo = p_psVectorBinDisect32(spline->knots->data.F32, (spline->n)+1, X);
    258     if (klo < 0) {
    259         psLogMsg(__func__, PS_LOG_WARN,
    260                  "WARNING: psMinimize.c: p_psNRSpline1DEval(): p_psVectorBinDisect32 returned an error (%d).\n", klo);
    261         return(NAN);
    262     }
    263     khi = klo + 1;
    264     H = spline->knots->data.F32[khi] - spline->knots->data.F32[klo];
    265     A = (spline->knots->data.F32[khi] - X) / H;
    266     B = (X - spline->knots->data.F32[klo]) / H;
    267     C = ((A*A*A)-A) * (H*H/6.0);
    268     D = ((B*B*B)-B) * (H*H/6.0);
    269  
    270     Y = (A * y->data.F32[klo]) +
    271         (B * y->data.F32[khi]) +
    272         (C * (spline->p_psDeriv2)[klo]) +
    273         (D * (spline->p_psDeriv2)[khi]);
    274  
    275     return(Y);
    276 }
    277 */
    278 /*****************************************************************************/
    279 /* FUNCTION IMPLEMENTATION - PUBLIC                                          */
    280 /*****************************************************************************/
    281 
    282 /*****************************************************************************
    283 psVectorFitSpline1D(): given a psSpline1D data structure and a set of x/y
    284 vectors, this routine generates the linear or cublic splines which satisfy
    285 those data points.
    286  
    287 The formula for calculating the spline polynomials is derived from Numerical
    288 Recipes in C.  The basic idea is that the polynomial is
    289  (1)     y = (A * y[0]) +
    290  (2)         (B * y[1]) +
    291  (3)         ((((A*A*A)-A) * mySpline->p_psDeriv2[0]) * H^2)/6.0 +
    292  (4)         ((((B*B*B)-B) * mySpline->p_psDeriv2[1]) * H^2)/6.0
    293 Where:
    294  H = x[1]-x[0]
    295  A = (x[1]-x)/H
    296  B = (x-x[0])/H
    297 The bulk of the code in this routine is the expansion of the above equation
    298 into a polynomial in terms of x, and then saving the coefficients of the
    299 powers of x in the spline polynomials.  This gets pretty complicated.
    300  
    301 XXX: usage of yErr is not specified in IfA documentation.
    302  
    303 XXX: Is the x argument redundant?  What do we do if the x argument is
    304 supplied, but does not equal the knots specified in mySpline?
    305  
    306 XXX: can psSpline be NULL?
    307  
    308 XXX: reimplement this assuming that mySpline is NULL?
    309  
    310 XXX: What happens if X is NULL, then an index vector is generated for X, but
    311 that index vector lies outside the range vectors in mySpline?
    312  
    313 XXX: Assumes mySpline->knots is psF32.  Must add psU32 and psF64.
    314  *****************************************************************************/
    315 psSpline1D *psVectorFitSpline1D(psSpline1D *mySpline,     ///< The spline which will be generated.
    316                                 const psVector* x,        ///< Ordinates (or NULL to just use the indices)
    317                                 const psVector* y,        ///< Coordinates
    318                                 const psVector* yErr)     ///< Errors in coordinates, or NULL
    319 {
    320     PS_ASSERT_VECTOR_NON_NULL(y, NULL);
    321     PS_ASSERT_VECTOR_TYPE_F32_OR_F64(y, NULL);
    322     if (mySpline != NULL) {
    323         PS_ASSERT_VECTOR_TYPE(mySpline->knots, PS_TYPE_F32, NULL);
    324     }
    325     psTrace(".psLib.dataManip.psVectorFitSpline1D", 4,
    326             "---- psVectorFitSpline1D() begin ----\n");
    327     psS32 numSplines = (y->n)-1;
    328     psF32 tmp;
    329     psF32 H;
    330     psS32 i;
    331     psF32 slope;
    332     psVector *x32 = NULL;
    333     psVector *y32 = NULL;
    334     psVector *yErr32 = NULL;
    335     static psVector *x32Static = NULL;
    336     static psVector *y32Static = NULL;
    337     static psVector *yErr32Static = NULL;
    338 
    339     PS_VECTOR_CONVERT_F64_TO_F32_STATIC(y, y32, y32Static);
    340 
    341     // If yErr==NULL, set all errors equal.
    342     if (yErr == NULL) {
    343         PS_VECTOR_GEN_YERR_STATIC_F32(yErr32Static, y->n);
    344         yErr32 = yErr32Static;
    345     } else {
    346         PS_ASSERT_VECTOR_TYPE_F32_OR_F64(yErr, NULL);
    347         PS_VECTOR_CONVERT_F64_TO_F32_STATIC(yErr, yErr32, yErr32Static);
    348     }
    349 
    350     // If x==NULL, create an x32 vector with x values set to (0:n).
    351     if (x == NULL) {
    352         PS_VECTOR_GEN_X_INDEX_STATIC_F32(x32Static, y->n);
    353         x32 = x32Static;
    354     } else {
    355         PS_ASSERT_VECTOR_TYPE_F32_OR_F64(x, NULL);
    356         PS_VECTOR_CONVERT_F64_TO_F32_STATIC(x, x32, x32Static);
    357     }
    358     PS_ASSERT_VECTORS_SIZE_EQUAL(x32, y32, NULL);
    359     PS_ASSERT_VECTORS_SIZE_EQUAL(yErr32, y32, NULL);
    360 
    361     /*
    362         XXX:
    363         This can not be implemented until SDR states what order spline should be
    364         created.
    365         Should we error if mySpline is not NULL?
    366         Should we error if mySPline is not NULL?
    367     */
    368     if (mySpline == NULL) {
    369         mySpline = psSpline1DAllocGeneric(x32, 3);
    370     }
    371     PS_ASSERT_PTR_NON_NULL(mySpline, NULL);
    372     PS_ASSERT_INT_NONNEGATIVE(mySpline->n, NULL);
    373 
    374     if (y32->n != (1 + mySpline->n)) {
    375         psError(PS_ERR_BAD_PARAMETER_SIZE, true,
    376                 "data size / spline size mismatch (%d %d)\n",
    377                 y32->n, mySpline->n);
    378         return(NULL);
    379     }
    380 
    381     // If these are linear splines, which means their polynomials will have
    382     // two coefficients, then we do the simple calculation.
    383     if (2 == (mySpline->spline[0])->n) {
    384         for (i=0;i<mySpline->n;i++) {
    385             slope = (y32->data.F32[i+1] - y32->data.F32[i]) /
    386                     (mySpline->knots->data.F32[i+1] - mySpline->knots->data.F32[i]);
    387             (mySpline->spline[i])->coeff[0] = y32->data.F32[i] -
    388                                               (slope * mySpline->knots->data.F32[i]);
    389 
    390             (mySpline->spline[i])->coeff[1] = slope;
    391             psTrace(".psLib.dataManip.psMinimize.psVectorFitSpline1D", 4,
    392                     "---- mySpline %d coeffs are (%f, %f)\n", i,
    393                     (mySpline->spline[i])->coeff[0],
    394                     (mySpline->spline[i])->coeff[1]);
    395         }
    396         psTrace(".psLib.dataManip.psMinimize.psVectorFitSpline1D", 4,
    397                 "---- Exiting psVectorFitSpline1D()()\n");
    398         return((psSpline1D *) mySpline);
    399     }
    400 
    401     // Check if these are cubic splines (n==4).  If not, psError.
    402     if (4 != (mySpline->spline[0])->n) {
    403         psError(PS_ERR_BAD_PARAMETER_SIZE, true,
    404                 "Don't know how to generate %d-order splines.",
    405                 (mySpline->spline[0])->n-1);
    406         return(NULL);
    407     }
    408 
    409     // If we get here, then we know these are cubic splines.  We first
    410     // generate the second derivatives at each data point.
    411     mySpline->p_psDeriv2 = calculateSecondDerivs(x32, y32);
    412     for (i=0;i<y32->n;i++)
    413         psTrace(".psLib.dataManip.psVectorFitSpline1D", 6,
    414                 "Second deriv[%d] is %f\n", i, mySpline->p_psDeriv2[i]);
    415 
    416     // We generate the coefficients of the spline polynomials.  I can't
    417     // concisely explain how this code works.  See above function comments
    418     // and Numerical Recipes in C.
    419     for (i=0;i<numSplines;i++) {
    420         H = x32->data.F32[i+1] - x32->data.F32[i];
    421         psTrace(".psLib.dataManip.psVectorFitSpline1D", 4,
    422                 "x data (%f - %f) (%f)\n",
    423                 x32->data.F32[i],
    424                 x32->data.F32[i+1], H);
    425         //
    426         // ******** Calculate 0-order term ********
    427         //
    428         // From (1)
    429         (mySpline->spline[i])->coeff[0] = (y32->data.F32[i] * x32->data.F32[i+1]/H);
    430         // From (2)
    431         ((mySpline->spline[i])->coeff[0])-= ((y32->data.F32[i+1] * x32->data.F32[i])/H);
    432         // From (3)
    433         tmp = (x32->data.F32[i+1] * x32->data.F32[i+1] * x32->data.F32[i+1]) / (H * H * H);
    434         tmp-= (x32->data.F32[i+1] / H);
    435         tmp*= (mySpline->p_psDeriv2)[i] * H * H / 6.0;
    436         ((mySpline->spline[i])->coeff[0])+= tmp;
    437         // From (4)
    438         tmp = -(x32->data.F32[i] * x32->data.F32[i] * x32->data.F32[i]) / (H * H * H);
    439         tmp+= (x32->data.F32[i] / H);
    440         tmp*= (mySpline->p_psDeriv2)[i+1] * H * H / 6.0;
    441         ((mySpline->spline[i])->coeff[0])+= tmp;
    442 
    443         //
    444         // ******** Calculate 1-order term ********
    445         //
    446         // From (1)
    447         (mySpline->spline[i])->coeff[1] = -(y32->data.F32[i]) / H;
    448         // From (2)
    449         ((mySpline->spline[i])->coeff[1])+= (y32->data.F32[i+1] / H);
    450         // From (3)
    451         tmp = -3.0 * (x32->data.F32[i+1] * x32->data.F32[i+1]) / (H * H * H);
    452         tmp+= (1.0 / H);
    453         tmp*= ((mySpline->p_psDeriv2)[i]) * H * H / 6.0;
    454         ((mySpline->spline[i])->coeff[1])+= tmp;
    455         // From (4)
    456         tmp = 3.0 * (x32->data.F32[i] * x32->data.F32[i]) / (H * H * H);
    457         tmp-= (1.0 / H);
    458         tmp*= ((mySpline->p_psDeriv2)[i+1]) * H * H / 6.0;
    459         ((mySpline->spline[i])->coeff[1])+= tmp;
    460 
    461         //
    462         // ******** Calculate 2-order term ********
    463         //
    464         // From (3)
    465         (mySpline->spline[i])->coeff[2] = ((mySpline->p_psDeriv2)[i]) * 3.0 * x32->data.F32[i+1] / (6.0 * H);
    466         // From (4)
    467         ((mySpline->spline[i])->coeff[2])-= (((mySpline->p_psDeriv2)[i+1]) * 3.0 * x32->data.F32[i] / (6.0 * H));
    468 
    469         //
    470         // ******** Calculate 3-order term ********
    471         //
    472         // From (3)
    473         (mySpline->spline[i])->coeff[3] = -((mySpline->p_psDeriv2)[i]) / (6.0 * H);
    474         // From (4)
    475         ((mySpline->spline[i])->coeff[3])+=  ((mySpline->p_psDeriv2)[i+1]) / (6.0 * H);
    476 
    477         psTrace(".psLib.dataManip.psVectorFitSpline1D", 6,
    478                 "(mySpline->spline[%d])->coeff[0] is %f\n", i, (mySpline->spline[i])->coeff[0]);
    479         psTrace(".psLib.dataManip.psVectorFitSpline1D", 6,
    480                 "(mySpline->spline[%d])->coeff[1] is %f\n", i, (mySpline->spline[i])->coeff[1]);
    481         psTrace(".psLib.dataManip.psVectorFitSpline1D", 6,
    482                 "(mySpline->spline[%d])->coeff[2] is %f\n", i, (mySpline->spline[i])->coeff[2]);
    483         psTrace(".psLib.dataManip.psVectorFitSpline1D", 6,
    484                 "(mySpline->spline[%d])->coeff[3] is %f\n", i, (mySpline->spline[i])->coeff[3]);
    485 
    486     }
    487 
    488     psTrace(".psLib.dataManip.psVectorFitSpline1D", 4,
    489             "---- psVectorFitSpline1D() end ----\n");
    490     return(mySpline);
    491 }
    492 
    493 
    494 
    495 
    496 
    497 
    498 
    499 
    500 
    501 /*****************************************************************************
    502 psVectorFitSpline1DNEW(): given a psSpline1D data structure and a set of x/y
    503  
    504 xF32 and yF32 are internal psVectors which are used to hold the psF32 versions
    505 of the input data, if necessary.  xPtr and yPtr are pointers to either xF32 or
    506 the x argument.  All computation is done on xPtr and yPtr.  xF32 and yF32 will
    507 simply be psFree() at the end.
    508  
    509 XXX: nKnots makes no sense.  This number is always equal to the size of the x
    510 an y vectors.
    511  
    512 XXX: How do we specify the spline order?  For now, order=3.
    513  *****************************************************************************/
    514 #define PS_XXX_SPLINE_ORDER 3
    515 psSpline1D *psVectorFitSpline1DNEW(const psVector* x,        ///< Ordinates (or NULL to just use the indices)
    516                                    const psVector* y,        ///< Coordinates
    517                                    int nKnots)
    518 {
    519     psTrace(".psLib.dataManip.psVectorFitSpline1D", 4, "---- psVectorFitSpline1DNEW() begin ----\n");
    520     PS_ASSERT_VECTOR_NON_NULL(y, NULL);
    521     PS_ASSERT_VECTOR_TYPE_F32_OR_F64(y, NULL);
    522     //    PS_ASSERT_INT_EQUAL(y->n, nKnots);
    523 
    524     //
    525     // The following code ensures that xPtr points to a psF32 version of the
    526     // ordinate data.
    527     //
    528     psVector *xF32 = NULL;
    529     psVector *xPtr = NULL;
    530     if (x != NULL) {
    531         PS_ASSERT_VECTORS_SIZE_EQUAL(x, y, NULL);
    532         if (PS_TYPE_F64 == x->type.type) {
    533             xF32 = psVectorAlloc(y->n, PS_TYPE_F32);
    534             for (psS32 i = 0 ; i < x->n ; i++) {
    535                 xF32->data.F32[i] = (psF32) x->data.F64[i];
    536             }
    537             xPtr = xF32;
    538         } else if (PS_TYPE_F32 == x->type.type) {
    539             xPtr = (psVector *) x;
    540         } else {
    541             printf("XXX: Gen Error message: x is wrong type.\n");
    542             return(NULL);
    543         }
    544     } else {
    545         // If x==NULL, create an x32 vector with x values set to (0:n).
    546         xF32 = psVectorAlloc(y->n, PS_TYPE_F32);
    547         for (psS32 i = 0 ; i < x->n ; i++) {
    548             xF32->data.F32[i] = (psF32) i;
    549         }
    550         xPtr = xF32;
    551     }
    552 
    553     //
    554     // If y is of type psF64, then create a new vector yF32 and convert the
    555     // y elements.  Regardless of y's type, we create a yPtr which will be
    556     // used in the remainder of this function.
    557     //
    558     psVector *yF32 = NULL;
    559     psVector *yPtr = NULL;
    560     if (PS_TYPE_F64 == y->type.type) {
    561         yF32 = psVectorAlloc(y->n, PS_TYPE_F32);
    562         for (psS32 i = 0 ; i < y->n ; i++) {
    563             yF32->data.F32[i] = (psF32) y->data.F64[i];
    564         }
    565         yPtr = yF32;
    566     } else {
    567         yPtr = (psVector *) y;
    568     }
    569 
    570     psSpline1D *mySpline = psSpline1DAllocGeneric(xPtr, PS_XXX_SPLINE_ORDER);
    571 
    572     psS32 numSplines = nKnots - 1;
    573     psF32 tmp;
    574     psF32 H;
    575     psS32 i;
    576     psF32 slope;
    577     // XXX: get rid of x32 and y32 (this is from old code)
    578     psVector *x32 = xPtr;
    579     psVector *y32 = yPtr;
    580 
    581     // If these are linear splines, which means their polynomials will have
    582     // two coefficients, then we do the simple calculation.
    583     if (1 == PS_XXX_SPLINE_ORDER) {
    584         for (i=0;i<mySpline->n;i++) {
    585             slope = (y32->data.F32[i+1] - y32->data.F32[i]) /
    586                     (mySpline->knots->data.F32[i+1] - mySpline->knots->data.F32[i]);
    587             (mySpline->spline[i])->coeff[0] = y32->data.F32[i] -
    588                                               (slope * mySpline->knots->data.F32[i]);
    589 
    590             (mySpline->spline[i])->coeff[1] = slope;
    591             psTrace(".psLib.dataManip.psMinimize.psVectorFitSpline1D", 4,
    592                     "---- mySpline %d coeffs are (%f, %f)\n", i,
    593                     (mySpline->spline[i])->coeff[0],
    594                     (mySpline->spline[i])->coeff[1]);
    595         }
    596         psTrace(".psLib.dataManip.psMinimize.psVectorFitSpline1D", 4,
    597                 "---- Exiting psVectorFitSpline1D()()\n");
    598         return((psSpline1D *) mySpline);
    599     }
    600 
    601     //
    602     // Check if these are cubic splines (n==4).  If not, psError.
    603     //
    604     if (3 != PS_XXX_SPLINE_ORDER) {
    605         psError(PS_ERR_BAD_PARAMETER_SIZE, true,
    606                 "Don't know how to generate %d-order splines.", PS_XXX_SPLINE_ORDER);
    607         return(NULL);
    608     }
    609 
    610     //
    611     // If we get here, then we know these are cubic splines.  We first
    612     // generate the second derivatives at each data point.
    613     //
    614     mySpline->p_psDeriv2 = calculateSecondDerivs(x32, y32);
    615     for (i=0;i<y32->n;i++)
    616         psTrace(".psLib.dataManip.psVectorFitSpline1D", 6,
    617                 "Second deriv[%d] is %f\n", i, mySpline->p_psDeriv2[i]);
    618 
    619     //
    620     // We generate the coefficients of the spline polynomials.  I can't
    621     // concisely explain how this code works.  See above function comments
    622     // and Numerical Recipes in C.
    623     //
    624     for (i=0;i<numSplines;i++) {
    625         H = x32->data.F32[i+1] - x32->data.F32[i];
    626         psTrace(".psLib.dataManip.psVectorFitSpline1D", 4,
    627                 "x data (%f - %f) (%f)\n",
    628                 x32->data.F32[i],
    629                 x32->data.F32[i+1], H);
    630         //
    631         // ******** Calculate 0-order term ********
    632         //
    633         // From (1)
    634         (mySpline->spline[i])->coeff[0] = (y32->data.F32[i] * x32->data.F32[i+1]/H);
    635         // From (2)
    636         ((mySpline->spline[i])->coeff[0])-= ((y32->data.F32[i+1] * x32->data.F32[i])/H);
    637         // From (3)
    638         tmp = (x32->data.F32[i+1] * x32->data.F32[i+1] * x32->data.F32[i+1]) / (H * H * H);
    639         tmp-= (x32->data.F32[i+1] / H);
    640         tmp*= (mySpline->p_psDeriv2)[i] * H * H / 6.0;
    641         ((mySpline->spline[i])->coeff[0])+= tmp;
    642         // From (4)
    643         tmp = -(x32->data.F32[i] * x32->data.F32[i] * x32->data.F32[i]) / (H * H * H);
    644         tmp+= (x32->data.F32[i] / H);
    645         tmp*= (mySpline->p_psDeriv2)[i+1] * H * H / 6.0;
    646         ((mySpline->spline[i])->coeff[0])+= tmp;
    647 
    648         //
    649         // ******** Calculate 1-order term ********
    650         //
    651         // From (1)
    652         (mySpline->spline[i])->coeff[1] = -(y32->data.F32[i]) / H;
    653         // From (2)
    654         ((mySpline->spline[i])->coeff[1])+= (y32->data.F32[i+1] / H);
    655         // From (3)
    656         tmp = -3.0 * (x32->data.F32[i+1] * x32->data.F32[i+1]) / (H * H * H);
    657         tmp+= (1.0 / H);
    658         tmp*= ((mySpline->p_psDeriv2)[i]) * H * H / 6.0;
    659         ((mySpline->spline[i])->coeff[1])+= tmp;
    660         // From (4)
    661         tmp = 3.0 * (x32->data.F32[i] * x32->data.F32[i]) / (H * H * H);
    662         tmp-= (1.0 / H);
    663         tmp*= ((mySpline->p_psDeriv2)[i+1]) * H * H / 6.0;
    664         ((mySpline->spline[i])->coeff[1])+= tmp;
    665 
    666         //
    667         // ******** Calculate 2-order term ********
    668         //
    669         // From (3)
    670         (mySpline->spline[i])->coeff[2] = ((mySpline->p_psDeriv2)[i]) * 3.0 * x32->data.F32[i+1] / (6.0 * H);
    671         // From (4)
    672         ((mySpline->spline[i])->coeff[2])-= (((mySpline->p_psDeriv2)[i+1]) * 3.0 * x32->data.F32[i] / (6.0 * H));
    673 
    674         //
    675         // ******** Calculate 3-order term ********
    676         //
    677         // From (3)
    678         (mySpline->spline[i])->coeff[3] = -((mySpline->p_psDeriv2)[i]) / (6.0 * H);
    679         // From (4)
    680         ((mySpline->spline[i])->coeff[3])+=  ((mySpline->p_psDeriv2)[i+1]) / (6.0 * H);
    681 
    682         psTrace(".psLib.dataManip.psVectorFitSpline1D", 6,
    683                 "(mySpline->spline[%d])->coeff[0] is %f\n", i, (mySpline->spline[i])->coeff[0]);
    684         psTrace(".psLib.dataManip.psVectorFitSpline1D", 6,
    685                 "(mySpline->spline[%d])->coeff[1] is %f\n", i, (mySpline->spline[i])->coeff[1]);
    686         psTrace(".psLib.dataManip.psVectorFitSpline1D", 6,
    687                 "(mySpline->spline[%d])->coeff[2] is %f\n", i, (mySpline->spline[i])->coeff[2]);
    688         psTrace(".psLib.dataManip.psVectorFitSpline1D", 6,
    689                 "(mySpline->spline[%d])->coeff[3] is %f\n", i, (mySpline->spline[i])->coeff[3]);
    690 
    691     }
    692 
    693     psFree(xF32);
    694     psFree(yF32);
    695 
    696     psTrace(".psLib.dataManip.psVectorFitSpline1D", 4,
    697             "---- psVectorFitSpline1D() end ----\n");
    698 
    699     return(mySpline);
    700 }
    701 
    702 
    703 
    704 
    705 //XXX: What's this for?
    706 psF64 p_psImageGetElementF64(psImage *a, int i, int j);
    707122/******************************************************************************
    708123psMinimizeLMChi2():  This routine will take an procedure which calculates
     
    717132     will have to convert all F32 input vectors to F64 regardless.  So,
    718133     the F64 port might be.
     134 
     135XXX: Change the whole thing to F64, if input data is F32, convert it.
    719136 *****************************************************************************/
    720137psBool psMinimizeLMChi2(psMinimization *min,
     
    816233        if (psTraceGetLevel (".psLib.dataManip.psMinimizeLMChi2") == 4) {
    817234            // XXX: Where is this?
    818             //            p_psVectorPrintRow (psTraceGetDestination(), Params, "params guess");
     235            // p_psVectorPrintRow (psTraceGetDestination(), Params, "params guess");
    819236        }
    820237        # endif /* PS_NO_TRACE */
     
    876293
    877294// XXX EAM: this needs to respect the mask on params
    878 // XXX EAM: check not NULL on alpha, beta, params
    879295// alpha, beta, params are already allocated
    880296psF64 p_psMinLM_SetABX (psImage  *alpha,
     
    887303                        psMinimizeLMChi2Func func)
    888304{
     305    PS_ASSERT_IMAGE_NON_NULL(alpha, NAN);
     306    PS_ASSERT_VECTOR_NON_NULL(beta, NAN);
     307    PS_ASSERT_VECTOR_NON_NULL(params, NAN);
     308    PS_ASSERT_VECTOR_NON_NULL(x, NAN);
     309    PS_ASSERT_VECTOR_NON_NULL(y, NAN);
     310    PS_ASSERT_VECTOR_NON_NULL(dy, NAN);
    889311
    890312    psF64 chisq;
     
    1011433}
    1012434
    1013 // XXX: put this in constants.h
    1014 # define PS_SWAP(X,Y) {double tmp=(X); (X) = (Y); (Y) = tmp;}
    1015 
    1016435// XXX EAM : temporary gauss-jordan solver based on gene's
    1017436// version based on the Numerical Recipes version
     
    1044463        for (j = 0; j < Nx; j++) {
    1045464            if (!isfinite(matrix[i][j])) {
    1046                 // XXX EAM: this should use the psError stack
    1047                 fprintf (stderr, "GAUSSJ: NaN\n");
     465                psError(PS_ERR_UNKNOWN, false, "Input matrix contains NaNs.\n");
    1048466                goto fescape;
    1049467            }
     
    1058476                    } else {
    1059477                        if (ipiv[k] > 1) {
    1060                             // XXX EAM: this should use the psError stack
    1061                             fprintf (stderr, "GAUSSJ: Singular Matrix! (1)\n");
     478                            psError(PS_ERR_UNKNOWN, false, "Singular Matrix (1).\n");
    1062479                            goto fescape;
    1063480                        }
     
    1076493        indxc[i] = icol;
    1077494        if (matrix[icol][icol] == 0.0) {
    1078             // XXX EAM: this should use the psError stack
    1079             fprintf (stderr, "GAUSSJ: Singular Matrix! (2)\n");
     495            psError(PS_ERR_UNKNOWN, false, "Singular Matrix (2).\n");
    1080496            goto fescape;
    1081497        }
     
    1118534}
    1119535
    1120 /******************************************************************************
    1121 vectorFitPolynomial1DCheb():  This routine will fit a Chebyshev polynomial of
    1122 degree myPoly to the data points (x, y) and return the coefficients of that
    1123 polynomial.
    1124  
    1125 XXX: yErr is currently ignored.
    1126 *****************************************************************************/
    1127 static psPolynomial1D *vectorFitPolynomial1DCheby(psPolynomial1D* myPoly,
    1128         const psVector* x,
    1129         const psVector* y,
    1130         const psVector* yErr)
    1131 {
    1132     psS32 j;
    1133     psS32 k;
    1134     psS32 n = x->n;
    1135     psF64 fac;
    1136     psF64 sum;
    1137     PS_VECTOR_GEN_STATIC_RECYCLED(f, n, PS_TYPE_F64);
    1138     psScalar *fScalar;
    1139     psScalar tmpScalar;
    1140     tmpScalar.type.type = PS_TYPE_F64;
    1141 
    1142     // XXX: These assignments appear too simple to warrant code and
    1143     // variable declarations.  I retain them here to maintain coherence
    1144     // with the NR code.
    1145     psF64 min = -1.0;
    1146     psF64 max = 1.0;
    1147     psF64 bma = 0.5 * (max-min);  // 1
    1148     psF64 bpa = 0.5 * (max+min);  // 0
    1149 
    1150     // In this loop, we first calculate the values of X for which the
    1151     // Chebyshev polynomials are zero (see NR, section 5.4).  Then we
    1152     // calculate the value of the function we are fitting the Chebyshev
    1153     // polynomials to at those values of X.  This is a bit tricky since
    1154     // we don't know that function.  So, we instead do 3-order LaGrange
    1155     // interpolation at the point X for the psVectors x,y for which we
    1156     // are fitting this ChebyShev polynomial to.
    1157 
    1158     for (psS32 i=0;i<n;i++) {
    1159         // NR 5.8.4
    1160         psF64 Y = cos(M_PI * (0.5 + ((psF32) i)) / ((psF32) n));
    1161         psF64 X = (Y + bma + bpa) - 1.0;
    1162         tmpScalar.data.F64 = X;
    1163 
    1164         // We interpolate against are tabluated x,y vectors to determine the
    1165         // function value at X.
    1166         fScalar = p_psVectorInterpolate((psVector *) x,
    1167                                         (psVector *) y,
    1168                                         3,
    1169                                         &tmpScalar);
    1170 
    1171         f->data.F64[i] = fScalar->data.F64;
    1172         psFree(fScalar);
    1173 
    1174         psTrace(".psLib.dataManip.vectorFitPolynomial1DCheby", 6,
    1175                 "(x, X, y, f(X)) is (%f, %f, %f, %f)\n",
    1176                 x->data.F64[i], X, y->data.F64[i], f->data.F64[i]);
    1177     }
    1178 
    1179     // We have the values for f() at the zero points, we now calculate the
    1180     // coefficients of the Chebyshev polynomial: NR 5.8.7.
    1181 
    1182     fac = 2.0/((psF32) n);
    1183     // XXX: is this loop bound correct?
    1184     for (j=0;j<myPoly->n;j++) {
    1185         sum = 0.0;
    1186         for (k=0;k<n;k++) {
    1187             sum+= f->data.F64[k] *
    1188                   cos(M_PI * ((psF32) j) * (0.5 + ((psF32) k)) / ((psF32) n));
    1189         }
    1190 
    1191         myPoly->coeff[j] = fac * sum;
    1192     }
    1193 
    1194     return(myPoly);
    1195 }
    1196 
    1197 /******************************************************************************
    1198 VectorFitPolynomial1DOrd():  This routine will fit an ordinary polynomial of
    1199 degree myPoly to the data points (x, y) and return the coefficients of that
    1200 polynomial.
    1201  
    1202 XXX: Use private name?
    1203 XXX: Use recycled vectors.
    1204  *****************************************************************************/
    1205 static psPolynomial1D* vectorFitPolynomial1DOrd(psPolynomial1D* myPoly,
    1206         const psVector* x,
    1207         const psVector* y,
    1208         const psVector* yErr)
    1209 {
    1210     psS32 polyOrder = myPoly->n;
    1211     psImage* A = NULL;
    1212     psImage* ALUD = NULL;
    1213     psVector* B = NULL;
    1214     psVector* outPerm = NULL;
    1215     psVector* X = NULL;         // NOTE: do we need this?
    1216     psVector* coeffs = NULL;
    1217     psS32 i = 0;
    1218     psS32 j = 0;
    1219     psS32 k = 0;
    1220     psVector* xSums = NULL;
    1221 
    1222     psTrace(".psLib.dataManip.vectorFitPolynomial1DOrd", 4,
    1223             "---- vectorFitPolynomial1DOrd() begin ----\n");
    1224     // printf("VectorFitPolynomial1D()\n");
    1225     // for (i=0;i<x->n;i++) {
    1226     // printf("(x, y, yErr) is (%f, %f, %f)\n", x->data.F64[i], y->data.F64[i], yErr->data.F64[i]);
    1227     // }
    1228 
    1229     A = psImageAlloc(polyOrder, polyOrder, PS_TYPE_F64);
    1230     ALUD = psImageAlloc(polyOrder, polyOrder, PS_TYPE_F64);
    1231 
    1232     B = psVectorAlloc(polyOrder, PS_TYPE_F64);
    1233     coeffs = psVectorAlloc(polyOrder, PS_TYPE_F64);
    1234     X = psVectorAlloc(x->n, PS_TYPE_F64);
    1235     xSums = psVectorAlloc(1 + 2 * polyOrder, PS_TYPE_F64);
    1236 
    1237     // Initialize data structures.
    1238     for (i = 0; i < polyOrder; i++) {
    1239         B->data.F64[i] = 0.0;
    1240         coeffs->data.F64[i] = 0.0;
    1241         for (j = 0; j < polyOrder; j++) {
    1242             A->data.F64[i][j] = 0.0;
    1243             ALUD->data.F64[i][j] = 0.0;
    1244         }
    1245     }
    1246     for (i = 0; i < X->n; i++) {
    1247         X->data.F64[i] = x->data.F64[i];
    1248     }
    1249 
    1250     // Build the B and A data structs.
    1251     if (yErr == NULL) {
    1252         for (i = 0; i < X->n; i++) {
    1253             buildSums1D(X->data.F64[i], 2 * polyOrder, xSums);
    1254 
    1255             for (k = 0; k < polyOrder; k++) {
    1256                 B->data.F64[k] += y->data.F64[i] * xSums->data.F64[k];
    1257             }
    1258 
    1259             for (k = 0; k < polyOrder; k++) {
    1260                 for (j = 0; j < polyOrder; j++) {
    1261                     A->data.F64[k][j] += xSums->data.F64[k + j];
    1262                 }
    1263             }
    1264         }
    1265     } else {
    1266         for (i = 0; i < X->n; i++) {
    1267             buildSums1D(X->data.F64[i], 2 * polyOrder, xSums);
    1268 
    1269             for (k = 0; k < polyOrder; k++) {
    1270                 B->data.F64[k] += y->data.F64[i] * xSums->data.F64[k] /
    1271                                   yErr->data.F64[i];
    1272             }
    1273 
    1274             for (k = 0; k < polyOrder; k++) {
    1275                 for (j = 0; j < polyOrder; j++) {
    1276                     A->data.F64[k][j] += xSums->data.F64[k + j] /
    1277                                          yErr->data.F64[i];
    1278                 }
    1279             }
    1280         }
    1281     }
    1282 
    1283     // XXX: How do we know if these routines were successful?
    1284     ALUD = psMatrixLUD(ALUD, &outPerm, A);
    1285     coeffs = psMatrixLUSolve(coeffs, ALUD, B, outPerm);
    1286 
    1287     for (k = 0; k < polyOrder; k++) {
    1288         myPoly->coeff[k] = coeffs->data.F64[k];
    1289         // printf("myPoly->coeff[%d] is %f\n", k, myPoly->coeff[k]);
    1290     }
    1291 
    1292     psFree(A);
    1293     psFree(ALUD);
    1294     psFree(B);
    1295     psFree(coeffs);
    1296     psFree(X);
    1297     psFree(outPerm);
    1298     psFree(xSums);
    1299 
    1300     psTrace(".psLib.dataManip.vectorFitPolynomial1DOrd", 4,
    1301             "---- vectorFitPolynomial1DOrd() begin ----\n");
    1302     return (myPoly);
    1303 }
    1304 
    1305 /******************************************************************************
    1306 psVectorFitPolynomial1D():  This routine must fit a polynomial of degree
    1307 myPoly to the data points (x, y) and return the coefficients of that
    1308 polynomial.
    1309  
    1310 XXX: type F32 is done via vector conversion only.
    1311  
    1312 XXX: Get rid of this.  Use new argument list.
    1313  *****************************************************************************/
    1314 psPolynomial1D* psVectorFitPolynomial1D(psPolynomial1D* poly,
    1315                                         const psVector* x,
    1316                                         const psVector* y,
    1317                                         const psVector* yErr)
    1318 {
    1319     PS_ASSERT_POLY_NON_NULL(poly, NULL);
    1320     PS_ASSERT_INT_NONNEGATIVE(poly->n, NULL);
    1321     PS_ASSERT_VECTOR_NON_NULL(y, NULL);
    1322     PS_ASSERT_VECTOR_NON_EMPTY(y, NULL);
    1323     PS_ASSERT_VECTOR_TYPE_F32_OR_F64(y, NULL);
    1324 
    1325     psS32 i;
    1326     psVector *x64 = NULL;
    1327     psVector *y64 = NULL;
    1328     psVector *yErr64 = NULL;
    1329     static psVector *x64Static = NULL;
    1330     static psVector *y64Static = NULL;
    1331     static psVector *yErr64Static = NULL;
    1332 
    1333     PS_VECTOR_CONVERT_F32_TO_F64_STATIC(y, y64, y64Static);
    1334     // If yErr==NULL, set all errors equal.
    1335     if (yErr == NULL) {
    1336         PS_VECTOR_GEN_YERR_STATIC_F64(yErr64Static, y->n);
    1337         yErr64 = yErr64Static;
    1338     } else {
    1339         PS_ASSERT_VECTOR_TYPE_F32_OR_F64(yErr, NULL);
    1340         PS_VECTOR_CONVERT_F32_TO_F64_STATIC(yErr, yErr64, yErr64Static);
    1341     }
    1342 
    1343     // If x==NULL, create an x64 vector with x values set to (0:n).
    1344     if (x == NULL) {
    1345         PS_VECTOR_GEN_X_INDEX_STATIC_F64(x64Static, y->n);
    1346         if (poly->type == PS_POLYNOMIAL_CHEB) {
    1347             p_psNormalizeVectorRangeF64(x64Static, -1.0, 1.0);
    1348         }
    1349         x64 = x64Static;
    1350     } else {
    1351         PS_ASSERT_VECTOR_TYPE_F32_OR_F64(x, NULL);
    1352         PS_VECTOR_CONVERT_F32_TO_F64_STATIC(x, x64, x64Static);
    1353         if (poly->type == PS_POLYNOMIAL_CHEB) {
    1354             p_psNormalizeVectorRangeF64(x64, -1.0, 1.0);
    1355         }
    1356     }
    1357     PS_ASSERT_VECTORS_SIZE_EQUAL(x64, y64, NULL);
    1358     PS_ASSERT_VECTORS_SIZE_EQUAL(yErr64, y64, NULL);
    1359 
    1360     // Call the appropriate vector fitting routine.
    1361     psPolynomial1D *rc = NULL;
    1362     if (poly->type == PS_POLYNOMIAL_CHEB) {
    1363         rc = vectorFitPolynomial1DCheby(poly, x64, y64, yErr64);
    1364     } else if (poly->type == PS_POLYNOMIAL_ORD) {
    1365         rc = vectorFitPolynomial1DOrd(poly, x64, y64, yErr64);
    1366     } else {
    1367         psError(PS_ERR_BAD_PARAMETER_VALUE, true,
    1368                 "unknown polynomial type.\n");
    1369         return(NULL);
    1370     }
    1371     if (rc == NULL) {
    1372         psError(PS_ERR_UNKNOWN, true, "Could not fit a polynomial to the data.  Returning NULL.\n");
    1373         return(NULL);
    1374     }
    1375 
    1376     return(poly);
    1377 }
    1378 
    1379536static void minimizationFree(psMinimization *min)
    1380537{
    1381     // There are non dynamic allocated items
     538    // There are no dynamically allocated items
    1382539}
    1383540
     
    1437594
    1438595/******************************************************************************
     596 ******************************************************************************
     597Powell routines.
     598******************************************************************************
     599*****************************************************************************/
     600
     601/******************************************************************************
    1439602p_psDetermineBracket():  This routine takes as input an arbitrary function,
    1440603and the parameter to vary, and the line along which it must vary.  This
     
    1446609Algorithm:
    1447610 
    1448 XXX completely ad hoc:
    1449 start with the user-supplied starting parameter and
     611XXX completely ad hoc: start with the user-supplied starting parameter and
    1450612call that b.  Calculate a/c as a fractional amount smaller/larger than b.
    1451613Repeat this process until a local minimum is found.
    1452614 
    1453 XXX:
    1454 new algorithm:
    1455 start at x=0, expand in one direction until the function
     615XXX: new algorithm:  start at x=0, expand in one direction until the function
    1456616decreases.  Then you have two points in the bracket.  Keep going until it
    1457617increases, or x is too large.  If thst does not work, expand in the other
    1458618direction.
    1459619 
    1460 XXX:
    1461 This is F32 only.
     620XXX: This is F32 only.  Must add F64 support (actually, make the defaults F64,
     621and convert F32 vectors to F64).
    1462622 
    1463 XXX:
    1464 output bracket vector should be an input as well.
     623XXX: output bracket vector should be an input as well.
    1465624*****************************************************************************/
    1466625psVector *p_psDetermineBracket(psVector *params,
     
    1716875XXX: This routine is not very efficient in terms of total evaluations of the
    1717876function.
    1718 XXX: This is F32 only
     877XXX: This is F32 only (make it F64).
    1719878XXX: Since this is an internal function, many of the parameter checks are
    1720879     redundant.
     
    18711030 
    18721031XXX: The SDR is silent about data types.  F32 is implemented here.
    1873  
    1874 XXX: Check for F32 types?
     1032Reimplement in F64, convert F32 vectors to F64.
    18751033 *****************************************************************************/
    18761034#define PS_MINIMIZE_POWELL_LINEMIN_MAX_ITERATIONS 20
     
    20831241This functions uses global variables to receive the function pointer, the
    20841242data values, and the data errors.
    2085 XXX: This is F32 only
     1243XXX: This is F32 only.  Must implement F64.
    20861244 *****************************************************************************/
    20871245static psF32 myPowellChi2Func(const psVector *params,
     
    21491307/******************************************************************************
    21501308 ******************************************************************************
    2151  ******************************************************************************
    2152  ******************************************************************************
    2153 EAM Code:
    2154  ******************************************************************************
    2155  ******************************************************************************
     1309 Analytical 1-D fitting routines.
    21561310 ******************************************************************************
    21571311 *****************************************************************************/
    2158 
    2159 static psVector *EAMBuildSums1D(
     1312// XXX: Make this a general type conversion macro, or function
     1313#define PS_VECTOR_GEN_F64_FROM_F32(VECF64, VECF32) \
     1314VECF64 = psVectorAlloc(VECF32->n, PS_TYPE_F64); \
     1315for (psS32 i = 0 ; i < VECF32->n ; i++) { \
     1316    VECF64->data.F64[i] = (psF64) VECF32->data.F32[i]; \
     1317} \
     1318
     1319#define PS_VECTOR_GEN_CHEBY_INDEX(VECF64, SIZE) \
     1320VECF64 = psVectorAlloc(SIZE, PS_TYPE_F64); \
     1321for (psS32 i = 0 ; i < SIZE ; i++) { \
     1322    VECF64->data.F64[i] = ((2.0 / ((psF64) (SIZE - 1))) * ((psF64) i)) - 1.0; \
     1323}\
     1324/******************************************************************************
     1325BuildSums1D(sums, x, polyOrder, sums): this routine calculates the powers of
     1326input parameter "x" between 0 and input parameter nTerms*2.  The result is
     1327returned as a psVector sums.
     1328*****************************************************************************/
     1329static psVector *BuildSums1D(
    21601330    psVector* sums,
    21611331    psF64 x,
     
    21661336
    21671337    //
    2168     // XXX: Why do we multiply by 2 here?  Better to do it outside and have the
    2169     // definition of this function remain sensible.
     1338    // XXX: Why do we multiply by 2 here?  It's better to do it outside and
     1339    // have the definition of this function remain sensible.
    21701340    //
    21711341    nSum = 2*nTerm;
     
    21841354}
    21851355
    2186 // XXX EAM : test version of 1d fitting
    2187 psPolynomial1D* VectorFitPolynomial1DOrd_EAM(
     1356/******************************************************************************
     1357BuildSums2D(sums, x, y, nXterm, nYterm): this routine calculates the powers of
     1358input parameter "x" and "y" between 0 and input parameter nXterms*2 and
     1359nYterm*2.  The result is returned as a psImage sums.
     1360 *****************************************************************************/
     1361static psImage *BuildSums2D(
     1362    psImage *sums,
     1363    psF64 x,
     1364    psF64 y,
     1365    psS32 nXterm,
     1366    psS32 nYterm)
     1367{
     1368    psS32 nXsum = 0;
     1369    psS32 nYsum = 0;
     1370    psF64 xSum = 1.0;
     1371    psF64 ySum = 1.0;
     1372
     1373    nXsum = 2*nXterm;
     1374    nYsum = 2*nYterm;
     1375    if (sums == NULL) {
     1376        sums = psImageAlloc(nXsum, nYsum, PS_TYPE_F64);
     1377    }
     1378    if ((nXsum != sums->numCols) || (nYsum != sums->numRows)) {
     1379        psFree (sums);
     1380        sums = psImageAlloc(nXsum, nYsum, PS_TYPE_F64);
     1381    }
     1382
     1383    ySum = 1.0;
     1384    for (int j = 0; j < nYsum; j++) {
     1385        xSum = ySum;
     1386        for (int i = 0; i < nXsum; i++) {
     1387            sums->data.F64[i][j] = xSum;
     1388            xSum *= x;
     1389        }
     1390        ySum *= y;
     1391    }
     1392    return (sums);
     1393}
     1394
     1395
     1396/******************************************************************************
     1397Polynomial2DEvalVectorD(myPoly, x, y): This routine takes as input two
     1398psVectors x and y, and evaluates myPoly for each pair of (x, y), and stores it
     1399in the output vector.  This routine works on single-precision polynomials with
     1400double precision data.
     1401 *****************************************************************************/
     1402psVector *Polynomial2DEvalVectorD(
     1403    const psPolynomial2D *myPoly,
     1404    const psVector *x,
     1405    const psVector *y)
     1406{
     1407    PS_ASSERT_POLY_NON_NULL(myPoly, NULL);
     1408    PS_ASSERT_VECTOR_NON_NULL(x, NULL);
     1409    PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F64, NULL);
     1410    PS_ASSERT_VECTOR_NON_NULL(y, NULL);
     1411    PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F64, NULL);
     1412
     1413    //
     1414    // Set the length of the output vector to the minimum of the x,y vectors.
     1415    //
     1416    psS32 vecLen=x->n;
     1417    if (y->n < vecLen) {
     1418        vecLen = y->n;
     1419    }
     1420
     1421    //
     1422    // Create output vector to return
     1423    //
     1424    psVector *tmp = psVectorAlloc(vecLen, PS_TYPE_F64);
     1425
     1426    //
     1427    // Evaluate the polynomial at the specified points
     1428    //
     1429    for (psS32 i=0; i<vecLen; i++) {
     1430        tmp->data.F64[i] = psPolynomial2DEval(myPoly, x->data.F64[i], y->data.F64[i]);
     1431    }
     1432
     1433    return(tmp);
     1434}
     1435
     1436/******************************************************************************
     1437 ******************************************************************************
     1438 1-D Vector Fitting Code.
     1439 ******************************************************************************
     1440 *****************************************************************************/
     1441
     1442/******************************************************************************
     1443vectorFitPolynomial1DCheb():  This routine will fit a Chebyshev polynomial of
     1444degree myPoly to the data points (x, y) and return the coefficients of that
     1445polynomial.
     1446 
     1447XXX: mask, maskValue, yErr are currently ignored.
     1448 
     1449XXX: Change arg order to that of the psLib function.
     1450*****************************************************************************/
     1451static psPolynomial1D *vectorFitPolynomial1DCheby(
    21881452    psPolynomial1D* myPoly,
    2189     psVector *mask,
    2190     const psVector *x,
    2191     const psVector *y,
    2192     const psVector *yErr)
    2193 {
    2194     // I think this is 1 dimension down
     1453    const psVector *mask,
     1454    psMaskType maskValue,
     1455    const psVector* y,
     1456    const psVector* yErr,
     1457    const psVector* x)
     1458{
     1459    // XXX: these ASSERTS are redundant.
     1460    PS_ASSERT_POLY_NON_NULL(myPoly, NULL);
     1461    PS_ASSERT_INT_NONNEGATIVE(myPoly->n, NULL);
     1462    PS_ASSERT_VECTOR_NON_NULL(y, NULL);
     1463    PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F64, NULL);
     1464    if (yErr != NULL) {
     1465        PS_ASSERT_VECTORS_SIZE_EQUAL(y, yErr, NULL);
     1466        PS_ASSERT_VECTOR_TYPE(yErr, PS_TYPE_F64, NULL);
     1467    }
     1468    if (x != NULL) {
     1469        PS_ASSERT_VECTORS_SIZE_EQUAL(y, x, NULL);
     1470        PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F64, NULL);
     1471    }
     1472
     1473    psS32 j;
     1474    psS32 k;
     1475    psS32 n = y->n;
     1476    psF64 fac;
     1477    psF64 sum;
     1478    PS_VECTOR_GEN_STATIC_RECYCLED(f, n, PS_TYPE_F64);
     1479    psScalar *fScalar;
     1480    psScalar tmpScalar;
     1481    tmpScalar.type.type = PS_TYPE_F64;
     1482
     1483    // XXX: These assignments appear too simple to warrant code and
     1484    // variable declarations.  I retain them here to maintain coherence
     1485    // with the NR code.
     1486    psF64 min = -1.0;
     1487    psF64 max = 1.0;
     1488    psF64 bma = 0.5 * (max-min);  // 1
     1489    psF64 bpa = 0.5 * (max+min);  // 0
     1490
     1491    // In this loop, we first calculate the values of X for which the
     1492    // Chebyshev polynomials are zero (see NR, section 5.4).  Then we
     1493    // calculate the value of the function we are fitting the Chebyshev
     1494    // polynomials to at those values of X.  This is a bit tricky since
     1495    // we don't know that function.  So, we instead do 3-order LaGrange
     1496    // interpolation at the point X for the psVectors x,y for which we
     1497    // are fitting this ChebyShev polynomial to.
     1498
     1499    for (psS32 i=0;i<n;i++) {
     1500        // NR 5.8.4
     1501        psF64 Y = cos(M_PI * (0.5 + ((psF32) i)) / ((psF32) n));
     1502        psF64 X = (Y + bma + bpa) - 1.0;
     1503        tmpScalar.data.F64 = X;
     1504
     1505        // We interpolate against the tabluated x,y vectors to determine the
     1506        // function value at X.
     1507        fScalar = p_psVectorInterpolate((psVector *) x,
     1508                                        (psVector *) y,
     1509                                        3,
     1510                                        &tmpScalar);
     1511
     1512        f->data.F64[i] = fScalar->data.F64;
     1513        psFree(fScalar);
     1514
     1515        psTrace(".psLib.dataManip.vectorFitPolynomial1DCheby", 6,
     1516                "(x, X, y, f(X)) is (%f, %f, %f, %f)\n",
     1517                x->data.F64[i], X, y->data.F64[i], f->data.F64[i]);
     1518    }
     1519
     1520    // We have the values for f() at the zero points, we now calculate the
     1521    // coefficients of the Chebyshev polynomial: NR 5.8.7.
     1522
     1523    fac = 2.0/((psF32) n);
     1524    // XXX: is this loop bound correct?
     1525    for (j=0;j<myPoly->n;j++) {
     1526        sum = 0.0;
     1527        for (k=0;k<n;k++) {
     1528            sum+= f->data.F64[k] *
     1529                  cos(M_PI * ((psF32) j) * (0.5 + ((psF32) k)) / ((psF32) n));
     1530        }
     1531
     1532        myPoly->coeff[j] = fac * sum;
     1533    }
     1534
     1535    return(myPoly);
     1536}
     1537
     1538/******************************************************************************
     1539VectorFitPolynomial1DOrd(myPoly, *mask, maskValue, *y, *yErr, *x): This is a
     1540private routine which will fit a 1-D polynomial to a set of (x, f) pairs.  The
     1541x and fErr vectors may be NULL.  All non-NULL vectors must be of type
     1542PS_TYPE_F64.
     1543 *****************************************************************************/
     1544psPolynomial1D* VectorFitPolynomial1DOrd(
     1545    psPolynomial1D* myPoly,
     1546    const psVector *mask,
     1547    psMaskType maskValue,
     1548    const psVector *f,
     1549    const psVector *fErr,
     1550    const psVector *x)
     1551{
     1552    // XXX: these ASSERTS are redundant.
     1553    PS_ASSERT_POLY_NON_NULL(myPoly, NULL);
     1554    PS_ASSERT_INT_NONNEGATIVE(myPoly->n, NULL);
     1555    PS_ASSERT_VECTOR_NON_NULL(f, NULL);
     1556    PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F64, NULL);
     1557    if (mask != NULL) {
     1558        PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL);
     1559        PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL);
     1560    }
     1561    if (x != NULL) {
     1562        PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL);
     1563        PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F64, NULL);
     1564    }
     1565    if (fErr != NULL) {
     1566        PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, NULL);
     1567        PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F64, NULL);
     1568    }
     1569
    21951570    psImage*     A = NULL;
    21961571    psVector*    B = NULL;
     
    22041579
    22051580    if (psTraceGetLevel (".psLib.dataManip.VectorFitPolynomial1DOrd") >= 5) {
    2206         FILE *f = fdopen((psTraceGetDestination ()), "a+");
    2207         fprintf (f, "VectorFitPolynomial1D()\n");
    2208         for (int i = 0; i < x->n; i++) {
    2209             fprintf (f, "(x, y, yErr) is (%f, %f, %f)\n", x->data.F64[i], y->data.F64[i], yErr->data.F64[i]);
    2210         }
    2211         fclose(f);
     1581        FILE *fp = fdopen((psTraceGetDestination ()), "a+");
     1582        fprintf(fp, "VectorFitPolynomial1D()\n");
     1583        for (int i = 0; i < f->n; i++) {
     1584            fprintf(fp, "(x, f, fErr) is (");
     1585            if (x != NULL) {
     1586                fprintf(fp, "%f, %f, ", x->data.F64[i], f->data.F64[i]);
     1587            } else {
     1588                fprintf(fp, "%f, %f, ", (psF64) i, f->data.F64[i]);
     1589            }
     1590            if (fErr != NULL) {
     1591                fprintf(fp, "%f)\n", fErr->data.F64[i]);
     1592            } else {
     1593                fprintf(fp, "NULL)\n");
     1594            }
     1595        }
     1596        fclose(fp);
    22121597    }
    22131598
     
    22271612    // xSums look like: 1, x, x^2, ... x^(2n+1)
    22281613    // Build the B and A data structs.
    2229     for (int k = 0; k < x->n; k++) {
     1614    for (int k = 0; k < f->n; k++) {
    22301615        if ((mask != NULL) && mask->data.U8[k])
    22311616            continue;
    2232         xSums = EAMBuildSums1D(xSums, x->data.F64[k], nTerm);
    2233 
    2234         if (yErr == NULL) {
     1617        if (x != NULL) {
     1618            xSums = BuildSums1D(xSums, x->data.F64[k], nTerm);
     1619        } else {
     1620            xSums = BuildSums1D(xSums, (psF64) k, nTerm);
     1621        }
     1622
     1623        if (fErr == NULL) {
    22351624            wt = 1.0;
    22361625        } else {
    2237             // this should filter yErr == 0 values
    2238             wt = 1.0 / PS_SQR(yErr->data.F64[k]);
     1626            // this should filter fErr == 0 values
     1627            wt = 1.0 / PS_SQR(fErr->data.F64[k]);
    22391628        }
    22401629        for (int i = 0; i < nTerm; i++) {
    2241             B->data.F64[i] += y->data.F64[k] * xSums->data.F64[i] * wt;
     1630            B->data.F64[i] += f->data.F64[k] * xSums->data.F64[i] * wt;
    22421631        }
    22431632
     
    22611650            myPoly->coeff[k] = B->data.F64[k];
    22621651        }
    2263     } else
     1652    } else {
    22641653        // LUD version of the fit
    2265     {
    22661654        psImage *ALUD = NULL;
    22671655        psVector* outPerm = NULL;
     
    22741662            myPoly->coeff[k] = coeffs->data.F64[k];
    22751663        }
     1664        psFree(ALUD);
     1665        psFree(coeffs);
     1666        psFree(outPerm);
    22761667    }
    22771668
     
    22811672
    22821673    psTrace(".psLib.dataManip.VectorFitPolynomial1DOrd", 4,
    2283             "---- VectorFitPolynomial1DOrd() begin ----\n");
     1674            "---- VectorFitPolynomial1DOrd() End ----\n");
    22841675    return (myPoly);
    22851676}
    22861677
    2287 // XXX EAM : this version uses the F64 vectors
    2288 psVector *Polynomial2DEvalVectorD(
    2289     const psPolynomial2D *myPoly,
     1678
     1679/******************************************************************************
     1680psVectorFitPolynomial1D():  This routine fits a polynomial of arbitrary degree
     1681(specified in poly) to the data points (x, y) and return that polynomial.
     1682Types F32 and F64 are supported, however, type F32 is done via vector
     1683conversion only.
     1684 *****************************************************************************/
     1685psPolynomial1D *psVectorFitPolynomial1D(
     1686    psPolynomial1D *poly,
     1687    const psVector *mask,
     1688    psMaskType maskValue,
     1689    const psVector *f,
     1690    const psVector *fErr,
     1691    const psVector *x)
     1692{
     1693    // Internal pointers for possibly NULL or mis-typed vectors.
     1694    psVector *x64 = NULL;
     1695    psVector *f64 = NULL;
     1696    psVector *fErr64 = NULL;
     1697
     1698    PS_ASSERT_POLY_NON_NULL(poly, NULL);
     1699    PS_ASSERT_INT_NONNEGATIVE(poly->n, NULL);
     1700    PS_ASSERT_VECTOR_NON_NULL(f, NULL);
     1701    PS_ASSERT_VECTOR_NON_EMPTY(f, NULL);
     1702    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, NULL);
     1703    if (f->type.type != PS_TYPE_F64) {
     1704        PS_VECTOR_GEN_F64_FROM_F32(f64, f);
     1705    } else {
     1706        f64 = (psVector *) f;
     1707    }
     1708
     1709    if (mask != NULL) {
     1710        PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL);
     1711        PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL);
     1712    }
     1713
     1714    if (x != NULL) {
     1715        PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL);
     1716        PS_ASSERT_VECTOR_TYPE_F32_OR_F64(x, NULL);
     1717        if (x->type.type != PS_TYPE_F64) {
     1718            PS_VECTOR_GEN_F64_FROM_F32(x64, x);
     1719        } else {
     1720            x64 = (psVector *) x;
     1721        }
     1722    }
     1723
     1724    if (fErr != NULL) {
     1725        PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, NULL);
     1726        PS_ASSERT_VECTOR_TYPE_F32_OR_F64(fErr, NULL);
     1727        if (fErr->type.type != PS_TYPE_F64) {
     1728            PS_VECTOR_GEN_F64_FROM_F32(fErr64, fErr);
     1729        } else {
     1730            fErr64 = (psVector *) fErr;
     1731        }
     1732    }
     1733
     1734    if (poly->type == PS_POLYNOMIAL_ORD) {
     1735        poly = VectorFitPolynomial1DOrd(poly, mask, maskValue, f64, fErr64, x64);
     1736        if (poly == NULL) {
     1737            psError(PS_ERR_UNKNOWN, false, "Could not fit polynomial.  Returning NULL.\n");
     1738            return(NULL);
     1739        }
     1740    } else if (poly->type == PS_POLYNOMIAL_CHEB) {
     1741        if (mask != NULL) {
     1742            psLogMsg(__func__, PS_LOG_WARN, "WARNING: ignoring mask and maskValue with Chebyshev polynomials.\n");
     1743        }
     1744        if (x == NULL) {
     1745            // If x==NULL, create an x64 vector with x values set to (-1:1).
     1746            PS_VECTOR_GEN_CHEBY_INDEX(x64, f64->n);
     1747        }
     1748        // XXX: Change arg order.
     1749        // XXX: Must modify this routine so that x64 or fErr64 can be NULL.
     1750        poly = vectorFitPolynomial1DCheby(poly, NULL, 0, f64, fErr64, x64);
     1751        if (x == NULL) {
     1752            psFree(x64);
     1753        }
     1754    } else {
     1755        psError(PS_ERR_UNKNOWN, true, "Incorrect polynomial type.  Returning NULL.\n");
     1756    }
     1757
     1758    // Free psVectors that were created for NULL arguments.
     1759    if (f->type.type != PS_TYPE_F64) {
     1760        psFree(f64);
     1761    }
     1762
     1763    if ((x != NULL) && (x->type.type != PS_TYPE_F64)) {
     1764        psFree(x64);
     1765    }
     1766
     1767    if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) {
     1768        psFree(fErr64);
     1769    }
     1770
     1771    return(NULL);
     1772}
     1773
     1774
     1775psPolynomial1D *psVectorClipFitPolynomial1D(
     1776    psPolynomial1D *poly,
     1777    psStats *stats,
     1778    const psVector *mask,
     1779    psMaskType maskValue,
     1780    const psVector *f,
     1781    const psVector *fErr,
     1782    const psVector *x)
     1783{
     1784    // Internal pointers for possibly NULL vectors.
     1785    psVector *x32 = NULL;
     1786
     1787    PS_ASSERT_POLY_NON_NULL(poly, NULL);
     1788    PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, NULL);
     1789    PS_ASSERT_PTR_NON_NULL(stats, NULL);
     1790    PS_ASSERT_VECTOR_NON_NULL(f, NULL);
     1791    PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F32, NULL);
     1792    if (mask != NULL) {
     1793        PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL);
     1794        PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL);
     1795    }
     1796    if (x != NULL) {
     1797        PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL);
     1798        PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F32, NULL);
     1799    }
     1800    if (fErr != NULL) {
     1801        PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, NULL);
     1802        PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F32, NULL);
     1803    }
     1804
     1805    psLogMsg(__func__, PS_LOG_WARN, "WARNING: This function has not been implemented.  Returning NULL.\n");
     1806    // Free psVectors that were created for NULL arguments.
     1807    if (x == NULL) {
     1808        psFree(x32);
     1809    }
     1810    return(NULL);
     1811}
     1812
     1813
     1814/******************************************************************************
     1815 ******************************************************************************
     1816 2-D Vector Fitting Code.
     1817 ******************************************************************************
     1818 *****************************************************************************/
     1819
     1820/******************************************************************************
     1821VectorFitPolynomial2DOrd(myPoly, *mask, maskValue, *f, *fErr, *x, *y): This is
     1822a private routine which will fit a 2-D polynomial to a set of (x, y)-(f)
     1823pairs.  All non-NULL vectors must be of type PS_TYPE_F64.
     1824 
     1825// XXX: What about the maskValue?
     1826 *****************************************************************************/
     1827psPolynomial2D* VectorFitPolynomial2DOrd(
     1828    psPolynomial2D* myPoly,
     1829    const psVector* mask,
     1830    psMaskType maskValue,
     1831    const psVector *f,
     1832    const psVector *fErr,
    22901833    const psVector *x,
    22911834    const psVector *y)
    22921835{
     1836    // These ASSERTS are redundant.
    22931837    PS_ASSERT_POLY_NON_NULL(myPoly, NULL);
     1838    PS_ASSERT_INT_NONNEGATIVE(myPoly->nX, NULL);
     1839    PS_ASSERT_INT_NONNEGATIVE(myPoly->nY, NULL);
     1840
     1841    PS_ASSERT_VECTOR_NON_NULL(f, NULL);
     1842    PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F64, NULL);
     1843    if (fErr != NULL) {
     1844        PS_ASSERT_VECTORS_SIZE_EQUAL(y, fErr, NULL);
     1845        PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F64, NULL);
     1846    }
     1847    PS_ASSERT_VECTOR_NON_NULL(y, NULL);
     1848    PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F64, NULL);
     1849    PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL);
    22941850    PS_ASSERT_VECTOR_NON_NULL(x, NULL);
    22951851    PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F64, NULL);
    2296     PS_ASSERT_VECTOR_NON_NULL(y, NULL);
    2297     PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F64, NULL);
    2298 
    2299     psVector *tmp;
    2300     psS32 vecLen=x->n;
    2301 
    2302     // Determine the length of the output vector to by the minimum of the x,y vectors
    2303     if (y->n < vecLen) {
    2304         vecLen = y->n;
    2305     }
    2306 
    2307     // Create output vector to return
    2308     tmp = psVectorAlloc(vecLen, PS_TYPE_F64);
    2309 
    2310     // Evaluate the polynomial at the specified points
    2311     for (psS32 i=0; i<vecLen; i++) {
    2312         tmp->data.F64[i] = psPolynomial2DEval(myPoly, x->data.F64[i], y->data.F64[i]);
    2313     }
    2314 
    2315     // Return output vector
    2316     return(tmp);
    2317 }
    2318 
    2319 // XXX EAM : EAMBuildSums2D in analogy with EAMBuildSums1D
    2320 static psImage *EAMBuildSums2D(
    2321     psImage *sums,
    2322     psF64 x,
    2323     psF64 y,
    2324     psS32 nXterm,
    2325     psS32 nYterm)
    2326 {
    2327     psS32 nXsum = 0;
    2328     psS32 nYsum = 0;
    2329     psF64 xSum = 1.0;
    2330     psF64 ySum = 1.0;
    2331 
    2332     nXsum = 2*nXterm;
    2333     nYsum = 2*nYterm;
    2334     if (sums == NULL) {
    2335         sums = psImageAlloc(nXsum, nYsum, PS_TYPE_F64);
    2336     }
    2337     if ((nXsum != sums->numCols) || (nYsum != sums->numRows)) {
    2338         psFree (sums);
    2339         sums = psImageAlloc(nXsum, nYsum, PS_TYPE_F64);
    2340     }
    2341 
    2342     ySum = 1.0;
    2343     for (int j = 0; j < nYsum; j++) {
    2344         xSum = ySum;
    2345         for (int i = 0; i < nXsum; i++) {
    2346             sums->data.F64[i][j] = xSum;
    2347             xSum *= x;
    2348         }
    2349         ySum *= y;
    2350     }
    2351     return (sums);
    2352 }
    2353 
    2354 // XXX EAM : test version of 2d fitting
    2355 psPolynomial2D* VectorFitPolynomial2DOrd_EAM(
    2356     psPolynomial2D* myPoly,
    2357     psVector* mask,
    2358     const psVector* x,
    2359     const psVector* y,
    2360     const psVector* z,
    2361     const psVector* zErr)
    2362 {
     1852    PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL);
     1853    if (mask != NULL) {
     1854        PS_ASSERT_VECTORS_SIZE_EQUAL(y, mask, NULL);
     1855        PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL);
     1856    }
     1857
    23631858    // I think this is 1 dimension down
    23641859    psImage*     A = NULL;
     
    23891884        if ((mask != NULL) && mask->data.U8[k])
    23901885            continue;
    2391         Sums = EAMBuildSums2D(Sums, x->data.F64[k], y->data.F64[k], nXterm, nYterm);
    2392 
    2393         if (zErr == NULL) {
     1886        Sums = BuildSums2D(Sums, x->data.F64[k], y->data.F64[k], nXterm, nYterm);
     1887
     1888        if (fErr == NULL) {
    23941889            wt = 1.0;
    23951890        } else {
    2396             // XXX: this should probably by zErr^2 !!
    2397             // this should filter zErr == 0 values
    2398             // XXX: Why isn't this zErr^2?
    2399             wt = 1.0 / zErr->data.F64[k];
     1891            // XXX: this should probably by fErr^2 !!
     1892            // this should filter fErr == 0 values
     1893            // XXX: Why isn't this fErr^2?
     1894            wt = 1.0 / fErr->data.F64[k];
    24001895        }
    24011896
     
    24041899        for (int n = 0; n < nXterm; n++) {
    24051900            for (int m = 0; m < nYterm; m++) {
    2406                 B->data.F64[n+m*nXterm] += z->data.F64[k] * Sums->data.F64[n][m] * wt;
     1901                B->data.F64[n+m*nXterm] += f->data.F64[k] * Sums->data.F64[n][m] * wt;
    24071902            }
    24081903        }
     
    24471942    const psVector* x,
    24481943    const psVector* y,
    2449     const psVector* z,
    2450     const psVector* dz)
     1944    const psVector* f,
     1945    const psVector* df)
    24511946{
    24521947    psVector *X;
     
    24551950    psVector *dZ;
    24561951
    2457     psVector *zFit   = NULL;
    2458     psVector *zResid = NULL;
     1952    psVector *fFit   = NULL;
     1953    psVector *fResid = NULL;
    24591954    psStats  *stats  = NULL;
    24601955
    24611956    X  = psVectorCopy (NULL, x, PS_TYPE_F64);
    24621957    Y  = psVectorCopy (NULL, y, PS_TYPE_F64);
    2463     Z  = psVectorCopy (NULL, z, PS_TYPE_F64);
    2464     dZ = psVectorCopy (NULL, dz, PS_TYPE_F64);
     1958    Z  = psVectorCopy (NULL, f, PS_TYPE_F64);
     1959    dZ = psVectorCopy (NULL, df, PS_TYPE_F64);
    24651960
    24661961    for (int N = 0; N < 3; N++) {
    24671962        // XXX EAM : this would be better defined with an element mask
    2468         poly   = VectorFitPolynomial2DOrd_EAM(poly, NULL, X, Y, Z, dZ);
    2469         zFit   = Polynomial2DEvalVectorD(poly, x, y);
    2470         zResid = (psVector *) psBinaryOp(NULL, (void *) z, "-", (void *) zFit);
     1963        poly   = VectorFitPolynomial2DOrd(poly, NULL, 0, X, Y, Z, dZ);
     1964        fFit   = Polynomial2DEvalVectorD(poly, x, y);
     1965        fResid = (psVector *) psBinaryOp(NULL, (void *) f, "-", (void *) fFit);
    24711966
    24721967        stats = psStatsAlloc (PS_STAT_CLIPPED_MEAN | PS_STAT_CLIPPED_STDEV);
    2473         stats  = psVectorStats (stats, zResid, NULL, NULL, 0);
     1968        stats  = psVectorStats (stats, fResid, NULL, NULL, 0);
    24741969        psTrace (".psphot.RobustFit", 4, "residual stats for robust fit:  %g +/- %g (%d pts)\n", stats->clippedMean, stats->clippedStdev, stats->clippedNvalues);
    24751970
    24761971        // re-create X, Y, Z, dZ if pts are valid
    24771972        int n = 0;
    2478         for (int i = 0; i < zResid->n; i++) {
    2479             if (fabs(zResid->data.F64[i] - stats->clippedMean) > 3*stats->clippedStdev) {
     1973        for (int i = 0; i < fResid->n; i++) {
     1974            if (fabs(fResid->data.F64[i] - stats->clippedMean) > 3*stats->clippedStdev) {
    24801975                continue;
    24811976            }
    24821977            X->data.F64[n]  =  x->data.F64[i];
    24831978            Y->data.F64[n]  =  y->data.F64[i];
    2484             Z->data.F64[n]  =  z->data.F64[i];
    2485             dZ->data.F64[n] = dz->data.F64[i];
     1979            Z->data.F64[n]  =  f->data.F64[i];
     1980            dZ->data.F64[n] = df->data.F64[i];
    24861981            n++;
    24871982        }
     
    25072002
    25082003psPolynomial2D* RobustFit2D(psPolynomial2D* poly,
    2509                             psVector* mask,
     2004                            const psVector* mask,
    25102005                            const psVector* x,
    25112006                            const psVector* y,
    2512                             const psVector* z,
    2513                             const psVector* dz)
     2007                            const psVector* f,
     2008                            const psVector* df)
    25142009{
    25152010    PS_ASSERT_VECTOR_NON_NULL(mask, NULL);
    25162011    PS_ASSERT_VECTOR_NON_NULL(x, NULL);
    25172012    PS_ASSERT_VECTOR_NON_NULL(y, NULL);
    2518     PS_ASSERT_VECTOR_NON_NULL(z, NULL);
    2519     PS_ASSERT_VECTOR_NON_NULL(dz, NULL);
    2520 
    2521     psVector *zFit   = NULL;
    2522     psVector *zResid = psVectorAlloc (x->n, PS_TYPE_F64);
     2013    PS_ASSERT_VECTOR_NON_NULL(f, NULL);
     2014    PS_ASSERT_VECTOR_NON_NULL(df, NULL);
     2015
     2016    psVector *fFit   = NULL;
     2017    psVector *fResid = psVectorAlloc (x->n, PS_TYPE_F64);
    25232018    psStats  *stats  = psStatsAlloc (PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_STDEV);
    25242019
    25252020    for (int N = 0; N < 3; N++) {
    2526         poly   = VectorFitPolynomial2DOrd_EAM (poly, mask, x, y, z, dz);
    2527         zFit   = Polynomial2DEvalVectorD (poly, x, y);
    2528         zResid = (psVector *) psBinaryOp(zResid, (void *) z, "-", (void *) zFit);
    2529 
    2530         stats  = psVectorStats (stats, zResid, NULL, mask, 1);
     2021        poly   = VectorFitPolynomial2DOrd (poly, mask, 0, x, y, f, df);
     2022        fFit   = Polynomial2DEvalVectorD (poly, x, y);
     2023        fResid = (psVector *) psBinaryOp(fResid, (void *) f, "-", (void *) fFit);
     2024
     2025        stats  = psVectorStats (stats, fResid, NULL, mask, 1);
    25312026        psTrace (".psphot.RobustFit", 4, "residual stats for robust fit:  %g +/- %g\n",
    25322027                 stats->sampleMean, stats->sampleStdev);
     
    25352030        // we are masking out any point which is out of range
    25362031        // recovery is not allowed with this scheme
    2537         for (int i = 0; i < zResid->n; i++) {
     2032        for (int i = 0; i < fResid->n; i++) {
    25382033            if (mask->data.U8[i])
    25392034                continue;
    2540             if (fabs(zResid->data.F64[i] - stats->sampleMean) > 3*stats->sampleStdev) {
     2035            if (fabs(fResid->data.F64[i] - stats->sampleMean) > 3*stats->sampleStdev) {
    25412036                mask->data.U8[i] = 1;
    25422037                continue;
    25432038            }
    25442039        }
    2545         psFree (zFit);
    2546     }
    2547     psFree (zResid);
     2040        psFree (fFit);
     2041    }
     2042    psFree (fResid);
    25482043    psFree (stats);
    25492044    return (poly);
    25502045}
    25512046
     2047
    25522048/******************************************************************************
    2553  ******************************************************************************
    2554  ******************************************************************************
    2555  ******************************************************************************
    2556 NEW Code:
    2557  ******************************************************************************
    2558  ******************************************************************************
    2559  ******************************************************************************
     2049psVectorFitPolynomial2D():  This routine fits a 2D polynomial of arbitrary
     2050degree (specified in poly) to the data points (x, y)-(f) and returns that
     2051polynomial.  Types F32 and F64 are supported, however, type F32 is done via
     2052vector conversion only.
    25602053 *****************************************************************************/
    2561 
    2562 #define PS_VECTOR_GEN_INDEX_F32(VEC, SIZE) \
    2563 VEC = psVectorAlloc(SIZE, PS_TYPE_F32); \
    2564 for (psS32 i = 0 ; i < SIZE ; i++) { \
    2565     VEC->data.F32[i] = (psF32) i; \
    2566 } \
    2567 
    2568 psPolynomial1D *psVectorFitPolynomial1D_NEW(
    2569     psPolynomial1D *poly,
    2570     const psVector *mask,
    2571     psMaskType maskValue,
    2572     const psVector *f,
    2573     const psVector *fErr,
    2574     const psVector *x)
    2575 {
    2576     // Internal pointers for possibly NULL vectors.
    2577     psVector *x32 = NULL;
    2578     psVector *fErr32 = NULL;
    2579 
    2580     PS_ASSERT_POLY_NON_NULL(poly, NULL);
    2581     PS_ASSERT_VECTOR_NON_NULL(f, NULL);
    2582     PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F32, NULL);
    2583     if (mask != NULL) {
    2584         PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL);
    2585         PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL);
    2586     }
    2587     if (x != NULL) {
    2588         PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL);
    2589         PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F32, NULL);
    2590     } else {
    2591         PS_VECTOR_GEN_INDEX_F32(x32, f->n);
    2592     }
    2593 
    2594     if (fErr != NULL) {
    2595         PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, NULL);
    2596         PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F32, NULL);
    2597     } else {
    2598         fErr = psVectorAlloc(f->n, PS_TYPE_F32);
    2599         PS_VECTOR_SET_F32(fErr, 1.0);
    2600     }
    2601 
    2602     psLogMsg(__func__, PS_LOG_WARN, "WARNING: This function has not been implemented.  Returning NULL.\n");
    2603     if (poly->type == PS_POLYNOMIAL_ORD) {
    2604         // XXX: Call EAM code
    2605     } else if (poly->type == PS_POLYNOMIAL_CHEB) {
    2606         // XXX: Call my code
    2607     } else {
    2608         printf("XXX: ERROR: incorrect polynomial type.\n");
    2609     }
    2610 
    2611     // Free psVectors that were created for NULL arguments.
    2612     if (x == NULL) {
    2613         psFree(x32);
    2614     }
    2615     if (fErr == NULL) {
    2616         psFree(fErr32);
    2617     }
    2618 
    2619     return(NULL);
    2620 }
    2621 
    2622 
    2623 psPolynomial2D *psVectorFitPolynomial2D_NEW(
    2624     psPolynomial1D *poly,
     2054psPolynomial2D *psVectorFitPolynomial2D(
     2055    psPolynomial2D *poly,
    26252056    const psVector *mask,
    26262057    psMaskType maskValue,
     
    26302061    const psVector *y)
    26312062{
    2632     // Internal pointers for possibly NULL vectors.
    2633     psVector *fErr32 = NULL;
     2063    // Internal pointers for possibly NULL or mis-typed vectors.
     2064    psVector *x64 = NULL;
     2065    psVector *y64 = NULL;
     2066    psVector *f64 = NULL;
     2067    psVector *fErr64 = NULL;
    26342068
    26352069    PS_ASSERT_POLY_NON_NULL(poly, NULL);
    26362070    PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, NULL);
     2071
     2072    //
     2073    // f
     2074    //
     2075    PS_ASSERT_VECTOR_NON_NULL(f, NULL);
     2076    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, NULL);
     2077    if (f->type.type != PS_TYPE_F64) {
     2078        PS_VECTOR_GEN_F64_FROM_F32(f64, f);
     2079    } else {
     2080        f64 = (psVector *) f;
     2081    }
     2082    if (mask != NULL) {
     2083        PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL);
     2084        PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL);
     2085    }
     2086
     2087    //
     2088    // x
     2089    //
     2090    PS_ASSERT_VECTOR_NON_NULL(x, NULL);
     2091    PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL);
     2092    if (x->type.type != PS_TYPE_F64) {
     2093        PS_VECTOR_GEN_F64_FROM_F32(x64, x);
     2094    } else {
     2095        x64 = (psVector *) x;
     2096    }
     2097
     2098    //
     2099    // y
     2100    //
     2101    PS_ASSERT_VECTOR_NON_NULL(y, NULL);
     2102    PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL);
     2103    if (y->type.type != PS_TYPE_F64) {
     2104        PS_VECTOR_GEN_F64_FROM_F32(y64, y);
     2105    } else {
     2106        y64 = (psVector *) y;
     2107    }
     2108
     2109    //
     2110    // fErr
     2111    //
     2112    if (fErr != NULL) {
     2113        PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, NULL);
     2114        PS_ASSERT_VECTOR_TYPE_F32_OR_F64(fErr, NULL);
     2115        if (fErr->type.type != PS_TYPE_F64) {
     2116            PS_VECTOR_GEN_F64_FROM_F32(fErr64, fErr);
     2117        } else {
     2118            fErr64 = (psVector *) fErr;
     2119        }
     2120    }
     2121
     2122    if (poly->type == PS_POLYNOMIAL_ORD) {
     2123        poly = VectorFitPolynomial2DOrd(poly, mask, maskValue, f64, fErr64, x64, y64);
     2124        if (poly == NULL) {
     2125            psError(PS_ERR_UNKNOWN, true, "Could not fit polynomial.  Returning NULL.\n");
     2126            // Free psVectors that were created for NULL arguments.
     2127            if (f->type.type != PS_TYPE_F64) {
     2128                psFree(f64);
     2129            }
     2130
     2131            if (x->type.type != PS_TYPE_F64) {
     2132                psFree(x64);
     2133            }
     2134
     2135            if (y->type.type != PS_TYPE_F64) {
     2136                psFree(y64);
     2137            }
     2138
     2139            if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) {
     2140                psFree(fErr64);
     2141            }
     2142            return(NULL);
     2143        }
     2144    } else if (poly->type == PS_POLYNOMIAL_CHEB) {
     2145        if (mask != NULL) {
     2146            psLogMsg(__func__, PS_LOG_WARN, "WARNING: ignoring mask and maskValue with Chebyshev polynomials.\n");
     2147        }
     2148        psLogMsg(__func__, PS_LOG_WARN, "WARNING: 2-D Chebyshev polynomial vector fitting has not been implemented.  Returning NULL.\n");
     2149        psFree(poly);
     2150        poly = NULL;
     2151    } else {
     2152        // Free psVectors that were created for NULL arguments.
     2153        if (f->type.type != PS_TYPE_F64) {
     2154            psFree(f64);
     2155        }
     2156
     2157        if (x->type.type != PS_TYPE_F64) {
     2158            psFree(x64);
     2159        }
     2160
     2161        if (y->type.type != PS_TYPE_F64) {
     2162            psFree(y64);
     2163        }
     2164
     2165        if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) {
     2166            psFree(fErr64);
     2167        }
     2168        psError(PS_ERR_UNKNOWN, true, "Incorrect polynomial type.  Returning NULL.\n");
     2169    }
     2170
     2171
     2172    // Free psVectors that were created for NULL arguments.
     2173    if (f->type.type != PS_TYPE_F64) {
     2174        psFree(f64);
     2175    }
     2176
     2177    if (x->type.type != PS_TYPE_F64) {
     2178        psFree(x64);
     2179    }
     2180
     2181    if (y->type.type != PS_TYPE_F64) {
     2182        psFree(y64);
     2183    }
     2184
     2185    if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) {
     2186        psFree(fErr64);
     2187    }
     2188
     2189    return(poly);
     2190}
     2191
     2192psPolynomial2D *psVectorClipFitPolynomial2D(
     2193    psPolynomial2D *poly,
     2194    psStats *stats,
     2195    const psVector *mask,
     2196    psMaskType maskValue,
     2197    const psVector *f,
     2198    const psVector *fErr,
     2199    const psVector *x,
     2200    const psVector *y)
     2201{
     2202    PS_ASSERT_POLY_NON_NULL(poly, NULL);
     2203    PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, NULL);
     2204    PS_ASSERT_PTR_NON_NULL(stats, NULL);
    26372205    PS_ASSERT_VECTOR_NON_NULL(f, NULL);
    26382206    PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F32, NULL);
     
    26482216    PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F32, NULL);
    26492217    if (fErr != NULL) {
    2650         PS_ASSERT_VECTORS_SIZE_EQUAL(fErr, mask, NULL);
     2218        PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, NULL);
    26512219        PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F32, NULL);
     2220    }
     2221
     2222    if (mask == NULL) {
     2223        // XXX: Change argument order.
     2224        poly = RobustFit2D_nomask(poly, x, y, f, fErr);
    26522225    } else {
    2653         fErr32 = psVectorAlloc(f->n, PS_TYPE_F32);
    2654         PS_VECTOR_SET_F32(fErr32, 1.0);
    2655     }
    2656 
    2657     psLogMsg(__func__, PS_LOG_WARN, "WARNING: This function has not been implemented.  Returning NULL.\n");
    2658     if (poly->type == PS_POLYNOMIAL_ORD) {
    2659         psLogMsg(__func__, PS_LOG_WARN, "WARNING: 2-D polynomial vector fitting has not been implemented.  Returning NULL.\n");
    2660     } else if (poly->type == PS_POLYNOMIAL_CHEB) {
    2661         psLogMsg(__func__, PS_LOG_WARN, "WARNING: 2-D Chebyshev polynomial vector fitting has not been implemented.  Returning NULL.\n");
    2662     } else {
    2663         printf("XXX: ERROR: incorrect polynomial type.\n");
    2664     }
    2665     if (fErr == NULL) {
    2666         psFree(fErr32);
    2667     }
    2668     return(NULL);
    2669 }
    2670 
    2671 psPolynomial3D *psVectorFitPolynomial3D_NEW(
    2672     psPolynomial1D *poly,
     2226        // XXX: Use maskValue.
     2227        // XXX: Change argument order.
     2228        poly = RobustFit2D(poly, mask, x, y, f, fErr);
     2229    }
     2230
     2231    if (poly == NULL) {
     2232        psError(PS_ERR_UNKNOWN, true, "Could not fit a polynomial to the data.  Returning NULL.\n");
     2233        return(NULL);
     2234    }
     2235    return(poly);
     2236}
     2237
     2238/******************************************************************************
     2239 ******************************************************************************
     2240 3-D Vector Fitting Code.
     2241 ******************************************************************************
     2242 *****************************************************************************/
     2243
     2244/******************************************************************************
     2245VectorFitPolynomial3DOrd(myPoly, *mask, maskValue, *f, *fErr, *x, *y, *z):
     2246This is a private routine which will fit a 3-D polynomial to a set of (x,
     2247y, z)-(f) pairs.  All non-NULL vectors must be of type PS_TYPE_F64.
     2248 
     2249XXX: This routine needs to be written.  Currently, this is simply a shell.  We
     2250can assume that all vectors have been converted to F64, that (f, x, y, z) are
     2251non-null and F64.  fErr may be NULL, but will be F64 is not.
     2252 *****************************************************************************/
     2253psPolynomial3D* VectorFitPolynomial3DOrd(
     2254    psPolynomial3D* myPoly,
     2255    const psVector* mask,
     2256    psMaskType maskValue,
     2257    const psVector *f,
     2258    const psVector *fErr,
     2259    const psVector *x,
     2260    const psVector *y,
     2261    const psVector *z)
     2262{
     2263    // These ASSERTS are redundant.
     2264    PS_ASSERT_POLY_NON_NULL(myPoly, NULL);
     2265    PS_ASSERT_INT_NONNEGATIVE(myPoly->nX, NULL);
     2266    PS_ASSERT_INT_NONNEGATIVE(myPoly->nY, NULL);
     2267    PS_ASSERT_INT_NONNEGATIVE(myPoly->nZ, NULL);
     2268
     2269    PS_ASSERT_VECTOR_NON_NULL(f, NULL);
     2270    PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F64, NULL);
     2271    if (fErr != NULL) {
     2272        PS_ASSERT_VECTORS_SIZE_EQUAL(y, fErr, NULL);
     2273        PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F64, NULL);
     2274    }
     2275    PS_ASSERT_VECTOR_NON_NULL(x, NULL);
     2276    PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F64, NULL);
     2277    PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL);
     2278    PS_ASSERT_VECTOR_NON_NULL(y, NULL);
     2279    PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F64, NULL);
     2280    PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL);
     2281    PS_ASSERT_VECTOR_NON_NULL(z, NULL);
     2282    PS_ASSERT_VECTOR_TYPE(z, PS_TYPE_F64, NULL);
     2283    PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, NULL);
     2284    if (mask != NULL) {
     2285        PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL);
     2286        PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL);
     2287    }
     2288
     2289    psError(PS_ERR_UNKNOWN, true, "3-D Polynomial Fitting is not Implemented.\n");
     2290    return (NULL);
     2291}
     2292
     2293/******************************************************************************
     2294psVectorFitPolynomial3D():  This routine fits a 3D polynomial of arbitrary
     2295degree (specified in poly) to the data points (x, y, z)-(f) and returns that
     2296polynomial.  Types F32 and F64 are supported, however, type F32 is done via
     2297vector conversion only.
     2298 *****************************************************************************/
     2299psPolynomial3D *psVectorFitPolynomial3D(
     2300    psPolynomial3D *poly,
    26732301    const psVector *mask,
    26742302    psMaskType maskValue,
     
    26792307    const psVector *z)
    26802308{
    2681     // Internal pointers for possibly NULL vectors.
    2682     psVector *fErr32 = NULL;
     2309    // Internal pointers for possibly NULL or mis-typed vectors.
     2310    psVector *x64 = NULL;
     2311    psVector *y64 = NULL;
     2312    psVector *z64 = NULL;
     2313    psVector *f64 = NULL;
     2314    psVector *fErr64 = NULL;
    26832315
    26842316    PS_ASSERT_POLY_NON_NULL(poly, NULL);
    26852317    PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, NULL);
     2318
     2319    //
     2320    // f
     2321    //
     2322    PS_ASSERT_VECTOR_NON_NULL(f, NULL);
     2323    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, NULL);
     2324    if (f->type.type != PS_TYPE_F64) {
     2325        PS_VECTOR_GEN_F64_FROM_F32(f64, f);
     2326    } else {
     2327        f64 = (psVector *) f;
     2328    }
     2329    if (mask != NULL) {
     2330        PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL);
     2331        PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL);
     2332    }
     2333
     2334    //
     2335    // x
     2336    //
     2337    PS_ASSERT_VECTOR_NON_NULL(x, NULL);
     2338    PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL);
     2339    if (x->type.type != PS_TYPE_F64) {
     2340        PS_VECTOR_GEN_F64_FROM_F32(x64, x);
     2341    } else {
     2342        x64 = (psVector *) x;
     2343    }
     2344
     2345    //
     2346    // y
     2347    //
     2348    PS_ASSERT_VECTOR_NON_NULL(y, NULL);
     2349    PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL);
     2350    if (y->type.type != PS_TYPE_F64) {
     2351        PS_VECTOR_GEN_F64_FROM_F32(y64, y);
     2352    } else {
     2353        y64 = (psVector *) y;
     2354    }
     2355
     2356    //
     2357    // z
     2358    //
     2359    PS_ASSERT_VECTOR_NON_NULL(z, NULL);
     2360    PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, NULL);
     2361    if (z->type.type != PS_TYPE_F64) {
     2362        PS_VECTOR_GEN_F64_FROM_F32(y64, z);
     2363    } else {
     2364        z64 = (psVector *) z;
     2365    }
     2366
     2367    //
     2368    // fErr
     2369    //
     2370    if (fErr != NULL) {
     2371        PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, NULL);
     2372        PS_ASSERT_VECTOR_TYPE_F32_OR_F64(fErr, NULL);
     2373        if (fErr->type.type != PS_TYPE_F64) {
     2374            PS_VECTOR_GEN_F64_FROM_F32(fErr64, fErr);
     2375        } else {
     2376            fErr64 = (psVector *) fErr;
     2377        }
     2378    }
     2379
     2380    if (poly->type == PS_POLYNOMIAL_ORD) {
     2381        poly = VectorFitPolynomial3DOrd(poly, mask, maskValue, f64, fErr64, x64, y64, z64);
     2382        if (poly == NULL) {
     2383            psError(PS_ERR_UNKNOWN, true, "Could not fit polynomial.  Returning NULL.\n");
     2384            // Free psVectors that were created for NULL arguments.
     2385            if (f->type.type != PS_TYPE_F64) {
     2386                psFree(f64);
     2387            }
     2388
     2389            if (x->type.type != PS_TYPE_F64) {
     2390                psFree(x64);
     2391            }
     2392
     2393            if (y->type.type != PS_TYPE_F64) {
     2394                psFree(y64);
     2395            }
     2396
     2397            if (z->type.type != PS_TYPE_F64) {
     2398                psFree(z64);
     2399            }
     2400
     2401            if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) {
     2402                psFree(fErr64);
     2403            }
     2404            return(NULL);
     2405        }
     2406    } else if (poly->type == PS_POLYNOMIAL_CHEB) {
     2407        if (mask != NULL) {
     2408            psLogMsg(__func__, PS_LOG_WARN, "WARNING: ignoring mask and maskValue with Chebyshev polynomials.\n");
     2409        }
     2410        psLogMsg(__func__, PS_LOG_WARN, "WARNING: 3-D Chebyshev polynomial vector fitting has not been implemented.  Returning NULL.\n");
     2411        psFree(poly);
     2412        poly = NULL;
     2413    } else {
     2414        // Free psVectors that were created for NULL arguments.
     2415        if (f->type.type != PS_TYPE_F64) {
     2416            psFree(f64);
     2417        }
     2418
     2419        if (x->type.type != PS_TYPE_F64) {
     2420            psFree(x64);
     2421        }
     2422
     2423        if (y->type.type != PS_TYPE_F64) {
     2424            psFree(y64);
     2425        }
     2426
     2427        if (z->type.type != PS_TYPE_F64) {
     2428            psFree(z64);
     2429        }
     2430
     2431        if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) {
     2432            psFree(fErr64);
     2433        }
     2434        psError(PS_ERR_UNKNOWN, true, "Incorrect polynomial type.  Returning NULL.\n");
     2435    }
     2436
     2437
     2438    // Free psVectors that were created for NULL arguments.
     2439    if (f->type.type != PS_TYPE_F64) {
     2440        psFree(f64);
     2441    }
     2442
     2443    if (x->type.type != PS_TYPE_F64) {
     2444        psFree(x64);
     2445    }
     2446
     2447    if (y->type.type != PS_TYPE_F64) {
     2448        psFree(y64);
     2449    }
     2450
     2451    if (z->type.type != PS_TYPE_F64) {
     2452        psFree(z64);
     2453    }
     2454
     2455    if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) {
     2456        psFree(fErr64);
     2457    }
     2458
     2459    return(poly);
     2460}
     2461
     2462psPolynomial3D *psVectorClipFitPolynomial3D(
     2463    psPolynomial3D *poly,
     2464    psStats *stats,
     2465    const psVector *mask,
     2466    psMaskType maskValue,
     2467    const psVector *f,
     2468    const psVector *fErr,
     2469    const psVector *x,
     2470    const psVector *y,
     2471    const psVector *z)
     2472{
     2473    PS_ASSERT_POLY_NON_NULL(poly, NULL);
     2474    PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, NULL);
     2475    PS_ASSERT_PTR_NON_NULL(stats, NULL);
    26862476    PS_ASSERT_VECTOR_NON_NULL(f, NULL);
    26872477    PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F32, NULL);
     
    26962486    PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL);
    26972487    PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F32, NULL);
    2698     PS_ASSERT_VECTOR_NON_NULL(z, NULL);
    2699     PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, NULL);
    2700     PS_ASSERT_VECTOR_TYPE(z, PS_TYPE_F32, NULL);
     2488    PS_ASSERT_VECTOR_NON_NULL(f, NULL);
     2489    PS_ASSERT_VECTORS_SIZE_EQUAL(f, f, NULL);
     2490    PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F32, NULL);
    27012491    if (fErr != NULL) {
    27022492        PS_ASSERT_VECTORS_SIZE_EQUAL(fErr, mask, NULL);
    27032493        PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F32, NULL);
    2704     } else {
    2705         fErr32 = psVectorAlloc(f->n, PS_TYPE_F32);
    2706         PS_VECTOR_SET_F32(fErr32, 1.0);
    27072494    }
    27082495
    27092496    psLogMsg(__func__, PS_LOG_WARN, "WARNING: This function has not been implemented.  Returning NULL.\n");
    2710     if (poly->type == PS_POLYNOMIAL_ORD) {
    2711         psLogMsg(__func__, PS_LOG_WARN, "WARNING: 3-D polynomial vector fitting has not been implemented.  Returning NULL.\n");
    2712     } else if (poly->type == PS_POLYNOMIAL_CHEB) {
    2713         psLogMsg(__func__, PS_LOG_WARN, "WARNING: 3-D Chebyshev polynomial vector fitting has not been implemented.  Returning NULL.\n");
    2714     } else {
    2715         printf("XXX: ERROR: incorrect polynomial type.\n");
    2716     }
    2717     if (fErr == NULL) {
    2718         psFree(fErr32);
    2719     }
    27202497    return(NULL);
    27212498}
    27222499
    2723 psPolynomial4D *psVectorFitPolynomial4D_NEW(
    2724     psPolynomial1D *poly,
     2500
     2501/******************************************************************************
     2502 ******************************************************************************
     2503 4-D Vector Fitting Code.
     2504 ******************************************************************************
     2505 *****************************************************************************/
     2506/******************************************************************************
     2507VectorFitPolynomial4DOrd(myPoly, *mask, maskValue, *f, *fErr, *x, *y, *z, *t):
     2508This is a private routine which will fit a 4-D polynomial to a set of (x,
     2509y, z, t)-(f) pairs.  All non-NULL vectors must be of type PS_TYPE_F64.
     2510 
     2511XXX: This routine needs to be written.  Currently, this is simply a shell.  We
     2512can assume that all vectors have been converted to F64, that (f, x, y, z) are
     2513non-null and F64.  fErr may be NULL, but will be F64 is not.
     2514 *****************************************************************************/
     2515psPolynomial4D* VectorFitPolynomial4DOrd(
     2516    psPolynomial4D* myPoly,
     2517    const psVector* mask,
     2518    psMaskType maskValue,
     2519    const psVector *f,
     2520    const psVector *fErr,
     2521    const psVector *x,
     2522    const psVector *y,
     2523    const psVector *z,
     2524    const psVector *t)
     2525{
     2526    // These ASSERTS are redundant.
     2527    PS_ASSERT_POLY_NON_NULL(myPoly, NULL);
     2528    PS_ASSERT_INT_NONNEGATIVE(myPoly->nX, NULL);
     2529    PS_ASSERT_INT_NONNEGATIVE(myPoly->nY, NULL);
     2530    PS_ASSERT_INT_NONNEGATIVE(myPoly->nZ, NULL);
     2531    PS_ASSERT_INT_NONNEGATIVE(myPoly->nT, NULL);
     2532    PS_ASSERT_VECTOR_NON_NULL(f, NULL);
     2533    PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F64, NULL);
     2534    if (fErr != NULL) {
     2535        PS_ASSERT_VECTORS_SIZE_EQUAL(y, fErr, NULL);
     2536        PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F64, NULL);
     2537    }
     2538    PS_ASSERT_VECTOR_NON_NULL(x, NULL);
     2539    PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F64, NULL);
     2540    PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL);
     2541    PS_ASSERT_VECTOR_NON_NULL(y, NULL);
     2542    PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F64, NULL);
     2543    PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL);
     2544    PS_ASSERT_VECTOR_NON_NULL(z, NULL);
     2545    PS_ASSERT_VECTOR_TYPE(z, PS_TYPE_F64, NULL);
     2546    PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, NULL);
     2547    PS_ASSERT_VECTOR_NON_NULL(t, NULL);
     2548    PS_ASSERT_VECTOR_TYPE(t, PS_TYPE_F64, NULL);
     2549    PS_ASSERT_VECTORS_SIZE_EQUAL(f, t, NULL);
     2550    if (mask != NULL) {
     2551        PS_ASSERT_VECTORS_SIZE_EQUAL(y, mask, NULL);
     2552        PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL);
     2553    }
     2554
     2555    psError(PS_ERR_UNKNOWN, true, "4-D Polynomial Fitting is not Implemented.\n");
     2556    return (NULL);
     2557}
     2558
     2559/******************************************************************************
     2560psVectorFitPolynomial4D():  This routine fits a 4D polynomial of arbitrary
     2561degree (specified in poly) to the data points (x, y, z, t)-(f) and returns
     2562that polynomial.  Types F32 and F64 are supported, however, type F32 is done
     2563via vector conversion only.
     2564 *****************************************************************************/
     2565psPolynomial4D *psVectorFitPolynomial4D(
     2566    psPolynomial4D *poly,
    27252567    const psVector *mask,
    27262568    psMaskType maskValue,
     
    27322574    const psVector *t)
    27332575{
    2734     // Internal pointers for possibly NULL vectors.
    2735     psVector *fErr32 = NULL;
     2576    // Internal pointers for possibly NULL or mis-typed vectors.
     2577    psVector *x64 = NULL;
     2578    psVector *y64 = NULL;
     2579    psVector *z64 = NULL;
     2580    psVector *t64 = NULL;
     2581    psVector *f64 = NULL;
     2582    psVector *fErr64 = NULL;
    27362583
    27372584    PS_ASSERT_POLY_NON_NULL(poly, NULL);
    27382585    PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, NULL);
     2586
     2587    //
     2588    // f
     2589    //
    27392590    PS_ASSERT_VECTOR_NON_NULL(f, NULL);
    2740     PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F32, NULL);
     2591    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, NULL);
     2592    if (f->type.type != PS_TYPE_F64) {
     2593        PS_VECTOR_GEN_F64_FROM_F32(f64, f);
     2594    } else {
     2595        f64 = (psVector *) f;
     2596    }
    27412597    if (mask != NULL) {
    27422598        PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL);
    27432599        PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL);
    27442600    }
     2601
     2602    //
     2603    // x
     2604    //
    27452605    PS_ASSERT_VECTOR_NON_NULL(x, NULL);
    2746     PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL);
    2747     PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F32, NULL);
     2606    PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL);
     2607    if (x->type.type != PS_TYPE_F64) {
     2608        PS_VECTOR_GEN_F64_FROM_F32(x64, x);
     2609    } else {
     2610        x64 = (psVector *) x;
     2611    }
     2612
     2613    //
     2614    // y
     2615    //
    27482616    PS_ASSERT_VECTOR_NON_NULL(y, NULL);
    27492617    PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL);
    2750     PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F32, NULL);
     2618    if (y->type.type != PS_TYPE_F64) {
     2619        PS_VECTOR_GEN_F64_FROM_F32(y64, y);
     2620    } else {
     2621        y64 = (psVector *) y;
     2622    }
     2623
     2624    //
     2625    // z
     2626    //
    27512627    PS_ASSERT_VECTOR_NON_NULL(z, NULL);
    27522628    PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, NULL);
    2753     PS_ASSERT_VECTOR_TYPE(z, PS_TYPE_F32, NULL);
     2629    if (z->type.type != PS_TYPE_F64) {
     2630        PS_VECTOR_GEN_F64_FROM_F32(y64, z);
     2631    } else {
     2632        z64 = (psVector *) z;
     2633    }
     2634
     2635    //
     2636    // t
     2637    //
    27542638    PS_ASSERT_VECTOR_NON_NULL(t, NULL);
    27552639    PS_ASSERT_VECTORS_SIZE_EQUAL(f, t, NULL);
    2756     PS_ASSERT_VECTOR_TYPE(t, PS_TYPE_F32, NULL);
    2757     if (fErr != NULL) {
    2758         PS_ASSERT_VECTORS_SIZE_EQUAL(fErr, mask, NULL);
    2759         PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F32, NULL);
     2640    if (t->type.type != PS_TYPE_F64) {
     2641        PS_VECTOR_GEN_F64_FROM_F32(y64, t);
    27602642    } else {
    2761         fErr32 = psVectorAlloc(f->n, PS_TYPE_F32);
    2762         PS_VECTOR_SET_F32(fErr32, 1.0);
    2763     }
    2764 
    2765     if (poly->type == PS_POLYNOMIAL_ORD) {
    2766         psLogMsg(__func__, PS_LOG_WARN, "WARNING: 4-D polynomial vector fitting has not been implemented.  Returning NULL.\n");
    2767     } else if (poly->type == PS_POLYNOMIAL_CHEB) {
    2768         psLogMsg(__func__, PS_LOG_WARN, "WARNING: 4-D Chebyshev polynomial vector fitting has not been implemented.  Returning NULL.\n");
    2769     } else {
    2770         printf("XXX: ERROR: incorrect polynomial type.\n");
    2771     }
    2772     if (fErr == NULL) {
    2773         psFree(fErr32);
    2774     }
    2775     return(NULL);
    2776 }
    2777 
    2778 
    2779 psPolynomial1D *psVectorClipFitPolynomial1D_NEW(
    2780     psPolynomial1D *poly,
    2781     psStats *stats,
    2782     const psVector *mask,
    2783     psMaskType maskValue,
    2784     const psVector *f,
    2785     const psVector *fErr,
    2786     const psVector *x)
    2787 {
    2788     // Internal pointers for possibly NULL vectors.
    2789     psVector *x32 = NULL;
    2790     psVector *fErr32 = NULL;
    2791 
    2792     PS_ASSERT_POLY_NON_NULL(poly, NULL);
    2793     PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, NULL);
    2794     PS_ASSERT_VECTOR_NON_NULL(f, NULL);
    2795     PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F32, NULL);
    2796     if (mask != NULL) {
    2797         PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL);
    2798         PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL);
    2799     }
    2800     if (x != NULL) {
    2801         PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL);
    2802         PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F32, NULL);
    2803     }
     2643        t64 = (psVector *) t;
     2644    }
     2645
     2646    //
     2647    // fErr
     2648    //
    28042649    if (fErr != NULL) {
    28052650        PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, NULL);
    2806         PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F32, NULL);
     2651        PS_ASSERT_VECTOR_TYPE_F32_OR_F64(fErr, NULL);
     2652        if (fErr->type.type != PS_TYPE_F64) {
     2653            PS_VECTOR_GEN_F64_FROM_F32(fErr64, fErr);
     2654        } else {
     2655            fErr64 = (psVector *) fErr;
     2656        }
     2657    }
     2658
     2659    if (poly->type == PS_POLYNOMIAL_ORD) {
     2660        poly = VectorFitPolynomial4DOrd(poly, mask, maskValue, f64, fErr64, x64, y64, z64, t64);
     2661        if (poly == NULL) {
     2662            psError(PS_ERR_UNKNOWN, true, "Could not fit polynomial.  Returning NULL.\n");
     2663            // Free psVectors that were created for NULL arguments.
     2664            if (f->type.type != PS_TYPE_F64) {
     2665                psFree(f64);
     2666            }
     2667
     2668            if (x->type.type != PS_TYPE_F64) {
     2669                psFree(x64);
     2670            }
     2671
     2672            if (y->type.type != PS_TYPE_F64) {
     2673                psFree(y64);
     2674            }
     2675
     2676            if (z->type.type != PS_TYPE_F64) {
     2677                psFree(z64);
     2678            }
     2679
     2680            if (t->type.type != PS_TYPE_F64) {
     2681                psFree(t64);
     2682            }
     2683
     2684            if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) {
     2685                psFree(fErr64);
     2686            }
     2687            return(NULL);
     2688        }
     2689    } else if (poly->type == PS_POLYNOMIAL_CHEB) {
     2690        if (mask != NULL) {
     2691            psLogMsg(__func__, PS_LOG_WARN, "WARNING: ignoring mask and maskValue with Chebyshev polynomials.\n");
     2692        }
     2693        psLogMsg(__func__, PS_LOG_WARN, "WARNING: 4-D Chebyshev polynomial vector fitting has not been implemented.  Returning NULL.\n");
     2694        psFree(poly);
     2695        poly = NULL;
    28072696    } else {
    2808         fErr32 = psVectorAlloc(f->n, PS_TYPE_F32);
    2809         PS_VECTOR_SET_F32(fErr32, 1.0);
    2810     }
    2811 
    2812     psLogMsg(__func__, PS_LOG_WARN, "WARNING: This function has not been implemented.  Returning NULL.\n");
     2697        // Free psVectors that were created for NULL arguments.
     2698        if (f->type.type != PS_TYPE_F64) {
     2699            psFree(f64);
     2700        }
     2701
     2702        if (x->type.type != PS_TYPE_F64) {
     2703            psFree(x64);
     2704        }
     2705
     2706        if (y->type.type != PS_TYPE_F64) {
     2707            psFree(y64);
     2708        }
     2709
     2710        if (z->type.type != PS_TYPE_F64) {
     2711            psFree(z64);
     2712        }
     2713
     2714        if (t->type.type != PS_TYPE_F64) {
     2715            psFree(t64);
     2716        }
     2717
     2718        if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) {
     2719            psFree(fErr64);
     2720        }
     2721        psError(PS_ERR_UNKNOWN, true, "Incorrect polynomial type.  Returning NULL.\n");
     2722    }
     2723
     2724
    28132725    // Free psVectors that were created for NULL arguments.
    2814     if (x == NULL) {
    2815         psFree(x32);
    2816     }
    2817     if (fErr == NULL) {
    2818         psFree(fErr32);
    2819     }
    2820     return(NULL);
    2821 }
    2822 
    2823 psPolynomial2D *psVectorClipFitPolynomial2D_NEW(
    2824     psPolynomial1D *poly,
    2825     psStats *stats,
    2826     const psVector *mask,
    2827     psMaskType maskValue,
    2828     const psVector *f,
    2829     const psVector *fErr,
    2830     const psVector *x,
    2831     const psVector *y)
    2832 {
    2833     // Internal pointers for possibly NULL vectors.
    2834     psVector *fErr32 = NULL;
    2835 
    2836     PS_ASSERT_POLY_NON_NULL(poly, NULL);
    2837     PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, NULL);
    2838     PS_ASSERT_VECTOR_NON_NULL(f, NULL);
    2839     PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F32, NULL);
    2840     if (mask != NULL) {
    2841         PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL);
    2842         PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL);
    2843     }
    2844     PS_ASSERT_VECTOR_NON_NULL(x, NULL);
    2845     PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL);
    2846     PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F32, NULL);
    2847     PS_ASSERT_VECTOR_NON_NULL(y, NULL);
    2848     PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL);
    2849     PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F32, NULL);
    2850     if (fErr != NULL) {
    2851         PS_ASSERT_VECTORS_SIZE_EQUAL(fErr, mask, NULL);
    2852         PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F32, NULL);
    2853     } else {
    2854         fErr32 = psVectorAlloc(f->n, PS_TYPE_F32);
    2855         PS_VECTOR_SET_F32(fErr32, 1.0);
    2856     }
    2857 
    2858     psLogMsg(__func__, PS_LOG_WARN, "WARNING: This function has not been implemented.  Returning NULL.\n");
    2859     if (fErr == NULL) {
    2860         psFree(fErr32);
    2861     }
    2862     return(NULL);
    2863 }
    2864 
    2865 psPolynomial3D *psVectorClipFitPolynomial3D_NEW(
    2866     psPolynomial1D *poly,
    2867     psStats *stats,
    2868     const psVector *mask,
    2869     psMaskType maskValue,
    2870     const psVector *f,
    2871     const psVector *fErr,
    2872     const psVector *x,
    2873     const psVector *y,
    2874     const psVector *z)
    2875 {
    2876     // Internal pointers for possibly NULL vectors.
    2877     psVector *fErr32 = NULL;
    2878 
    2879     PS_ASSERT_POLY_NON_NULL(poly, NULL);
    2880     PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, NULL);
    2881     PS_ASSERT_VECTOR_NON_NULL(f, NULL);
    2882     PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F32, NULL);
    2883     if (mask != NULL) {
    2884         PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL);
    2885         PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL);
    2886     }
    2887     PS_ASSERT_VECTOR_NON_NULL(x, NULL);
    2888     PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL);
    2889     PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F32, NULL);
    2890     PS_ASSERT_VECTOR_NON_NULL(y, NULL);
    2891     PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL);
    2892     PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F32, NULL);
    2893     PS_ASSERT_VECTOR_NON_NULL(z, NULL);
    2894     PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, NULL);
    2895     PS_ASSERT_VECTOR_TYPE(z, PS_TYPE_F32, NULL);
    2896     if (fErr != NULL) {
    2897         PS_ASSERT_VECTORS_SIZE_EQUAL(fErr, mask, NULL);
    2898         PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F32, NULL);
    2899     } else {
    2900         fErr32 = psVectorAlloc(f->n, PS_TYPE_F32);
    2901         PS_VECTOR_SET_F32(fErr32, 1.0);
    2902     }
    2903 
    2904     psLogMsg(__func__, PS_LOG_WARN, "WARNING: This function has not been implemented.  Returning NULL.\n");
    2905     if (fErr == NULL) {
    2906         psFree(fErr32);
    2907     }
    2908     return(NULL);
    2909 }
    2910 
    2911 psPolynomial4D *psVectorClipFitPolynomial4D_NEW(
    2912     psPolynomial1D *poly,
     2726    if (f->type.type != PS_TYPE_F64) {
     2727        psFree(f64);
     2728    }
     2729
     2730    if (x->type.type != PS_TYPE_F64) {
     2731        psFree(x64);
     2732    }
     2733
     2734    if (y->type.type != PS_TYPE_F64) {
     2735        psFree(y64);
     2736    }
     2737
     2738    if (z->type.type != PS_TYPE_F64) {
     2739        psFree(z64);
     2740    }
     2741
     2742    if (t->type.type != PS_TYPE_F64) {
     2743        psFree(t64);
     2744    }
     2745
     2746    if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) {
     2747        psFree(fErr64);
     2748    }
     2749
     2750    return(poly);
     2751}
     2752
     2753
     2754psPolynomial4D *psVectorClipFitPolynomial4D(
     2755    psPolynomial4D *poly,
    29132756    psStats *stats,
    29142757    const psVector *mask,
     
    29212764    const psVector *t)
    29222765{
    2923     // Internal pointers for possibly NULL vectors.
    2924     psVector *fErr32 = NULL;
    2925 
    29262766    PS_ASSERT_POLY_NON_NULL(poly, NULL);
    29272767    PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, NULL);
     2768    PS_ASSERT_PTR_NON_NULL(stats, NULL);
    29282769    PS_ASSERT_VECTOR_NON_NULL(f, NULL);
    29292770    PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F32, NULL);
     
    29382779    PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL);
    29392780    PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F32, NULL);
    2940     PS_ASSERT_VECTOR_NON_NULL(z, NULL);
    2941     PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, NULL);
    2942     PS_ASSERT_VECTOR_TYPE(z, PS_TYPE_F32, NULL);
     2781    PS_ASSERT_VECTOR_NON_NULL(f, NULL);
     2782    PS_ASSERT_VECTORS_SIZE_EQUAL(f, f, NULL);
     2783    PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F32, NULL);
    29432784    PS_ASSERT_VECTOR_NON_NULL(t, NULL);
    29442785    PS_ASSERT_VECTORS_SIZE_EQUAL(f, t, NULL);
     
    29472788        PS_ASSERT_VECTORS_SIZE_EQUAL(fErr, mask, NULL);
    29482789        PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F32, NULL);
    2949     } else {
    2950         fErr32 = psVectorAlloc(f->n, PS_TYPE_F32);
    2951         PS_VECTOR_SET_F32(fErr32, 1.0);
    29522790    }
    29532791
    29542792    psLogMsg(__func__, PS_LOG_WARN, "WARNING: This function has not been implemented.  Returning NULL.\n");
    2955     if (fErr == NULL) {
    2956         psFree(fErr32);
    2957     }
     2793
    29582794    return(NULL);
    29592795}
  • trunk/psLib/src/math/psMinimize.h

    r4963 r4991  
    88 *  @author GLG, MHPCC
    99 *
    10  *  @version $Revision: 1.56 $ $Name: not supported by cvs2svn $
    11  *  @date $Date: 2005-09-07 23:46:04 $
     10 *  @version $Revision: 1.57 $ $Name: not supported by cvs2svn $
     11 *  @date $Date: 2005-09-11 22:18:40 $
    1212 *
    1313 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     
    8585 *  @return psPolynomial1D*    polynomial fit
    8686 */
    87 psPolynomial1D* psVectorFitPolynomial1D(
    88     psPolynomial1D* poly,            ///< Polynomial to fit
    89     const psVector* x,                 ///< Ordinates (or NULL to just use the indices)
    90     const psVector* y,                 ///< Coordinates
    91     const psVector* yErr               ///< Errors in coordinates, or NULL
    92 );
    93 
    94 
    95 
    96 
    97 
    98 psPolynomial1D *psVectorFitPolynomial1D_NEW(
     87
     88psPolynomial1D *psVectorFitPolynomial1D(
    9989    psPolynomial1D *poly,
    10090    const psVector *mask,
     
    10595);
    10696
    107 psPolynomial2D *psVectorFitPolynomial2D_NEW(
    108     psPolynomial1D *poly,
     97psPolynomial2D *psVectorFitPolynomial2D(
     98    psPolynomial2D *poly,
    10999    const psVector *mask,
    110100    psMaskType maskValue,
     
    115105);
    116106
    117 psPolynomial3D *psVectorFitPolynomial3D_NEW(
    118     psPolynomial1D *poly,
     107psPolynomial3D *psVectorFitPolynomial3D(
     108    psPolynomial3D *poly,
    119109    const psVector *mask,
    120110    psMaskType maskValue,
     
    126116);
    127117
    128 psPolynomial4D *psVectorFitPolynomial4D_NEW(
    129     psPolynomial1D *poly,
     118psPolynomial4D *psVectorFitPolynomial4D(
     119    psPolynomial4D *poly,
    130120    const psVector *mask,
    131121    psMaskType maskValue,
     
    139129
    140130
    141 psPolynomial1D *psVectorClipFitPolynomial1D_NEW(
     131psPolynomial1D *psVectorClipFitPolynomial1D(
    142132    psPolynomial1D *poly,
    143133    psStats *stats,
     
    149139);
    150140
    151 psPolynomial2D *psVectorClipFitPolynomial2D_NEW(
    152     psPolynomial1D *poly,
     141psPolynomial2D *psVectorClipFitPolynomial2D(
     142    psPolynomial2D *poly,
    153143    psStats *stats,
    154144    const psVector *mask,
     
    160150);
    161151
    162 psPolynomial3D *psVectorClipFitPolynomial3D_NEW(
    163     psPolynomial1D *poly,
     152psPolynomial3D *psVectorClipFitPolynomial3D(
     153    psPolynomial3D *poly,
    164154    psStats *stats,
    165155    const psVector *mask,
     
    172162);
    173163
    174 psPolynomial4D *psVectorClipFitPolynomial4D_NEW(
    175     psPolynomial1D *poly,
     164psPolynomial4D *psVectorClipFitPolynomial4D(
     165    psPolynomial4D *poly,
    176166    psStats *stats,
    177167    const psVector *mask,
     
    183173    const psVector *z,
    184174    const psVector *t
    185 );
    186 
    187 
    188 
    189 
    190 /** Derive a one-dimensional spline fit.
    191  *
    192  *  Given a psSpline1D data structure and a set of x,y vectors, this routine
    193  *  generates the linear splines which satisfy those data points.
    194  *
    195  *  @return psSpline1D*:  the calculated one-dimensional splines
    196  */
    197 psSpline1D *psVectorFitSpline1D(
    198     psSpline1D *mySpline,              ///< The spline which will be generated.
    199     const psVector* x,                 ///< Ordinates (or NULL to just use the indices)
    200     const psVector* y,                 ///< Coordinates
    201     const psVector* yErr               ///< Errors in coordinates, or NULL
    202 );
    203 psSpline1D *psVectorFitSpline1DNEW(
    204     const psVector* x,                 ///< Ordinates (or NULL to just use the indices)
    205     const psVector* y,                 ///< Coordinates
    206     int nKnots
    207175);
    208176
     
    233201    const psVector *yErr,              ///< Errors in the measurement coordinates
    234202    psMinimizeLMChi2Func func          ///< Specified function
     203);
     204
     205bool psMinimizeGaussNewtonDelta (
     206    psVector *delta,
     207    const psVector *params,
     208    const psVector *paramMask,
     209    const psArray  *x,
     210    const psVector *y,
     211    const psVector *yErr,
     212    psMinimizeLMChi2Func func
    235213);
    236214
  • trunk/psLib/src/math/psPolynomial.c

    r4971 r4991  
    77*  polynomials.  It also contains a Gaussian functions.
    88*
    9 *  @version $Revision: 1.119 $ $Name: not supported by cvs2svn $
    10 *  @date $Date: 2005-09-08 00:14:31 $
     9*  @version $Revision: 1.120 $ $Name: not supported by cvs2svn $
     10*  @date $Date: 2005-09-11 22:18:40 $
    1111*
    1212*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     
    564564 of numbers with the specified mean and sigma.
    565565 
    566 XXX: It's possible to have a different seed everutime.  However, for now,
     566XXX: It's possible to have a different seed everytime.  However, for now,
    567567for testability, we use a common seed.
    568568 *****************************************************************************/
  • trunk/psLib/src/math/psSpline.c

    r4971 r4991  
    77*  splines.
    88*
    9 *  @version $Revision: 1.122 $ $Name: not supported by cvs2svn $
    10 *  @date $Date: 2005-09-08 00:14:32 $
     9*  @version $Revision: 1.123 $ $Name: not supported by cvs2svn $
     10*  @date $Date: 2005-09-11 22:18:40 $
    1111*
    1212*
     
    207207}
    208208
     209
     210/*****************************************************************************
     211CalculateSecondDerivs(): Given a set of x/y vectors corresponding to a
     212tabulated function at n points, this routine calculates the second
     213derivatives of the interpolating cubic splines at those n points.
     214 
     215The first and second derivatives at the endpoints, undefined in the SDR, are
     216here defined to be 0.0.  They can be modified via ypo and yp1.
     217 
     218This routine assumes that vectors x and y are of the appropriate types/sizes
     219(F32).
     220 
     221XXX: This algorithm is derived from the Numerical Recipes.
     222XXX: use recycled vectors for internal data.
     223XXX: do an F64 version?
     224 *****************************************************************************/
     225static psF32 *calculateSecondDerivs(const psVector* x,        ///< Ordinates (or NULL to just use the indices)
     226                                    const psVector* y)        ///< Coordinates
     227{
     228    psTrace(".psLib.dataManip.calculateSecondDerivs", 4,
     229            "---- calculateSecondDerivs() begin ----\n");
     230
     231    psS32 i;
     232    psS32 k;
     233    psF32 sig;
     234    psF32 p;
     235    psS32 n = y->n;
     236    psF32 *u = (psF32 *) psAlloc(n * sizeof(psF32));
     237    psF32 *derivs2 = (psF32 *) psAlloc(n * sizeof(psF32));
     238    psF32 *X = (psF32 *) & (x->data.F32[0]);
     239    psF32 *Y = (psF32 *) & (y->data.F32[0]);
     240    psF32 qn;
     241
     242    // XXX: The second derivatives at the endpoints, undefined in the SDR,
     243    // are set in psConstants.h: PS_LEFT_SPLINE_DERIV, PS_RIGHT_SPLINE_DERIV.
     244    derivs2[0] = -0.5;
     245    u[0]= (3.0/(X[1]-X[0])) * ((Y[1]-Y[0])/(X[1]-X[0]) - PS_LEFT_SPLINE_DERIV);
     246
     247    for (i=1;i<=(n-2);i++) {
     248        sig = (X[i] - X[i-1]) / (X[i+1] - X[i-1]);
     249        p = sig * derivs2[i-1] + 2.0;
     250        derivs2[i] = (sig - 1.0) / p;
     251        u[i] = ((Y[i+1] - Y[i])/(X[i+1]-X[i])) - ((Y[i]-Y[i-1])/(X[i]-X[i-1]));
     252        u[i] = ((6.0 * u[i] / (X[i+1] - X[i-1])) - (sig * u[i-1])) / p;
     253
     254        psTrace(".psLib.dataManip.calculateSecondDerivs", 6,
     255                "X[%d] is %f\n", i, X[i]);
     256        psTrace(".psLib.dataManip.calculateSecondDerivs", 6,
     257                "Y[%d] is %f\n", i, Y[i]);
     258        psTrace(".psLib.dataManip.calculateSecondDerivs", 6,
     259                "u[%d] is %f\n", i, u[i]);
     260    }
     261
     262    qn = 0.5;
     263    u[n-1] = (3.0/(X[n-1]-X[n-2])) * (PS_RIGHT_SPLINE_DERIV - (Y[n-1]-Y[n-2])/(X[n-1]-X[n-2]));
     264    derivs2[n-1] = (u[n-1] - (qn * u[n-2])) / ((qn * derivs2[n-2]) + 1.0);
     265
     266    for (k=(n-2);k>=0;k--) {
     267        derivs2[k] = derivs2[k] * derivs2[k+1] + u[k];
     268
     269        psTrace(".psLib.dataManip.calculateSecondDerivs", 6,
     270                "derivs2[%d] is %f\n", k, derivs2[k]);
     271    }
     272
     273    psFree(u);
     274    psTrace(".psLib.dataManip.calculateSecondDerivs", 4,
     275            "---- calculateSecondDerivs() end ----\n");
     276    return(derivs2);
     277}
     278
     279/*****************************************************************************/
     280/* FUNCTION IMPLEMENTATION - PUBLIC                                          */
     281/*****************************************************************************/
     282
     283/*****************************************************************************
     284psVectorFitSpline1D(): given a psSpline1D data structure and a set of x/y
     285vectors, this routine generates the linear or cublic splines which satisfy
     286those data points.
     287 
     288The formula for calculating the spline polynomials is derived from Numerical
     289Recipes in C.  The basic idea is that the polynomial is
     290 (1)     y = (A * y[0]) +
     291 (2)         (B * y[1]) +
     292 (3)         ((((A*A*A)-A) * mySpline->p_psDeriv2[0]) * H^2)/6.0 +
     293 (4)         ((((B*B*B)-B) * mySpline->p_psDeriv2[1]) * H^2)/6.0
     294Where:
     295 H = x[1]-x[0]
     296 A = (x[1]-x)/H
     297 B = (x-x[0])/H
     298The bulk of the code in this routine is the expansion of the above equation
     299into a polynomial in terms of x, and then saving the coefficients of the
     300powers of x in the spline polynomials.  This gets pretty complicated.
     301 
     302XXX: usage of yErr is not specified in IfA documentation.
     303 
     304XXX: Is the x argument redundant?  What do we do if the x argument is
     305supplied, but does not equal the knots specified in mySpline?
     306 
     307XXX: can psSpline be NULL?
     308 
     309XXX: reimplement this assuming that mySpline is NULL?
     310 
     311XXX: What happens if X is NULL, then an index vector is generated for X, but
     312that index vector lies outside the range vectors in mySpline?
     313 
     314XXX: Assumes mySpline->knots is psF32.  Must add psU32 and psF64.
     315 *****************************************************************************/
     316psSpline1D *psVectorFitSpline1D(psSpline1D *mySpline,     ///< The spline which will be generated.
     317                                const psVector* x,        ///< Ordinates (or NULL to just use the indices)
     318                                const psVector* y,        ///< Coordinates
     319                                const psVector* yErr)     ///< Errors in coordinates, or NULL
     320{
     321    PS_ASSERT_VECTOR_NON_NULL(y, NULL);
     322    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(y, NULL);
     323    if (mySpline != NULL) {
     324        PS_ASSERT_VECTOR_TYPE(mySpline->knots, PS_TYPE_F32, NULL);
     325    }
     326    psTrace(".psLib.dataManip.psVectorFitSpline1D", 4,
     327            "---- psVectorFitSpline1D() begin ----\n");
     328    psS32 numSplines = (y->n)-1;
     329    psF32 tmp;
     330    psF32 H;
     331    psS32 i;
     332    psF32 slope;
     333    psVector *x32 = NULL;
     334    psVector *y32 = NULL;
     335    psVector *yErr32 = NULL;
     336    static psVector *x32Static = NULL;
     337    static psVector *y32Static = NULL;
     338    static psVector *yErr32Static = NULL;
     339
     340    PS_VECTOR_CONVERT_F64_TO_F32_STATIC(y, y32, y32Static);
     341
     342    // If yErr==NULL, set all errors equal.
     343    if (yErr == NULL) {
     344        PS_VECTOR_GEN_YERR_STATIC_F32(yErr32Static, y->n);
     345        yErr32 = yErr32Static;
     346    } else {
     347        PS_ASSERT_VECTOR_TYPE_F32_OR_F64(yErr, NULL);
     348        PS_VECTOR_CONVERT_F64_TO_F32_STATIC(yErr, yErr32, yErr32Static);
     349    }
     350
     351    // If x==NULL, create an x32 vector with x values set to (0:n).
     352    if (x == NULL) {
     353        PS_VECTOR_GEN_X_INDEX_STATIC_F32(x32Static, y->n);
     354        x32 = x32Static;
     355    } else {
     356        PS_ASSERT_VECTOR_TYPE_F32_OR_F64(x, NULL);
     357        PS_VECTOR_CONVERT_F64_TO_F32_STATIC(x, x32, x32Static);
     358    }
     359    PS_ASSERT_VECTORS_SIZE_EQUAL(x32, y32, NULL);
     360    PS_ASSERT_VECTORS_SIZE_EQUAL(yErr32, y32, NULL);
     361
     362    /*
     363        XXX:
     364        This can not be implemented until SDR states what order spline should be
     365        created.
     366        Should we error if mySpline is not NULL?
     367        Should we error if mySPline is not NULL?
     368    */
     369    if (mySpline == NULL) {
     370        mySpline = psSpline1DAllocGeneric(x32, 3);
     371    }
     372    PS_ASSERT_PTR_NON_NULL(mySpline, NULL);
     373    PS_ASSERT_INT_NONNEGATIVE(mySpline->n, NULL);
     374
     375    if (y32->n != (1 + mySpline->n)) {
     376        psError(PS_ERR_BAD_PARAMETER_SIZE, true,
     377                "data size / spline size mismatch (%d %d)\n",
     378                y32->n, mySpline->n);
     379        return(NULL);
     380    }
     381
     382    // If these are linear splines, which means their polynomials will have
     383    // two coefficients, then we do the simple calculation.
     384    if (2 == (mySpline->spline[0])->n) {
     385        for (i=0;i<mySpline->n;i++) {
     386            slope = (y32->data.F32[i+1] - y32->data.F32[i]) /
     387                    (mySpline->knots->data.F32[i+1] - mySpline->knots->data.F32[i]);
     388            (mySpline->spline[i])->coeff[0] = y32->data.F32[i] -
     389                                              (slope * mySpline->knots->data.F32[i]);
     390
     391            (mySpline->spline[i])->coeff[1] = slope;
     392            psTrace(".psLib.dataManip.psMinimize.psVectorFitSpline1D", 4,
     393                    "---- mySpline %d coeffs are (%f, %f)\n", i,
     394                    (mySpline->spline[i])->coeff[0],
     395                    (mySpline->spline[i])->coeff[1]);
     396        }
     397        psTrace(".psLib.dataManip.psMinimize.psVectorFitSpline1D", 4,
     398                "---- Exiting psVectorFitSpline1D()()\n");
     399        return((psSpline1D *) mySpline);
     400    }
     401
     402    // Check if these are cubic splines (n==4).  If not, psError.
     403    if (4 != (mySpline->spline[0])->n) {
     404        psError(PS_ERR_BAD_PARAMETER_SIZE, true,
     405                "Don't know how to generate %d-order splines.",
     406                (mySpline->spline[0])->n-1);
     407        return(NULL);
     408    }
     409
     410    // If we get here, then we know these are cubic splines.  We first
     411    // generate the second derivatives at each data point.
     412    mySpline->p_psDeriv2 = calculateSecondDerivs(x32, y32);
     413    for (i=0;i<y32->n;i++)
     414        psTrace(".psLib.dataManip.psVectorFitSpline1D", 6,
     415                "Second deriv[%d] is %f\n", i, mySpline->p_psDeriv2[i]);
     416
     417    // We generate the coefficients of the spline polynomials.  I can't
     418    // concisely explain how this code works.  See above function comments
     419    // and Numerical Recipes in C.
     420    for (i=0;i<numSplines;i++) {
     421        H = x32->data.F32[i+1] - x32->data.F32[i];
     422        psTrace(".psLib.dataManip.psVectorFitSpline1D", 4,
     423                "x data (%f - %f) (%f)\n",
     424                x32->data.F32[i],
     425                x32->data.F32[i+1], H);
     426        //
     427        // ******** Calculate 0-order term ********
     428        //
     429        // From (1)
     430        (mySpline->spline[i])->coeff[0] = (y32->data.F32[i] * x32->data.F32[i+1]/H);
     431        // From (2)
     432        ((mySpline->spline[i])->coeff[0])-= ((y32->data.F32[i+1] * x32->data.F32[i])/H);
     433        // From (3)
     434        tmp = (x32->data.F32[i+1] * x32->data.F32[i+1] * x32->data.F32[i+1]) / (H * H * H);
     435        tmp-= (x32->data.F32[i+1] / H);
     436        tmp*= (mySpline->p_psDeriv2)[i] * H * H / 6.0;
     437        ((mySpline->spline[i])->coeff[0])+= tmp;
     438        // From (4)
     439        tmp = -(x32->data.F32[i] * x32->data.F32[i] * x32->data.F32[i]) / (H * H * H);
     440        tmp+= (x32->data.F32[i] / H);
     441        tmp*= (mySpline->p_psDeriv2)[i+1] * H * H / 6.0;
     442        ((mySpline->spline[i])->coeff[0])+= tmp;
     443
     444        //
     445        // ******** Calculate 1-order term ********
     446        //
     447        // From (1)
     448        (mySpline->spline[i])->coeff[1] = -(y32->data.F32[i]) / H;
     449        // From (2)
     450        ((mySpline->spline[i])->coeff[1])+= (y32->data.F32[i+1] / H);
     451        // From (3)
     452        tmp = -3.0 * (x32->data.F32[i+1] * x32->data.F32[i+1]) / (H * H * H);
     453        tmp+= (1.0 / H);
     454        tmp*= ((mySpline->p_psDeriv2)[i]) * H * H / 6.0;
     455        ((mySpline->spline[i])->coeff[1])+= tmp;
     456        // From (4)
     457        tmp = 3.0 * (x32->data.F32[i] * x32->data.F32[i]) / (H * H * H);
     458        tmp-= (1.0 / H);
     459        tmp*= ((mySpline->p_psDeriv2)[i+1]) * H * H / 6.0;
     460        ((mySpline->spline[i])->coeff[1])+= tmp;
     461
     462        //
     463        // ******** Calculate 2-order term ********
     464        //
     465        // From (3)
     466        (mySpline->spline[i])->coeff[2] = ((mySpline->p_psDeriv2)[i]) * 3.0 * x32->data.F32[i+1] / (6.0 * H);
     467        // From (4)
     468        ((mySpline->spline[i])->coeff[2])-= (((mySpline->p_psDeriv2)[i+1]) * 3.0 * x32->data.F32[i] / (6.0 * H));
     469
     470        //
     471        // ******** Calculate 3-order term ********
     472        //
     473        // From (3)
     474        (mySpline->spline[i])->coeff[3] = -((mySpline->p_psDeriv2)[i]) / (6.0 * H);
     475        // From (4)
     476        ((mySpline->spline[i])->coeff[3])+=  ((mySpline->p_psDeriv2)[i+1]) / (6.0 * H);
     477
     478        psTrace(".psLib.dataManip.psVectorFitSpline1D", 6,
     479                "(mySpline->spline[%d])->coeff[0] is %f\n", i, (mySpline->spline[i])->coeff[0]);
     480        psTrace(".psLib.dataManip.psVectorFitSpline1D", 6,
     481                "(mySpline->spline[%d])->coeff[1] is %f\n", i, (mySpline->spline[i])->coeff[1]);
     482        psTrace(".psLib.dataManip.psVectorFitSpline1D", 6,
     483                "(mySpline->spline[%d])->coeff[2] is %f\n", i, (mySpline->spline[i])->coeff[2]);
     484        psTrace(".psLib.dataManip.psVectorFitSpline1D", 6,
     485                "(mySpline->spline[%d])->coeff[3] is %f\n", i, (mySpline->spline[i])->coeff[3]);
     486
     487    }
     488
     489    psTrace(".psLib.dataManip.psVectorFitSpline1D", 4,
     490            "---- psVectorFitSpline1D() end ----\n");
     491    return(mySpline);
     492}
     493
     494
     495
     496
     497
     498
     499
     500
     501
     502/*****************************************************************************
     503psVectorFitSpline1DNEW(): given a psSpline1D data structure and a set of x/y
     504 
     505xF32 and yF32 are internal psVectors which are used to hold the psF32 versions
     506of the input data, if necessary.  xPtr and yPtr are pointers to either xF32 or
     507the x argument.  All computation is done on xPtr and yPtr.  xF32 and yF32 will
     508simply be psFree() at the end.
     509 
     510XXX: nKnots makes no sense.  This number is always equal to the size of the x
     511an y vectors.
     512 
     513XXX: How do we specify the spline order?  For now, order=3.
     514 *****************************************************************************/
     515#define PS_XXX_SPLINE_ORDER 3
     516psSpline1D *psVectorFitSpline1DNEW(const psVector* x,        ///< Ordinates (or NULL to just use the indices)
     517                                   const psVector* y,        ///< Coordinates
     518                                   int nKnots)
     519{
     520    psTrace(".psLib.dataManip.psVectorFitSpline1D", 4, "---- psVectorFitSpline1DNEW() begin ----\n");
     521    PS_ASSERT_VECTOR_NON_NULL(y, NULL);
     522    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(y, NULL);
     523    //    PS_ASSERT_INT_EQUAL(y->n, nKnots);
     524
     525    //
     526    // The following code ensures that xPtr points to a psF32 version of the
     527    // ordinate data.
     528    //
     529    psVector *xF32 = NULL;
     530    psVector *xPtr = NULL;
     531    if (x != NULL) {
     532        PS_ASSERT_VECTORS_SIZE_EQUAL(x, y, NULL);
     533        if (PS_TYPE_F64 == x->type.type) {
     534            xF32 = psVectorAlloc(y->n, PS_TYPE_F32);
     535            for (psS32 i = 0 ; i < x->n ; i++) {
     536                xF32->data.F32[i] = (psF32) x->data.F64[i];
     537            }
     538            xPtr = xF32;
     539        } else if (PS_TYPE_F32 == x->type.type) {
     540            xPtr = (psVector *) x;
     541        } else {
     542            psError(PS_ERR_UNKNOWN, true, "psVector x is wrong type.\n");
     543            return(NULL);
     544        }
     545    } else {
     546        // If x==NULL, create an x32 vector with x values set to (0:n).
     547        xF32 = psVectorAlloc(y->n, PS_TYPE_F32);
     548        for (psS32 i = 0 ; i < x->n ; i++) {
     549            xF32->data.F32[i] = (psF32) i;
     550        }
     551        xPtr = xF32;
     552    }
     553
     554    //
     555    // If y is of type psF64, then create a new vector yF32 and convert the
     556    // y elements.  Regardless of y's type, we create a yPtr which will be
     557    // used in the remainder of this function.
     558    //
     559    psVector *yF32 = NULL;
     560    psVector *yPtr = NULL;
     561    if (PS_TYPE_F64 == y->type.type) {
     562        yF32 = psVectorAlloc(y->n, PS_TYPE_F32);
     563        for (psS32 i = 0 ; i < y->n ; i++) {
     564            yF32->data.F32[i] = (psF32) y->data.F64[i];
     565        }
     566        yPtr = yF32;
     567    } else {
     568        yPtr = (psVector *) y;
     569    }
     570
     571    psSpline1D *mySpline = psSpline1DAllocGeneric(xPtr, PS_XXX_SPLINE_ORDER);
     572
     573    psS32 numSplines = nKnots - 1;
     574    psF32 tmp;
     575    psF32 H;
     576    psS32 i;
     577    psF32 slope;
     578    // XXX: get rid of x32 and y32 (this is from old code)
     579    psVector *x32 = xPtr;
     580    psVector *y32 = yPtr;
     581
     582    // If these are linear splines, which means their polynomials will have
     583    // two coefficients, then we do the simple calculation.
     584    if (1 == PS_XXX_SPLINE_ORDER) {
     585        for (i=0;i<mySpline->n;i++) {
     586            slope = (y32->data.F32[i+1] - y32->data.F32[i]) /
     587                    (mySpline->knots->data.F32[i+1] - mySpline->knots->data.F32[i]);
     588            (mySpline->spline[i])->coeff[0] = y32->data.F32[i] -
     589                                              (slope * mySpline->knots->data.F32[i]);
     590
     591            (mySpline->spline[i])->coeff[1] = slope;
     592            psTrace(".psLib.dataManip.psMinimize.psVectorFitSpline1D", 4,
     593                    "---- mySpline %d coeffs are (%f, %f)\n", i,
     594                    (mySpline->spline[i])->coeff[0],
     595                    (mySpline->spline[i])->coeff[1]);
     596        }
     597        psTrace(".psLib.dataManip.psMinimize.psVectorFitSpline1D", 4,
     598                "---- Exiting psVectorFitSpline1D()()\n");
     599        return((psSpline1D *) mySpline);
     600    }
     601
     602    //
     603    // Check if these are cubic splines (n==4).  If not, psError.
     604    //
     605    if (3 != PS_XXX_SPLINE_ORDER) {
     606        psError(PS_ERR_BAD_PARAMETER_SIZE, true,
     607                "Don't know how to generate %d-order splines.", PS_XXX_SPLINE_ORDER);
     608        return(NULL);
     609    }
     610
     611    //
     612    // If we get here, then we know these are cubic splines.  We first
     613    // generate the second derivatives at each data point.
     614    //
     615    mySpline->p_psDeriv2 = calculateSecondDerivs(x32, y32);
     616    for (i=0;i<y32->n;i++)
     617        psTrace(".psLib.dataManip.psVectorFitSpline1D", 6,
     618                "Second deriv[%d] is %f\n", i, mySpline->p_psDeriv2[i]);
     619
     620    //
     621    // We generate the coefficients of the spline polynomials.  I can't
     622    // concisely explain how this code works.  See above function comments
     623    // and Numerical Recipes in C.
     624    //
     625    for (i=0;i<numSplines;i++) {
     626        H = x32->data.F32[i+1] - x32->data.F32[i];
     627        psTrace(".psLib.dataManip.psVectorFitSpline1D", 4,
     628                "x data (%f - %f) (%f)\n",
     629                x32->data.F32[i],
     630                x32->data.F32[i+1], H);
     631        //
     632        // ******** Calculate 0-order term ********
     633        //
     634        // From (1)
     635        (mySpline->spline[i])->coeff[0] = (y32->data.F32[i] * x32->data.F32[i+1]/H);
     636        // From (2)
     637        ((mySpline->spline[i])->coeff[0])-= ((y32->data.F32[i+1] * x32->data.F32[i])/H);
     638        // From (3)
     639        tmp = (x32->data.F32[i+1] * x32->data.F32[i+1] * x32->data.F32[i+1]) / (H * H * H);
     640        tmp-= (x32->data.F32[i+1] / H);
     641        tmp*= (mySpline->p_psDeriv2)[i] * H * H / 6.0;
     642        ((mySpline->spline[i])->coeff[0])+= tmp;
     643        // From (4)
     644        tmp = -(x32->data.F32[i] * x32->data.F32[i] * x32->data.F32[i]) / (H * H * H);
     645        tmp+= (x32->data.F32[i] / H);
     646        tmp*= (mySpline->p_psDeriv2)[i+1] * H * H / 6.0;
     647        ((mySpline->spline[i])->coeff[0])+= tmp;
     648
     649        //
     650        // ******** Calculate 1-order term ********
     651        //
     652        // From (1)
     653        (mySpline->spline[i])->coeff[1] = -(y32->data.F32[i]) / H;
     654        // From (2)
     655        ((mySpline->spline[i])->coeff[1])+= (y32->data.F32[i+1] / H);
     656        // From (3)
     657        tmp = -3.0 * (x32->data.F32[i+1] * x32->data.F32[i+1]) / (H * H * H);
     658        tmp+= (1.0 / H);
     659        tmp*= ((mySpline->p_psDeriv2)[i]) * H * H / 6.0;
     660        ((mySpline->spline[i])->coeff[1])+= tmp;
     661        // From (4)
     662        tmp = 3.0 * (x32->data.F32[i] * x32->data.F32[i]) / (H * H * H);
     663        tmp-= (1.0 / H);
     664        tmp*= ((mySpline->p_psDeriv2)[i+1]) * H * H / 6.0;
     665        ((mySpline->spline[i])->coeff[1])+= tmp;
     666
     667        //
     668        // ******** Calculate 2-order term ********
     669        //
     670        // From (3)
     671        (mySpline->spline[i])->coeff[2] = ((mySpline->p_psDeriv2)[i]) * 3.0 * x32->data.F32[i+1] / (6.0 * H);
     672        // From (4)
     673        ((mySpline->spline[i])->coeff[2])-= (((mySpline->p_psDeriv2)[i+1]) * 3.0 * x32->data.F32[i] / (6.0 * H));
     674
     675        //
     676        // ******** Calculate 3-order term ********
     677        //
     678        // From (3)
     679        (mySpline->spline[i])->coeff[3] = -((mySpline->p_psDeriv2)[i]) / (6.0 * H);
     680        // From (4)
     681        ((mySpline->spline[i])->coeff[3])+=  ((mySpline->p_psDeriv2)[i+1]) / (6.0 * H);
     682
     683        psTrace(".psLib.dataManip.psVectorFitSpline1D", 6,
     684                "(mySpline->spline[%d])->coeff[0] is %f\n", i, (mySpline->spline[i])->coeff[0]);
     685        psTrace(".psLib.dataManip.psVectorFitSpline1D", 6,
     686                "(mySpline->spline[%d])->coeff[1] is %f\n", i, (mySpline->spline[i])->coeff[1]);
     687        psTrace(".psLib.dataManip.psVectorFitSpline1D", 6,
     688                "(mySpline->spline[%d])->coeff[2] is %f\n", i, (mySpline->spline[i])->coeff[2]);
     689        psTrace(".psLib.dataManip.psVectorFitSpline1D", 6,
     690                "(mySpline->spline[%d])->coeff[3] is %f\n", i, (mySpline->spline[i])->coeff[3]);
     691
     692    }
     693
     694    psFree(xF32);
     695    psFree(yF32);
     696
     697    psTrace(".psLib.dataManip.psVectorFitSpline1D", 4,
     698            "---- psVectorFitSpline1D() end ----\n");
     699
     700    return(mySpline);
     701}
     702
     703
     704
     705
     706
    209707/*****************************************************************************/
    210708/*  FUNCTION IMPLEMENTATION - PUBLIC                                         */
     
    283781        }
    284782    } else {
    285         printf("XXX: Generate an error here.\n");
     783        psError(PS_ERR_UNKNOWN, true, "psVector in has an incorrect type.\n");
    286784        return(NULL);
    287785    }
  • trunk/psLib/src/math/psSpline.h

    r4969 r4991  
    1010 *  @author GLG, MHPCC
    1111 *
    12  *  @version $Revision: 1.54 $ $Name: not supported by cvs2svn $
    13  *  @date $Date: 2005-09-08 00:02:48 $
     12 *  @version $Revision: 1.55 $ $Name: not supported by cvs2svn $
     13 *  @date $Date: 2005-09-11 22:18:40 $
    1414 *
    1515 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     
    118118);
    119119
     120/** Derive a one-dimensional spline fit.
     121 *
     122 *  Given a psSpline1D data structure and a set of x,y vectors, this routine
     123 *  generates the linear splines which satisfy those data points.
     124 *
     125 *  @return psSpline1D*:  the calculated one-dimensional splines
     126 */
     127psSpline1D *psVectorFitSpline1D(
     128    psSpline1D *mySpline,              ///< The spline which will be generated.
     129    const psVector* x,                 ///< Ordinates (or NULL to just use the indices)
     130    const psVector* y,                 ///< Coordinates
     131    const psVector* yErr               ///< Errors in coordinates, or NULL
     132);
     133
     134psSpline1D *psVectorFitSpline1DNEW(
     135    const psVector* x,                 ///< Ordinates (or NULL to just use the indices)
     136    const psVector* y,                 ///< Coordinates
     137    int nKnots
     138);
     139
    120140/** \} */ // End of MathGroup Functions
    121141
  • trunk/psLib/src/math/psStats.c

    r4962 r4991  
    1717 *
    1818 *
    19  *  @version $Revision: 1.144 $ $Name: not supported by cvs2svn $
    20  *  @date $Date: 2005-09-07 21:40:09 $
     19 *  @version $Revision: 1.145 $ $Name: not supported by cvs2svn $
     20 *  @date $Date: 2005-09-11 22:18:40 $
    2121 *
    2222 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    746746XXX: Write a general routine which smoothes a psVector.  This routine should
    747747call that.  Is that possible?
     748 
     749XXX: This is, or will be, prettier than the previous
     750psVectorSmoothHistGaussian().  However, it is not being used, yet.
    748751 *****************************************************************************/
    749752psVector *p_psVectorSmoothHistGaussianNEW(psHistogram *histogram,
     
    15491552
    15501553        // Determine the coefficients of the polynomial.
    1551         myPoly = psVectorFitPolynomial1D(myPoly, x, y, yErr);
     1554        //        myPoly = psVectorFitPolynomial1D(myPoly, x, y, yErr);
     1555        myPoly = psVectorFitPolynomial1D(myPoly, NULL, 0, y, yErr, x);
    15521556        if (myPoly == NULL) {
    15531557            psError(PS_ERR_UNEXPECTED_NULL,
     
    18251829        psPolynomial1D *tmpPoly = psPolynomial1DAlloc(3, PS_POLYNOMIAL_ORD);
    18261830        // XXX: What about the NULL x argument?
    1827         tmpPoly = psVectorFitPolynomial1D(tmpPoly, NULL, y, NULL);
     1831        tmpPoly = psVectorFitPolynomial1D(tmpPoly, NULL, 0, y, NULL, NULL);
    18281832        if (tmpPoly == NULL) {
    18291833            psLogMsg(__func__, PS_LOG_WARN,
     
    19361940        }
    19371941    } else {
    1938         printf("XXX: Generate an error here.\n");
     1942        psError(PS_ERR_UNKNOWN, true, "Unallowable vector type.\n");
    19391943        return(NULL);
    19401944    }
     
    19501954psVector *Fit1DGaussian(psVector *x, psVector*y)
    19511955{
    1952     printf("XXX: Generate an error here.\n");
    1953     printf("XXX: Error: This function was previously part of psStats.c, was removed, was purged from CVS, and now needs to be retrieved from tape.\n");
     1956    psError(PS_ERR_UNKNOWN, true, "This code has not been implemented yet.\n");
     1957    // XXX: This function was previously part of psStats.c, was removed, was
     1958    // purged from CVS, and now needs to be retrieved from tape.
     1959
    19541960    return(NULL);
    19551961}
     
    21682174            stats->robustLQ = binLo25F32;
    21692175            stats->robustUQ = binHi25F32;
    2170             // XXX: No idea how to calculate stats->stdev
    21712176
    21722177            // PS_BIN_MIDPOINT(robustHistogram, modeBinNum);
    2173 
    21742178            // XXX: I think sumNfit == sumN50 here.
    21752179            stats->robustNfit = -1;
Note: See TracChangeset for help on using the changeset viewer.