IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Oct 11, 2021, 11:33:33 AM (5 years ago)
Author:
eugene
Message:

add chebyshev polynomials to 2D fitting; add chebyshev support functions; use chebyshev polynomials for inverse transformation

Location:
branches/eam_branches/ipp-dev-20210817/psLib
Files:
1 added
6 edited

Legend:

Unmodified
Added
Removed
  • branches/eam_branches/ipp-dev-20210817/psLib/src/astro/psCoord.c

    r41531 r41831  
    4040#include "psMinimizePolyFit.h"
    4141
     42# define TEST_SAVE_INVERSE_TRANSFORM 0
     43
     44# if (TEST_SAVE_INVERSE_TRANSFORM)
     45# include "psBinaryOp.h"
     46# endif
     47
    4248# define ELIXIR_CODE 1
    4349
     
    8692    }
    8793
    88     psPlaneTransform *out = psPlaneTransformAlloc(1, 1);
     94    // since the output polynomial is 1st order, a Chebyshev is not really useful
     95    psPlaneTransform *out = psPlaneTransformAlloc(1, 1, PS_POLYNOMIAL_ORD);
    8996
    9097    psF64 r12 = 0.0;
     
    191198}
    192199
    193 psPlaneTransform* psPlaneTransformAlloc(int order1, int order2)
     200psPlaneTransform* psPlaneTransformAlloc(int order1, int order2, psPolynomialType type)
    194201{
    195202    PS_ASSERT_INT_NONNEGATIVE(order1, NULL);
     
    198205    psPlaneTransform *pt = psAlloc(sizeof(psPlaneTransform));
    199206
    200     pt->x = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, order1, order2);
    201     pt->y = psPolynomial2DAlloc(PS_POLYNOMIAL_ORD, order1, order2);
     207    pt->x = psPolynomial2DAlloc(type, order1, order2);
     208    pt->y = psPolynomial2DAlloc(type, order1, order2);
    202209
    203210    psMemSetDeallocator(pt, (psFreeFunc) planeTransformFree);
     
    797804    }
    798805
     806    // both polynomials in both input transforms must match type -- and for now be ORD
     807    psAssert (trans1->x->type == PS_POLYNOMIAL_ORD, "fix for CHEB");
     808    psAssert (trans1->y->type == PS_POLYNOMIAL_ORD, "fix for CHEB");
     809    psAssert (trans2->x->type == PS_POLYNOMIAL_ORD, "fix for CHEB");
     810    psAssert (trans2->y->type == PS_POLYNOMIAL_ORD, "fix for CHEB");
     811
    799812    //
    800813    // Determine the size of the new psPlaneTransform.
     
    814827    psPlaneTransform *myPT = NULL;
    815828    if (out == NULL) {
    816         myPT = psPlaneTransformAlloc(orderX, orderY);
     829        myPT = psPlaneTransformAlloc(orderX, orderY, PS_POLYNOMIAL_ORD);
    817830    } else {
    818831        if ((out->x->nX == orderX) &&
     
    834847        } else {
    835848            psFree(out);
    836             myPT = psPlaneTransformAlloc(orderX, orderY);
     849            myPT = psPlaneTransformAlloc(orderX, orderY, PS_POLYNOMIAL_ORD);
    837850        }
    838851    }
     
    10371050    psPlaneTransform *myPT = NULL;
    10381051    if (out == NULL) {
    1039         myPT = psPlaneTransformAlloc(order, order);
     1052      myPT = psPlaneTransformAlloc(order, order, PS_POLYNOMIAL_CHEB);
    10401053    } else {
    10411054      // the user has supplied a model with a specific order : fit that order
     
    10711084    result &= psVectorFitPolynomial2D(myPT->x, NULL, 0, xOut, NULL, xIn, yIn);
    10721085    result &= psVectorFitPolynomial2D(myPT->y, NULL, 0, yOut, NULL, xIn, yIn);
     1086
     1087# if (TEST_SAVE_INVERSE_TRANSFORM)
     1088
     1089    psVector *xFit = psPolynomial2DEvalVector (myPT->x, xIn, yIn);
     1090    psVector *xRes = (psVector *) psBinaryOp (NULL, xOut, "-", xFit);
     1091
     1092    psVector *yFit = psPolynomial2DEvalVector (myPT->y, xIn, yIn);
     1093    psVector *yRes = (psVector *) psBinaryOp (NULL, yOut, "-", yFit);
     1094
     1095    static int nOut = 0;
     1096    char filename[1024];
     1097    snprintf (filename, 1024, "test.fit.%03d.ply", nOut);
     1098    FILE *fp = fopen (filename, "w");
     1099   
     1100    fprintf (fp, " ---- xFit ---- \n");
     1101
     1102    for (int ix = 0; ix < myPT->x->nX + 1; ix++) {
     1103      for (int iy = 0; iy < myPT->x->nY + 1; iy++) {
     1104        fprintf (fp, "%18.12e ", myPT->x->coeff[ix][iy]);
     1105      }
     1106      fprintf (fp, "\n");
     1107    }
     1108    fprintf (fp, " ---- yFit ---- \n");
     1109
     1110    for (int ix = 0; ix < myPT->y->nX + 1; ix++) {
     1111      for (int iy = 0; iy < myPT->y->nY + 1; iy++) {
     1112        fprintf (fp, "%18.12e ", myPT->y->coeff[ix][iy]);
     1113      }
     1114      fprintf (fp, "\n");
     1115    }
     1116    fclose (fp);
     1117   
     1118    snprintf (filename, 1024, "test.fit.%03d.dat", nOut); nOut ++;
     1119    FILE *f1 = fopen (filename, "w");
     1120    for (int i = 0; i < xFit->n; i++) {
     1121      fprintf (f1, "%d : %f %f : %f %f : %f %f : %f %f\n", i,
     1122               xIn->data.F64[i], yIn->data.F64[i],
     1123               xOut->data.F64[i], yOut->data.F64[i],
     1124               xFit->data.F64[i], yFit->data.F64[i],
     1125               xRes->data.F64[i], yRes->data.F64[i]);
     1126    }
     1127    fclose (f1);
     1128
     1129    psStats *myStats = psStatsAlloc (PS_STAT_SAMPLE_STDEV);
     1130    psVectorStats (myStats, xRes, NULL, NULL, 0); float dX = myStats->sampleStdev;
     1131    psVectorStats (myStats, yRes, NULL, NULL, 0); float dY = myStats->sampleStdev;
     1132    fprintf (stderr, "xRes Sigma: %f  --  yRes Sigma %f\n", dX, dY);
     1133
     1134    psFree (myStats);
     1135    psFree (xFit);
     1136    psFree (yFit);
     1137    psFree (xRes);
     1138    psFree (yRes);
     1139
     1140# endif
    10731141
    10741142    psFree(inCoord);
  • branches/eam_branches/ipp-dev-20210817/psLib/src/astro/psCoord.h

    r41531 r41831  
    178178
    179179psPlaneTransform* psPlaneTransformAlloc(
    180     int order1,                        ///< The order of the x term in the transform.
    181     int order2                         ///< The order of the y term in the transform.
     180    int order1,                       ///< The order of the x term in the transform.
     181    int order2,                       ///< The order of the y term in the transform.
     182    psPolynomialType type             ///< The polynomial type (ORD or CHEB) for this transform
    182183) PS_ATTR_MALLOC;
    183184
  • branches/eam_branches/ipp-dev-20210817/psLib/src/db/psDB.c

    r40290 r41831  
    28752875
    28762876    switch (pType) {
    2877     case PS_DATA_S8:
     2877      case PS_DATA_S8:
    28782878        isNaN = PS_IS_NAN(psS8, data, PS_MAX_S8);
    28792879        break;
    2880     case PS_DATA_S16:
     2880      case PS_DATA_S16:
    28812881        isNaN = PS_IS_NAN(psS16, data, PS_MAX_S16);
    28822882        break;
    2883     case PS_DATA_S32:
     2883      case PS_DATA_S32:
    28842884        isNaN = PS_IS_NAN(psS32, data, PS_MAX_S32);
    28852885        break;
    2886     case PS_DATA_S64:
     2886      case PS_DATA_S64:
    28872887        isNaN = PS_IS_NAN(psS64, data, PS_MAX_S64);
    28882888        break;
    2889     case PS_DATA_U8:
     2889      case PS_DATA_U8:
    28902890        isNaN = PS_IS_NAN(psU8, data, PS_MAX_U8);
    28912891        break;
    2892     case PS_DATA_U16:
     2892      case PS_DATA_U16:
    28932893        isNaN = PS_IS_NAN(psU16, data, PS_MAX_U16);
    28942894        break;
    2895     case PS_DATA_U32:
     2895      case PS_DATA_U32:
    28962896        isNaN = PS_IS_NAN(psU32, data, PS_MAX_U32);
    28972897        break;
    2898     case PS_DATA_U64:
     2898      case PS_DATA_U64:
    28992899        isNaN = PS_IS_NAN(psU64, data, PS_MAX_U64);
    29002900        break;
    2901     case PS_DATA_F32:
    2902       isNaN = isnan(*((psF32 *) data));
    2903       break;
    2904     case PS_DATA_F64:
    2905       isNaN = isnan(*((psF64 *) data));
    2906       break;
    2907     case PS_DATA_BOOL:
    2908         // XXX: what is NaN for a bool?
    2909         isNaN = PS_IS_NAN(psU8, data, PS_MAX_U8);
     2901      case PS_DATA_F32:
     2902        isNaN = !isfinite(*((psF32 *) data)); // trap nan, +inf, -inf
     2903        break;
     2904      case PS_DATA_F64:
     2905        isNaN = !isfinite(*((psF64 *) data)); // trap nan, +inf, -inf
     2906        break;
     2907      case PS_DATA_BOOL:
     2908        isNaN = PS_IS_NAN(psU8, data, PS_MAX_U8); // probably meaningless
    29102909        break;
    29112910    }
  • branches/eam_branches/ipp-dev-20210817/psLib/src/math/psMinimizePolyFit.c

    r41532 r41831  
    3535
    3636#include "psMinimizePolyFit.h"
     37#include "psAbort.h"
    3738#include "psAssert.h"
    3839#include "psMinimizeLMM.h"  // For Gauss-Jordan routines
     
    12251226
    12261227/******************************************************************************
     1228VectorFitPolynomial2DCheb(myPoly, *mask, maskValue, *f, *fErr, *x, *y): This is
     1229a private routine which will fit a 2-D polynomial to a set of (x, y)-(f)
     1230pairs.  All non-NULL vectors must be of type PS_TYPE_F64.
     1231 
     1232 *****************************************************************************/
     1233static bool VectorFitPolynomial2DCheb(
     1234    psPolynomial2D* myPoly,
     1235    const psVector *f,
     1236    const psVector *x,
     1237    const psVector *y)
     1238{
     1239    psTrace("psLib.math", 4, "---- %s() begin ----\n", __func__);
     1240    PS_ASSERT_POLY_NON_NULL(myPoly, false);
     1241    PS_ASSERT_INT_NONNEGATIVE(myPoly->nX, false);
     1242    PS_ASSERT_INT_NONNEGATIVE(myPoly->nY, false);
     1243    PS_ASSERT_VECTOR_NON_NULL(f, false);
     1244    PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F64, false);
     1245    PS_ASSERT_VECTOR_NON_NULL(x, false);
     1246    PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F64, false);
     1247    PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, false);
     1248    PS_ASSERT_VECTOR_NON_NULL(y, false);
     1249    PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F64, false);
     1250    PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, false);
     1251
     1252    // Number of polynomial terms
     1253    int nXterm = 1 + myPoly->nX;      // Number of terms in x
     1254    int nYterm = 1 + myPoly->nY;      // Number of terms in y
     1255    int nTerm = nXterm * nYterm;      // Total number of terms
     1256    if (nXterm > 9) {
     1257        psError(PS_ERR_UNKNOWN, false, "failed 2D chebyshev fit: orders higher than 9 are not yet coded\n");
     1258        return false;
     1259    }
     1260    if (nYterm > 9) {
     1261        psError(PS_ERR_UNKNOWN, false, "failed 2D chebyshev fit: orders higher than 9 are not yet coded\n");
     1262        return false;
     1263    }
     1264
     1265    // determine scale factors
     1266    if (!psChebyshevSetScale (myPoly, x, 0)) { psError(PS_ERR_UNKNOWN, false, "failed 2D chebyshev fit.\n"); return false; }
     1267    if (!psChebyshevSetScale (myPoly, y, 1)) { psError(PS_ERR_UNKNOWN, false, "failed 2D chebyshev fit.\n"); return false; }
     1268
     1269    // generate normalized vectors
     1270    psVector *xNorm = psChebyshevNormVector (myPoly, x, 0);
     1271    psVector *yNorm = psChebyshevNormVector (myPoly, y, 1);
     1272
     1273    // generate the N cheb polynomials based on xNorm, yNorm
     1274    psArray *xPolySet = psArrayAlloc (nXterm);
     1275    for (int i = 0; i < nXterm; i++) {
     1276        xPolySet->data[i] = psChebyshevPolyVector (xNorm, i);
     1277    }
     1278    psArray *yPolySet = psArrayAlloc (nYterm);
     1279    for (int i = 0; i < nYterm; i++) {
     1280        yPolySet->data[i] = psChebyshevPolyVector (yNorm, i);
     1281    }
     1282
     1283    psF64 *fData = f->data.F64;         // Dereference f
     1284
     1285    psImage *A = psImageAlloc(nTerm, nTerm, PS_TYPE_F64); // Least-squares matrix
     1286    psVector *B = psVectorAlloc(nTerm, PS_TYPE_F64); // Least-squares vector
     1287
     1288    // Initialize data structures (should not be able to fail)
     1289    psAssert (psImageInit(A, 0.0), "Could initialize data structures A");
     1290    psAssert (psVectorInit(B, 0.0), "Could initialize data structures B");
     1291
     1292    // Dereference stuff, to make the loop go faster
     1293    psF64 **matrix = A->data.F64;       // Dereference the least-squares matrix
     1294    psF64 *vector = B->data.F64;        // Dereference the least-squares vector
     1295
     1296    // loop over all elements of the data vector
     1297    for (int k = 0; k < x->n; k++) {
     1298
     1299        if (!finite(fData[k])) continue;
     1300   
     1301        // XXX can we only calculate the upper diagonal?
     1302        int nelem = 0;
     1303        for (int jx = 0; jx < nXterm; jx++) {
     1304            psVector *jxCheb = xPolySet->data[jx];
     1305            for (int jy = 0; jy < nYterm; jy++) {
     1306                psVector *jyCheb = yPolySet->data[jy];
     1307                psF64 chebValue = jxCheb->data.F64[k] * jyCheb->data.F64[k];
     1308               
     1309                vector[nelem] += fData[k] * chebValue;
     1310
     1311                int melem = 0;
     1312                for (int kx = 0; kx < nXterm; kx++) {
     1313                    psVector *kxCheb = xPolySet->data[kx];
     1314                    for (int ky = 0; ky < nYterm; ky++) {
     1315                        psVector *kyCheb = yPolySet->data[ky];
     1316                        matrix[nelem][melem] += chebValue * kxCheb->data.F64[k]*kyCheb->data.F64[k];
     1317                        melem++;
     1318                    }
     1319                }
     1320                nelem++;
     1321            }
     1322        }
     1323    }
     1324
     1325    if (psTraceGetLevel("psLib.math") >= 4) {
     1326        printf("Least-squares vector:\n");
     1327        for (int i = 0; i < nTerm; i++) {
     1328            printf("%f ", B->data.F64[i]);
     1329        }
     1330        printf("\n");
     1331        printf("Least-squares matrix:\n");
     1332        for (int i = 0; i < nTerm; i++) {
     1333            for (int j = 0; j < nTerm; j++) {
     1334                printf("%f ", A->data.F64[i][j]);
     1335            }
     1336            printf("\n");
     1337        }
     1338    }
     1339
     1340    bool status = false;
     1341    if (USE_GAUSS_JORDAN) {
     1342        status = psMatrixGJSolve(A, B);
     1343    } else {
     1344        status = psMatrixLUSolve(A, B);
     1345    }
     1346    if (!status) {
     1347        psError(PS_ERR_UNKNOWN, false, "Could not solve linear equations.\n");
     1348        goto escape;
     1349    }
     1350
     1351    // unroll the result:
     1352    int nelem = 0;
     1353    for (int jx = 0; jx < nXterm; jx++) {
     1354        for (int jy = 0; jy < nYterm; jy++) {
     1355            myPoly->coeff[jx][jy]    = B->data.F64[nelem];
     1356            myPoly->coeffErr[jx][jy] = sqrt(A->data.F64[nelem][nelem]);
     1357            nelem ++;
     1358        }
     1359    }
     1360    psFree(A);
     1361    psFree(B);
     1362
     1363    psFree (xNorm);
     1364    psFree (yNorm);
     1365    psFree (xPolySet);
     1366    psFree (yPolySet);
     1367
     1368    return true;
     1369
     1370escape:
     1371    psFree (A);
     1372    psFree (B);
     1373    return false;
     1374}
     1375
     1376/******************************************************************************
    12271377psVectorFitPolynomial2D():  This routine fits a 2D polynomial of arbitrary
    12281378degree (specified in poly) to the data points (x, y)-(f) and returns that
     
    12401390{
    12411391    PS_ASSERT_POLY_NON_NULL(poly, false);
    1242     PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, false);
     1392    // PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, false);
    12431393
    12441394    PS_ASSERT_VECTOR_NON_NULL(f, false);
     
    12771427        break;
    12781428    case PS_POLYNOMIAL_CHEB:
    1279         if (mask != NULL) {
    1280             psLogMsg(__func__, PS_LOG_WARN, "WARNING: ignoring mask and maskValue with Chebyshev polynomials.\n");
    1281         }
    1282         psError(PS_ERR_UNKNOWN, true, "2-D Chebyshev polynomial vector fitting has not been implemented.  Returning NULL.\n");
    1283         result = false;
    1284         break;
     1429      if (mask != NULL) {
     1430          psLogMsg(__func__, PS_LOG_WARN, "WARNING: ignoring mask and maskValue with Chebyshev polynomials.\n");
     1431      }
     1432      if (fErr != NULL) {
     1433          psLogMsg(__func__, PS_LOG_WARN, "WARNING: ignoring error values for Chebyshev polynomials.\n");
     1434      }
     1435      result = VectorFitPolynomial2DCheb(poly, f64, x64, y64);
     1436      if (!result) {
     1437          psError(PS_ERR_UNKNOWN, true, "Could not fit polynomial.  Returning NULL.\n");
     1438      }
     1439      break;
    12851440    default:
    12861441        psError(PS_ERR_UNKNOWN, true, "Incorrect polynomial type.  Returning NULL.\n");
  • branches/eam_branches/ipp-dev-20210817/psLib/src/math/psPolynomial.c

    r15253 r41831  
    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/** This function generates a vector containing the values of a Chebyshev polynomial of
     260    the given order evaluated at the coordinates given by the input vector, i.e., this
     261    function returns the vector T^n (x_i) where x_i is the input vector of values and n is
     262    the polynomial order.
     263 */
     264psVector *psChebyshevPolyVector (const psVector *vec, int order) {
     265
     266    if (order > 9) {
     267        psWarning ("Chebyshev orders higher than 9 are not yet coded\n");
     268        return NULL;
     269    }
     270
     271    psVector *out = psVectorAlloc (vec->n, PS_TYPE_F64);
     272
     273    // easy but non-general implementation
     274    switch (order) {
     275      case 0:
     276        for (int i = 0; i < vec->n; i++) {                                                   out->data.F64[i] = 1.0; } break;
     277      case 1:
     278        for (int i = 0; i < vec->n; i++) { psF64 x = vec->data.F64[i];                       out->data.F64[i] = x; } break;
     279      case 2:
     280        for (int i = 0; i < vec->n; i++) { psF64 x = vec->data.F64[i]; psF64 x2 = PS_SQR(x); out->data.F64[i] = 2.0*x2 - 1.0; } break;
     281      case 3:
     282        for (int i = 0; i < vec->n; i++) { psF64 x = vec->data.F64[i]; psF64 x2 = PS_SQR(x); out->data.F64[i] = x*(4.0*x2 - 3.0); } break;
     283      case 4:
     284        for (int i = 0; i < vec->n; i++) { psF64 x = vec->data.F64[i]; psF64 x2 = PS_SQR(x); out->data.F64[i] = x2*(8.0*x2 - 8.0) + 1.0; } break;
     285      case 5:
     286        for (int i = 0; i < vec->n; i++) { psF64 x = vec->data.F64[i]; psF64 x2 = PS_SQR(x); out->data.F64[i] = x *(x2*(16.0*x2 - 20.0) + 5.0); } break;
     287      case 6:
     288        for (int i = 0; i < vec->n; i++) { psF64 x = vec->data.F64[i]; psF64 x2 = PS_SQR(x); out->data.F64[i] = x2*(x2*(32.0*x2 - 48.0) + 18.0) - 1.0; } break;
     289      case 7:
     290        for (int i = 0; i < vec->n; i++) { psF64 x = vec->data.F64[i]; psF64 x2 = PS_SQR(x); out->data.F64[i] = x *(x2*(x2*(64.0*x2 - 112.0) + 56.0) - 7.0); } break;
     291      case 8:
     292        for (int i = 0; i < vec->n; i++) { psF64 x = vec->data.F64[i]; psF64 x2 = PS_SQR(x); out->data.F64[i] = x2*(x2*(x2*(128.0*x2 - 256.0) + 160.0) - 32.0) + 1.0; } break;
     293      case 9:
     294        for (int i = 0; i < vec->n; i++) { psF64 x = vec->data.F64[i]; psF64 x2 = PS_SQR(x); out->data.F64[i] = x *(x2*(x2*(x2*(256.0*x2 - 576.0) + 432.0) - 129.0) + 9.0); } break;
     295      default:
     296        psWarning ("Chebyshev orders higher than 9 are not yet coded\n");
     297        psFree (out);
     298        return NULL;
     299    }
     300
     301    return out;
     302}
     303
    205304/*****************************************************************************
    206305    Polynomial coefficients will be accessed in [w][x][y][z] fashion.
     
    234333
    235334// XXX: You can do this without having to psAlloc() vector d.
    236 // XXX: How does the mask vector effect Crenshaw's formula?
     335// XXX: How does the mask vector affect Clenshaw's formula?
    237336// NOTE: We assume that x is scaled between -1.0 and 1.0;
    238337// XXX: Create a faster version for low-order Chebyshevs.
     
    343442                                  const psPolynomial2D* poly)
    344443{
    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);
     444  // XXX transform x,y to chebyshev range
     445  // PS_ASSERT_DOUBLE_WITHIN_RANGE(x, -1.0, 1.0, 0.0);
     446  // PS_ASSERT_DOUBLE_WITHIN_RANGE(y, -1.0, 1.0, 0.0);
    347447    PS_ASSERT_POLY_NON_NULL(poly, NAN);
    348448
     
    354454    unsigned int maxChebyPoly = 0;
    355455
     456    psF64 xNorm = x*poly->scale[0] + poly->zero[0];
     457    psF64 yNorm = y*poly->scale[1] + poly->zero[1];
     458
    356459    // Determine how many Chebyshev polynomials
    357460    // are needed, then create them.
     
    366469            if (!(poly->coeffMask[loop_x][loop_y] & PS_POLY_MASK_SET)) {
    367470                polySum += poly->coeff[loop_x][loop_y] *
    368                            psPolynomial1DEval(chebPolys[loop_x], x) *
    369                            psPolynomial1DEval(chebPolys[loop_y], y);
     471                           psPolynomial1DEval(chebPolys[loop_x], xNorm) *
     472                           psPolynomial1DEval(chebPolys[loop_y], yNorm);
    370473            }
    371474        }
     
    603706    }
    604707
     708    // scale & zero are used for Chebyshev polynomials to define the relationship between
     709    // the independent variables and the normalized version with range -1 : +1.  These
     710    // must be determined for a specific data set.
     711    newPoly->scale[0] = NAN;
     712    newPoly->zero[0]  = NAN;
     713
    605714    return(newPoly);
    606715}
     
    638747            newPoly->coeffMask[x][y] = PS_POLY_MASK_NONE;
    639748        }
     749    }
     750
     751    // scale & zero are used for Chebyshev polynomials to define the relationship between
     752    // the independent variables and the normalized version with range -1 : +1.  These
     753    // must be determined for a specific data set.
     754    for (int i = 0; i < 2; i++) {
     755      newPoly->scale[i] = NAN;
     756      newPoly->zero[i]  = NAN;
    640757    }
    641758
     
    756873            }
    757874        }
     875    }
     876
     877    // scale & zero are used for Chebyshev polynomials to define the relationship between
     878    // the independent variables and the normalized version with range -1 : +1.  These
     879    // must be determined for a specific data set.
     880    for (int i = 0; i < 3; i++) {
     881      newPoly->scale[i] = NAN;
     882      newPoly->zero[i]  = NAN;
    758883    }
    759884
     
    820945    }
    821946
     947    // scale & zero are used for Chebyshev polynomials to define the relationship between
     948    // the independent variables and the normalized version with range -1 : +1.  These
     949    // must be determined for a specific data set.
     950    for (int i = 0; i < 4; i++) {
     951      newPoly->scale[i] = NAN;
     952      newPoly->zero[i]  = NAN;
     953    }
     954
    822955    return(newPoly);
    823956}
     
    841974
    842975// this function must accept F32 and F64 input x vectors
     976// EAM XXX these functions seem inefficiently implemented with many nested function calls.
     977// they might benefit from unrolling.
    843978psVector *psPolynomial1DEvalVector(const psPolynomial1D *poly,
    844979                                   const psVector *x)
     
    8881023}
    8891024
     1025psVector *psPolynomial2DEvalChebVector(const psPolynomial2D *poly,
     1026                                       const psVector *x,
     1027                                       const psVector *y)
     1028{
     1029
     1030    if (!isfinite(poly->scale[0]) || !isfinite(poly->zero[0]) || !isfinite(poly->scale[1]) || !isfinite(poly->zero[1])) {
     1031        // re-calculate if not already determined? 
     1032        psError(PS_ERR_UNKNOWN, true, "normalization scales are not set for chebyshev polynomial");
     1033        return (NULL);
     1034    }
     1035
     1036    // Number of polynomial terms
     1037    int nXterm = 1 + poly->nX;      // Number of terms in x
     1038    int nYterm = 1 + poly->nY;      // Number of terms in y
     1039    if (nXterm > 9) {
     1040        psError(PS_ERR_UNKNOWN, false, "failed 2D chebyshev fit: orders higher than 9 are not yet coded\n");
     1041        return NULL;
     1042    }
     1043    if (nYterm > 9) {
     1044        psError(PS_ERR_UNKNOWN, false, "failed 2D chebyshev fit: orders higher than 9 are not yet coded\n");
     1045        return NULL;
     1046    }
     1047
     1048    // Generate normalized vectors for the range -1 : +1.  These functions cast to psF64
     1049    psVector *xNorm = psChebyshevNormVector (poly, x, 0);
     1050    psVector *yNorm = psChebyshevNormVector (poly, y, 1);
     1051   
     1052    // Generate the N cheb polynomials based on xNorm, yNorm
     1053    psArray *xPolySet = psArrayAlloc (nXterm);
     1054    for (int i = 0; i < nXterm; i++) {
     1055        xPolySet->data[i] = psChebyshevPolyVector (xNorm, i);
     1056    }
     1057    psArray *yPolySet = psArrayAlloc (nYterm);
     1058    for (int i = 0; i < nYterm; i++) {
     1059        yPolySet->data[i] = psChebyshevPolyVector (yNorm, i);
     1060    }
     1061
     1062    psVector *out = psVectorAlloc (x->n, PS_TYPE_F64);
     1063
     1064    psF64 *xData = xNorm->data.F64;
     1065    psF64 *yData = yNorm->data.F64;
     1066    psF64 *fData = out->data.F64;
     1067
     1068    // loop over all elements of the data vector
     1069    for (int i = 0; i < x->n; i++) {
     1070
     1071        if (!finite(xData[i])) {fData[i] = NAN; continue; }
     1072        if (!finite(yData[i])) {fData[i] = NAN; continue; }
     1073
     1074        psF64 sum = 0.0;
     1075        for (int jx = 0; jx < nXterm; jx++) {
     1076            psVector *jxCheb = xPolySet->data[jx];
     1077            for (int jy = 0; jy < nYterm; jy++) {
     1078                psVector *jyCheb = yPolySet->data[jy];
     1079                sum += poly->coeff[jx][jy] * jxCheb->data.F64[i] * jyCheb->data.F64[i];
     1080            }
     1081        }
     1082        fData[i] = sum;
     1083    }
     1084
     1085    psFree (xPolySet);
     1086    psFree (yPolySet);
     1087    psFree (xNorm);
     1088    psFree (yNorm);
     1089
     1090    return out;
     1091}
     1092
    8901093// this function must support input data types of F32 and F64
    8911094// all input vectors data types must match (all F32 or all F64)
     
    9011104    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(y, NULL);
    9021105
    903     psVector *tmp;
    904     unsigned int vecLen=x->n;
     1106    unsigned int vecLen = x->n;
     1107
     1108    // input vector types must match
     1109    if (y->type.type != x->type.type) {
     1110        psError(PS_ERR_UNKNOWN, true, "type mismatch in data vectors");
     1111        return (NULL);
     1112    }
    9051113
    9061114    // 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;
     1115    // XXX shouldn't we require x & y to have the same length?  seems meaningless otherwise
     1116    if (y->n != vecLen) {
     1117        psError(PS_ERR_UNKNOWN, true, "length mismatch in data vectors");
     1118        return (NULL);
     1119    }
     1120
     1121    if (poly->type == PS_POLYNOMIAL_CHEB) {
     1122        psVector *out = psPolynomial2DEvalChebVector (poly, x, y);
     1123        return out;
    9091124    }
    9101125
    9111126    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:
     1127      case PS_TYPE_F32: {
     1128          // Create output vector to return
     1129          psVector *out = psVectorAlloc(vecLen, PS_TYPE_F32);
     1130
     1131          // Evaluate the polynomial at the specified points
     1132          for (unsigned int i = 0; i < vecLen; i++) {
     1133              out->data.F32[i] = psPolynomial2DEval(poly,x->data.F32[i],y->data.F32[i]);
     1134          }
     1135          return out;
     1136      }
     1137      case PS_TYPE_F64: {
     1138          // Create output vector to return
     1139          psVector *out = psVectorAlloc(vecLen, PS_TYPE_F64);
     1140
     1141          // Evaluate the polynomial at the specified points
     1142          for (unsigned int i = 0; i < vecLen; i++) {
     1143              out->data.F64[i] = psPolynomial2DEval(poly,x->data.F64[i],y->data.F64[i]);
     1144          }
     1145          return out;
     1146      }
     1147      default:
    9411148        psError(PS_ERR_UNKNOWN, false, "invalid input data type.\n");
    9421149        return (NULL);
    9431150    }
    944     // Return output vector
    945     return(tmp);
     1151    psAbort ("impossible");
     1152    return NULL;
    9461153}
    9471154
  • branches/eam_branches/ipp-dev-20210817/psLib/src/math/psPolynomial.h

    r15253 r41831  
    6868    psF64 *coeffErr;                    ///< Error in coefficients
    6969    psMaskType *coeffMask;              ///< Coefficient mask
     70    double scale[1];                    ///< Chebyshev scale factor
     71    double zero[1];                     ///< Chebyshev zero point
    7072}
    7173psPolynomial1D;
     
    8082    psF64 **coeffErr;                   ///< Error in coefficients
    8183    psMaskType **coeffMask;                  ///< Coefficients mask
     84    double scale[2];                    ///< Chebyshev scale factor
     85    double zero[2];                     ///< Chebyshev zero point
    8286}
    8387psPolynomial2D;
     
    9397    psF64 ***coeffErr;                  ///< Error in coefficients
    9498    psMaskType ***coeffMask;                 ///< Coefficients mask
     99    double scale[3];                    ///< Chebyshev scale factor
     100    double zero[3];                     ///< Chebyshev zero point
    95101}
    96102psPolynomial3D;
     
    107113    psF64 ****coeffErr;                 ///< Error in coefficients
    108114    psMaskType ****coeffMask;           ///< Coefficients mask
     115    double scale[4];                    ///< Chebyshev scale factor
     116    double zero[4];                     ///< Chebyshev zero point
    109117}
    110118psPolynomial4D;
     
    305313p_chebyPolys;
    306314
     315
     316// chebyshev support functions:
     317bool psChebyshevSetScale (psPolynomial2D* myPoly, const psVector *vec, int dir);
     318psVector *psChebyshevNormVector (const psPolynomial2D* myPoly, const psVector *vec, int dir);
     319psVector *psChebyshevPolyVector (const psVector *vec, int order);
    307320
    308321/*****************************************************************************
Note: See TracChangeset for help on using the changeset viewer.