IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Dec 28, 2006, 6:38:42 PM (19 years ago)
Author:
magnier
Message:

changed return value for psVectorFit functions to bool; now using stats->option to set FitClip

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/psLib/src/math/psMinimizePolyFit.c

    r10778 r10848  
    1010 *  @author EAM, IfA
    1111 *
    12  *  @version $Revision: 1.26 $ $Name: not supported by cvs2svn $
    13  *  @date $Date: 2006-12-17 09:43:48 $
     12 *  @version $Revision: 1.27 $ $Name: not supported by cvs2svn $
     13 *  @date $Date: 2006-12-29 04:38:42 $
    1414 *
    1515 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     
    5555    }\
    5656}\
     57
     58// free a local temporary F64 vector (TEMP) which is a copy of a non-F64 vector (ORIG)
     59# define PS_FREE_TEMP_F64_VECTOR(ORIG, TEMP) \
     60if ((ORIG != NULL) && (ORIG->type.type != PS_TYPE_F64)) { psFree(TEMP); }
    5761
    5862/*****************************************************************************/
     
    281285 *****************************************************************************/
    282286
    283 
    284287/******************************************************************************
    285288 ******************************************************************************
     
    288291 *****************************************************************************/
    289292
    290 static psPolynomial1D* VectorFitPolynomial1DOrd(
    291     psPolynomial1D* myPoly,
    292     const psVector *mask,
    293     psMaskType maskValue,
    294     const psVector *f,
    295     const psVector *fErr,
    296     const psVector *x);
    297 
    298293/******************************************************************************
    299294vectorFitPolynomial1DCheb():  This routine will fit a Chebyshev
     
    301296coefficients of that polynomial.
    302297*****************************************************************************/
    303 static psPolynomial1D *vectorFitPolynomial1DCheb(
     298static bool vectorFitPolynomial1DCheb(
    304299    psPolynomial1D* myPoly,
    305300    const psVector *mask,
     
    404399        if (!psMatrixGJSolve(A, B)) {
    405400            psError(PS_ERR_UNKNOWN, false, "Could not solve linear equations.  Returning NULL.\n");
    406             psFree(myPoly);
    407             myPoly = NULL;
     401            goto escape_GJ;
    408402        } else {
    409403            // the first nTerm entries in B correspond directly to the desired
     
    427421        if (ALUD == NULL) {
    428422            psError(PS_ERR_UNKNOWN, false, "Could not do LUD decomposition on matrix.  Returning NULL.\n");
    429             psFree(myPoly);
    430             myPoly = NULL;
     423            goto escape_LUD;
    431424        } else {
    432425            coeffs = psMatrixLUSolve(coeffs, ALUD, B, outPerm);
    433426            if (coeffs == NULL) {
    434427                psError(PS_ERR_UNKNOWN, false, "Could not solve LUD matrix.  Returning NULL.\n");
    435                 psFree(myPoly);
    436                 myPoly = NULL;
     428                goto escape_LUD;
    437429            } else {
    438430                for (psS32 k = 0; k < numTerms; k++) {
     
    441433            }
    442434        }
    443 
    444 
    445435        psFree(ALUD);
    446436        psFree(coeffs);
    447437        psFree(outPerm);
    448438    }
    449 
    450439    psFree(A);
    451440    psFree(B);
    452 
    453     return(myPoly);
     441    return true;
     442
     443escape_LUD:
     444    // XXX drop the LUD version!
     445    psFree(A);
     446    psFree(B);
     447    return false;
     448
     449escape_GJ:
     450    psFree(A);
     451    psFree(B);
     452    return false;
    454453}
    455454
     
    459458x and fErr vectors may be NULL.  All non-NULL vectors must be of type
    460459PS_TYPE_F64.
    461  *****************************************************************************/
    462 static psPolynomial1D* VectorFitPolynomial1DOrd(
     460 
     461XXX EAM : since this is a private function, can we drop the ASSERTS?
     462XXX EAM : can we drop the LUD version? it does not calculate coeffErr values!!
     463*****************************************************************************/
     464static bool VectorFitPolynomial1DOrd(
    463465    psPolynomial1D* myPoly,
    464466    const psVector *mask,
     
    469471{
    470472    psTrace("psLib.math", 4, "---- %s() begin ----\n", __func__);
    471     PS_ASSERT_POLY_NON_NULL(myPoly, NULL);
    472     PS_ASSERT_VECTOR_NON_NULL(f, NULL);
    473     PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F64, NULL);
     473    PS_ASSERT_POLY_NON_NULL(myPoly, false);
     474    PS_ASSERT_VECTOR_NON_NULL(f, false);
     475    PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F64, false);
    474476    if (mask) {
    475         PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL);
    476         PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL);
     477        PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, false);
     478        PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false);
    477479    }
    478480    if (x) {
    479         PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL);
    480         PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F64, NULL);
     481        PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, false);
     482        PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F64, false);
    481483    }
    482484    if (fErr) {
    483         PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, NULL);
    484         PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F64, NULL);
     485        PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, false);
     486        PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F64, false);
    485487    }
    486488
     
    510512    if (!psImageInit(A, 0.0) || !psVectorInit(B, 0.0)) {
    511513        psError(PS_ERR_UNKNOWN, false, "Could initialize data structures A, B.  Returning NULL.\n");
    512         psFree(myPoly);
    513514        psFree(A);
    514515        psFree(B);
    515516        psTrace("psLib.math", 4, "---- %s() End ----\n", __func__);
    516         return(NULL);
     517        return false;
    517518    }
    518519
     
    596597        if (!psMatrixGJSolve(A, B)) {
    597598            psError(PS_ERR_UNKNOWN, false, "Could not solve linear equations.  Returning NULL.\n");
    598             psFree(myPoly);
    599             myPoly = NULL;
     599            goto escape_GJ;
    600600        } else {
    601601            // the first nTerm entries in B correspond directly to the desired
     
    617617        if (ALUD == NULL) {
    618618            psError(PS_ERR_UNKNOWN, false, "Could not do LUD decomposition on matrix.  Returning NULL.\n");
    619             psFree(myPoly);
    620             myPoly = NULL;
     619            goto escape_LUD;
    621620        } else {
    622621            coeffs = psMatrixLUSolve(coeffs, ALUD, B, outPerm);
    623622            if (coeffs == NULL) {
    624623                psError(PS_ERR_UNKNOWN, false, "Could not solve LUD matrix.  Returning NULL.\n");
    625                 psFree(myPoly);
    626                 myPoly = NULL;
     624                goto escape_LUD;
    627625            } else {
    628626                for (psS32 k = 0; k < nTerm; k++) {
     
    632630            }
    633631        }
    634 
    635632        psFree(ALUD);
    636633        psFree(coeffs);
    637634        psFree(outPerm);
    638635    }
    639 
    640 
    641636    psFree(A);
    642637    psFree(B);
    643638
    644639    psTrace("psLib.math", 4, "---- %s() End ----\n", __func__);
    645     return (myPoly);
     640    return true;
     641
     642escape_LUD:
     643    psFree(A);
     644    psFree(B);
     645    return false;
     646
     647escape_GJ:
     648    psFree(A);
     649    psFree(B);
     650    return false;
    646651}
    647652
     
    653658conversion only.
    654659 *****************************************************************************/
    655 psPolynomial1D *psVectorFitPolynomial1D(
     660bool psVectorFitPolynomial1D(
    656661    psPolynomial1D *poly,
    657662    const psVector *mask,
     
    661666    const psVector *x)
    662667{
    663     // Internal pointers for possibly NULL or mis-typed vectors.
     668    PS_ASSERT_POLY_NON_NULL(poly, false);
     669    PS_ASSERT_INT_NONNEGATIVE(poly->nX, false);
     670
     671    PS_ASSERT_VECTOR_NON_NULL(f, false);
     672    PS_ASSERT_VECTOR_NON_EMPTY(f, false);
     673    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, false);
     674    if (mask != NULL) {
     675        PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, false);
     676        PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false);
     677    }
     678    if (fErr != NULL) {
     679        PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, false);
     680        PS_ASSERT_VECTOR_TYPE_F32_OR_F64(fErr, false);
     681    }
     682    if (x != NULL) {
     683        PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, false);
     684        PS_ASSERT_VECTOR_TYPE_F32_OR_F64(x, false);
     685    }
     686
     687    // Convert input vectors to F64 if necessary.
     688    psVector *f64 = (f->type.type == PS_TYPE_F64) ? (psVector *) f : psVectorCopy (NULL, f, PS_TYPE_F64);
    664689    psVector *x64 = NULL;
    665     psVector *f64 = NULL;
     690    if (x != NULL) {
     691        x64 = (x->type.type == PS_TYPE_F64) ? (psVector *) x : psVectorCopy (NULL, x, PS_TYPE_F64);
     692    }
    666693    psVector *fErr64 = NULL;
    667 
    668     PS_ASSERT_POLY_NON_NULL(poly, NULL);
    669     //PS_ASSERT_INT_NONNEGATIVE(poly->nX, NULL);
    670     PS_ASSERT_VECTOR_NON_NULL(f, NULL);
    671     PS_ASSERT_VECTOR_NON_EMPTY(f, NULL);
    672     PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, NULL);
    673     if (mask != NULL) {
    674         PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL);
    675         PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL);
    676     }
    677     if (x != NULL) {
    678         PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL);
    679         PS_ASSERT_VECTOR_TYPE_F32_OR_F64(x, NULL);
    680     }
    681694    if (fErr != NULL) {
    682         PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, NULL);
    683         PS_ASSERT_VECTOR_TYPE_F32_OR_F64(fErr, NULL);
    684     }
    685 
    686     f64 = (f->type.type == PS_TYPE_F64) ? (psVector *) f : psVectorCopy(NULL, f, PS_TYPE_F64);
    687 
    688     if (x != NULL) {
    689         x64 = (x->type.type == PS_TYPE_F64) ? (psVector *) x : psVectorCopy(NULL, x, PS_TYPE_F64);
    690     }
    691 
    692     if (fErr != NULL) {
    693         fErr64 = (fErr->type.type == PS_TYPE_F64) ? (psVector *) fErr : psVectorCopy(NULL, fErr, PS_TYPE_F64);
    694     }
     695        fErr64 = (fErr->type.type == PS_TYPE_F64) ? (psVector *) fErr : psVectorCopy (NULL, fErr, PS_TYPE_F64);
     696    }
     697
     698    bool result = true;
    695699
    696700    switch (poly->type) {
    697701    case PS_POLYNOMIAL_ORD:
    698         poly = VectorFitPolynomial1DOrd(poly, mask, maskValue, f64, fErr64, x64);
    699         if (poly == NULL) {
     702        result = VectorFitPolynomial1DOrd(poly, mask, maskValue, f64, fErr64, x64);
     703        if (!result) {
    700704            psError(PS_ERR_UNKNOWN, false, "Could not fit polynomial.  Returning NULL.\n");
    701705        }
     
    703707    case PS_POLYNOMIAL_CHEB:
    704708        if (mask != NULL) {
    705             //            psLogMsg(__func__, PS_LOG_WARN, "WARNING: ignoring mask and maskValue with Chebyshev polynomials.\n");
     709            psLogMsg(__func__, PS_LOG_WARN, "WARNING: ignoring mask and maskValue with Chebyshev polynomials.\n");
    706710        }
    707711        if (fErr != NULL) {
     
    713717        }
    714718
    715         poly = vectorFitPolynomial1DCheb(poly, mask, maskValue, f64, fErr64, x64);
     719        result = vectorFitPolynomial1DCheb(poly, mask, maskValue, f64, fErr64, x64);
     720        if (!result) {
     721            psError(PS_ERR_UNKNOWN, false, "Could not fit polynomial.  Returning NULL.\n");
     722        }
    716723
    717724        if (x == NULL) {
     
    721728    default:
    722729        psError(PS_ERR_UNKNOWN, true, "Incorrect polynomial type (%d).  Returning NULL.\n", poly->type);
    723         poly = NULL;
     730        result = false;
    724731        break;
    725732    }
    726733
    727734    // Free psVectors that were created for NULL arguments.
    728     if (f->type.type != PS_TYPE_F64) {
    729         psFree(f64);
    730     }
    731 
    732     if ((x != NULL) && (x->type.type != PS_TYPE_F64)) {
    733         psFree(x64);
    734     }
    735 
    736     if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) {
    737         psFree(fErr64);
    738     }
    739 
    740     return(poly);
     735    PS_FREE_TEMP_F64_VECTOR (f, f64);
     736    PS_FREE_TEMP_F64_VECTOR (x, x64);
     737    PS_FREE_TEMP_F64_VECTOR (fErr, fErr64);
     738
     739    return result;
    741740}
    742741
    743742// This function accepts F32 and F64 input vectors.
    744 psPolynomial1D *psVectorClipFitPolynomial1D(
     743bool psVectorClipFitPolynomial1D(
    745744    psPolynomial1D *poly,
    746745    psStats *stats,
     
    752751{
    753752    psTrace("psLib.math", 3, "---- %s() begin ----\n", __func__);
    754     PS_ASSERT_POLY_NON_NULL(poly, NULL);
    755     PS_ASSERT_PTR_NON_NULL(stats, NULL);
    756     PS_ASSERT_VECTOR_NON_NULL(f, NULL);
    757     PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, NULL);
    758     PS_ASSERT_VECTOR_NON_NULL(mask, NULL);
    759     PS_ASSERT_VECTORS_SIZE_EQUAL(mask, f, NULL);
    760     PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL);
     753    PS_ASSERT_POLY_NON_NULL(poly, false);
     754    PS_ASSERT_PTR_NON_NULL(stats, false);
     755    PS_ASSERT_VECTOR_NON_NULL(f, false);
     756    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, false);
     757    PS_ASSERT_VECTOR_NON_NULL(mask, false);
     758    PS_ASSERT_VECTORS_SIZE_EQUAL(mask, f, false);
     759    PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false);
     760
    761761    if (fErr != NULL) {
    762         PS_ASSERT_VECTORS_SIZE_EQUAL(fErr, f, NULL);
    763         PS_ASSERT_VECTOR_TYPE(fErr, f->type.type, NULL);
     762        PS_ASSERT_VECTORS_SIZE_EQUAL(fErr, f, false);
     763        PS_ASSERT_VECTOR_TYPE(fErr, f->type.type, false);
    764764    }
    765765
     
    767767    psVector *x = NULL;
    768768    if (xIn != NULL) {
    769         PS_ASSERT_VECTORS_SIZE_EQUAL(xIn, f, NULL);
    770         PS_ASSERT_VECTOR_TYPE(xIn, f->type.type, NULL);
     769        PS_ASSERT_VECTORS_SIZE_EQUAL(xIn, f, false);
     770        PS_ASSERT_VECTOR_TYPE(xIn, f->type.type, false);
    771771        x = (psVector *) xIn;
    772772    } else {
     
    781781        } else {
    782782            psError(PS_ERR_UNKNOWN, true, "Error, bad poly type.\n");
    783             return(NULL);
    784         }
     783            return false;
     784        }
     785    }
     786
     787    // the user supplies one of various stats option pairs,
     788    // determine the desired mean and stdev STATS options:
     789    // XXX enforce consistency?
     790    // XXX psStatsGetValue() probably has inverted precedence
     791    psStatsOptions meanOption = stats->options & (PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_MEDIAN | PS_STAT_ROBUST_MEDIAN | PS_STAT_CLIPPED_MEAN | PS_STAT_FITTED_MEAN | PS_STAT_FITTED_MEAN_V2);
     792    psStatsOptions stdevOption = stats->options & (PS_STAT_SAMPLE_STDEV | PS_STAT_ROBUST_STDEV | PS_STAT_CLIPPED_STDEV | PS_STAT_FITTED_STDEV | PS_STAT_FITTED_STDEV_V2);
     793    if (!meanOption) {
     794        psError(PS_ERR_UNKNOWN, true, "no valid mean stats option selected");
     795        return false;
     796    }
     797    if (!stdevOption) {
     798        psError(PS_ERR_UNKNOWN, true, "no valid stdev stats option selected");
     799        return false;
    785800    }
    786801
     
    798813        minClipSigma = fabs(stats->clipSigma);
    799814    }
    800 
    801     psVector *fit   = NULL;
    802815    psVector *resid = psVectorAlloc(f->n, PS_TYPE_F64);
    803816
    804     // eventual expansion: user supplies one of various stats option pairs,
    805     // eg (SAMPLE_MEAN | SAMPLE_STDEV) and the correct pair is used to
    806     // evaluate the clipping sigma
    807     // for now, for the SAMPLE_MEDIAN and SAMPLE_STDEV to be used
    808     stats->options |= (PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV);
    809     stats->options |= (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);
    810817    psTrace("psLib.math", 4, "stats->clipIter is %d\n", stats->clipIter);
    811818    psTrace("psLib.math", 4, "(minClipSigma, maxClipSigma) is (%.2f, %.2f)\n", minClipSigma, maxClipSigma);
     
    822829            }
    823830        }
    824         poly = psVectorFitPolynomial1D(poly, mask, maskValue, f, fErr, x);
    825         if (poly == NULL) {
    826             psError(PS_ERR_UNKNOWN, false, "Could not fit polynomial.  Returning NULL.\n");
     831        if (!psVectorFitPolynomial1D(poly, mask, maskValue, f, fErr, x)) {
     832            psError(PS_ERR_UNKNOWN, false, "Could not fit polynomial.  Returning false.\n");
    827833            if (xIn == NULL) {
    828834                psFree(x);
    829835            }
    830             return(NULL);
    831         }
    832 
    833         fit = psPolynomial1DEvalVector(poly, x);
     836            return false;
     837        }
     838
     839        psVector *fit = psPolynomial1DEvalVector(poly, x);
    834840        if (fit == NULL) {
    835             psError(PS_ERR_UNKNOWN, false, "Could not call psPolynomial3DEvalVector().  Returning NULL.\n");
     841            psError(PS_ERR_UNKNOWN, false, "Could not call psPolynomial3DEvalVector().  Returning false.\n");
    836842            psFree(resid);
    837             return(NULL);
     843            return false;
    838844        }
    839845        for (psS32 i = 0 ; i < f->n ; i++) {
     
    856862
    857863        if (!psVectorStats(stats, resid, NULL, mask, maskValue)) {
    858             psError(PS_ERR_UNKNOWN, false, "Could not compute statistics on the resid vector.  Returning NULL.\n");
    859             psFree(resid)
    860             psFree(fit)
    861             return(NULL);
    862         }
    863         # if (USE_ROBUST_STATS_FOR_CLIPPING)
    864             psTrace("psLib.math", 5, "Median is %f\n", stats->robustMedian);
    865         psTrace("psLib.math", 5, "Stdev is %f\n", stats->robustStdev);
    866         psF32 minClipValue = -minClipSigma*stats->robustStdev;
    867         psF32 maxClipValue = +maxClipSigma*stats->robustStdev;
    868         psF32 clipMedian = stats->robustMedian;
    869         # else
    870 
    871             psTrace("psLib.math", 5, "Median is %f\n", stats->sampleMedian);
    872         psTrace("psLib.math", 5, "Stdev is %f\n", stats->sampleStdev);
    873         psF32 minClipValue = -minClipSigma*stats->robustStdev;
    874         psF32 maxClipValue = +maxClipSigma*stats->robustStdev;
    875         psF32 clipMedian = stats->sampleMedian;
    876         # endif
     864            psError(PS_ERR_UNKNOWN, false, "Could not compute statistics on the resid vector.  Returning false.\n");
     865            psFree(resid);
     866            psFree(fit);
     867            return false;
     868        }
     869
     870        double meanValue = psStatsGetValue (stats, meanOption);
     871        double stdevValue = psStatsGetValue (stats, stdevOption);
     872
     873        psTrace("psLib.math", 5, "Mean is %f\n", meanValue);
     874        psTrace("psLib.math", 5, "Stdev is %f\n", stdevValue);
     875        psF32 minClipValue = -minClipSigma*stdevValue;
     876        psF32 maxClipValue = +maxClipSigma*stdevValue;
    877877
    878878        // set mask if pts are not valid
     
    884884            }
    885885
    886             if ((resid->data.F64[i] - clipMedian > maxClipValue) || (resid->data.F64[i] - clipMedian < minClipValue)) {
     886            if ((resid->data.F64[i] - meanValue > maxClipValue) || (resid->data.F64[i] - meanValue < minClipValue)) {
    887887                if (f->type.type == PS_TYPE_F64) {
    888888                    psTrace("psLib.math", 6, "Masking element %d (%f).  resid->data.F64[%d] is %f\n",
     
    906906        //
    907907        psTrace("psLib.math", 6, "keeping %d of %ld pts for fit\n", Nkeep, x->n);
     908        stats->clippedNvalues = Nkeep;
    908909        psFree(fit);
    909910    }
     
    917918
    918919    psTrace("psLib.math", 3, "---- %s() end ----\n", __func__);
    919     return (poly);
     920    return true;
    920921}
    921922
     
    933934 
    934935 *****************************************************************************/
    935 static psPolynomial2D* VectorFitPolynomial2DOrd(
     936static bool VectorFitPolynomial2DOrd(
    936937    psPolynomial2D* myPoly,
    937938    const psVector* mask,
     
    943944{
    944945    psTrace("psLib.math", 4, "---- %s() begin ----\n", __func__);
    945     PS_ASSERT_POLY_NON_NULL(myPoly, NULL);
    946     PS_ASSERT_INT_NONNEGATIVE(myPoly->nX, NULL);
    947     PS_ASSERT_INT_NONNEGATIVE(myPoly->nY, NULL);
    948     PS_ASSERT_VECTOR_NON_NULL(f, NULL);
    949     PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F64, NULL);
     946    PS_ASSERT_POLY_NON_NULL(myPoly, false);
     947    PS_ASSERT_INT_NONNEGATIVE(myPoly->nX, false);
     948    PS_ASSERT_INT_NONNEGATIVE(myPoly->nY, false);
     949    PS_ASSERT_VECTOR_NON_NULL(f, false);
     950    PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F64, false);
    950951    if (fErr != NULL) {
    951         PS_ASSERT_VECTORS_SIZE_EQUAL(y, fErr, NULL);
    952         PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F64, NULL);
    953     }
    954     PS_ASSERT_VECTOR_NON_NULL(x, NULL);
    955     PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F64, NULL);
    956     PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL);
    957     PS_ASSERT_VECTOR_NON_NULL(y, NULL);
    958     PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F64, NULL);
    959     PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL);
     952        PS_ASSERT_VECTORS_SIZE_EQUAL(y, fErr, false);
     953        PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F64, false);
     954    }
     955    PS_ASSERT_VECTOR_NON_NULL(x, false);
     956    PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F64, false);
     957    PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, false);
     958    PS_ASSERT_VECTOR_NON_NULL(y, false);
     959    PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F64, false);
     960    PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, false);
    960961    if (mask != NULL) {
    961         PS_ASSERT_VECTORS_SIZE_EQUAL(y, mask, NULL);
    962         PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL);
     962        PS_ASSERT_VECTORS_SIZE_EQUAL(y, mask, false);
     963        PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false);
    963964    }
    964965
     
    974975    if (!psImageInit(A, 0.0) || !psVectorInit(B, 0.0)) {
    975976        psError(PS_ERR_UNKNOWN, false, "Could initialize data structures A, B.  Returning NULL.\n");
    976         psFree(myPoly);
    977977        psFree(A);
    978978        psFree(B);
    979979        psTrace("psLib.math", 4, "---- %s() End ----\n", __func__);
    980         return(NULL);
     980        return false;
    981981    }
    982982
     
    10401040    if (!psMatrixGJSolve(A, B)) {
    10411041        psError(PS_ERR_UNKNOWN, false, "Could not solve linear equations.  Returning NULL.\n");
    1042         psFree(myPoly);
    1043         myPoly = NULL;
    1044     } else {
    1045         // select the appropriate solution entries
    1046         for (int i = 0; i < nTerm; i++) {
    1047             int l = i / nYterm;         // x index
    1048             int m = i % nYterm;         // y index
    1049             myPoly->coeff[l][m] = B->data.F64[i];
    1050             myPoly->coeffErr[l][m] = sqrt(A->data.F64[i][i]);
    1051         }
    1052     }
    1053 
     1042        psFree(A);
     1043        psFree(B);
     1044        return false;
     1045    }
     1046
     1047    // select the appropriate solution entries
     1048    for (int i = 0; i < nTerm; i++) {
     1049        int l = i / nYterm;         // x index
     1050        int m = i % nYterm;         // y index
     1051        myPoly->coeff[l][m] = B->data.F64[i];
     1052        myPoly->coeffErr[l][m] = sqrt(A->data.F64[i][i]);
     1053    }
    10541054    psFree(A);
    10551055    psFree(B);
    10561056
    10571057    psTrace("psLib.math", 4, "---- %s() end ----\n", __func__);
    1058     return (myPoly);
     1058    return true;
    10591059}
    10601060
     
    10651065vector conversion only.
    10661066 *****************************************************************************/
    1067 psPolynomial2D *psVectorFitPolynomial2D(
     1067bool psVectorFitPolynomial2D(
    10681068    psPolynomial2D *poly,
    10691069    const psVector *mask,
     
    10741074    const psVector *y)
    10751075{
    1076     // Internal pointers for possibly NULL or mis-typed vectors.
    1077     psVector *x64 = NULL;
    1078     psVector *y64 = NULL;
    1079     psVector *f64 = NULL;
     1076    PS_ASSERT_POLY_NON_NULL(poly, false);
     1077    PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, false);
     1078
     1079    PS_ASSERT_VECTOR_NON_NULL(f, false);
     1080    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, false);
     1081    PS_ASSERT_VECTOR_NON_NULL(x, false);
     1082    PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, false);
     1083    PS_ASSERT_VECTOR_NON_NULL(y, false);
     1084    PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, false);
     1085    if (mask != NULL) {
     1086        PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, false);
     1087        PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false);
     1088    }
     1089    if (fErr != NULL) {
     1090        PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, false);
     1091        PS_ASSERT_VECTOR_TYPE_F32_OR_F64(fErr, false);
     1092    }
     1093
     1094    // Convert input vectors to F64 if necessary.
     1095    psVector *f64 = (f->type.type == PS_TYPE_F64) ? (psVector *) f : psVectorCopy(NULL, f, PS_TYPE_F64);
     1096    psVector *x64 = (x->type.type == PS_TYPE_F64) ? (psVector *) x : psVectorCopy(NULL, x, PS_TYPE_F64);
     1097    psVector *y64 = (y->type.type == PS_TYPE_F64) ? (psVector *) y : psVectorCopy(NULL, y, PS_TYPE_F64);
     1098
    10801099    psVector *fErr64 = NULL;
    1081 
    1082     PS_ASSERT_POLY_NON_NULL(poly, NULL);
    1083     PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, NULL);
    1084 
    1085     PS_ASSERT_VECTOR_NON_NULL(f, NULL);
    1086     PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, NULL);
    1087 
    1088     if (mask != NULL) {
    1089         PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL);
    1090         PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL);
    1091     }
    1092     PS_ASSERT_VECTOR_NON_NULL(x, NULL);
    1093     PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL);
    1094     PS_ASSERT_VECTOR_NON_NULL(y, NULL);
    1095     PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL);
    10961100    if (fErr != NULL) {
    1097         PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, NULL);
    1098         PS_ASSERT_VECTOR_TYPE_F32_OR_F64(fErr, NULL);
    1099     }
    1100 
    1101     //
    1102     // Convert input vectors to F64 if necessary.
    1103     //
    1104     if (f->type.type != PS_TYPE_F64) {
    1105         f64 = psVectorCopy(NULL, f, PS_TYPE_F64);
    1106     } else {
    1107         f64 = (psVector *) f;
    1108     }
    1109 
    1110     if (x->type.type != PS_TYPE_F64) {
    1111         x64 = psVectorCopy(NULL, x, PS_TYPE_F64);
    1112     } else {
    1113         x64 = (psVector *) x;
    1114     }
    1115 
    1116     if (y->type.type != PS_TYPE_F64) {
    1117         y64 = psVectorCopy(NULL, y, PS_TYPE_F64);
    1118     } else {
    1119         y64 = (psVector *) y;
    1120     }
    1121 
    1122     //
    1123     // fErr
    1124     //
    1125     if (fErr != NULL) {
    1126         if (fErr->type.type != PS_TYPE_F64) {
    1127             fErr64 = psVectorCopy(NULL, fErr, PS_TYPE_F64);
    1128         } else {
    1129             fErr64 = (psVector *) fErr;
    1130         }
    1131     }
    1132 
    1133     if (poly->type == PS_POLYNOMIAL_ORD) {
    1134         poly = VectorFitPolynomial2DOrd(poly, mask, maskValue, f64, fErr64, x64, y64);
    1135         if (poly == NULL) {
     1101        fErr64 = (fErr->type.type == PS_TYPE_F64) ? (psVector *) fErr : psVectorCopy(NULL, fErr, PS_TYPE_F64);
     1102    }
     1103
     1104    bool result = true;
     1105
     1106    switch (poly->type) {
     1107    case PS_POLYNOMIAL_ORD:
     1108        result = VectorFitPolynomial2DOrd(poly, mask, maskValue, f64, fErr64, x64, y64);
     1109        if (!result) {
    11361110            psError(PS_ERR_UNKNOWN, true, "Could not fit polynomial.  Returning NULL.\n");
    1137             // Free psVectors that were created for NULL arguments.
    1138             if (f->type.type != PS_TYPE_F64) {
    1139                 psFree(f64);
    1140             }
    1141 
    1142             if (x->type.type != PS_TYPE_F64) {
    1143                 psFree(x64);
    1144             }
    1145 
    1146             if (y->type.type != PS_TYPE_F64) {
    1147                 psFree(y64);
    1148             }
    1149 
    1150             if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) {
    1151                 psFree(fErr64);
    1152             }
    1153             return(NULL);
    1154         }
    1155     } else if (poly->type == PS_POLYNOMIAL_CHEB) {
     1111        }
     1112        break;
     1113    case PS_POLYNOMIAL_CHEB:
    11561114        if (mask != NULL) {
    11571115            psLogMsg(__func__, PS_LOG_WARN, "WARNING: ignoring mask and maskValue with Chebyshev polynomials.\n");
    11581116        }
    1159         psLogMsg(__func__, PS_LOG_WARN, "WARNING: 2-D Chebyshev polynomial vector fitting has not been implemented.  Returning NULL.\n");
    1160         psFree(poly);
    1161         poly = NULL;
    1162     } else {
    1163         // Free psVectors that were created for NULL arguments.
    1164         if (f->type.type != PS_TYPE_F64) {
    1165             psFree(f64);
    1166         }
    1167 
    1168         if (x->type.type != PS_TYPE_F64) {
    1169             psFree(x64);
    1170         }
    1171 
    1172         if (y->type.type != PS_TYPE_F64) {
    1173             psFree(y64);
    1174         }
    1175 
    1176         if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) {
    1177             psFree(fErr64);
    1178         }
     1117        psError(PS_ERR_UNKNOWN, true, "2-D Chebyshev polynomial vector fitting has not been implemented.  Returning NULL.\n");
     1118        result = false;
     1119        break;
     1120    default:
    11791121        psError(PS_ERR_UNKNOWN, true, "Incorrect polynomial type.  Returning NULL.\n");
    1180     }
    1181 
     1122        result = false;
     1123        break;
     1124    }
    11821125
    11831126    // Free psVectors that were created for NULL arguments.
    1184     if (f->type.type != PS_TYPE_F64) {
    1185         psFree(f64);
    1186     }
    1187 
    1188     if (x->type.type != PS_TYPE_F64) {
    1189         psFree(x64);
    1190     }
    1191 
    1192     if (y->type.type != PS_TYPE_F64) {
    1193         psFree(y64);
    1194     }
    1195 
    1196     if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) {
    1197         psFree(fErr64);
    1198     }
    1199 
    1200     return(poly);
     1127    PS_FREE_TEMP_F64_VECTOR (f, f64);
     1128    PS_FREE_TEMP_F64_VECTOR (x, x64);
     1129    PS_FREE_TEMP_F64_VECTOR (y, y64);
     1130    PS_FREE_TEMP_F64_VECTOR (fErr, fErr64);
     1131
     1132    return result;
    12011133}
    12021134
    1203 psPolynomial2D *psVectorClipFitPolynomial2D(
     1135bool psVectorClipFitPolynomial2D(
    12041136    psPolynomial2D *poly,
    12051137    psStats *stats,
     
    12121144{
    12131145    psTrace("psLib.math", 3, "---- %s() begin ----\n", __func__);
    1214     PS_ASSERT_POLY_NON_NULL(poly, NULL);
    1215     PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, NULL);
    1216     PS_ASSERT_PTR_NON_NULL(stats, NULL);
    1217     PS_ASSERT_VECTOR_NON_NULL(mask, NULL);
    1218     PS_ASSERT_VECTOR_NON_NULL(f, NULL);
    1219     PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, NULL);
    1220     if (mask != NULL) {
    1221         PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL);
    1222         PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL);
    1223     }
    1224     PS_ASSERT_VECTOR_NON_NULL(x, NULL);
    1225     PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL);
    1226     PS_ASSERT_VECTOR_TYPE(x, f->type.type, NULL);
    1227 
    1228     PS_ASSERT_VECTOR_NON_NULL(y, NULL);
    1229     PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL);
    1230     PS_ASSERT_VECTOR_TYPE(y, f->type.type, NULL);
     1146    PS_ASSERT_POLY_NON_NULL(poly, false);
     1147    PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, false);
     1148    PS_ASSERT_PTR_NON_NULL(stats, false);
     1149    PS_ASSERT_VECTOR_NON_NULL(mask, false);
     1150    PS_ASSERT_VECTOR_NON_NULL(f, false);
     1151    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, false);
     1152
     1153    PS_ASSERT_VECTOR_NON_NULL(x, false);
     1154    PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, false);
     1155    PS_ASSERT_VECTOR_TYPE(x, f->type.type, false);
     1156
     1157    PS_ASSERT_VECTOR_NON_NULL(y, false);
     1158    PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, false);
     1159    PS_ASSERT_VECTOR_TYPE(y, f->type.type, false);
     1160
     1161    PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, false);
     1162    PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false);
    12311163
    12321164    if (fErr != NULL) {
    1233         PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, NULL);
    1234         PS_ASSERT_VECTOR_TYPE(fErr, f->type.type, NULL);
     1165        PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, false);
     1166        PS_ASSERT_VECTOR_TYPE(fErr, f->type.type, false);
     1167    }
     1168
     1169    // the user supplies one of various stats option pairs,
     1170    // determine the desired mean and stdev STATS options:
     1171    // XXX enforce consistency?
     1172    // XXX psStatsGetValue() probably has inverted precedence
     1173    psStatsOptions meanOption = stats->options & (PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_MEDIAN | PS_STAT_ROBUST_MEDIAN | PS_STAT_CLIPPED_MEAN | PS_STAT_FITTED_MEAN | PS_STAT_FITTED_MEAN_V2);
     1174    psStatsOptions stdevOption = stats->options & (PS_STAT_SAMPLE_STDEV | PS_STAT_ROBUST_STDEV | PS_STAT_CLIPPED_STDEV | PS_STAT_FITTED_STDEV | PS_STAT_FITTED_STDEV_V2);
     1175    if (!meanOption) {
     1176        psError(PS_ERR_UNKNOWN, true, "no valid mean stats option selected");
     1177        return false;
     1178    }
     1179    if (!stdevOption) {
     1180        psError(PS_ERR_UNKNOWN, true, "no valid stdev stats option selected");
     1181        return false;
    12351182    }
    12361183
     
    12501197    psVector *resid = psVectorAlloc(f->n, PS_TYPE_F64);
    12511198
    1252     // eventual expansion: user supplies one of various stats option pairs,
    1253     // eg (SAMPLE_MEAN | SAMPLE_STDEV) and the correct pair is used to
    1254     // evaluate the clipping sigma
    1255     // for now, for the SAMPLE_MEDIAN and SAMPLE_STDEV to be used
    1256     stats->options |= (PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV);
    1257     stats->options |= (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);
    12581199    psTrace("psLib.math", 4, "stats->clipIter is %d\n", stats->clipIter);
    12591200    psTrace("psLib.math", 4, "(minClipSigma, maxClipSigma) is (%.2f, %.2f)\n", minClipSigma, maxClipSigma);
     
    12701211        }
    12711212
    1272         poly = psVectorFitPolynomial2D(poly, mask, maskValue, f, fErr, x, y);
    1273         if (poly == NULL) {
    1274             psError(PS_ERR_UNKNOWN, false, "Could not fit a polynomial to the data.  Returning NULL.\n");
     1213        if (!psVectorFitPolynomial2D(poly, mask, maskValue, f, fErr, x, y)) {
     1214            psError(PS_ERR_UNKNOWN, false, "Could not fit a polynomial to the data.  Returning false.\n");
    12751215            psFree(resid)
    1276             return(NULL);
     1216            return false;
    12771217        }
    12781218
     
    12811221            psError(PS_ERR_UNKNOWN, false, "Could not call psPolynomial3DEvalVector().  Returning NULL.\n");
    12821222            psFree(resid)
    1283             return(NULL);
     1223            return false;
    12841224        }
    12851225
     
    13071247            psFree(resid)
    13081248            psFree(fit)
    1309             return(NULL);
    1310         }
    1311         # if (USE_ROBUST_STATS_FOR_CLIPPING)
    1312             psTrace("psLib.math", 5, "Median is %f\n", stats->robustMedian);
    1313         psTrace("psLib.math", 5, "Stdev is %f\n", stats->robustStdev);
    1314         psTrace("psLib.math", 5, "Sample Median is %f\n", stats->sampleMedian);
    1315         psTrace("psLib.math", 5, "Sample Stdev is %f\n", stats->sampleStdev);
    1316         psF32 minClipValue = -minClipSigma*stats->robustStdev;
    1317         psF32 maxClipValue = +maxClipSigma*stats->robustStdev;
    1318         psF32 clipMedian = stats->robustMedian;
    1319         # else
    1320 
    1321             psTrace("psLib.math", 5, "Median is %f\n", stats->sampleMedian);
    1322         psTrace("psLib.math", 5, "Stdev is %f\n", stats->sampleStdev);
    1323         psTrace("psLib.math", 5, "Robust Median is %f\n", stats->robustMedian);
    1324         psTrace("psLib.math", 5, "Robust Stdev is %f\n", stats->robustStdev);
    1325         psF32 minClipValue = -minClipSigma*stats->robustStdev;
    1326         psF32 maxClipValue = +maxClipSigma*stats->robustStdev;
    1327         psF32 clipMedian = stats->sampleMedian;
    1328         # endif
     1249            return false;
     1250        }
     1251
     1252        double meanValue = psStatsGetValue (stats, meanOption);
     1253        double stdevValue = psStatsGetValue (stats, stdevOption);
     1254
     1255        psTrace("psLib.math", 5, "Mean is %f\n", meanValue);
     1256        psTrace("psLib.math", 5, "Stdev is %f\n", stdevValue);
     1257        psF32 minClipValue = -minClipSigma*stdevValue;
     1258        psF32 maxClipValue = +maxClipSigma*stdevValue;
    13291259
    13301260        // set mask if pts are not valid
     
    13361266            }
    13371267
    1338             if ((resid->data.F64[i] - clipMedian > maxClipValue) || (resid->data.F64[i] - clipMedian < minClipValue)) {
     1268            if ((resid->data.F64[i] - meanValue > maxClipValue) || (resid->data.F64[i] - meanValue < minClipValue)) {
    13391269                if (fit->type.type == PS_TYPE_F64) {
    13401270                    psTrace("psLib.math", 6, "Masking element %d (%f).  resid->data.F64[%d] is %f\n",
     
    13521282            Nkeep++;
    13531283        }
    1354 
    13551284        psTrace("psLib.math", 4, "keeping %d of %ld pts for fit\n", Nkeep, x->n);
     1285        stats->clippedNvalues = Nkeep;
    13561286        psFree(fit);
    13571287    }
     
    13591289    psFree(resid);
    13601290
    1361     if (poly == NULL) {
    1362         psError(PS_ERR_UNKNOWN, true, "Could not fit a polynomial to the data.  Returning NULL.\n");
    1363         return(NULL);
    1364     }
    1365 
    13661291    psTrace("psLib.math", 3, "---- %s() end ----\n", __func__);
    1367     return(poly);
     1292    return true;
    13681293}
    13691294
     
    13811306 
    13821307 *****************************************************************************/
    1383 static psPolynomial3D* VectorFitPolynomial3DOrd(
     1308static bool VectorFitPolynomial3DOrd(
    13841309    psPolynomial3D* myPoly,
    13851310    const psVector* mask,
     
    13921317{
    13931318    psTrace("psLib.math", 4, "---- %s() begin ----\n", __func__);
    1394     PS_ASSERT_POLY_NON_NULL(myPoly, NULL);
    1395     PS_ASSERT_INT_NONNEGATIVE(myPoly->nX, NULL);
    1396     PS_ASSERT_INT_NONNEGATIVE(myPoly->nY, NULL);
    1397     PS_ASSERT_INT_NONNEGATIVE(myPoly->nZ, NULL);
    1398 
    1399     PS_ASSERT_VECTOR_NON_NULL(f, NULL);
    1400     PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F64, NULL);
     1319    PS_ASSERT_POLY_NON_NULL(myPoly, false);
     1320    PS_ASSERT_INT_NONNEGATIVE(myPoly->nX, false);
     1321    PS_ASSERT_INT_NONNEGATIVE(myPoly->nY, false);
     1322    PS_ASSERT_INT_NONNEGATIVE(myPoly->nZ, false);
     1323
     1324    PS_ASSERT_VECTOR_NON_NULL(f, false);
     1325    PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F64, false);
    14011326    if (fErr != NULL) {
    1402         PS_ASSERT_VECTORS_SIZE_EQUAL(y, fErr, NULL);
    1403         PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F64, NULL);
    1404     }
    1405     PS_ASSERT_VECTOR_NON_NULL(x, NULL);
    1406     PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F64, NULL);
    1407     PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL);
    1408     PS_ASSERT_VECTOR_NON_NULL(y, NULL);
    1409     PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F64, NULL);
    1410     PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL);
    1411     PS_ASSERT_VECTOR_NON_NULL(z, NULL);
    1412     PS_ASSERT_VECTOR_TYPE(z, PS_TYPE_F64, NULL);
    1413     PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, NULL);
     1327        PS_ASSERT_VECTORS_SIZE_EQUAL(y, fErr, false);
     1328        PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F64, false);
     1329    }
     1330    PS_ASSERT_VECTOR_NON_NULL(x, false);
     1331    PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F64, false);
     1332    PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, false);
     1333    PS_ASSERT_VECTOR_NON_NULL(y, false);
     1334    PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F64, false);
     1335    PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, false);
     1336    PS_ASSERT_VECTOR_NON_NULL(z, false);
     1337    PS_ASSERT_VECTOR_TYPE(z, PS_TYPE_F64, false);
     1338    PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, false);
    14141339    if (mask != NULL) {
    1415         PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL);
    1416         PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL);
    1417     }
    1418 
     1340        PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, false);
     1341        PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false);
     1342    }
    14191343
    14201344    int nXterm = 1 + myPoly->nX;        // Number of x terms
     
    14291353    if (!psImageInit(A, 0.0) || !psVectorInit(B, 0.0)) {
    14301354        psError(PS_ERR_UNKNOWN, false, "Could initialize data structures A, B.  Returning NULL.\n");
    1431         psFree(myPoly);
    14321355        psFree(A);
    14331356        psFree(B);
    14341357        psTrace("psLib.math", 4, "---- %s() End ----\n", __func__);
    1435         return(NULL);
     1358        return false;
    14361359    }
    14371360
     
    15111434        // The matrices were overflowing, so I switched to LUD.
    15121435        if (!psMatrixGJSolve(A, B)) {
    1513             psFree(A);
    1514             psFree(B);
    15151436            psError(PS_ERR_UNKNOWN, false, "Failed to perform GaussJordan elimination.\n");
    1516             return(NULL);
     1437            goto escape_GJ;
    15171438        }
    15181439        // select the appropriate solution entries
     
    15341455        if (ALUD == NULL) {
    15351456            psError(PS_ERR_UNKNOWN, false, "Could not do LUD decomposition on matrix.  Returning NULL.\n");
    1536             psFree(myPoly);
    1537             myPoly = NULL;
     1457            goto escape_LUD;
    15381458        } else {
    15391459            coeffs = psMatrixLUSolve(coeffs, ALUD, B, outPerm);
    15401460            if (coeffs == NULL) {
    15411461                psError(PS_ERR_UNKNOWN, false, "Could not solve LUD matrix.  Returning NULL.\n");
    1542                 psFree(myPoly);
    1543                 myPoly = NULL;
     1462                goto escape_LUD;
    15441463            } else {
    15451464                // select the appropriate solution entries
     
    15651484
    15661485    psTrace("psLib.math", 4, "---- %s() end ----\n", __func__);
    1567     return (myPoly);
     1486    return true;
     1487
     1488escape_LUD:
     1489    psFree(A);
     1490    psFree(B);
     1491    return false;
     1492
     1493escape_GJ:
     1494
     1495    psFree(A);
     1496    psFree(B);
     1497    return false;
    15681498}
    15691499
     
    15741504vector conversion only.
    15751505 *****************************************************************************/
    1576 psPolynomial3D *psVectorFitPolynomial3D(
     1506bool psVectorFitPolynomial3D(
    15771507    psPolynomial3D *poly,
    15781508    const psVector *mask,
     
    15841514    const psVector *z)
    15851515{
    1586     // Internal pointers for possibly NULL or mis-typed vectors.
    1587     psVector *x64 = NULL;
    1588     psVector *y64 = NULL;
    1589     psVector *z64 = NULL;
    1590     psVector *f64 = NULL;
     1516    PS_ASSERT_POLY_NON_NULL(poly, false);
     1517    PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, false);
     1518
     1519    PS_ASSERT_VECTOR_NON_NULL(f, false);
     1520    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, false);
     1521    PS_ASSERT_VECTOR_NON_NULL(x, false);
     1522    PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, false);
     1523    PS_ASSERT_VECTOR_NON_NULL(y, false);
     1524    PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, false);
     1525    PS_ASSERT_VECTOR_NON_NULL(z, false);
     1526    PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, false);
     1527    if (mask != NULL) {
     1528        PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, false);
     1529        PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false);
     1530    }
     1531    if (fErr != NULL) {
     1532        PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, false);
     1533        PS_ASSERT_VECTOR_TYPE_F32_OR_F64(fErr, false);
     1534    }
     1535
     1536    // Convert input vectors to F64 if necessary.
     1537    psVector *f64 = (f->type.type == PS_TYPE_F64) ? (psVector *) f : psVectorCopy(NULL, f, PS_TYPE_F64);
     1538    psVector *x64 = (x->type.type == PS_TYPE_F64) ? (psVector *) x : psVectorCopy(NULL, x, PS_TYPE_F64);
     1539    psVector *y64 = (y->type.type == PS_TYPE_F64) ? (psVector *) y : psVectorCopy(NULL, y, PS_TYPE_F64);
     1540    psVector *z64 = (z->type.type == PS_TYPE_F64) ? (psVector *) z : psVectorCopy(NULL, z, PS_TYPE_F64);
     1541
    15911542    psVector *fErr64 = NULL;
    1592 
    1593     PS_ASSERT_POLY_NON_NULL(poly, NULL);
    1594     PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, NULL);
    1595 
    1596     PS_ASSERT_VECTOR_NON_NULL(f, NULL);
    1597     PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, NULL);
    1598     if (mask != NULL) {
    1599         PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL);
    1600         PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL);
    1601     }
    1602     PS_ASSERT_VECTOR_NON_NULL(x, NULL);
    1603     PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL);
    1604     PS_ASSERT_VECTOR_NON_NULL(y, NULL);
    1605     PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL);
    1606     PS_ASSERT_VECTOR_NON_NULL(z, NULL);
    1607     PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, NULL);
    16081543    if (fErr != NULL) {
    1609         PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, NULL);
    1610         //        PS_ASSERT_VECTOR_TYPE(fErr, f->type.type, NULL);
    1611     }
    1612 
    1613     //
    1614     // Convert input vectors to F64 if necessary.
    1615     //
    1616     if (f->type.type != PS_TYPE_F64) {
    1617         f64 = psVectorCopy(NULL, f, PS_TYPE_F64);
    1618     } else {
    1619         f64 = (psVector *) f;
    1620     }
    1621     if (x->type.type != PS_TYPE_F64) {
    1622         x64 = psVectorCopy(NULL, x, PS_TYPE_F64);
    1623     } else {
    1624         x64 = (psVector *) x;
    1625     }
    1626     if (y->type.type != PS_TYPE_F64) {
    1627         y64 = psVectorCopy(NULL, y, PS_TYPE_F64);
    1628     } else {
    1629         y64 = (psVector *) y;
    1630     }
    1631 
    1632     if (z->type.type != PS_TYPE_F64) {
    1633         z64 = psVectorCopy(NULL, z, PS_TYPE_F64);
    1634     } else {
    1635         z64 = (psVector *) z;
    1636     }
    1637 
    1638     if (fErr != NULL) {
    1639         if (fErr->type.type != PS_TYPE_F64) {
    1640             fErr64 = psVectorCopy(NULL, fErr, PS_TYPE_F64);
    1641         } else {
    1642             fErr64 = (psVector *) fErr;
    1643         }
    1644     }
    1645 
    1646     if (poly->type == PS_POLYNOMIAL_ORD) {
    1647         poly = VectorFitPolynomial3DOrd(poly, mask, maskValue, f64, fErr64, x64, y64, z64);
    1648         if (poly == NULL) {
     1544        fErr64 = (fErr->type.type == PS_TYPE_F64) ? (psVector *) fErr : psVectorCopy(NULL, fErr, PS_TYPE_F64);
     1545    }
     1546
     1547    bool result = true;
     1548
     1549    switch (poly->type) {
     1550    case PS_POLYNOMIAL_ORD:
     1551        result = VectorFitPolynomial3DOrd(poly, mask, maskValue, f64, fErr64, x64, y64, z64);
     1552        if (!result) {
    16491553            psError(PS_ERR_UNKNOWN, true, "Could not fit polynomial.  Returning NULL.\n");
    1650             // Free psVectors that were created for NULL arguments.
    1651             if (f->type.type != PS_TYPE_F64) {
    1652                 psFree(f64);
    1653             }
    1654 
    1655             if (x->type.type != PS_TYPE_F64) {
    1656                 psFree(x64);
    1657             }
    1658 
    1659             if (y->type.type != PS_TYPE_F64) {
    1660                 psFree(y64);
    1661             }
    1662 
    1663             if (z->type.type != PS_TYPE_F64) {
    1664                 psFree(z64);
    1665             }
    1666 
    1667             if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) {
    1668                 psFree(fErr64);
    1669             }
    1670             return(NULL);
    1671         }
    1672     } else if (poly->type == PS_POLYNOMIAL_CHEB) {
     1554        }
     1555        break;
     1556    case PS_POLYNOMIAL_CHEB:
    16731557        if (mask != NULL) {
    16741558            psLogMsg(__func__, PS_LOG_WARN, "WARNING: ignoring mask and maskValue with Chebyshev polynomials.\n");
    16751559        }
    1676         psLogMsg(__func__, PS_LOG_WARN, "WARNING: 3-D Chebyshev polynomial vector fitting has not been implemented.  Returning NULL.\n");
    1677         psFree(poly);
    1678         poly = NULL;
    1679     } else {
    1680         // Free psVectors that were created for NULL arguments.
    1681         if (f->type.type != PS_TYPE_F64) {
    1682             psFree(f64);
    1683         }
    1684 
    1685         if (x->type.type != PS_TYPE_F64) {
    1686             psFree(x64);
    1687         }
    1688 
    1689         if (y->type.type != PS_TYPE_F64) {
    1690             psFree(y64);
    1691         }
    1692 
    1693         if (z->type.type != PS_TYPE_F64) {
    1694             psFree(z64);
    1695         }
    1696 
    1697         if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) {
    1698             psFree(fErr64);
    1699         }
     1560        psError(PS_ERR_UNKNOWN, true, "3-D Chebyshev polynomial vector fitting has not been implemented.  Returning NULL.\n");
     1561        result = false;
     1562        break;
     1563    default:
    17001564        psError(PS_ERR_UNKNOWN, true, "Incorrect polynomial type.  Returning NULL.\n");
    1701     }
    1702 
     1565        result = false;
     1566        break;
     1567    }
    17031568
    17041569    // Free psVectors that were created for NULL arguments.
    1705     if (f->type.type != PS_TYPE_F64) {
    1706         psFree(f64);
    1707     }
    1708 
    1709     if (x->type.type != PS_TYPE_F64) {
    1710         psFree(x64);
    1711     }
    1712 
    1713     if (y->type.type != PS_TYPE_F64) {
    1714         psFree(y64);
    1715     }
    1716 
    1717     if (z->type.type != PS_TYPE_F64) {
    1718         psFree(z64);
    1719     }
    1720 
    1721     if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) {
    1722         psFree(fErr64);
    1723     }
    1724 
    1725     return(poly);
     1570    PS_FREE_TEMP_F64_VECTOR (f, f64);
     1571    PS_FREE_TEMP_F64_VECTOR (x, x64);
     1572    PS_FREE_TEMP_F64_VECTOR (y, y64);
     1573    PS_FREE_TEMP_F64_VECTOR (z, z64);
     1574    PS_FREE_TEMP_F64_VECTOR (fErr, fErr64);
     1575
     1576    return result;
    17261577}
    17271578
    1728 psPolynomial3D *psVectorClipFitPolynomial3D(
     1579bool psVectorClipFitPolynomial3D(
    17291580    psPolynomial3D *poly,
    17301581    psStats *stats,
     
    17381589{
    17391590    psTrace("psLib.math", 3, "---- %s() begin ----\n", __func__);
    1740     PS_ASSERT_POLY_NON_NULL(poly, NULL);
    1741     PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, NULL);
    1742     PS_ASSERT_PTR_NON_NULL(stats, NULL);
    1743     PS_ASSERT_VECTOR_NON_NULL(mask, NULL);
    1744     PS_ASSERT_VECTOR_NON_NULL(f, NULL);
    1745     PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, NULL);
    1746     if (mask != NULL) {
    1747         PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL);
    1748         PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL);
    1749     }
    1750     PS_ASSERT_VECTOR_NON_NULL(x, NULL);
    1751     PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL);
    1752     PS_ASSERT_VECTOR_TYPE(x, f->type.type, NULL);
    1753 
    1754     PS_ASSERT_VECTOR_NON_NULL(y, NULL);
    1755     PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL);
    1756     PS_ASSERT_VECTOR_TYPE(y, f->type.type, NULL);
    1757 
    1758     PS_ASSERT_VECTOR_NON_NULL(z, NULL);
    1759     PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, NULL);
    1760     PS_ASSERT_VECTOR_TYPE(z, f->type.type, NULL);
     1591    PS_ASSERT_POLY_NON_NULL(poly, false);
     1592    PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, false);
     1593    PS_ASSERT_PTR_NON_NULL(stats, false);
     1594    PS_ASSERT_VECTOR_NON_NULL(mask, false);
     1595    PS_ASSERT_VECTOR_NON_NULL(f, false);
     1596    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, false);
     1597
     1598    PS_ASSERT_VECTOR_NON_NULL(x, false);
     1599    PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, false);
     1600    PS_ASSERT_VECTOR_TYPE(x, f->type.type, false);
     1601
     1602    PS_ASSERT_VECTOR_NON_NULL(y, false);
     1603    PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, false);
     1604    PS_ASSERT_VECTOR_TYPE(y, f->type.type, false);
     1605
     1606    PS_ASSERT_VECTOR_NON_NULL(z, false);
     1607    PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, false);
     1608    PS_ASSERT_VECTOR_TYPE(z, f->type.type, false);
     1609
     1610    PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, false);
     1611    PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false);
    17611612
    17621613    if (fErr != NULL) {
    1763         PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, NULL);
    1764         PS_ASSERT_VECTOR_TYPE(fErr, f->type.type, NULL);
     1614        PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, false);
     1615        PS_ASSERT_VECTOR_TYPE(fErr, f->type.type, false);
     1616    }
     1617
     1618    // the user supplies one of various stats option pairs,
     1619    // determine the desired mean and stdev STATS options:
     1620    // XXX enforce consistency?
     1621    // XXX psStatsGetValue() probably has inverted precedence
     1622    psStatsOptions meanOption = stats->options & (PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_MEDIAN | PS_STAT_ROBUST_MEDIAN | PS_STAT_CLIPPED_MEAN | PS_STAT_FITTED_MEAN | PS_STAT_FITTED_MEAN_V2);
     1623    psStatsOptions stdevOption = stats->options & (PS_STAT_SAMPLE_STDEV | PS_STAT_ROBUST_STDEV | PS_STAT_CLIPPED_STDEV | PS_STAT_FITTED_STDEV | PS_STAT_FITTED_STDEV_V2);
     1624    if (!meanOption) {
     1625        psError(PS_ERR_UNKNOWN, true, "no valid mean stats option selected");
     1626        return false;
     1627    }
     1628    if (!stdevOption) {
     1629        psError(PS_ERR_UNKNOWN, true, "no valid stdev stats option selected");
     1630        return false;
    17651631    }
    17661632
     
    17781644        minClipSigma = fabs(stats->clipSigma);
    17791645    }
    1780     psVector *fit   = NULL;
    17811646    psVector *resid = psVectorAlloc(f->n, PS_TYPE_F64);
    17821647
    1783     // eventual expansion: user supplies one of various stats option pairs,
    1784     // eg (SAMPLE_MEAN | SAMPLE_STDEV) and the correct pair is used to
    1785     // evaluate the clipping sigma
    1786     // for now, for the SAMPLE_MEDIAN and SAMPLE_STDEV to be used
    1787     stats->options |= (PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV);
    1788     stats->options |= (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);
    17891648    psTrace("psLib.math", 4, "stats->clipIter is %d\n", stats->clipIter);
    17901649    psTrace("psLib.math", 4, "(minClipSigma, maxClipSigma) is (%.2f, %.2f)\n", minClipSigma, maxClipSigma);
     
    18011660        }
    18021661
    1803         poly = psVectorFitPolynomial3D(poly, mask, maskValue, f, fErr, x, y, z);
    1804         if (poly == NULL) {
     1662        if (!psVectorFitPolynomial3D(poly, mask, maskValue, f, fErr, x, y, z)) {
    18051663            psError(PS_ERR_UNKNOWN, false, "Could not fit a polynomial to the data.  Returning NULL.\n");
    18061664            psFree(resid)
    1807             psFree(fit)
    1808             return(NULL);
    1809         }
    1810         fit = psPolynomial3DEvalVector(poly, x, y, z);
     1665            return false;
     1666        }
     1667        psVector *fit = psPolynomial3DEvalVector(poly, x, y, z);
    18111668        if (fit == NULL) {
    18121669            psError(PS_ERR_UNKNOWN, false, "Could not call psPolynomial3DEvalVector().  Returning NULL.\n");
    18131670            psFree(resid)
    1814             return(NULL);
     1671            return false;
    18151672        }
    18161673        for (psS32 i = 0 ; i < f->n ; i++) {
     
    18371694            psFree(resid)
    18381695            psFree(fit)
    1839             return(NULL);
    1840         }
    1841 
    1842         # if (USE_ROBUST_STATS_FOR_CLIPPING)
    1843             psTrace("psLib.math", 5, "Median is %f\n", stats->robustMedian);
    1844         psTrace("psLib.math", 5, "Stdev is %f\n", stats->robustStdev);
    1845         psF32 minClipValue = -minClipSigma*stats->robustStdev;
    1846         psF32 maxClipValue = +maxClipSigma*stats->robustStdev;
    1847         psF32 clipMedian = stats->robustMedian;
    1848         # else
    1849 
    1850             psTrace("psLib.math", 5, "Median is %f\n", stats->sampleMedian);
    1851         psTrace("psLib.math", 5, "Stdev is %f\n", stats->sampleStdev);
    1852         psF32 minClipValue = -minClipSigma*stats->robustStdev;
    1853         psF32 maxClipValue = +maxClipSigma*stats->robustStdev;
    1854         psF32 clipMedian = stats->sampleMedian;
    1855         # endif
     1696            return false;
     1697        }
     1698
     1699        double meanValue = psStatsGetValue (stats, meanOption);
     1700        double stdevValue = psStatsGetValue (stats, stdevOption);
     1701
     1702        psTrace("psLib.math", 5, "Mean is %f\n", meanValue);
     1703        psTrace("psLib.math", 5, "Stdev is %f\n", stdevValue);
     1704        psF32 minClipValue = -minClipSigma*stdevValue;
     1705        psF32 maxClipValue = +maxClipSigma*stdevValue;
    18561706
    18571707        // set mask if pts are not valid
     
    18631713            }
    18641714
    1865             if ((resid->data.F64[i] - clipMedian > maxClipValue) || (resid->data.F64[i] - clipMedian < minClipValue))  {
     1715            if ((resid->data.F64[i] - meanValue > maxClipValue) || (resid->data.F64[i] - meanValue < minClipValue))  {
    18661716                if (f->type.type == PS_TYPE_F64) {
    18671717                    psTrace("psLib.math", 6, "Masking element %d (%f).  resid->data.F64[%d] is %f\n",
     
    18791729            Nkeep++;
    18801730        }
    1881 
    18821731        psTrace("psLib.math", 6, "keeping %d of %ld pts for fit\n", Nkeep, x->n);
     1732        stats->clippedNvalues = Nkeep;
    18831733        psFree(fit);
    18841734    }
     
    18861736    psFree(resid);
    18871737
    1888     if (poly == NULL) {
    1889         psError(PS_ERR_UNKNOWN, true, "Could not fit a polynomial to the data.  Returning NULL.\n");
    1890         return(NULL);
    1891     }
    1892 
    18931738    psTrace("psLib.math", 3, "---- %s() end ----\n", __func__);
    1894     return(poly);
     1739    return true;
    18951740}
    18961741
     
    19061751 
    19071752 *****************************************************************************/
    1908 static psPolynomial4D* VectorFitPolynomial4DOrd(
     1753static bool VectorFitPolynomial4DOrd(
    19091754    psPolynomial4D* myPoly,
    19101755    const psVector* mask,
     
    19181763{
    19191764    psTrace("psLib.math", 4, "---- %s() begin ----\n", __func__);
    1920     PS_ASSERT_POLY_NON_NULL(myPoly, NULL);
    1921     PS_ASSERT_INT_NONNEGATIVE(myPoly->nX, NULL);
    1922     PS_ASSERT_INT_NONNEGATIVE(myPoly->nY, NULL);
    1923     PS_ASSERT_INT_NONNEGATIVE(myPoly->nZ, NULL);
    1924     PS_ASSERT_INT_NONNEGATIVE(myPoly->nT, NULL);
    1925     PS_ASSERT_VECTOR_NON_NULL(f, NULL);
    1926     PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F64, NULL);
     1765    PS_ASSERT_POLY_NON_NULL(myPoly, false);
     1766    PS_ASSERT_INT_NONNEGATIVE(myPoly->nX, false);
     1767    PS_ASSERT_INT_NONNEGATIVE(myPoly->nY, false);
     1768    PS_ASSERT_INT_NONNEGATIVE(myPoly->nZ, false);
     1769    PS_ASSERT_INT_NONNEGATIVE(myPoly->nT, false);
     1770    PS_ASSERT_VECTOR_NON_NULL(f, false);
     1771    PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F64, false);
    19271772    if (fErr != NULL) {
    1928         PS_ASSERT_VECTORS_SIZE_EQUAL(y, fErr, NULL);
    1929         PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F64, NULL);
    1930     }
    1931     PS_ASSERT_VECTOR_NON_NULL(x, NULL);
    1932     PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F64, NULL);
    1933     PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL);
    1934     PS_ASSERT_VECTOR_NON_NULL(y, NULL);
    1935     PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F64, NULL);
    1936     PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL);
    1937     PS_ASSERT_VECTOR_NON_NULL(z, NULL);
    1938     PS_ASSERT_VECTOR_TYPE(z, PS_TYPE_F64, NULL);
    1939     PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, NULL);
    1940     PS_ASSERT_VECTOR_NON_NULL(t, NULL);
    1941     PS_ASSERT_VECTOR_TYPE(t, PS_TYPE_F64, NULL);
    1942     PS_ASSERT_VECTORS_SIZE_EQUAL(f, t, NULL);
     1773        PS_ASSERT_VECTORS_SIZE_EQUAL(y, fErr, false);
     1774        PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F64, false);
     1775    }
     1776    PS_ASSERT_VECTOR_NON_NULL(x, false);
     1777    PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F64, false);
     1778    PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, false);
     1779    PS_ASSERT_VECTOR_NON_NULL(y, false);
     1780    PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F64, false);
     1781    PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, false);
     1782    PS_ASSERT_VECTOR_NON_NULL(z, false);
     1783    PS_ASSERT_VECTOR_TYPE(z, PS_TYPE_F64, false);
     1784    PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, false);
     1785    PS_ASSERT_VECTOR_NON_NULL(t, false);
     1786    PS_ASSERT_VECTOR_TYPE(t, PS_TYPE_F64, false);
     1787    PS_ASSERT_VECTORS_SIZE_EQUAL(f, t, false);
    19431788    if (mask) {
    1944         PS_ASSERT_VECTORS_SIZE_EQUAL(y, mask, NULL);
    1945         PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL);
     1789        PS_ASSERT_VECTORS_SIZE_EQUAL(y, mask, false);
     1790        PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false);
    19461791    }
    19471792
     
    19591804    if (!psImageInit(A, 0.0) || !psVectorInit(B, 0.0)) {
    19601805        psError(PS_ERR_UNKNOWN, false, "Could initialize data structures A, B.  Returning NULL.\n");
    1961         psFree(myPoly);
    19621806        psFree(A);
    19631807        psFree(B);
    19641808        psTrace("psLib.math", 4, "---- %s() End ----\n", __func__);
    1965         return(NULL);
     1809        return false;
    19661810    }
    19671811
     
    20511895        // The GaussJordan version was overflowing, so I'm using LUD.
    20521896        if (!psMatrixGJSolve(A, B)) {
    2053             psFree(A);
    2054             psFree(B);
    20551897            psError(PS_ERR_UNKNOWN, false, "Failed to perform GaussJordan elimination.\n");
    2056             return(NULL);
     1898            goto escape_GJ;
    20571899        }
    20581900
     
    20761918        if (ALUD == NULL) {
    20771919            psError(PS_ERR_UNKNOWN, false, "Could not do LUD decomposition on matrix.  Returning NULL.\n");
    2078             psFree(myPoly);
    2079             myPoly = NULL;
     1920            goto escape_LUD;
    20801921        } else {
    20811922            coeffs = psMatrixLUSolve(coeffs, ALUD, B, outPerm);
    20821923            if (coeffs == NULL) {
    20831924                psError(PS_ERR_UNKNOWN, false, "Could not solve LUD matrix.  Returning NULL.\n");
    2084                 psFree(myPoly);
    2085                 myPoly = NULL;
     1925                goto escape_LUD;
    20861926            } else {
    20871927                // select the appropriate solution entries
     
    21001940            }
    21011941        }
    2102 
    21031942        psFree(ALUD);
    21041943        psFree(coeffs);
    21051944        psFree(outPerm);
    2106 
    2107     }
    2108 
     1945    }
    21091946    psFree(A);
    21101947    psFree(B);
    21111948
    21121949    psTrace("psLib.math", 4, "---- %s() end ----\n", __func__);
    2113     return (myPoly);
     1950    return true;
     1951
     1952escape_LUD:
     1953    psFree(A);
     1954    psFree(B);
     1955    return false;
     1956
     1957escape_GJ:
     1958    psFree(A);
     1959    psFree(B);
     1960    return false;
    21141961}
    21151962
     
    21201967via vector conversion only.
    21211968 *****************************************************************************/
    2122 psPolynomial4D *psVectorFitPolynomial4D(
     1969bool psVectorFitPolynomial4D(
    21231970    psPolynomial4D *poly,
    21241971    const psVector *mask,
     
    21311978    const psVector *t)
    21321979{
    2133     // Internal pointers for possibly NULL or mis-typed vectors.
    2134     psVector *x64 = NULL;
    2135     psVector *y64 = NULL;
    2136     psVector *z64 = NULL;
    2137     psVector *t64 = NULL;
    2138     psVector *f64 = NULL;
     1980    PS_ASSERT_POLY_NON_NULL(poly, false);
     1981    PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, false);
     1982
     1983    PS_ASSERT_VECTOR_NON_NULL(f, false);
     1984    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, false);
     1985    PS_ASSERT_VECTOR_NON_NULL(x, false);
     1986    PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, false);
     1987    PS_ASSERT_VECTOR_NON_NULL(y, false);
     1988    PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, false);
     1989    PS_ASSERT_VECTOR_NON_NULL(z, false);
     1990    PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, false);
     1991    PS_ASSERT_VECTOR_NON_NULL(t, false);
     1992    PS_ASSERT_VECTORS_SIZE_EQUAL(f, t, false);
     1993    if (mask) {
     1994        PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, false);
     1995        PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false);
     1996    }
     1997    if (fErr != NULL) {
     1998        PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, false);
     1999        PS_ASSERT_VECTOR_TYPE_F32_OR_F64(fErr, false);
     2000    }
     2001
     2002    // Convert input vectors to F64 if necessary.
     2003    psVector *f64 = (f->type.type == PS_TYPE_F64) ? (psVector *) f : psVectorCopy(NULL, f, PS_TYPE_F64);
     2004    psVector *x64 = (x->type.type == PS_TYPE_F64) ? (psVector *) x : psVectorCopy(NULL, x, PS_TYPE_F64);
     2005    psVector *y64 = (y->type.type == PS_TYPE_F64) ? (psVector *) y : psVectorCopy(NULL, y, PS_TYPE_F64);
     2006    psVector *z64 = (z->type.type == PS_TYPE_F64) ? (psVector *) z : psVectorCopy(NULL, z, PS_TYPE_F64);
     2007    psVector *t64 = (t->type.type == PS_TYPE_F64) ? (psVector *) t : psVectorCopy(NULL, t, PS_TYPE_F64);
     2008
    21392009    psVector *fErr64 = NULL;
    2140 
    2141     PS_ASSERT_POLY_NON_NULL(poly, NULL);
    2142     PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, NULL);
    2143 
    2144     PS_ASSERT_VECTOR_NON_NULL(f, NULL);
    2145     PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, NULL);
    2146     if (mask) {
    2147         PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL);
    2148         PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL);
    2149     }
    2150     PS_ASSERT_VECTOR_NON_NULL(x, NULL);
    2151     PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL);
    2152     PS_ASSERT_VECTOR_NON_NULL(y, NULL);
    2153     PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL);
    2154     PS_ASSERT_VECTOR_NON_NULL(z, NULL);
    2155     PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, NULL);
    2156     PS_ASSERT_VECTOR_NON_NULL(t, NULL);
    2157     PS_ASSERT_VECTORS_SIZE_EQUAL(f, t, NULL);
    21582010    if (fErr != NULL) {
    2159         PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, NULL);
    2160         PS_ASSERT_VECTOR_TYPE_F32_OR_F64(fErr, NULL);
    2161     }
    2162 
    2163 
    2164     //
    2165     // Convert input vector to F64 if necessary.
    2166     //
    2167     if (f->type.type != PS_TYPE_F64) {
    2168         f64 = psVectorCopy(NULL, f, PS_TYPE_F64);
    2169     } else {
    2170         f64 = (psVector *) f;
    2171     }
    2172     if (x->type.type != PS_TYPE_F64) {
    2173         x64 = psVectorCopy(NULL, x, PS_TYPE_F64);
    2174     } else {
    2175         x64 = (psVector *) x;
    2176     }
    2177     if (y->type.type != PS_TYPE_F64) {
    2178         y64 = psVectorCopy(NULL, y, PS_TYPE_F64);
    2179     } else {
    2180         y64 = (psVector *) y;
    2181     }
    2182     if (z->type.type != PS_TYPE_F64) {
    2183         z64 = psVectorCopy(NULL, z, PS_TYPE_F64);
    2184     } else {
    2185         z64 = (psVector *) z;
    2186     }
    2187     if (t->type.type != PS_TYPE_F64) {
    2188         t64 = psVectorCopy(NULL, t, PS_TYPE_F64);
    2189     } else {
    2190         t64 = (psVector *) t;
    2191     }
    2192     //
    2193     // fErr
    2194     //
    2195     if (fErr != NULL) {
    2196         if (fErr->type.type != PS_TYPE_F64) {
    2197             fErr64 = psVectorCopy(NULL, fErr, PS_TYPE_F64);
    2198         } else {
    2199             fErr64 = (psVector *) fErr;
    2200         }
    2201     }
    2202 
    2203     if (poly->type == PS_POLYNOMIAL_ORD) {
    2204         poly = VectorFitPolynomial4DOrd(poly, mask, maskValue, f64, fErr64, x64, y64, z64, t64);
    2205         if (poly == NULL) {
     2011        fErr64 = (fErr->type.type == PS_TYPE_F64) ? (psVector *) fErr : psVectorCopy(NULL, fErr, PS_TYPE_F64);
     2012    }
     2013
     2014    bool result = true;
     2015
     2016    switch (poly->type) {
     2017    case PS_POLYNOMIAL_ORD:
     2018        result = VectorFitPolynomial4DOrd(poly, mask, maskValue, f64, fErr64, x64, y64, z64, t64);
     2019        if (!result) {
    22062020            psError(PS_ERR_UNKNOWN, true, "Could not fit polynomial.  Returning NULL.\n");
    2207             // Free psVectors that were created for NULL arguments.
    2208             if (f->type.type != PS_TYPE_F64) {
    2209                 psFree(f64);
    2210             }
    2211 
    2212             if (x->type.type != PS_TYPE_F64) {
    2213                 psFree(x64);
    2214             }
    2215 
    2216             if (y->type.type != PS_TYPE_F64) {
    2217                 psFree(y64);
    2218             }
    2219 
    2220             if (z->type.type != PS_TYPE_F64) {
    2221                 psFree(z64);
    2222             }
    2223 
    2224             if (t->type.type != PS_TYPE_F64) {
    2225                 psFree(t64);
    2226             }
    2227 
    2228             if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) {
    2229                 psFree(fErr64);
    2230             }
    2231             return(NULL);
    2232         }
    2233     } else if (poly->type == PS_POLYNOMIAL_CHEB) {
     2021        }
     2022        break;
     2023    case PS_POLYNOMIAL_CHEB:
    22342024        if (mask != NULL) {
    22352025            psLogMsg(__func__, PS_LOG_WARN, "WARNING: ignoring mask and maskValue with Chebyshev polynomials.\n");
    22362026        }
    2237         psLogMsg(__func__, PS_LOG_WARN, "WARNING: 4-D Chebyshev polynomial vector fitting has not been implemented.  Returning NULL.\n");
    2238         psFree(poly);
    2239         poly = NULL;
    2240     } else {
    2241         // Free psVectors that were created for NULL arguments.
    2242         if (f->type.type != PS_TYPE_F64) {
    2243             psFree(f64);
    2244         }
    2245 
    2246         if (x->type.type != PS_TYPE_F64) {
    2247             psFree(x64);
    2248         }
    2249 
    2250         if (y->type.type != PS_TYPE_F64) {
    2251             psFree(y64);
    2252         }
    2253 
    2254         if (z->type.type != PS_TYPE_F64) {
    2255             psFree(z64);
    2256         }
    2257 
    2258         if (t->type.type != PS_TYPE_F64) {
    2259             psFree(t64);
    2260         }
    2261 
    2262         if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) {
    2263             psFree(fErr64);
    2264         }
     2027        psError(PS_ERR_UNKNOWN, true, "4-D Chebyshev polynomial vector fitting has not been implemented.  Returning NULL.\n");
     2028        result = false;
     2029        break;
     2030    default:
    22652031        psError(PS_ERR_UNKNOWN, true, "Incorrect polynomial type.  Returning NULL.\n");
    2266     }
    2267 
     2032        result = false;
     2033        break;
     2034    }
    22682035
    22692036    // Free psVectors that were created for NULL arguments.
    2270     if (f->type.type != PS_TYPE_F64) {
    2271         psFree(f64);
    2272     }
    2273 
    2274     if (x->type.type != PS_TYPE_F64) {
    2275         psFree(x64);
    2276     }
    2277 
    2278     if (y->type.type != PS_TYPE_F64) {
    2279         psFree(y64);
    2280     }
    2281 
    2282     if (z->type.type != PS_TYPE_F64) {
    2283         psFree(z64);
    2284     }
    2285 
    2286     if (t->type.type != PS_TYPE_F64) {
    2287         psFree(t64);
    2288     }
    2289 
    2290     if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) {
    2291         psFree(fErr64);
    2292     }
    2293 
    2294     return(poly);
     2037    PS_FREE_TEMP_F64_VECTOR (f, f64);
     2038    PS_FREE_TEMP_F64_VECTOR (x, x64);
     2039    PS_FREE_TEMP_F64_VECTOR (y, y64);
     2040    PS_FREE_TEMP_F64_VECTOR (z, z64);
     2041    PS_FREE_TEMP_F64_VECTOR (t, t64);
     2042    PS_FREE_TEMP_F64_VECTOR (fErr, fErr64);
     2043
     2044    return result;
    22952045}
    22962046
    22972047
    2298 psPolynomial4D *psVectorClipFitPolynomial4D(
     2048bool psVectorClipFitPolynomial4D(
    22992049    psPolynomial4D *poly,
    23002050    psStats *stats,
     
    23092059{
    23102060    psTrace("psLib.math", 3, "---- %s() begin ----\n", __func__);
    2311     PS_ASSERT_POLY_NON_NULL(poly, NULL);
    2312     PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, NULL);
    2313     PS_ASSERT_PTR_NON_NULL(stats, NULL);
    2314     PS_ASSERT_VECTOR_NON_NULL(mask, NULL);
    2315     PS_ASSERT_VECTOR_NON_NULL(f, NULL);
    2316     PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, NULL);
    2317     if (mask) {
    2318         PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL);
    2319         PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL);
    2320     }
    2321     PS_ASSERT_VECTOR_NON_NULL(x, NULL);
    2322     PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL);
    2323     PS_ASSERT_VECTOR_TYPE(x, f->type.type, NULL);
    2324 
    2325     PS_ASSERT_VECTOR_NON_NULL(y, NULL);
    2326     PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL);
    2327     PS_ASSERT_VECTOR_TYPE(y, f->type.type, NULL);
    2328 
    2329     PS_ASSERT_VECTOR_NON_NULL(z, NULL);
    2330     PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, NULL);
    2331     PS_ASSERT_VECTOR_TYPE(z, f->type.type, NULL);
    2332 
    2333     PS_ASSERT_VECTOR_NON_NULL(t, NULL);
    2334     PS_ASSERT_VECTORS_SIZE_EQUAL(f, t, NULL);
    2335     PS_ASSERT_VECTOR_TYPE(t, f->type.type, NULL);
     2061    PS_ASSERT_POLY_NON_NULL(poly, false);
     2062    PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, false);
     2063    PS_ASSERT_PTR_NON_NULL(stats, false);
     2064    PS_ASSERT_VECTOR_NON_NULL(mask, false);
     2065    PS_ASSERT_VECTOR_NON_NULL(f, false);
     2066    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, false);
     2067
     2068    PS_ASSERT_VECTOR_NON_NULL(x, false);
     2069    PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, false);
     2070    PS_ASSERT_VECTOR_TYPE(x, f->type.type, false);
     2071
     2072    PS_ASSERT_VECTOR_NON_NULL(y, false);
     2073    PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, false);
     2074    PS_ASSERT_VECTOR_TYPE(y, f->type.type, false);
     2075
     2076    PS_ASSERT_VECTOR_NON_NULL(z, false);
     2077    PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, false);
     2078    PS_ASSERT_VECTOR_TYPE(z, f->type.type, false);
     2079
     2080    PS_ASSERT_VECTOR_NON_NULL(t, false);
     2081    PS_ASSERT_VECTORS_SIZE_EQUAL(f, t, false);
     2082    PS_ASSERT_VECTOR_TYPE(t, f->type.type, false);
     2083
     2084    PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, false);
     2085    PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false);
    23362086
    23372087    if (fErr != NULL) {
    2338         PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, NULL);
    2339         PS_ASSERT_VECTOR_TYPE(fErr, f->type.type, NULL);
     2088        PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, false);
     2089        PS_ASSERT_VECTOR_TYPE(fErr, f->type.type, false);
     2090    }
     2091
     2092    // the user supplies one of various stats option pairs,
     2093    // determine the desired mean and stdev STATS options:
     2094    // XXX enforce consistency?
     2095    // XXX psStatsGetValue() probably has inverted precedence
     2096    psStatsOptions meanOption = stats->options & (PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_MEDIAN | PS_STAT_ROBUST_MEDIAN | PS_STAT_CLIPPED_MEAN | PS_STAT_FITTED_MEAN | PS_STAT_FITTED_MEAN_V2);
     2097    psStatsOptions stdevOption = stats->options & (PS_STAT_SAMPLE_STDEV | PS_STAT_ROBUST_STDEV | PS_STAT_CLIPPED_STDEV | PS_STAT_FITTED_STDEV | PS_STAT_FITTED_STDEV_V2);
     2098    if (!meanOption) {
     2099        psError(PS_ERR_UNKNOWN, true, "no valid mean stats option selected");
     2100        return false;
     2101    }
     2102    if (!stdevOption) {
     2103        psError(PS_ERR_UNKNOWN, true, "no valid stdev stats option selected");
     2104        return false;
    23402105    }
    23412106
     
    23532118        minClipSigma = fabs(stats->clipSigma);
    23542119    }
    2355     psVector *fit   = NULL;
    23562120    psVector *resid = psVectorAlloc(f->n, PS_TYPE_F64);
    23572121
    2358     // eventual expansion: user supplies one of various stats option pairs,
    2359     // eg (SAMPLE_MEAN | SAMPLE_STDEV) and the correct pair is used to
    2360     // evaluate the clipping sigma
    2361     // for now, for the SAMPLE_MEDIAN and SAMPLE_STDEV to be used
    2362     stats->options |= (PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV);
    2363     stats->options |= (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);
    23642122    psTrace("psLib.math", 4, "stats->clipIter is %d\n", stats->clipIter);
    23652123    psTrace("psLib.math", 4, "(minClipSigma, maxClipSigma) is (%.2f, %.2f)\n", minClipSigma, maxClipSigma);
     
    23762134        }
    23772135
    2378         poly = psVectorFitPolynomial4D (poly, mask, maskValue, f, fErr, x, y, z, t);
    2379         if (poly == NULL) {
     2136        if (!psVectorFitPolynomial4D (poly, mask, maskValue, f, fErr, x, y, z, t)) {
    23802137            psError(PS_ERR_UNKNOWN, false, "Could not fit a polynomial to the data.  Returning NULL.\n");
    23812138            psFree(resid)
    2382             psFree(fit)
    2383             return(NULL);
    2384         }
    2385 
    2386         fit = psPolynomial4DEvalVector (poly, x, y, z, t);
     2139            return false;
     2140        }
     2141
     2142        psVector *fit = psPolynomial4DEvalVector (poly, x, y, z, t);
    23872143        if (fit == NULL) {
    23882144            psError(PS_ERR_UNKNOWN, false, "Could not call psPolynomial4DEvalVector().  Returning NULL.\n");
    23892145            psFree(resid)
    2390             return(NULL);
     2146            return false;
    23912147        }
    23922148        for (psS32 i = 0 ; i < f->n ; i++) {
     
    24132169            psFree(resid)
    24142170            psFree(fit)
    2415             return(NULL);
    2416         }
    2417         # if (USE_ROBUST_STATS_FOR_CLIPPING)
    2418             psTrace("psLib.math", 5, "Median is %f\n", stats->robustMedian);
    2419         psTrace("psLib.math", 5, "Stdev is %f\n", stats->robustStdev);
    2420         psF32 minClipValue = -minClipSigma*stats->robustStdev;
    2421         psF32 maxClipValue = +maxClipSigma*stats->robustStdev;
    2422         psF32 clipMedian = stats->robustMedian;
    2423         # else
    2424 
    2425             psTrace("psLib.math", 5, "Median is %f\n", stats->sampleMedian);
    2426         psTrace("psLib.math", 5, "Stdev is %f\n", stats->sampleStdev);
    2427         psF32 minClipValue = -minClipSigma*stats->robustStdev;
    2428         psF32 maxClipValue = +maxClipSigma*stats->robustStdev;
    2429         psF32 clipMedian = stats->sampleMedian;
    2430         # endif
     2171            return false;
     2172        }
     2173
     2174        double meanValue = psStatsGetValue (stats, meanOption);
     2175        double stdevValue = psStatsGetValue (stats, stdevOption);
     2176
     2177        psTrace("psLib.math", 5, "Mean is %f\n", meanValue);
     2178        psTrace("psLib.math", 5, "Stdev is %f\n", stdevValue);
     2179        psF32 minClipValue = -minClipSigma*stdevValue;
     2180        psF32 maxClipValue = +maxClipSigma*stdevValue;
    24312181
    24322182        // set mask if pts are not valid
     
    24382188            }
    24392189
    2440             if ((resid->data.F64[i] - clipMedian > maxClipValue) || (resid->data.F64[i] - clipMedian < minClipValue)) {
     2190            if ((resid->data.F64[i] - meanValue > maxClipValue) || (resid->data.F64[i] - meanValue < minClipValue)) {
    24412191                if (f->type.type == PS_TYPE_F64) {
    24422192                    psTrace("psLib.math", 6, "Masking element %d (%f).  resid->data.F64[%d] is %f\n",
     
    24522202                continue;
    24532203            }
    2454 
    24552204            Nkeep++;
    24562205        }
    2457 
    24582206        psTrace("psLib.math", 6, "keeping %d of %ld pts for fit\n", Nkeep, x->n);
     2207        stats->clippedNvalues = Nkeep;
    24592208        psFree (fit);
    24602209    }
     
    24622211    psFree (resid);
    24632212
    2464     if (poly == NULL) {
    2465         psError(PS_ERR_UNKNOWN, true, "Could not fit a polynomial to the data.  Returning NULL.\n");
    2466         return(NULL);
    2467     }
    2468 
    24692213    psTrace("psLib.math", 3, "---- %s() end ----\n", __func__);
    2470     return(poly);
     2214    return true;
    24712215}
Note: See TracChangeset for help on using the changeset viewer.