Changeset 41896
- Timestamp:
- Nov 4, 2021, 6:10:51 PM (5 years ago)
- Location:
- trunk/psLib
- Files:
-
- 8 edited
- 1 copied
-
src/astro/psCoord.c (modified) (9 diffs)
-
src/astro/psCoord.h (modified) (1 diff)
-
src/db/psDB.c (modified) (1 diff)
-
src/fits/psFitsTableNew.c (modified) (2 diffs)
-
src/fits/psFitsTableNew.h (modified) (2 diffs)
-
src/math/psMinimizePolyFit.c (modified) (4 diffs)
-
src/math/psPolynomial.c (modified) (12 diffs)
-
src/math/psPolynomial.h (modified) (5 diffs)
-
test/math/tap_psPolyFit2DCheb.c (copied) (copied from branches/eam_branches/ipp-dev-20210817/psLib/test/math/tap_psPolyFit2DCheb.c )
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/astro/psCoord.c
r41531 r41896 40 40 #include "psMinimizePolyFit.h" 41 41 42 # define TEST_SAVE_INVERSE_TRANSFORM 0 43 44 # if (TEST_SAVE_INVERSE_TRANSFORM) 45 # include "psBinaryOp.h" 46 # endif 47 42 48 # define ELIXIR_CODE 1 43 49 … … 86 92 } 87 93 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); 89 96 90 97 psF64 r12 = 0.0; … … 191 198 } 192 199 193 psPlaneTransform* psPlaneTransformAlloc(int order1, int order2 )200 psPlaneTransform* psPlaneTransformAlloc(int order1, int order2, psPolynomialType type) 194 201 { 195 202 PS_ASSERT_INT_NONNEGATIVE(order1, NULL); … … 198 205 psPlaneTransform *pt = psAlloc(sizeof(psPlaneTransform)); 199 206 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); 202 209 203 210 psMemSetDeallocator(pt, (psFreeFunc) planeTransformFree); … … 797 804 } 798 805 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 799 812 // 800 813 // Determine the size of the new psPlaneTransform. … … 814 827 psPlaneTransform *myPT = NULL; 815 828 if (out == NULL) { 816 myPT = psPlaneTransformAlloc(orderX, orderY);829 myPT = psPlaneTransformAlloc(orderX, orderY, PS_POLYNOMIAL_ORD); 817 830 } else { 818 831 if ((out->x->nX == orderX) && … … 834 847 } else { 835 848 psFree(out); 836 myPT = psPlaneTransformAlloc(orderX, orderY );849 myPT = psPlaneTransformAlloc(orderX, orderY, PS_POLYNOMIAL_ORD); 837 850 } 838 851 } … … 1037 1050 psPlaneTransform *myPT = NULL; 1038 1051 if (out == NULL) { 1039 myPT = psPlaneTransformAlloc(order, order);1052 myPT = psPlaneTransformAlloc(order, order, PS_POLYNOMIAL_CHEB); 1040 1053 } else { 1041 1054 // the user has supplied a model with a specific order : fit that order … … 1071 1084 result &= psVectorFitPolynomial2D(myPT->x, NULL, 0, xOut, NULL, xIn, yIn); 1072 1085 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 1073 1141 1074 1142 psFree(inCoord); -
trunk/psLib/src/astro/psCoord.h
r41531 r41896 178 178 179 179 psPlaneTransform* 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 182 183 ) PS_ATTR_MALLOC; 183 184 -
trunk/psLib/src/db/psDB.c
r40290 r41896 2875 2875 2876 2876 switch (pType) { 2877 case PS_DATA_S8:2877 case PS_DATA_S8: 2878 2878 isNaN = PS_IS_NAN(psS8, data, PS_MAX_S8); 2879 2879 break; 2880 case PS_DATA_S16:2880 case PS_DATA_S16: 2881 2881 isNaN = PS_IS_NAN(psS16, data, PS_MAX_S16); 2882 2882 break; 2883 case PS_DATA_S32:2883 case PS_DATA_S32: 2884 2884 isNaN = PS_IS_NAN(psS32, data, PS_MAX_S32); 2885 2885 break; 2886 case PS_DATA_S64:2886 case PS_DATA_S64: 2887 2887 isNaN = PS_IS_NAN(psS64, data, PS_MAX_S64); 2888 2888 break; 2889 case PS_DATA_U8:2889 case PS_DATA_U8: 2890 2890 isNaN = PS_IS_NAN(psU8, data, PS_MAX_U8); 2891 2891 break; 2892 case PS_DATA_U16:2892 case PS_DATA_U16: 2893 2893 isNaN = PS_IS_NAN(psU16, data, PS_MAX_U16); 2894 2894 break; 2895 case PS_DATA_U32:2895 case PS_DATA_U32: 2896 2896 isNaN = PS_IS_NAN(psU32, data, PS_MAX_U32); 2897 2897 break; 2898 case PS_DATA_U64:2898 case PS_DATA_U64: 2899 2899 isNaN = PS_IS_NAN(psU64, data, PS_MAX_U64); 2900 2900 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 2910 2909 break; 2911 2910 } -
trunk/psLib/src/fits/psFitsTableNew.c
r33030 r41896 137 137 138 138 return table; 139 } 140 141 psFitsTable *psFitsTableCreate (psArray *tableColumns, int numRows) { 142 143 psFitsTable *table = psFitsTableAlloc (tableColumns->n, numRows); 144 145 // now define the table colums 146 for (int i = 0; i < tableColumns->n; i++) { 147 psFitsTableColumn *column = &table->columns[i]; 148 149 psFitsTableColumn *myColumn = tableColumns->data[i]; 150 151 column->name = psStringCopy (myColumn->name); 152 column->type = myColumn->type; 153 column->vectorType = myColumn->vectorType; 154 column->elementSize = myColumn->elementSize; 155 156 psMetadataAddS32(table->index, PS_LIST_TAIL, column->name, 0, NULL, i); 157 158 switch (column->type) { 159 case PS_DATA_S8: column->data.S8 = psAlloc(sizeof(psS8) *table->numRows); break; 160 case PS_DATA_S16: column->data.S16 = psAlloc(sizeof(psS16)*table->numRows); break; 161 case PS_DATA_S32: column->data.S32 = psAlloc(sizeof(psS32)*table->numRows); break; 162 case PS_DATA_S64: column->data.S64 = psAlloc(sizeof(psS64)*table->numRows); break; 163 case PS_DATA_U8: column->data.U8 = psAlloc(sizeof(psU8) *table->numRows); break; 164 case PS_DATA_U16: column->data.U16 = psAlloc(sizeof(psU16)*table->numRows); break; 165 case PS_DATA_U32: column->data.U32 = psAlloc(sizeof(psU32)*table->numRows); break; 166 case PS_DATA_U64: column->data.U64 = psAlloc(sizeof(psU64)*table->numRows); break; 167 case PS_DATA_F32: column->data.F32 = psAlloc(sizeof(psF32)*table->numRows); break; 168 case PS_DATA_F64: column->data.F64 = psAlloc(sizeof(psF64)*table->numRows); break; 169 default: break; 170 } 171 } 172 return table; 173 } 174 175 static void freeColumn(psFitsTableColumn *column) 176 { 177 // add any element frees here 178 return; 179 } 180 181 psFitsTableColumn *psFitsTableColumnAlloc (char *name, psDataType type) { 182 183 psFitsTableColumn *column = psAlloc(sizeof(psFitsTableColumn)); 184 psMemSetDeallocator(column, (psFreeFunc) freeColumn); 185 186 column->name = psStringCopy (name); 187 column->type = type; 188 column->vectorType = 0; 189 column->elementSize = 1; 190 column->data.S8 = NULL; // no data yet allocated, place-holder only 191 return column; 192 } 193 194 bool psFitsTableColumnAdd (psArray *tableColumns, char *name, psDataType type) { 195 psFitsTableColumn *column = psFitsTableColumnAlloc (name, type); 196 psArrayAdd (tableColumns, 10, column); 197 return true; 139 198 } 140 199 … … 397 456 psFitsTableGetNumTYPE(Bool, BOOL); 398 457 458 #define psFitsTableSetNumTYPE(TYPE, NAME) \ 459 bool psFitsTableSet##NAME(psFitsTable *table, int row, const char *name, ps##TYPE value) { \ 460 \ 461 if (row >= table->numRows || row < 0) { return false; } \ 462 \ 463 bool mdok; \ 464 int col = psMetadataLookupS32(&mdok, table->index, name); \ 465 if (!mdok) { return false; } \ 466 if (col < 0) { return false; } \ 467 \ 468 psFitsTableColumn *column = &table->columns[col]; \ 469 switch (column->type) { \ 470 case PS_DATA_S8: \ 471 column->data.S8[row] = (psS8) value; \ 472 break; \ 473 case PS_DATA_S16: \ 474 column->data.S16[row] = (psS16) value; \ 475 break; \ 476 case PS_DATA_S32: \ 477 column->data.S32[row] = (psS32) value; \ 478 break; \ 479 case PS_DATA_S64: \ 480 column->data.S64[row] = (psS64) value; \ 481 break; \ 482 case PS_DATA_U8: \ 483 column->data.U8[row] = (psU8) value; \ 484 break; \ 485 case PS_DATA_U16: \ 486 column->data.U16[row] = (psU16) value; \ 487 break; \ 488 case PS_DATA_U32: \ 489 column->data.U32[row] = (psU32) value; \ 490 break; \ 491 case PS_DATA_U64: \ 492 column->data.U64[row] = (psU64) value; \ 493 break; \ 494 case PS_DATA_F32: \ 495 column->data.F32[row] = (psF32) value; \ 496 break; \ 497 case PS_DATA_F64: \ 498 column->data.F64[row] = (psF64) value; \ 499 break; \ 500 case PS_DATA_BOOL: \ 501 if (value) { column->data.F64[row] = 1; } \ 502 else { column->data.F64[row] = 0; } \ 503 break; \ 504 default: \ 505 /* if you get to this point, the value is not a number. */ \ 506 return false; \ 507 break; \ 508 } \ 509 return true; \ 510 } 511 512 psFitsTableSetNumTYPE(S8, S8); 513 psFitsTableSetNumTYPE(U8, U8); 514 psFitsTableSetNumTYPE(S16, S16); 515 psFitsTableSetNumTYPE(U16, U16); 516 psFitsTableSetNumTYPE(S32, S32); 517 psFitsTableSetNumTYPE(U32, U32); 518 psFitsTableSetNumTYPE(S64, S64); 519 psFitsTableSetNumTYPE(U64, U64); 520 psFitsTableSetNumTYPE(F32, F32); 521 psFitsTableSetNumTYPE(F64, F64); 522 psFitsTableSetNumTYPE(Bool, BOOL); 523 399 524 // remove rows from table that are marked in the mask array as censored. 400 525 bool psFitsTableCensor(psFitsTable *table, bool *censorMask) -
trunk/psLib/src/fits/psFitsTableNew.h
r32263 r41896 55 55 // Get value for given row and column name 56 56 psBool psFitsTableGetBool(bool *status, psFitsTable *table, int row, const char* name); 57 psS8 psFitsTableGetS8(bool *status, psFitsTable *table, int row, const char* name);58 psU8 psFitsTableGetU8(bool *status, psFitsTable *table, int row, const char* name);57 psS8 psFitsTableGetS8(bool *status, psFitsTable *table, int row, const char* name); 58 psU8 psFitsTableGetU8(bool *status, psFitsTable *table, int row, const char* name); 59 59 psS16 psFitsTableGetS16(bool *status, psFitsTable *table, int row, const char* name); 60 60 psU16 psFitsTableGetU16(bool *status, psFitsTable *table, int row, const char* name); … … 63 63 psS64 psFitsTableGetS64(bool *status, psFitsTable *table, int row, const char* name); 64 64 psU64 psFitsTableGetU64(bool *status, psFitsTable *table, int row, const char* name); 65 66 65 psF32 psFitsTableGetF32(bool *status, psFitsTable *table, int row, const char* name); 67 66 psF64 psFitsTableGetF64(bool *status, psFitsTable *table, int row, const char* name); 68 67 68 psFitsTable *psFitsTableCreate (psArray *tableColumns, int numRows); 69 bool psFitsTableColumnAdd (psArray *tableColumns, char *name, psDataType type); 70 psFitsTableColumn *psFitsTableColumnAlloc (char *name, psDataType type); 71 72 bool psFitsTableSetS8 (psFitsTable *table, int row, const char* name, psS8 value); 73 bool psFitsTableSetU8 (psFitsTable *table, int row, const char* name, psU8 value); 74 bool psFitsTableSetS16(psFitsTable *table, int row, const char* name, psS16 value); 75 bool psFitsTableSetU16(psFitsTable *table, int row, const char* name, psU16 value); 76 bool psFitsTableSetS32(psFitsTable *table, int row, const char* name, psS32 value); 77 bool psFitsTableSetU32(psFitsTable *table, int row, const char* name, psU32 value); 78 bool psFitsTableSetS64(psFitsTable *table, int row, const char* name, psS64 value); 79 bool psFitsTableSetU64(psFitsTable *table, int row, const char* name, psU64 value); 80 bool psFitsTableSetF32(psFitsTable *table, int row, const char* name, psF32 value); 81 bool psFitsTableSetF64(psFitsTable *table, int row, const char* name, psF64 value); 82 69 83 #endif -
trunk/psLib/src/math/psMinimizePolyFit.c
r41532 r41896 35 35 36 36 #include "psMinimizePolyFit.h" 37 #include "psAbort.h" 37 38 #include "psAssert.h" 38 39 #include "psMinimizeLMM.h" // For Gauss-Jordan routines … … 1225 1226 1226 1227 /****************************************************************************** 1228 VectorFitPolynomial2DCheb(myPoly, *mask, maskValue, *f, *fErr, *x, *y): This is 1229 a private routine which will fit a 2-D polynomial to a set of (x, y)-(f) 1230 pairs. All non-NULL vectors must be of type PS_TYPE_F64. 1231 1232 *****************************************************************************/ 1233 static 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 1370 escape: 1371 psFree (A); 1372 psFree (B); 1373 return false; 1374 } 1375 1376 /****************************************************************************** 1227 1377 psVectorFitPolynomial2D(): This routine fits a 2D polynomial of arbitrary 1228 1378 degree (specified in poly) to the data points (x, y)-(f) and returns that … … 1240 1390 { 1241 1391 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); 1243 1393 1244 1394 PS_ASSERT_VECTOR_NON_NULL(f, false); … … 1277 1427 break; 1278 1428 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; 1285 1440 default: 1286 1441 psError(PS_ERR_UNKNOWN, true, "Incorrect polynomial type. Returning NULL.\n"); -
trunk/psLib/src/math/psPolynomial.c
r15253 r41896 36 36 #include "psLogMsg.h" 37 37 #include "psPolynomial.h" 38 #include "psAbort.h" 38 39 #include "psAssert.h" 39 40 … … 203 204 204 205 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 */ 210 bool 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 */ 238 psVector *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 */ 275 psVector *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 205 315 /***************************************************************************** 206 316 Polynomial coefficients will be accessed in [w][x][y][z] fashion. … … 233 343 } 234 344 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); 345 static psF64 chebPolynomial1DEval(psF64 x, const psPolynomial1D* poly) { 346 244 347 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 377 void oldcode_1(void) { 245 378 psVector *d; 379 psF64 tmp = 0.0; 246 380 247 381 unsigned int nTerms = 1 + poly->nX; 248 382 unsigned int i; 249 psF64 tmp = 0.0;250 383 251 384 // Special case where the Chebyshev poly is constant. … … 268 401 } 269 402 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]; 296 407 } 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 433 void 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); 311 447 312 448 return(tmp); 313 449 } 450 # endif 314 451 315 452 static psF64 ordPolynomial2DEval(psF64 x, … … 343 480 const psPolynomial2D* poly) 344 481 { 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);347 482 PS_ASSERT_POLY_NON_NULL(poly, NAN); 348 483 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 352 487 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 } 377 526 return(polySum); 378 527 } … … 603 752 } 604 753 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 605 760 return(newPoly); 606 761 } … … 638 793 newPoly->coeffMask[x][y] = PS_POLY_MASK_NONE; 639 794 } 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; 640 803 } 641 804 … … 756 919 } 757 920 } 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; 758 929 } 759 930 … … 820 991 } 821 992 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 822 1001 return(newPoly); 823 1002 } 824 1003 1004 /* note these functions accept unscaled values and apply the scaling saved on poly */ 825 1005 psF64 psPolynomial1DEval(const psPolynomial1D* poly, 826 1006 psF64 x) … … 830 1010 if (poly->type == PS_POLYNOMIAL_ORD) { 831 1011 return(ordPolynomial1DEval(x, poly)); 832 } else if (poly->type == PS_POLYNOMIAL_CHEB) { 1012 } 1013 if (poly->type == PS_POLYNOMIAL_CHEB) { 833 1014 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 839 1020 return(NAN); 840 1021 } 841 1022 842 1023 // 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. 843 1026 psVector *psPolynomial1DEvalVector(const psPolynomial1D *poly, 844 1027 const psVector *x) … … 878 1061 if (poly->type == PS_POLYNOMIAL_ORD) { 879 1062 return(ordPolynomial2DEval(x, y, poly)); 880 } else if (poly->type == PS_POLYNOMIAL_CHEB) { 1063 } 1064 if (poly->type == PS_POLYNOMIAL_CHEB) { 881 1065 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); 887 1070 return(NAN); 1071 } 1072 1073 psVector *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; 888 1140 } 889 1141 … … 901 1153 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(y, NULL); 902 1154 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 } 905 1162 906 1163 // 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; 909 1173 } 910 1174 911 1175 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: 941 1197 psError(PS_ERR_UNKNOWN, false, "invalid input data type.\n"); 942 1198 return (NULL); 943 1199 } 944 // Return output vector945 return (tmp);1200 psAbort ("impossible"); 1201 return NULL; 946 1202 } 947 1203 -
trunk/psLib/src/math/psPolynomial.h
r15253 r41896 68 68 psF64 *coeffErr; ///< Error in coefficients 69 69 psMaskType *coeffMask; ///< Coefficient mask 70 double scale[1]; ///< Chebyshev scale factor 71 double zero[1]; ///< Chebyshev zero point 70 72 } 71 73 psPolynomial1D; … … 80 82 psF64 **coeffErr; ///< Error in coefficients 81 83 psMaskType **coeffMask; ///< Coefficients mask 84 double scale[2]; ///< Chebyshev scale factor 85 double zero[2]; ///< Chebyshev zero point 82 86 } 83 87 psPolynomial2D; … … 93 97 psF64 ***coeffErr; ///< Error in coefficients 94 98 psMaskType ***coeffMask; ///< Coefficients mask 99 double scale[3]; ///< Chebyshev scale factor 100 double zero[3]; ///< Chebyshev zero point 95 101 } 96 102 psPolynomial3D; … … 107 113 psF64 ****coeffErr; ///< Error in coefficients 108 114 psMaskType ****coeffMask; ///< Coefficients mask 115 double scale[4]; ///< Chebyshev scale factor 116 double zero[4]; ///< Chebyshev zero point 109 117 } 110 118 psPolynomial4D; … … 305 313 p_chebyPolys; 306 314 315 316 // chebyshev support functions: 317 bool psChebyshevSetScale (psPolynomial2D* myPoly, const psVector *vec, int dir); 318 psVector *psChebyshevNormVector (const psPolynomial2D* myPoly, const psVector *vec, int dir); 319 psVector *psChebyshevPolyVector (const psVector *vec, int order); 307 320 308 321 /*****************************************************************************
Note:
See TracChangeset
for help on using the changeset viewer.
