Changeset 41896 for trunk/psLib/src/math/psPolynomial.c
- Timestamp:
- Nov 4, 2021, 6:10:51 PM (5 years ago)
- File:
-
- 1 edited
-
trunk/psLib/src/math/psPolynomial.c (modified) (12 diffs)
Legend:
- Unmodified
- Added
- Removed
-
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
Note:
See TracChangeset
for help on using the changeset viewer.
