Changeset 41831 for branches/eam_branches/ipp-dev-20210817
- Timestamp:
- Oct 11, 2021, 11:33:33 AM (5 years ago)
- Location:
- branches/eam_branches/ipp-dev-20210817/psLib
- Files:
-
- 1 added
- 6 edited
-
src/astro/psCoord.c (modified) (9 diffs)
-
src/astro/psCoord.h (modified) (1 diff)
-
src/db/psDB.c (modified) (1 diff)
-
src/math/psMinimizePolyFit.c (modified) (4 diffs)
-
src/math/psPolynomial.c (modified) (13 diffs)
-
src/math/psPolynomial.h (modified) (5 diffs)
-
test/math/tap_psPolyFit2DCheb.c (added)
Legend:
- Unmodified
- Added
- Removed
-
branches/eam_branches/ipp-dev-20210817/psLib/src/astro/psCoord.c
r41531 r41831 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); -
branches/eam_branches/ipp-dev-20210817/psLib/src/astro/psCoord.h
r41531 r41831 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 -
branches/eam_branches/ipp-dev-20210817/psLib/src/db/psDB.c
r40290 r41831 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 } -
branches/eam_branches/ipp-dev-20210817/psLib/src/math/psMinimizePolyFit.c
r41532 r41831 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"); -
branches/eam_branches/ipp-dev-20210817/psLib/src/math/psPolynomial.c
r15253 r41831 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 /** 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 */ 264 psVector *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 205 304 /***************************************************************************** 206 305 Polynomial coefficients will be accessed in [w][x][y][z] fashion. … … 234 333 235 334 // 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? 237 336 // NOTE: We assume that x is scaled between -1.0 and 1.0; 238 337 // XXX: Create a faster version for low-order Chebyshevs. … … 343 442 const psPolynomial2D* poly) 344 443 { 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); 347 447 PS_ASSERT_POLY_NON_NULL(poly, NAN); 348 448 … … 354 454 unsigned int maxChebyPoly = 0; 355 455 456 psF64 xNorm = x*poly->scale[0] + poly->zero[0]; 457 psF64 yNorm = y*poly->scale[1] + poly->zero[1]; 458 356 459 // Determine how many Chebyshev polynomials 357 460 // are needed, then create them. … … 366 469 if (!(poly->coeffMask[loop_x][loop_y] & PS_POLY_MASK_SET)) { 367 470 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); 370 473 } 371 474 } … … 603 706 } 604 707 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 605 714 return(newPoly); 606 715 } … … 638 747 newPoly->coeffMask[x][y] = PS_POLY_MASK_NONE; 639 748 } 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; 640 757 } 641 758 … … 756 873 } 757 874 } 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; 758 883 } 759 884 … … 820 945 } 821 946 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 822 955 return(newPoly); 823 956 } … … 841 974 842 975 // 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. 843 978 psVector *psPolynomial1DEvalVector(const psPolynomial1D *poly, 844 979 const psVector *x) … … 888 1023 } 889 1024 1025 psVector *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 890 1093 // this function must support input data types of F32 and F64 891 1094 // all input vectors data types must match (all F32 or all F64) … … 901 1104 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(y, NULL); 902 1105 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 } 905 1113 906 1114 // 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; 909 1124 } 910 1125 911 1126 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: 941 1148 psError(PS_ERR_UNKNOWN, false, "invalid input data type.\n"); 942 1149 return (NULL); 943 1150 } 944 // Return output vector945 return (tmp);1151 psAbort ("impossible"); 1152 return NULL; 946 1153 } 947 1154 -
branches/eam_branches/ipp-dev-20210817/psLib/src/math/psPolynomial.h
r15253 r41831 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.
