IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Nov 4, 2021, 6:10:51 PM (5 years ago)
Author:
eugene
Message:

merge changes from eam_branches/ipp-dev-20210817 (fix chebyshevs 1D, 2D, set DB field to NULL for inf, psFitsTableNew)

File:
1 edited

Legend:

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

    r15253 r41896  
    3636#include "psLogMsg.h"
    3737#include "psPolynomial.h"
     38#include "psAbort.h"
    3839#include "psAssert.h"
    3940
     
    203204
    204205
     206/** This function calculates the appropriate scaling factors needed to normalize the
     207 * input vector to the range -1 : +1.  These are stored on the polynomial in the given
     208 * direction.
     209 */
     210bool psChebyshevSetScale (psPolynomial2D* myPoly, const psVector *vec, int dir) {
     211
     212    psAssert ((dir == 0) || (dir == 1), "invalid direction %d\n", dir);
     213
     214    // find the min and max of the vector
     215    psF64 minValue = NAN;
     216    psF64 maxValue = NAN;
     217
     218    for (int i = 0; i < vec->n; i++) {
     219        if (isnan(vec->data.F64[i])) continue;
     220        if (isnan(minValue)) { minValue = vec->data.F64[i]; }
     221        if (isnan(maxValue)) { maxValue = vec->data.F64[i]; }
     222        minValue = PS_MIN(minValue, vec->data.F64[i]);
     223        maxValue = PS_MAX(maxValue, vec->data.F64[i]);
     224    }
     225    if (minValue == maxValue) {
     226        psWarning ("insufficient data range to determine scale factors\n");
     227        return false;
     228    }
     229
     230    myPoly->scale[dir] = 2.0 / (maxValue - minValue);
     231    myPoly->zero[dir]  = 1 - myPoly->scale[dir] * maxValue;
     232    return true;
     233}
     234
     235/** This function generates a normalized vector in the range -1 : +1 based on the input
     236    vector using the scale factors stored in myPoly in the given direction.
     237 */
     238psVector *psChebyshevNormVector (const psPolynomial2D* myPoly, const psVector *vec, int dir) {
     239
     240    psVector *norm = psVectorAlloc (vec->n, PS_TYPE_F64);
     241
     242    if (vec->type.type == PS_TYPE_F64) {
     243        for (int i = 0; i < vec->n; i++) {
     244            norm->data.F64[i] = vec->data.F64[i]*myPoly->scale[dir] + myPoly->zero[dir];
     245        }
     246        return norm;
     247    }
     248    if (vec->type.type == PS_TYPE_F32) {
     249        for (int i = 0; i < vec->n; i++) {
     250            norm->data.F64[i] = vec->data.F32[i]*myPoly->scale[dir] + myPoly->zero[dir];
     251        }
     252        return norm;
     253    }
     254
     255    psError(PS_ERR_UNKNOWN, true, "invalid type for chebyshev polynomial");
     256    return NULL;
     257}
     258
     259# define CHEB_EVAL_0(OUT,IN) {OUT = 1.0;}
     260# define CHEB_EVAL_1(OUT,IN) {                       OUT = IN; }
     261# define CHEB_EVAL_2(OUT,IN) {psF64 X2 = PS_SQR(IN); OUT = 2.0*X2 - 1.0; }
     262# define CHEB_EVAL_3(OUT,IN) {psF64 X2 = PS_SQR(IN); OUT = IN*(4.0*X2 - 3.0); }
     263# define CHEB_EVAL_4(OUT,IN) {psF64 X2 = PS_SQR(IN); OUT = X2*(8.0*X2 - 8.0) + 1.0; }
     264# define CHEB_EVAL_5(OUT,IN) {psF64 X2 = PS_SQR(IN); OUT = IN *(X2*(16.0*X2 - 20.0) + 5.0); }
     265# define CHEB_EVAL_6(OUT,IN) {psF64 X2 = PS_SQR(IN); OUT = X2*(X2*(32.0*X2 - 48.0) + 18.0) - 1.0; }
     266# define CHEB_EVAL_7(OUT,IN) {psF64 X2 = PS_SQR(IN); OUT = IN *(X2*(X2*(64.0*X2 - 112.0) + 56.0) - 7.0); }
     267# define CHEB_EVAL_8(OUT,IN) {psF64 X2 = PS_SQR(IN); OUT = X2*(X2*(X2*(128.0*X2 - 256.0) + 160.0) - 32.0) + 1.0; }
     268# define CHEB_EVAL_9(OUT,IN) {psF64 X2 = PS_SQR(IN); OUT = IN *(X2*(X2*(X2*(256.0*X2 - 576.0) + 432.0) - 129.0) + 9.0); }
     269
     270/** This function generates a vector containing the values of a Chebyshev polynomial of
     271    the given order evaluated at the coordinates given by the input vector, i.e., this
     272    function returns the vector T^n (x_i) where x_i is the input vector of values and n is
     273    the polynomial order.
     274 */
     275psVector *psChebyshevPolyVector (const psVector *vec, int order) {
     276
     277    if (order > 9) {
     278        psWarning ("Chebyshev orders higher than 9 are not yet coded\n");
     279        return NULL;
     280    }
     281
     282    psVector *out = psVectorAlloc (vec->n, PS_TYPE_F64);
     283
     284    // easy but non-general implementation
     285    switch (order) {
     286      case 0:
     287        for (int i = 0; i < vec->n; i++) { CHEB_EVAL_0(out->data.F64[i], vec->data.F64[i]); } break;
     288      case 1:
     289        for (int i = 0; i < vec->n; i++) { CHEB_EVAL_1(out->data.F64[i], vec->data.F64[i]); } break;
     290      case 2:
     291        for (int i = 0; i < vec->n; i++) { CHEB_EVAL_2(out->data.F64[i], vec->data.F64[i]); } break;
     292      case 3:
     293        for (int i = 0; i < vec->n; i++) { CHEB_EVAL_3(out->data.F64[i], vec->data.F64[i]); } break;
     294      case 4:
     295        for (int i = 0; i < vec->n; i++) { CHEB_EVAL_4(out->data.F64[i], vec->data.F64[i]); } break;
     296      case 5:
     297        for (int i = 0; i < vec->n; i++) { CHEB_EVAL_5(out->data.F64[i], vec->data.F64[i]); } break;
     298      case 6:
     299        for (int i = 0; i < vec->n; i++) { CHEB_EVAL_6(out->data.F64[i], vec->data.F64[i]); } break;
     300      case 7:
     301        for (int i = 0; i < vec->n; i++) { CHEB_EVAL_7(out->data.F64[i], vec->data.F64[i]); } break;
     302      case 8:
     303        for (int i = 0; i < vec->n; i++) { CHEB_EVAL_8(out->data.F64[i], vec->data.F64[i]); } break;
     304      case 9:
     305        for (int i = 0; i < vec->n; i++) { CHEB_EVAL_9(out->data.F64[i], vec->data.F64[i]); } break;
     306      default:
     307        psWarning ("Chebyshev orders higher than 9 are not yet coded\n");
     308        psFree (out);
     309        return NULL;
     310    }
     311
     312    return out;
     313}
     314
    205315/*****************************************************************************
    206316    Polynomial coefficients will be accessed in [w][x][y][z] fashion.
     
    233343}
    234344
    235 // XXX: You can do this without having to psAlloc() vector d.
    236 // XXX: How does the mask vector effect Crenshaw's formula?
    237 // NOTE: We assume that x is scaled between -1.0 and 1.0;
    238 // XXX: Create a faster version for low-order Chebyshevs.
    239 static psF64 chebPolynomial1DEval(
    240     psF64 x,
    241     const psPolynomial1D* poly)
    242 {
    243     PS_ASSERT_DOUBLE_WITHIN_RANGE(x, -1.0, 1.0, NAN);
     345static psF64 chebPolynomial1DEval(psF64 x, const psPolynomial1D* poly) {
     346
    244347    PS_ASSERT_INT_LARGER_THAN_OR_EQUAL(poly->nX, 0, NAN);
     348
     349    psF64 xNorm = x*poly->scale[0] + poly->zero[0];
     350
     351    psF64 polySum = 0.0;
     352
     353    for (int ix = 0; ix <= poly->nX; ix++) {
     354        if (poly->coeffMask[ix] & PS_POLY_MASK_SET) continue;
     355        psF64 xCheb = NAN;
     356        switch (ix) {
     357          case 0: CHEB_EVAL_0 (xCheb, xNorm); break;
     358          case 1: CHEB_EVAL_1 (xCheb, xNorm); break;
     359          case 2: CHEB_EVAL_2 (xCheb, xNorm); break;
     360          case 3: CHEB_EVAL_3 (xCheb, xNorm); break;
     361          case 4: CHEB_EVAL_4 (xCheb, xNorm); break;
     362          case 5: CHEB_EVAL_5 (xCheb, xNorm); break;
     363          case 6: CHEB_EVAL_6 (xCheb, xNorm); break;
     364          case 7: CHEB_EVAL_7 (xCheb, xNorm); break;
     365          case 8: CHEB_EVAL_8 (xCheb, xNorm); break;
     366          case 9: CHEB_EVAL_9 (xCheb, xNorm); break;
     367          default:
     368            break;
     369        }
     370        polySum += poly->coeff[ix] * xCheb;
     371    }
     372    return polySum;
     373}
     374
     375/*** version 1 is a general case and could be used for Norder > 9.  ***/
     376# ifdef CHEB_VERSION_1
     377void oldcode_1(void) {
    245378    psVector *d;
     379    psF64 tmp = 0.0;
    246380
    247381    unsigned int nTerms = 1 + poly->nX;
    248382    unsigned int i;
    249     psF64 tmp = 0.0;
    250383
    251384    // Special case where the Chebyshev poly is constant.
     
    268401    }
    269402
    270     if (1) {
    271         // General case where the Chebyshev poly has 2 or more terms.
    272         d = psVectorAlloc(nTerms, PS_TYPE_F64);
    273         if (!(poly->coeffMask[nTerms-1] & PS_POLY_MASK_SET)) {
    274             d->data.F64[nTerms-1] = poly->coeff[nTerms-1];
    275         } else {
    276             d->data.F64[nTerms-1] = 0.0;
    277         }
    278 
    279         d->data.F64[nTerms-2] = (2.0 * x * d->data.F64[nTerms-1]);
    280         if (!(poly->coeffMask[nTerms-2] & PS_POLY_MASK_SET)) {
    281             d->data.F64[nTerms-2] += poly->coeff[nTerms-2];
    282         }
    283 
    284         for (i=nTerms-3;i>=1;i--) {
    285             d->data.F64[i] = (2.0 * x * d->data.F64[i+1]) - (d->data.F64[i+2]);
    286             if (!(poly->coeffMask[i] & PS_POLY_MASK_SET)) {
    287                 d->data.F64[i] += poly->coeff[i];
    288             }
    289         }
    290 
    291         tmp = (x * d->data.F64[1]) - (d->data.F64[2]);
    292         if (!(poly->coeffMask[0] & PS_POLY_MASK_SET)) {
    293             tmp += (0.5 * poly->coeff[0]);
    294         }
    295         psFree(d);
     403    // General case where the Chebyshev poly has 2 or more terms.
     404    d = psVectorAlloc(nTerms, PS_TYPE_F64);
     405    if (!(poly->coeffMask[nTerms-1] & PS_POLY_MASK_SET)) {
     406        d->data.F64[nTerms-1] = poly->coeff[nTerms-1];
    296407    } else {
    297         // XXX: This is old code that does not use Clenshaw's formula.  Get rid of it.
    298         psPolynomial1D **chebPolys = p_psCreateChebyshevPolys(1 + poly->nX);
    299 
    300         tmp = 0.0;
    301         for (psS32 i=0;i<(1 + poly->nX);i++) {
    302             tmp+= (poly->coeff[i] * psPolynomial1DEval(chebPolys[i], x));
    303         }
    304         tmp-= (poly->coeff[0]/2.0);
    305 
    306         for (psS32 i=0;i<(1 + poly->nX);i++) {
    307             psFree(chebPolys[i]);
    308         }
    309         psFree(chebPolys);
    310     }
     408        d->data.F64[nTerms-1] = 0.0;
     409    }
     410
     411    d->data.F64[nTerms-2] = (2.0 * x * d->data.F64[nTerms-1]);
     412    if (!(poly->coeffMask[nTerms-2] & PS_POLY_MASK_SET)) {
     413        d->data.F64[nTerms-2] += poly->coeff[nTerms-2];
     414    }
     415
     416    for (i=nTerms-3;i>=1;i--) {
     417        d->data.F64[i] = (2.0 * x * d->data.F64[i+1]) - (d->data.F64[i+2]);
     418        if (!(poly->coeffMask[i] & PS_POLY_MASK_SET)) {
     419            d->data.F64[i] += poly->coeff[i];
     420        }
     421    }
     422
     423    tmp = (x * d->data.F64[1]) - (d->data.F64[2]);
     424    if (!(poly->coeffMask[0] & PS_POLY_MASK_SET)) {
     425        tmp += (0.5 * poly->coeff[0]);
     426    }
     427    psFree(d);
     428}
     429# endif
     430
     431/*** version 0 should be removed when version 2 is ready ***/
     432# ifdef CHEB_VERSION_0
     433void oldcode_0(void) {
     434    // XXX: This is old code that does not use Clenshaw's formula.  Get rid of it.
     435    psPolynomial1D **chebPolys = p_psCreateChebyshevPolys(1 + poly->nX);
     436
     437    tmp = 0.0;
     438    for (psS32 i=0;i<(1 + poly->nX);i++) {
     439        tmp+= (poly->coeff[i] * psPolynomial1DEval(chebPolys[i], x));
     440    }
     441    tmp-= (poly->coeff[0]/2.0);
     442
     443    for (psS32 i=0;i<(1 + poly->nX);i++) {
     444        psFree(chebPolys[i]);
     445    }
     446    psFree(chebPolys);
    311447
    312448    return(tmp);
    313449}
     450# endif
    314451
    315452static psF64 ordPolynomial2DEval(psF64 x,
     
    343480                                  const psPolynomial2D* poly)
    344481{
    345     PS_ASSERT_DOUBLE_WITHIN_RANGE(x, -1.0, 1.0, 0.0);
    346     PS_ASSERT_DOUBLE_WITHIN_RANGE(y, -1.0, 1.0, 0.0);
    347482    PS_ASSERT_POLY_NON_NULL(poly, NAN);
    348483
    349     unsigned int loop_x = 0;
    350     unsigned int loop_y = 0;
    351     unsigned int i = 0;
     484    psF64 xNorm = x*poly->scale[0] + poly->zero[0];
     485    psF64 yNorm = y*poly->scale[1] + poly->zero[1];
     486
    352487    psF64 polySum = 0.0;
    353     psPolynomial1D* *chebPolys = NULL;
    354     unsigned int maxChebyPoly = 0;
    355 
    356     // Determine how many Chebyshev polynomials
    357     // are needed, then create them.
    358     maxChebyPoly = poly->nX;
    359     if (poly->nY > maxChebyPoly) {
    360         maxChebyPoly = poly->nY;
    361     }
    362     chebPolys = p_psCreateChebyshevPolys(maxChebyPoly + 1);
    363 
    364     for (loop_x = 0; loop_x < (1 + poly->nX); loop_x++) {
    365         for (loop_y = 0; loop_y < (1 + poly->nY); loop_y++) {
    366             if (!(poly->coeffMask[loop_x][loop_y] & PS_POLY_MASK_SET)) {
    367                 polySum += poly->coeff[loop_x][loop_y] *
    368                            psPolynomial1DEval(chebPolys[loop_x], x) *
    369                            psPolynomial1DEval(chebPolys[loop_y], y);
    370             }
    371         }
    372     }
    373     for (i=0;i<maxChebyPoly+1;i++) {
    374         psFree(chebPolys[i]);
    375     }
    376     psFree(chebPolys);
     488
     489    // XXX this could be quicker if we saved the N xvalues are re-used the resuls
     490    for (int ix = 0; ix <= poly->nX; ix++) {
     491        psF64 xCheb = NAN;
     492        switch (ix) {
     493          case 0: CHEB_EVAL_0 (xCheb, xNorm); break;
     494          case 1: CHEB_EVAL_1 (xCheb, xNorm); break;
     495          case 2: CHEB_EVAL_2 (xCheb, xNorm); break;
     496          case 3: CHEB_EVAL_3 (xCheb, xNorm); break;
     497          case 4: CHEB_EVAL_4 (xCheb, xNorm); break;
     498          case 5: CHEB_EVAL_5 (xCheb, xNorm); break;
     499          case 6: CHEB_EVAL_6 (xCheb, xNorm); break;
     500          case 7: CHEB_EVAL_7 (xCheb, xNorm); break;
     501          case 8: CHEB_EVAL_8 (xCheb, xNorm); break;
     502          case 9: CHEB_EVAL_9 (xCheb, xNorm); break;
     503          default:
     504            break;
     505        }
     506        for (int iy = 0; iy <= poly->nY; iy++) {
     507            if (poly->coeffMask[ix][iy] & PS_POLY_MASK_SET) continue;
     508            psF64 yCheb = NAN;
     509            switch (iy) {
     510              case 0: CHEB_EVAL_0 (yCheb, yNorm); break;
     511              case 1: CHEB_EVAL_1 (yCheb, yNorm); break;
     512              case 2: CHEB_EVAL_2 (yCheb, yNorm); break;
     513              case 3: CHEB_EVAL_3 (yCheb, yNorm); break;
     514              case 4: CHEB_EVAL_4 (yCheb, yNorm); break;
     515              case 5: CHEB_EVAL_5 (yCheb, yNorm); break;
     516              case 6: CHEB_EVAL_6 (yCheb, yNorm); break;
     517              case 7: CHEB_EVAL_7 (yCheb, yNorm); break;
     518              case 8: CHEB_EVAL_8 (yCheb, yNorm); break;
     519              case 9: CHEB_EVAL_9 (yCheb, yNorm); break;
     520              default:
     521                break;
     522            }
     523            polySum += poly->coeff[ix][iy] * xCheb * yCheb;
     524        }
     525    }
    377526    return(polySum);
    378527}
     
    603752    }
    604753
     754    // scale & zero are used for Chebyshev polynomials to define the relationship between
     755    // the independent variables and the normalized version with range -1 : +1.  These
     756    // must be determined for a specific data set.
     757    newPoly->scale[0] = NAN;
     758    newPoly->zero[0]  = NAN;
     759
    605760    return(newPoly);
    606761}
     
    638793            newPoly->coeffMask[x][y] = PS_POLY_MASK_NONE;
    639794        }
     795    }
     796
     797    // scale & zero are used for Chebyshev polynomials to define the relationship between
     798    // the independent variables and the normalized version with range -1 : +1.  These
     799    // must be determined for a specific data set.
     800    for (int i = 0; i < 2; i++) {
     801      newPoly->scale[i] = NAN;
     802      newPoly->zero[i]  = NAN;
    640803    }
    641804
     
    756919            }
    757920        }
     921    }
     922
     923    // scale & zero are used for Chebyshev polynomials to define the relationship between
     924    // the independent variables and the normalized version with range -1 : +1.  These
     925    // must be determined for a specific data set.
     926    for (int i = 0; i < 3; i++) {
     927      newPoly->scale[i] = NAN;
     928      newPoly->zero[i]  = NAN;
    758929    }
    759930
     
    820991    }
    821992
     993    // scale & zero are used for Chebyshev polynomials to define the relationship between
     994    // the independent variables and the normalized version with range -1 : +1.  These
     995    // must be determined for a specific data set.
     996    for (int i = 0; i < 4; i++) {
     997      newPoly->scale[i] = NAN;
     998      newPoly->zero[i]  = NAN;
     999    }
     1000
    8221001    return(newPoly);
    8231002}
    8241003
     1004/* note these functions accept unscaled values and apply the scaling saved on poly */
    8251005psF64 psPolynomial1DEval(const psPolynomial1D* poly,
    8261006                         psF64 x)
     
    8301010    if (poly->type == PS_POLYNOMIAL_ORD) {
    8311011        return(ordPolynomial1DEval(x, poly));
    832     } else if (poly->type == PS_POLYNOMIAL_CHEB) {
     1012    }
     1013    if (poly->type == PS_POLYNOMIAL_CHEB) {
    8331014        return(chebPolynomial1DEval(x, poly));
    834     } else {
    835         psError(PS_ERR_BAD_PARAMETER_TYPE, true,
    836                 _("Unknown polynomial type 0x%x found.  Evaluation failed."),
    837                 poly->type);
    838     }
     1015    }
     1016    psError(PS_ERR_BAD_PARAMETER_TYPE, true,
     1017            _("Unknown polynomial type 0x%x found.  Evaluation failed."),
     1018            poly->type);
     1019
    8391020    return(NAN);
    8401021}
    8411022
    8421023// this function must accept F32 and F64 input x vectors
     1024// EAM XXX these functions seem inefficiently implemented with many nested function calls.
     1025// they might benefit from unrolling.
    8431026psVector *psPolynomial1DEvalVector(const psPolynomial1D *poly,
    8441027                                   const psVector *x)
     
    8781061    if (poly->type == PS_POLYNOMIAL_ORD) {
    8791062        return(ordPolynomial2DEval(x, y, poly));
    880     } else if (poly->type == PS_POLYNOMIAL_CHEB) {
     1063    }
     1064    if (poly->type == PS_POLYNOMIAL_CHEB) {
    8811065        return(chebPolynomial2DEval(x, y, poly));
    882     } else {
    883         psError(PS_ERR_BAD_PARAMETER_TYPE, true,
    884                 _("Unknown polynomial type 0x%x found.  Evaluation failed."),
    885                 poly->type);
    886     }
     1066    }
     1067    psError(PS_ERR_BAD_PARAMETER_TYPE, true,
     1068            _("Unknown polynomial type 0x%x found.  Evaluation failed."),
     1069            poly->type);
    8871070    return(NAN);
     1071}
     1072
     1073psVector *psPolynomial2DEvalChebVector(const psPolynomial2D *poly,
     1074                                       const psVector *x,
     1075                                       const psVector *y)
     1076{
     1077
     1078    if (!isfinite(poly->scale[0]) || !isfinite(poly->zero[0]) || !isfinite(poly->scale[1]) || !isfinite(poly->zero[1])) {
     1079        // re-calculate if not already determined? 
     1080        psError(PS_ERR_UNKNOWN, true, "normalization scales are not set for chebyshev polynomial");
     1081        return (NULL);
     1082    }
     1083
     1084    // Number of polynomial terms
     1085    int nXterm = 1 + poly->nX;      // Number of terms in x
     1086    int nYterm = 1 + poly->nY;      // Number of terms in y
     1087    if (nXterm > 9) {
     1088        psError(PS_ERR_UNKNOWN, false, "failed 2D chebyshev fit: orders higher than 9 are not yet coded\n");
     1089        return NULL;
     1090    }
     1091    if (nYterm > 9) {
     1092        psError(PS_ERR_UNKNOWN, false, "failed 2D chebyshev fit: orders higher than 9 are not yet coded\n");
     1093        return NULL;
     1094    }
     1095
     1096    // Generate normalized vectors for the range -1 : +1.  These functions cast to psF64
     1097    psVector *xNorm = psChebyshevNormVector (poly, x, 0);
     1098    psVector *yNorm = psChebyshevNormVector (poly, y, 1);
     1099   
     1100    // Generate the N cheb polynomials based on xNorm, yNorm
     1101    psArray *xPolySet = psArrayAlloc (nXterm);
     1102    for (int i = 0; i < nXterm; i++) {
     1103        xPolySet->data[i] = psChebyshevPolyVector (xNorm, i);
     1104    }
     1105    psArray *yPolySet = psArrayAlloc (nYterm);
     1106    for (int i = 0; i < nYterm; i++) {
     1107        yPolySet->data[i] = psChebyshevPolyVector (yNorm, i);
     1108    }
     1109
     1110    psVector *out = psVectorAlloc (x->n, PS_TYPE_F64);
     1111
     1112    psF64 *xData = xNorm->data.F64;
     1113    psF64 *yData = yNorm->data.F64;
     1114    psF64 *fData = out->data.F64;
     1115
     1116    // loop over all elements of the data vector
     1117    for (int i = 0; i < x->n; i++) {
     1118
     1119        if (!finite(xData[i])) {fData[i] = NAN; continue; }
     1120        if (!finite(yData[i])) {fData[i] = NAN; continue; }
     1121
     1122        psF64 sum = 0.0;
     1123        for (int jx = 0; jx < nXterm; jx++) {
     1124            psVector *jxCheb = xPolySet->data[jx];
     1125            for (int jy = 0; jy < nYterm; jy++) {
     1126                psVector *jyCheb = yPolySet->data[jy];
     1127                if (poly->coeffMask[jx][jy] & PS_POLY_MASK_SET) continue;
     1128                sum += poly->coeff[jx][jy] * jxCheb->data.F64[i] * jyCheb->data.F64[i];
     1129            }
     1130        }
     1131        fData[i] = sum;
     1132    }
     1133
     1134    psFree (xPolySet);
     1135    psFree (yPolySet);
     1136    psFree (xNorm);
     1137    psFree (yNorm);
     1138
     1139    return out;
    8881140}
    8891141
     
    9011153    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(y, NULL);
    9021154
    903     psVector *tmp;
    904     unsigned int vecLen=x->n;
     1155    unsigned int vecLen = x->n;
     1156
     1157    // input vector types must match
     1158    if (y->type.type != x->type.type) {
     1159        psError(PS_ERR_UNKNOWN, true, "type mismatch in data vectors");
     1160        return (NULL);
     1161    }
    9051162
    9061163    // Determine the length of the output vector to by the minimum of the x,y vectors
    907     if (y->n < vecLen) {
    908         vecLen = y->n;
     1164    // XXX shouldn't we require x & y to have the same length?  seems meaningless otherwise
     1165    if (y->n != vecLen) {
     1166        psError(PS_ERR_UNKNOWN, true, "length mismatch in data vectors");
     1167        return (NULL);
     1168    }
     1169
     1170    if (poly->type == PS_POLYNOMIAL_CHEB) {
     1171        psVector *out = psPolynomial2DEvalChebVector (poly, x, y);
     1172        return out;
    9091173    }
    9101174
    9111175    switch (x->type.type) {
    912     case PS_TYPE_F32:
    913         if (y->type.type != x->type.type) {
    914             psError(PS_ERR_UNKNOWN, true, "type mismatch in data vectors");
    915             return (NULL);
    916         }
    917 
    918         // Create output vector to return
    919         tmp = psVectorAlloc(vecLen, PS_TYPE_F32);
    920 
    921         // Evaluate the polynomial at the specified points
    922         for (unsigned int i=0; i<vecLen; i++) {
    923             tmp->data.F32[i] = psPolynomial2DEval(poly,x->data.F32[i],y->data.F32[i]);
    924         }
    925         break;
    926     case PS_TYPE_F64:
    927         if (y->type.type != x->type.type) {
    928             psError(PS_ERR_UNKNOWN, true, "type mismatch in data vectors");
    929             return (NULL);
    930         }
    931 
    932         // Create output vector to return
    933         tmp = psVectorAlloc(vecLen, PS_TYPE_F64);
    934 
    935         // Evaluate the polynomial at the specified points
    936         for (unsigned int i=0; i<vecLen; i++) {
    937             tmp->data.F64[i] = psPolynomial2DEval(poly,x->data.F64[i],y->data.F64[i]);
    938         }
    939         break;
    940     default:
     1176      case PS_TYPE_F32: {
     1177          // Create output vector to return
     1178          psVector *out = psVectorAlloc(vecLen, PS_TYPE_F32);
     1179
     1180          // Evaluate the polynomial at the specified points
     1181          for (unsigned int i = 0; i < vecLen; i++) {
     1182              out->data.F32[i] = psPolynomial2DEval(poly,x->data.F32[i],y->data.F32[i]);
     1183          }
     1184          return out;
     1185      }
     1186      case PS_TYPE_F64: {
     1187          // Create output vector to return
     1188          psVector *out = psVectorAlloc(vecLen, PS_TYPE_F64);
     1189
     1190          // Evaluate the polynomial at the specified points
     1191          for (unsigned int i = 0; i < vecLen; i++) {
     1192              out->data.F64[i] = psPolynomial2DEval(poly,x->data.F64[i],y->data.F64[i]);
     1193          }
     1194          return out;
     1195      }
     1196      default:
    9411197        psError(PS_ERR_UNKNOWN, false, "invalid input data type.\n");
    9421198        return (NULL);
    9431199    }
    944     // Return output vector
    945     return(tmp);
     1200    psAbort ("impossible");
     1201    return NULL;
    9461202}
    9471203
Note: See TracChangeset for help on using the changeset viewer.