Changeset 4991
- Timestamp:
- Sep 11, 2005, 12:18:40 PM (21 years ago)
- Location:
- trunk/psLib/src
- Files:
-
- 8 edited
-
astro/psCoord.c (modified) (5 diffs)
-
math/psConstants.h (modified) (3 diffs)
-
math/psMinimize.c (modified) (40 diffs)
-
math/psMinimize.h (modified) (11 diffs)
-
math/psPolynomial.c (modified) (2 diffs)
-
math/psSpline.c (modified) (3 diffs)
-
math/psSpline.h (modified) (2 diffs)
-
math/psStats.c (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/astro/psCoord.c
r4957 r4991 10 10 * @author GLG, MHPCC 11 11 * 12 * @version $Revision: 1.8 5$ $Name: not supported by cvs2svn $13 * @date $Date: 2005-09- 07 21:33:48$12 * @version $Revision: 1.86 $ $Name: not supported by cvs2svn $ 13 * @date $Date: 2005-09-11 22:18:40 $ 14 14 * 15 15 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 545 545 int nSamples) 546 546 { 547 548 // XXX: This does not yet use region and nSamples: need to modify -rdd549 550 547 PS_ASSERT_PTR_NON_NULL(trans1, NULL); 551 548 PS_ASSERT_PTR_NON_NULL(trans2, NULL); … … 905 902 ) 906 903 { 907 /* 908 PS_ASSERT_PTR_NON_NULL(transformation, NULL); 909 PS_ASSERT_POLY_NON_NULL(transformation->x, NULL); 910 PS_ASSERT_POLY_NON_NULL(transformation->y, NULL); 911 PS_ASSERT_PTR_NON_NULL(coord, NULL); 912 913 if (out == NULL) { 914 out = psPlaneAlloc(); 915 } 916 917 out->x = 0.0; 918 out->y = 0.0; 919 out->xErr = 0.0; 920 out->yErr = 0.0; 921 922 psPolynomial2D *xPoly = transformation->x; 923 psPolynomial2D *yPoly = transformation->y; 924 925 // 926 // Calculate the derivative with respect to x. 927 // 928 psF32 xSum = 1.0; 929 psF32 ySum = 1.0; 930 931 // This loop starts at loop_x=1 since the derivative of the loop_x=0 terms are all 0.0 932 for (psS32 loop_x = 1; loop_x < xPoly->nX; loop_x++) { 933 ySum = 1.0; 934 for (psS32 loop_y = 0; loop_y < xPoly->nY; loop_y++) { 935 // 936 // For each iteration of the loop, we multiple the (x, y) coefficient 937 // by (coord->x^(loop_x-1) * coord->y^loop_y) 938 // 939 940 out->x+= xPoly->coeff[loop_x][loop_y] * xSum * ySum; 941 ySum*= coord->y; 942 } 943 xSum*= coord->x; 944 } 945 946 // 947 // Calculate the derivative with respect to x. 948 // 949 xSum = 1.0; 950 951 // This loop starts at loop_y=1 since the derivative of the loop_y=0 terms are all 0.0 952 for (psS32 loop_x = 0; loop_x < yPoly->nX; loop_x++) { 953 ySum = 1.0; 954 for (psS32 loop_y = 1; loop_y < yPoly->nY; loop_y++) { 955 // 956 // For each iteration of the loop, we multiple the (x, y) coefficient 957 // by (coord->x^(loop_x-1) * coord->y^loop_y) 958 // 959 960 out->y+= yPoly->coeff[loop_x][loop_y] * xSum * ySum; 961 ySum*= coord->y; 962 } 963 xSum*= coord->x; 964 } 965 */ 904 PS_ASSERT_PTR_NON_NULL(transformation, NULL); 905 PS_ASSERT_POLY_NON_NULL(transformation->x, NULL); 906 PS_ASSERT_POLY_NON_NULL(transformation->y, NULL); 907 PS_ASSERT_PTR_NON_NULL(coord, NULL); 908 909 if (out == NULL) { 910 out = psPlaneAlloc(); 911 } 912 913 out->x = 0.0; 914 out->y = 0.0; 915 out->xErr = 0.0; 916 out->yErr = 0.0; 917 918 psPolynomial2D *xPoly = transformation->x; 919 psPolynomial2D *yPoly = transformation->y; 920 921 // 922 // Calculate the derivative with respect to x. 923 // 924 psF32 xSum = 1.0; 925 psF32 ySum = 1.0; 926 927 // This loop starts at loop_x=1 since the derivative of the loop_x=0 terms are all 0.0 928 for (psS32 loop_x = 1; loop_x < xPoly->nX; loop_x++) { 929 ySum = 1.0; 930 for (psS32 loop_y = 0; loop_y < xPoly->nY; loop_y++) { 931 // 932 // For each iteration of the loop, we multiple the (x, y) coefficient 933 // by (coord->x^(loop_x-1) * coord->y^loop_y) 934 // 935 936 out->x+= xPoly->coeff[loop_x][loop_y] * xSum * ySum; 937 ySum*= coord->y; 938 } 939 xSum*= coord->x; 940 } 941 942 // 943 // Calculate the derivative with respect to x. 944 // 945 xSum = 1.0; 946 947 // This loop starts at loop_y=1 since the derivative of the loop_y=0 terms are all 0.0 948 for (psS32 loop_x = 0; loop_x < yPoly->nX; loop_x++) { 949 ySum = 1.0; 950 for (psS32 loop_y = 1; loop_y < yPoly->nY; loop_y++) { 951 // 952 // For each iteration of the loop, we multiple the (x, y) coefficient 953 // by (coord->x^(loop_x-1) * coord->y^loop_y) 954 // 955 956 out->y+= yPoly->coeff[loop_x][loop_y] * xSum * ySum; 957 ySum*= coord->y; 958 } 959 xSum*= coord->x; 960 } 966 961 return(out); 967 962 } … … 970 965 { 971 966 if(sphere == NULL) { 972 // psError();967 psError( PS_ERR_UNKNOWN, true, "psSphere argument is NULL. Returning NULL.\n"); 973 968 return NULL; 974 969 } … … 990 985 { 991 986 if(cube == NULL) { 992 // psError();987 psError( PS_ERR_UNKNOWN, true, "psCube argument is NULL. Returning NULL.\n"); 993 988 return NULL; 994 989 } -
trunk/psLib/src/math/psConstants.h
r4581 r4991 6 6 * @author GLG, MHPCC 7 7 * 8 * @version $Revision: 1.7 5$ $Name: not supported by cvs2svn $9 * @date $Date: 2005-0 7-20 01:21:13$8 * @version $Revision: 1.76 $ $Name: not supported by cvs2svn $ 9 * @date $Date: 2005-09-11 22:18:40 $ 10 10 * 11 11 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 357 357 358 358 #define PS_VECTOR_PRINT_F32(NAME) \ 359 for (int my_i=0;my_i<(NAME)->n;my_i++) { \ 360 printf("%s->data.F32[%d] is %f\n", #NAME, my_i, (NAME)->data.F32[my_i]); \ 361 } \ 362 printf("\n"); \ 359 if (NAME != NULL) { \ 360 for (int my_i=0;my_i<(NAME)->n;my_i++) { \ 361 printf("%s->data.F32[%d] is %f\n", #NAME, my_i, (NAME)->data.F32[my_i]); \ 362 } \ 363 printf("\n"); \ 364 } else {\ 365 printf("MACRO WARNING: vector %s is NULL.\n", #NAME); \ 366 }\ 363 367 364 368 #define PS_VECTOR_PRINT_F64(NAME) \ 365 for (int my_i=0;my_i<(NAME)->n;my_i++) { \ 366 printf("%s->data.F64[%d] is %f\n", #NAME, my_i, (NAME)->data.F64[my_i]); \ 367 } \ 368 printf("\n"); \ 369 369 if (NAME != NULL) { \ 370 for (int my_i=0;my_i<(NAME)->n;my_i++) { \ 371 printf("%s->data.F64[%d] is %f\n", #NAME, my_i, (NAME)->data.F64[my_i]); \ 372 } \ 373 printf("\n"); \ 374 } else {\ 375 printf("MACRO WARNING: vector %s is NULL.\n", #NAME); \ 376 }\ 370 377 371 378 #define PS_VECTOR_CONVERT_F64_TO_F32_STATIC(OLD, NEW_PTR32, NEW_STATIC32) \ … … 742 749 #define PS_SQR(A) \ 743 750 ((A) * (A)) 751 752 # define PS_SWAP(X,Y) {double tmp=(X); (X) = (Y); (Y) = tmp;} -
trunk/psLib/src/math/psMinimize.c
r4958 r4991 8 8 * 9 9 * @author GLG, MHPCC 10 * @author EAM, IfA 10 11 * 11 * @version $Revision: 1.13 4$ $Name: not supported by cvs2svn $12 * @date $Date: 2005-09- 07 21:35:50 $12 * @version $Revision: 1.135 $ $Name: not supported by cvs2svn $ 13 * @date $Date: 2005-09-11 22:18:40 $ 13 14 * 14 15 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 32 33 /*****************************************************************************/ 33 34 /* DEFINE STATEMENTS */ 35 /* What are the following macros for? */ 34 36 /*****************************************************************************/ 35 37 #define PS_SEG psLib … … 57 59 /*****************************************************************************/ 58 60 61 /****************************************************************************** 62 ****************************************************************************** 63 Levenberg-Marquadt routines. 64 ****************************************************************************** 65 *****************************************************************************/ 59 66 // measure the distance to the minimum assuming a linear model 67 // XXX: Move this to the pub area. 60 68 bool psMinimizeGaussNewtonDelta (psVector *delta, 61 69 const psVector *params, … … 112 120 } 113 121 114 /******************************************************************************115 buildSums1D(x, polyOrder, sums): this routine calculates the powers of input116 parameter "x" between 0 and input parameter polyOrder. The result is returned117 as a psVector sums.118 119 XXX: Use a static vector.120 121 XXX: should the argument be polyOrder or numTerms?122 *****************************************************************************/123 static void buildSums1D(psF64 x,124 psS32 polyOrder,125 psVector* sums)126 {127 psS32 i = 0;128 psF64 xSum = 0.0;129 psS32 numTerms = polyOrder + 1;130 131 if (sums == NULL) {132 sums = psVectorAlloc(numTerms, PS_TYPE_F64);133 } else if (numTerms > sums->n) {134 sums = psVectorRealloc(sums, numTerms);135 }136 137 xSum = 1.0;138 for (i = 0; i < numTerms; i++) {139 sums->data.F64[i] = xSum;140 xSum *= x;141 }142 }143 144 /*****************************************************************************145 CalculateSecondDerivs(): Given a set of x/y vectors corresponding to a146 tabulated function at n points, this routine calculates the second147 derivatives of the interpolating cubic splines at those n points.148 149 The first and second derivatives at the endpoints, undefined in the SDR, are150 here defined to be 0.0. They can be modified via ypo and yp1.151 152 This routine assumes that vectors x and y are of the appropriate types/sizes153 (F32).154 155 XXX: This algorithm is derived from the Numerical Recipes.156 XXX: use recycled vectors for internal data.157 XXX: do an F64 version?158 *****************************************************************************/159 static psF32 *calculateSecondDerivs(const psVector* x, ///< Ordinates (or NULL to just use the indices)160 const psVector* y) ///< Coordinates161 {162 psTrace(".psLib.dataManip.calculateSecondDerivs", 4,163 "---- calculateSecondDerivs() begin ----\n");164 165 psS32 i;166 psS32 k;167 psF32 sig;168 psF32 p;169 psS32 n = y->n;170 psF32 *u = (psF32 *) psAlloc(n * sizeof(psF32));171 psF32 *derivs2 = (psF32 *) psAlloc(n * sizeof(psF32));172 psF32 *X = (psF32 *) & (x->data.F32[0]);173 psF32 *Y = (psF32 *) & (y->data.F32[0]);174 psF32 qn;175 176 // XXX: The second derivatives at the endpoints, undefined in the SDR,177 // are set in psConstants.h: PS_LEFT_SPLINE_DERIV, PS_RIGHT_SPLINE_DERIV.178 derivs2[0] = -0.5;179 u[0]= (3.0/(X[1]-X[0])) * ((Y[1]-Y[0])/(X[1]-X[0]) - PS_LEFT_SPLINE_DERIV);180 181 for (i=1;i<=(n-2);i++) {182 sig = (X[i] - X[i-1]) / (X[i+1] - X[i-1]);183 p = sig * derivs2[i-1] + 2.0;184 derivs2[i] = (sig - 1.0) / p;185 u[i] = ((Y[i+1] - Y[i])/(X[i+1]-X[i])) - ((Y[i]-Y[i-1])/(X[i]-X[i-1]));186 u[i] = ((6.0 * u[i] / (X[i+1] - X[i-1])) - (sig * u[i-1])) / p;187 188 psTrace(".psLib.dataManip.calculateSecondDerivs", 6,189 "X[%d] is %f\n", i, X[i]);190 psTrace(".psLib.dataManip.calculateSecondDerivs", 6,191 "Y[%d] is %f\n", i, Y[i]);192 psTrace(".psLib.dataManip.calculateSecondDerivs", 6,193 "u[%d] is %f\n", i, u[i]);194 }195 196 qn = 0.5;197 u[n-1] = (3.0/(X[n-1]-X[n-2])) * (PS_RIGHT_SPLINE_DERIV - (Y[n-1]-Y[n-2])/(X[n-1]-X[n-2]));198 derivs2[n-1] = (u[n-1] - (qn * u[n-2])) / ((qn * derivs2[n-2]) + 1.0);199 200 for (k=(n-2);k>=0;k--) {201 derivs2[k] = derivs2[k] * derivs2[k+1] + u[k];202 203 psTrace(".psLib.dataManip.calculateSecondDerivs", 6,204 "derivs2[%d] is %f\n", k, derivs2[k]);205 }206 207 psFree(u);208 psTrace(".psLib.dataManip.calculateSecondDerivs", 4,209 "---- calculateSecondDerivs() end ----\n");210 return(derivs2);211 }212 213 /******************************************************************************214 p_psNRSpline1DEval(): This routine does NR-style evaluation of cubic splines.215 It takes advantage of the 2nd derivatives of the cubic splines, which are216 stored in the psSPline1D data structure, and computes the interpolated value217 directly, without computing (or using) the interpolating cubic spline218 polynomial.219 220 This routine is here mostly for a sanity check on the psLib function221 evalSpline() which computes the interpolated value based on the cubic spline222 polynomials which are stored in psSpline1D.223 224 XXX: This is F32 only225 226 XXX: spline->knots must be psF32227 228 XXXX: Remove this for next code shipment.229 *****************************************************************************/230 /*231 psF32 p_psNRSpline1DEval(psSpline1D *spline,232 const psVector* x,233 const psVector* y,234 psF32 X)235 {236 PS_ASSERT_PTR_NON_NULL(spline, NAN);237 PS_ASSERT_INT_NONNEGATIVE(spline->n, NAN);238 PS_ASSERT_VECTOR_NON_NULL(spline->domains, NAN);239 PS_ASSERT_PTR_NON_NULL(spline->p_psDeriv2, NAN);240 PS_ASSERT_VECTOR_NON_NULL(x, NAN);241 PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F32, NAN);242 PS_ASSERT_VECTOR_NON_NULL(y, NAN);243 PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F32, NAN);244 PS_ASSERT_VECTOR_TYPE(spline->knots, PS_TYPE_F32, NULL);245 246 psS32 n;247 psS32 klo;248 psS32 khi;249 psF32 H;250 psF32 A;251 psF32 B;252 psF32 C;253 psF32 D;254 psF32 Y;255 256 n = spline->n;257 klo = p_psVectorBinDisect32(spline->knots->data.F32, (spline->n)+1, X);258 if (klo < 0) {259 psLogMsg(__func__, PS_LOG_WARN,260 "WARNING: psMinimize.c: p_psNRSpline1DEval(): p_psVectorBinDisect32 returned an error (%d).\n", klo);261 return(NAN);262 }263 khi = klo + 1;264 H = spline->knots->data.F32[khi] - spline->knots->data.F32[klo];265 A = (spline->knots->data.F32[khi] - X) / H;266 B = (X - spline->knots->data.F32[klo]) / H;267 C = ((A*A*A)-A) * (H*H/6.0);268 D = ((B*B*B)-B) * (H*H/6.0);269 270 Y = (A * y->data.F32[klo]) +271 (B * y->data.F32[khi]) +272 (C * (spline->p_psDeriv2)[klo]) +273 (D * (spline->p_psDeriv2)[khi]);274 275 return(Y);276 }277 */278 /*****************************************************************************/279 /* FUNCTION IMPLEMENTATION - PUBLIC */280 /*****************************************************************************/281 282 /*****************************************************************************283 psVectorFitSpline1D(): given a psSpline1D data structure and a set of x/y284 vectors, this routine generates the linear or cublic splines which satisfy285 those data points.286 287 The formula for calculating the spline polynomials is derived from Numerical288 Recipes in C. The basic idea is that the polynomial is289 (1) y = (A * y[0]) +290 (2) (B * y[1]) +291 (3) ((((A*A*A)-A) * mySpline->p_psDeriv2[0]) * H^2)/6.0 +292 (4) ((((B*B*B)-B) * mySpline->p_psDeriv2[1]) * H^2)/6.0293 Where:294 H = x[1]-x[0]295 A = (x[1]-x)/H296 B = (x-x[0])/H297 The bulk of the code in this routine is the expansion of the above equation298 into a polynomial in terms of x, and then saving the coefficients of the299 powers of x in the spline polynomials. This gets pretty complicated.300 301 XXX: usage of yErr is not specified in IfA documentation.302 303 XXX: Is the x argument redundant? What do we do if the x argument is304 supplied, but does not equal the knots specified in mySpline?305 306 XXX: can psSpline be NULL?307 308 XXX: reimplement this assuming that mySpline is NULL?309 310 XXX: What happens if X is NULL, then an index vector is generated for X, but311 that index vector lies outside the range vectors in mySpline?312 313 XXX: Assumes mySpline->knots is psF32. Must add psU32 and psF64.314 *****************************************************************************/315 psSpline1D *psVectorFitSpline1D(psSpline1D *mySpline, ///< The spline which will be generated.316 const psVector* x, ///< Ordinates (or NULL to just use the indices)317 const psVector* y, ///< Coordinates318 const psVector* yErr) ///< Errors in coordinates, or NULL319 {320 PS_ASSERT_VECTOR_NON_NULL(y, NULL);321 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(y, NULL);322 if (mySpline != NULL) {323 PS_ASSERT_VECTOR_TYPE(mySpline->knots, PS_TYPE_F32, NULL);324 }325 psTrace(".psLib.dataManip.psVectorFitSpline1D", 4,326 "---- psVectorFitSpline1D() begin ----\n");327 psS32 numSplines = (y->n)-1;328 psF32 tmp;329 psF32 H;330 psS32 i;331 psF32 slope;332 psVector *x32 = NULL;333 psVector *y32 = NULL;334 psVector *yErr32 = NULL;335 static psVector *x32Static = NULL;336 static psVector *y32Static = NULL;337 static psVector *yErr32Static = NULL;338 339 PS_VECTOR_CONVERT_F64_TO_F32_STATIC(y, y32, y32Static);340 341 // If yErr==NULL, set all errors equal.342 if (yErr == NULL) {343 PS_VECTOR_GEN_YERR_STATIC_F32(yErr32Static, y->n);344 yErr32 = yErr32Static;345 } else {346 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(yErr, NULL);347 PS_VECTOR_CONVERT_F64_TO_F32_STATIC(yErr, yErr32, yErr32Static);348 }349 350 // If x==NULL, create an x32 vector with x values set to (0:n).351 if (x == NULL) {352 PS_VECTOR_GEN_X_INDEX_STATIC_F32(x32Static, y->n);353 x32 = x32Static;354 } else {355 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(x, NULL);356 PS_VECTOR_CONVERT_F64_TO_F32_STATIC(x, x32, x32Static);357 }358 PS_ASSERT_VECTORS_SIZE_EQUAL(x32, y32, NULL);359 PS_ASSERT_VECTORS_SIZE_EQUAL(yErr32, y32, NULL);360 361 /*362 XXX:363 This can not be implemented until SDR states what order spline should be364 created.365 Should we error if mySpline is not NULL?366 Should we error if mySPline is not NULL?367 */368 if (mySpline == NULL) {369 mySpline = psSpline1DAllocGeneric(x32, 3);370 }371 PS_ASSERT_PTR_NON_NULL(mySpline, NULL);372 PS_ASSERT_INT_NONNEGATIVE(mySpline->n, NULL);373 374 if (y32->n != (1 + mySpline->n)) {375 psError(PS_ERR_BAD_PARAMETER_SIZE, true,376 "data size / spline size mismatch (%d %d)\n",377 y32->n, mySpline->n);378 return(NULL);379 }380 381 // If these are linear splines, which means their polynomials will have382 // two coefficients, then we do the simple calculation.383 if (2 == (mySpline->spline[0])->n) {384 for (i=0;i<mySpline->n;i++) {385 slope = (y32->data.F32[i+1] - y32->data.F32[i]) /386 (mySpline->knots->data.F32[i+1] - mySpline->knots->data.F32[i]);387 (mySpline->spline[i])->coeff[0] = y32->data.F32[i] -388 (slope * mySpline->knots->data.F32[i]);389 390 (mySpline->spline[i])->coeff[1] = slope;391 psTrace(".psLib.dataManip.psMinimize.psVectorFitSpline1D", 4,392 "---- mySpline %d coeffs are (%f, %f)\n", i,393 (mySpline->spline[i])->coeff[0],394 (mySpline->spline[i])->coeff[1]);395 }396 psTrace(".psLib.dataManip.psMinimize.psVectorFitSpline1D", 4,397 "---- Exiting psVectorFitSpline1D()()\n");398 return((psSpline1D *) mySpline);399 }400 401 // Check if these are cubic splines (n==4). If not, psError.402 if (4 != (mySpline->spline[0])->n) {403 psError(PS_ERR_BAD_PARAMETER_SIZE, true,404 "Don't know how to generate %d-order splines.",405 (mySpline->spline[0])->n-1);406 return(NULL);407 }408 409 // If we get here, then we know these are cubic splines. We first410 // generate the second derivatives at each data point.411 mySpline->p_psDeriv2 = calculateSecondDerivs(x32, y32);412 for (i=0;i<y32->n;i++)413 psTrace(".psLib.dataManip.psVectorFitSpline1D", 6,414 "Second deriv[%d] is %f\n", i, mySpline->p_psDeriv2[i]);415 416 // We generate the coefficients of the spline polynomials. I can't417 // concisely explain how this code works. See above function comments418 // and Numerical Recipes in C.419 for (i=0;i<numSplines;i++) {420 H = x32->data.F32[i+1] - x32->data.F32[i];421 psTrace(".psLib.dataManip.psVectorFitSpline1D", 4,422 "x data (%f - %f) (%f)\n",423 x32->data.F32[i],424 x32->data.F32[i+1], H);425 //426 // ******** Calculate 0-order term ********427 //428 // From (1)429 (mySpline->spline[i])->coeff[0] = (y32->data.F32[i] * x32->data.F32[i+1]/H);430 // From (2)431 ((mySpline->spline[i])->coeff[0])-= ((y32->data.F32[i+1] * x32->data.F32[i])/H);432 // From (3)433 tmp = (x32->data.F32[i+1] * x32->data.F32[i+1] * x32->data.F32[i+1]) / (H * H * H);434 tmp-= (x32->data.F32[i+1] / H);435 tmp*= (mySpline->p_psDeriv2)[i] * H * H / 6.0;436 ((mySpline->spline[i])->coeff[0])+= tmp;437 // From (4)438 tmp = -(x32->data.F32[i] * x32->data.F32[i] * x32->data.F32[i]) / (H * H * H);439 tmp+= (x32->data.F32[i] / H);440 tmp*= (mySpline->p_psDeriv2)[i+1] * H * H / 6.0;441 ((mySpline->spline[i])->coeff[0])+= tmp;442 443 //444 // ******** Calculate 1-order term ********445 //446 // From (1)447 (mySpline->spline[i])->coeff[1] = -(y32->data.F32[i]) / H;448 // From (2)449 ((mySpline->spline[i])->coeff[1])+= (y32->data.F32[i+1] / H);450 // From (3)451 tmp = -3.0 * (x32->data.F32[i+1] * x32->data.F32[i+1]) / (H * H * H);452 tmp+= (1.0 / H);453 tmp*= ((mySpline->p_psDeriv2)[i]) * H * H / 6.0;454 ((mySpline->spline[i])->coeff[1])+= tmp;455 // From (4)456 tmp = 3.0 * (x32->data.F32[i] * x32->data.F32[i]) / (H * H * H);457 tmp-= (1.0 / H);458 tmp*= ((mySpline->p_psDeriv2)[i+1]) * H * H / 6.0;459 ((mySpline->spline[i])->coeff[1])+= tmp;460 461 //462 // ******** Calculate 2-order term ********463 //464 // From (3)465 (mySpline->spline[i])->coeff[2] = ((mySpline->p_psDeriv2)[i]) * 3.0 * x32->data.F32[i+1] / (6.0 * H);466 // From (4)467 ((mySpline->spline[i])->coeff[2])-= (((mySpline->p_psDeriv2)[i+1]) * 3.0 * x32->data.F32[i] / (6.0 * H));468 469 //470 // ******** Calculate 3-order term ********471 //472 // From (3)473 (mySpline->spline[i])->coeff[3] = -((mySpline->p_psDeriv2)[i]) / (6.0 * H);474 // From (4)475 ((mySpline->spline[i])->coeff[3])+= ((mySpline->p_psDeriv2)[i+1]) / (6.0 * H);476 477 psTrace(".psLib.dataManip.psVectorFitSpline1D", 6,478 "(mySpline->spline[%d])->coeff[0] is %f\n", i, (mySpline->spline[i])->coeff[0]);479 psTrace(".psLib.dataManip.psVectorFitSpline1D", 6,480 "(mySpline->spline[%d])->coeff[1] is %f\n", i, (mySpline->spline[i])->coeff[1]);481 psTrace(".psLib.dataManip.psVectorFitSpline1D", 6,482 "(mySpline->spline[%d])->coeff[2] is %f\n", i, (mySpline->spline[i])->coeff[2]);483 psTrace(".psLib.dataManip.psVectorFitSpline1D", 6,484 "(mySpline->spline[%d])->coeff[3] is %f\n", i, (mySpline->spline[i])->coeff[3]);485 486 }487 488 psTrace(".psLib.dataManip.psVectorFitSpline1D", 4,489 "---- psVectorFitSpline1D() end ----\n");490 return(mySpline);491 }492 493 494 495 496 497 498 499 500 501 /*****************************************************************************502 psVectorFitSpline1DNEW(): given a psSpline1D data structure and a set of x/y503 504 xF32 and yF32 are internal psVectors which are used to hold the psF32 versions505 of the input data, if necessary. xPtr and yPtr are pointers to either xF32 or506 the x argument. All computation is done on xPtr and yPtr. xF32 and yF32 will507 simply be psFree() at the end.508 509 XXX: nKnots makes no sense. This number is always equal to the size of the x510 an y vectors.511 512 XXX: How do we specify the spline order? For now, order=3.513 *****************************************************************************/514 #define PS_XXX_SPLINE_ORDER 3515 psSpline1D *psVectorFitSpline1DNEW(const psVector* x, ///< Ordinates (or NULL to just use the indices)516 const psVector* y, ///< Coordinates517 int nKnots)518 {519 psTrace(".psLib.dataManip.psVectorFitSpline1D", 4, "---- psVectorFitSpline1DNEW() begin ----\n");520 PS_ASSERT_VECTOR_NON_NULL(y, NULL);521 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(y, NULL);522 // PS_ASSERT_INT_EQUAL(y->n, nKnots);523 524 //525 // The following code ensures that xPtr points to a psF32 version of the526 // ordinate data.527 //528 psVector *xF32 = NULL;529 psVector *xPtr = NULL;530 if (x != NULL) {531 PS_ASSERT_VECTORS_SIZE_EQUAL(x, y, NULL);532 if (PS_TYPE_F64 == x->type.type) {533 xF32 = psVectorAlloc(y->n, PS_TYPE_F32);534 for (psS32 i = 0 ; i < x->n ; i++) {535 xF32->data.F32[i] = (psF32) x->data.F64[i];536 }537 xPtr = xF32;538 } else if (PS_TYPE_F32 == x->type.type) {539 xPtr = (psVector *) x;540 } else {541 printf("XXX: Gen Error message: x is wrong type.\n");542 return(NULL);543 }544 } else {545 // If x==NULL, create an x32 vector with x values set to (0:n).546 xF32 = psVectorAlloc(y->n, PS_TYPE_F32);547 for (psS32 i = 0 ; i < x->n ; i++) {548 xF32->data.F32[i] = (psF32) i;549 }550 xPtr = xF32;551 }552 553 //554 // If y is of type psF64, then create a new vector yF32 and convert the555 // y elements. Regardless of y's type, we create a yPtr which will be556 // used in the remainder of this function.557 //558 psVector *yF32 = NULL;559 psVector *yPtr = NULL;560 if (PS_TYPE_F64 == y->type.type) {561 yF32 = psVectorAlloc(y->n, PS_TYPE_F32);562 for (psS32 i = 0 ; i < y->n ; i++) {563 yF32->data.F32[i] = (psF32) y->data.F64[i];564 }565 yPtr = yF32;566 } else {567 yPtr = (psVector *) y;568 }569 570 psSpline1D *mySpline = psSpline1DAllocGeneric(xPtr, PS_XXX_SPLINE_ORDER);571 572 psS32 numSplines = nKnots - 1;573 psF32 tmp;574 psF32 H;575 psS32 i;576 psF32 slope;577 // XXX: get rid of x32 and y32 (this is from old code)578 psVector *x32 = xPtr;579 psVector *y32 = yPtr;580 581 // If these are linear splines, which means their polynomials will have582 // two coefficients, then we do the simple calculation.583 if (1 == PS_XXX_SPLINE_ORDER) {584 for (i=0;i<mySpline->n;i++) {585 slope = (y32->data.F32[i+1] - y32->data.F32[i]) /586 (mySpline->knots->data.F32[i+1] - mySpline->knots->data.F32[i]);587 (mySpline->spline[i])->coeff[0] = y32->data.F32[i] -588 (slope * mySpline->knots->data.F32[i]);589 590 (mySpline->spline[i])->coeff[1] = slope;591 psTrace(".psLib.dataManip.psMinimize.psVectorFitSpline1D", 4,592 "---- mySpline %d coeffs are (%f, %f)\n", i,593 (mySpline->spline[i])->coeff[0],594 (mySpline->spline[i])->coeff[1]);595 }596 psTrace(".psLib.dataManip.psMinimize.psVectorFitSpline1D", 4,597 "---- Exiting psVectorFitSpline1D()()\n");598 return((psSpline1D *) mySpline);599 }600 601 //602 // Check if these are cubic splines (n==4). If not, psError.603 //604 if (3 != PS_XXX_SPLINE_ORDER) {605 psError(PS_ERR_BAD_PARAMETER_SIZE, true,606 "Don't know how to generate %d-order splines.", PS_XXX_SPLINE_ORDER);607 return(NULL);608 }609 610 //611 // If we get here, then we know these are cubic splines. We first612 // generate the second derivatives at each data point.613 //614 mySpline->p_psDeriv2 = calculateSecondDerivs(x32, y32);615 for (i=0;i<y32->n;i++)616 psTrace(".psLib.dataManip.psVectorFitSpline1D", 6,617 "Second deriv[%d] is %f\n", i, mySpline->p_psDeriv2[i]);618 619 //620 // We generate the coefficients of the spline polynomials. I can't621 // concisely explain how this code works. See above function comments622 // and Numerical Recipes in C.623 //624 for (i=0;i<numSplines;i++) {625 H = x32->data.F32[i+1] - x32->data.F32[i];626 psTrace(".psLib.dataManip.psVectorFitSpline1D", 4,627 "x data (%f - %f) (%f)\n",628 x32->data.F32[i],629 x32->data.F32[i+1], H);630 //631 // ******** Calculate 0-order term ********632 //633 // From (1)634 (mySpline->spline[i])->coeff[0] = (y32->data.F32[i] * x32->data.F32[i+1]/H);635 // From (2)636 ((mySpline->spline[i])->coeff[0])-= ((y32->data.F32[i+1] * x32->data.F32[i])/H);637 // From (3)638 tmp = (x32->data.F32[i+1] * x32->data.F32[i+1] * x32->data.F32[i+1]) / (H * H * H);639 tmp-= (x32->data.F32[i+1] / H);640 tmp*= (mySpline->p_psDeriv2)[i] * H * H / 6.0;641 ((mySpline->spline[i])->coeff[0])+= tmp;642 // From (4)643 tmp = -(x32->data.F32[i] * x32->data.F32[i] * x32->data.F32[i]) / (H * H * H);644 tmp+= (x32->data.F32[i] / H);645 tmp*= (mySpline->p_psDeriv2)[i+1] * H * H / 6.0;646 ((mySpline->spline[i])->coeff[0])+= tmp;647 648 //649 // ******** Calculate 1-order term ********650 //651 // From (1)652 (mySpline->spline[i])->coeff[1] = -(y32->data.F32[i]) / H;653 // From (2)654 ((mySpline->spline[i])->coeff[1])+= (y32->data.F32[i+1] / H);655 // From (3)656 tmp = -3.0 * (x32->data.F32[i+1] * x32->data.F32[i+1]) / (H * H * H);657 tmp+= (1.0 / H);658 tmp*= ((mySpline->p_psDeriv2)[i]) * H * H / 6.0;659 ((mySpline->spline[i])->coeff[1])+= tmp;660 // From (4)661 tmp = 3.0 * (x32->data.F32[i] * x32->data.F32[i]) / (H * H * H);662 tmp-= (1.0 / H);663 tmp*= ((mySpline->p_psDeriv2)[i+1]) * H * H / 6.0;664 ((mySpline->spline[i])->coeff[1])+= tmp;665 666 //667 // ******** Calculate 2-order term ********668 //669 // From (3)670 (mySpline->spline[i])->coeff[2] = ((mySpline->p_psDeriv2)[i]) * 3.0 * x32->data.F32[i+1] / (6.0 * H);671 // From (4)672 ((mySpline->spline[i])->coeff[2])-= (((mySpline->p_psDeriv2)[i+1]) * 3.0 * x32->data.F32[i] / (6.0 * H));673 674 //675 // ******** Calculate 3-order term ********676 //677 // From (3)678 (mySpline->spline[i])->coeff[3] = -((mySpline->p_psDeriv2)[i]) / (6.0 * H);679 // From (4)680 ((mySpline->spline[i])->coeff[3])+= ((mySpline->p_psDeriv2)[i+1]) / (6.0 * H);681 682 psTrace(".psLib.dataManip.psVectorFitSpline1D", 6,683 "(mySpline->spline[%d])->coeff[0] is %f\n", i, (mySpline->spline[i])->coeff[0]);684 psTrace(".psLib.dataManip.psVectorFitSpline1D", 6,685 "(mySpline->spline[%d])->coeff[1] is %f\n", i, (mySpline->spline[i])->coeff[1]);686 psTrace(".psLib.dataManip.psVectorFitSpline1D", 6,687 "(mySpline->spline[%d])->coeff[2] is %f\n", i, (mySpline->spline[i])->coeff[2]);688 psTrace(".psLib.dataManip.psVectorFitSpline1D", 6,689 "(mySpline->spline[%d])->coeff[3] is %f\n", i, (mySpline->spline[i])->coeff[3]);690 691 }692 693 psFree(xF32);694 psFree(yF32);695 696 psTrace(".psLib.dataManip.psVectorFitSpline1D", 4,697 "---- psVectorFitSpline1D() end ----\n");698 699 return(mySpline);700 }701 702 703 704 705 //XXX: What's this for?706 psF64 p_psImageGetElementF64(psImage *a, int i, int j);707 122 /****************************************************************************** 708 123 psMinimizeLMChi2(): This routine will take an procedure which calculates … … 717 132 will have to convert all F32 input vectors to F64 regardless. So, 718 133 the F64 port might be. 134 135 XXX: Change the whole thing to F64, if input data is F32, convert it. 719 136 *****************************************************************************/ 720 137 psBool psMinimizeLMChi2(psMinimization *min, … … 816 233 if (psTraceGetLevel (".psLib.dataManip.psMinimizeLMChi2") == 4) { 817 234 // XXX: Where is this? 818 // p_psVectorPrintRow (psTraceGetDestination(), Params, "params guess");235 // p_psVectorPrintRow (psTraceGetDestination(), Params, "params guess"); 819 236 } 820 237 # endif /* PS_NO_TRACE */ … … 876 293 877 294 // XXX EAM: this needs to respect the mask on params 878 // XXX EAM: check not NULL on alpha, beta, params879 295 // alpha, beta, params are already allocated 880 296 psF64 p_psMinLM_SetABX (psImage *alpha, … … 887 303 psMinimizeLMChi2Func func) 888 304 { 305 PS_ASSERT_IMAGE_NON_NULL(alpha, NAN); 306 PS_ASSERT_VECTOR_NON_NULL(beta, NAN); 307 PS_ASSERT_VECTOR_NON_NULL(params, NAN); 308 PS_ASSERT_VECTOR_NON_NULL(x, NAN); 309 PS_ASSERT_VECTOR_NON_NULL(y, NAN); 310 PS_ASSERT_VECTOR_NON_NULL(dy, NAN); 889 311 890 312 psF64 chisq; … … 1011 433 } 1012 434 1013 // XXX: put this in constants.h1014 # define PS_SWAP(X,Y) {double tmp=(X); (X) = (Y); (Y) = tmp;}1015 1016 435 // XXX EAM : temporary gauss-jordan solver based on gene's 1017 436 // version based on the Numerical Recipes version … … 1044 463 for (j = 0; j < Nx; j++) { 1045 464 if (!isfinite(matrix[i][j])) { 1046 // XXX EAM: this should use the psError stack 1047 fprintf (stderr, "GAUSSJ: NaN\n"); 465 psError(PS_ERR_UNKNOWN, false, "Input matrix contains NaNs.\n"); 1048 466 goto fescape; 1049 467 } … … 1058 476 } else { 1059 477 if (ipiv[k] > 1) { 1060 // XXX EAM: this should use the psError stack 1061 fprintf (stderr, "GAUSSJ: Singular Matrix! (1)\n"); 478 psError(PS_ERR_UNKNOWN, false, "Singular Matrix (1).\n"); 1062 479 goto fescape; 1063 480 } … … 1076 493 indxc[i] = icol; 1077 494 if (matrix[icol][icol] == 0.0) { 1078 // XXX EAM: this should use the psError stack 1079 fprintf (stderr, "GAUSSJ: Singular Matrix! (2)\n"); 495 psError(PS_ERR_UNKNOWN, false, "Singular Matrix (2).\n"); 1080 496 goto fescape; 1081 497 } … … 1118 534 } 1119 535 1120 /******************************************************************************1121 vectorFitPolynomial1DCheb(): This routine will fit a Chebyshev polynomial of1122 degree myPoly to the data points (x, y) and return the coefficients of that1123 polynomial.1124 1125 XXX: yErr is currently ignored.1126 *****************************************************************************/1127 static psPolynomial1D *vectorFitPolynomial1DCheby(psPolynomial1D* myPoly,1128 const psVector* x,1129 const psVector* y,1130 const psVector* yErr)1131 {1132 psS32 j;1133 psS32 k;1134 psS32 n = x->n;1135 psF64 fac;1136 psF64 sum;1137 PS_VECTOR_GEN_STATIC_RECYCLED(f, n, PS_TYPE_F64);1138 psScalar *fScalar;1139 psScalar tmpScalar;1140 tmpScalar.type.type = PS_TYPE_F64;1141 1142 // XXX: These assignments appear too simple to warrant code and1143 // variable declarations. I retain them here to maintain coherence1144 // with the NR code.1145 psF64 min = -1.0;1146 psF64 max = 1.0;1147 psF64 bma = 0.5 * (max-min); // 11148 psF64 bpa = 0.5 * (max+min); // 01149 1150 // In this loop, we first calculate the values of X for which the1151 // Chebyshev polynomials are zero (see NR, section 5.4). Then we1152 // calculate the value of the function we are fitting the Chebyshev1153 // polynomials to at those values of X. This is a bit tricky since1154 // we don't know that function. So, we instead do 3-order LaGrange1155 // interpolation at the point X for the psVectors x,y for which we1156 // are fitting this ChebyShev polynomial to.1157 1158 for (psS32 i=0;i<n;i++) {1159 // NR 5.8.41160 psF64 Y = cos(M_PI * (0.5 + ((psF32) i)) / ((psF32) n));1161 psF64 X = (Y + bma + bpa) - 1.0;1162 tmpScalar.data.F64 = X;1163 1164 // We interpolate against are tabluated x,y vectors to determine the1165 // function value at X.1166 fScalar = p_psVectorInterpolate((psVector *) x,1167 (psVector *) y,1168 3,1169 &tmpScalar);1170 1171 f->data.F64[i] = fScalar->data.F64;1172 psFree(fScalar);1173 1174 psTrace(".psLib.dataManip.vectorFitPolynomial1DCheby", 6,1175 "(x, X, y, f(X)) is (%f, %f, %f, %f)\n",1176 x->data.F64[i], X, y->data.F64[i], f->data.F64[i]);1177 }1178 1179 // We have the values for f() at the zero points, we now calculate the1180 // coefficients of the Chebyshev polynomial: NR 5.8.7.1181 1182 fac = 2.0/((psF32) n);1183 // XXX: is this loop bound correct?1184 for (j=0;j<myPoly->n;j++) {1185 sum = 0.0;1186 for (k=0;k<n;k++) {1187 sum+= f->data.F64[k] *1188 cos(M_PI * ((psF32) j) * (0.5 + ((psF32) k)) / ((psF32) n));1189 }1190 1191 myPoly->coeff[j] = fac * sum;1192 }1193 1194 return(myPoly);1195 }1196 1197 /******************************************************************************1198 VectorFitPolynomial1DOrd(): This routine will fit an ordinary polynomial of1199 degree myPoly to the data points (x, y) and return the coefficients of that1200 polynomial.1201 1202 XXX: Use private name?1203 XXX: Use recycled vectors.1204 *****************************************************************************/1205 static psPolynomial1D* vectorFitPolynomial1DOrd(psPolynomial1D* myPoly,1206 const psVector* x,1207 const psVector* y,1208 const psVector* yErr)1209 {1210 psS32 polyOrder = myPoly->n;1211 psImage* A = NULL;1212 psImage* ALUD = NULL;1213 psVector* B = NULL;1214 psVector* outPerm = NULL;1215 psVector* X = NULL; // NOTE: do we need this?1216 psVector* coeffs = NULL;1217 psS32 i = 0;1218 psS32 j = 0;1219 psS32 k = 0;1220 psVector* xSums = NULL;1221 1222 psTrace(".psLib.dataManip.vectorFitPolynomial1DOrd", 4,1223 "---- vectorFitPolynomial1DOrd() begin ----\n");1224 // printf("VectorFitPolynomial1D()\n");1225 // for (i=0;i<x->n;i++) {1226 // printf("(x, y, yErr) is (%f, %f, %f)\n", x->data.F64[i], y->data.F64[i], yErr->data.F64[i]);1227 // }1228 1229 A = psImageAlloc(polyOrder, polyOrder, PS_TYPE_F64);1230 ALUD = psImageAlloc(polyOrder, polyOrder, PS_TYPE_F64);1231 1232 B = psVectorAlloc(polyOrder, PS_TYPE_F64);1233 coeffs = psVectorAlloc(polyOrder, PS_TYPE_F64);1234 X = psVectorAlloc(x->n, PS_TYPE_F64);1235 xSums = psVectorAlloc(1 + 2 * polyOrder, PS_TYPE_F64);1236 1237 // Initialize data structures.1238 for (i = 0; i < polyOrder; i++) {1239 B->data.F64[i] = 0.0;1240 coeffs->data.F64[i] = 0.0;1241 for (j = 0; j < polyOrder; j++) {1242 A->data.F64[i][j] = 0.0;1243 ALUD->data.F64[i][j] = 0.0;1244 }1245 }1246 for (i = 0; i < X->n; i++) {1247 X->data.F64[i] = x->data.F64[i];1248 }1249 1250 // Build the B and A data structs.1251 if (yErr == NULL) {1252 for (i = 0; i < X->n; i++) {1253 buildSums1D(X->data.F64[i], 2 * polyOrder, xSums);1254 1255 for (k = 0; k < polyOrder; k++) {1256 B->data.F64[k] += y->data.F64[i] * xSums->data.F64[k];1257 }1258 1259 for (k = 0; k < polyOrder; k++) {1260 for (j = 0; j < polyOrder; j++) {1261 A->data.F64[k][j] += xSums->data.F64[k + j];1262 }1263 }1264 }1265 } else {1266 for (i = 0; i < X->n; i++) {1267 buildSums1D(X->data.F64[i], 2 * polyOrder, xSums);1268 1269 for (k = 0; k < polyOrder; k++) {1270 B->data.F64[k] += y->data.F64[i] * xSums->data.F64[k] /1271 yErr->data.F64[i];1272 }1273 1274 for (k = 0; k < polyOrder; k++) {1275 for (j = 0; j < polyOrder; j++) {1276 A->data.F64[k][j] += xSums->data.F64[k + j] /1277 yErr->data.F64[i];1278 }1279 }1280 }1281 }1282 1283 // XXX: How do we know if these routines were successful?1284 ALUD = psMatrixLUD(ALUD, &outPerm, A);1285 coeffs = psMatrixLUSolve(coeffs, ALUD, B, outPerm);1286 1287 for (k = 0; k < polyOrder; k++) {1288 myPoly->coeff[k] = coeffs->data.F64[k];1289 // printf("myPoly->coeff[%d] is %f\n", k, myPoly->coeff[k]);1290 }1291 1292 psFree(A);1293 psFree(ALUD);1294 psFree(B);1295 psFree(coeffs);1296 psFree(X);1297 psFree(outPerm);1298 psFree(xSums);1299 1300 psTrace(".psLib.dataManip.vectorFitPolynomial1DOrd", 4,1301 "---- vectorFitPolynomial1DOrd() begin ----\n");1302 return (myPoly);1303 }1304 1305 /******************************************************************************1306 psVectorFitPolynomial1D(): This routine must fit a polynomial of degree1307 myPoly to the data points (x, y) and return the coefficients of that1308 polynomial.1309 1310 XXX: type F32 is done via vector conversion only.1311 1312 XXX: Get rid of this. Use new argument list.1313 *****************************************************************************/1314 psPolynomial1D* psVectorFitPolynomial1D(psPolynomial1D* poly,1315 const psVector* x,1316 const psVector* y,1317 const psVector* yErr)1318 {1319 PS_ASSERT_POLY_NON_NULL(poly, NULL);1320 PS_ASSERT_INT_NONNEGATIVE(poly->n, NULL);1321 PS_ASSERT_VECTOR_NON_NULL(y, NULL);1322 PS_ASSERT_VECTOR_NON_EMPTY(y, NULL);1323 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(y, NULL);1324 1325 psS32 i;1326 psVector *x64 = NULL;1327 psVector *y64 = NULL;1328 psVector *yErr64 = NULL;1329 static psVector *x64Static = NULL;1330 static psVector *y64Static = NULL;1331 static psVector *yErr64Static = NULL;1332 1333 PS_VECTOR_CONVERT_F32_TO_F64_STATIC(y, y64, y64Static);1334 // If yErr==NULL, set all errors equal.1335 if (yErr == NULL) {1336 PS_VECTOR_GEN_YERR_STATIC_F64(yErr64Static, y->n);1337 yErr64 = yErr64Static;1338 } else {1339 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(yErr, NULL);1340 PS_VECTOR_CONVERT_F32_TO_F64_STATIC(yErr, yErr64, yErr64Static);1341 }1342 1343 // If x==NULL, create an x64 vector with x values set to (0:n).1344 if (x == NULL) {1345 PS_VECTOR_GEN_X_INDEX_STATIC_F64(x64Static, y->n);1346 if (poly->type == PS_POLYNOMIAL_CHEB) {1347 p_psNormalizeVectorRangeF64(x64Static, -1.0, 1.0);1348 }1349 x64 = x64Static;1350 } else {1351 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(x, NULL);1352 PS_VECTOR_CONVERT_F32_TO_F64_STATIC(x, x64, x64Static);1353 if (poly->type == PS_POLYNOMIAL_CHEB) {1354 p_psNormalizeVectorRangeF64(x64, -1.0, 1.0);1355 }1356 }1357 PS_ASSERT_VECTORS_SIZE_EQUAL(x64, y64, NULL);1358 PS_ASSERT_VECTORS_SIZE_EQUAL(yErr64, y64, NULL);1359 1360 // Call the appropriate vector fitting routine.1361 psPolynomial1D *rc = NULL;1362 if (poly->type == PS_POLYNOMIAL_CHEB) {1363 rc = vectorFitPolynomial1DCheby(poly, x64, y64, yErr64);1364 } else if (poly->type == PS_POLYNOMIAL_ORD) {1365 rc = vectorFitPolynomial1DOrd(poly, x64, y64, yErr64);1366 } else {1367 psError(PS_ERR_BAD_PARAMETER_VALUE, true,1368 "unknown polynomial type.\n");1369 return(NULL);1370 }1371 if (rc == NULL) {1372 psError(PS_ERR_UNKNOWN, true, "Could not fit a polynomial to the data. Returning NULL.\n");1373 return(NULL);1374 }1375 1376 return(poly);1377 }1378 1379 536 static void minimizationFree(psMinimization *min) 1380 537 { 1381 // There are no n dynamicallocated items538 // There are no dynamically allocated items 1382 539 } 1383 540 … … 1437 594 1438 595 /****************************************************************************** 596 ****************************************************************************** 597 Powell routines. 598 ****************************************************************************** 599 *****************************************************************************/ 600 601 /****************************************************************************** 1439 602 p_psDetermineBracket(): This routine takes as input an arbitrary function, 1440 603 and the parameter to vary, and the line along which it must vary. This … … 1446 609 Algorithm: 1447 610 1448 XXX completely ad hoc: 1449 start with the user-supplied starting parameter and 611 XXX completely ad hoc: start with the user-supplied starting parameter and 1450 612 call that b. Calculate a/c as a fractional amount smaller/larger than b. 1451 613 Repeat this process until a local minimum is found. 1452 614 1453 XXX: 1454 new algorithm: 1455 start at x=0, expand in one direction until the function 615 XXX: new algorithm: start at x=0, expand in one direction until the function 1456 616 decreases. Then you have two points in the bracket. Keep going until it 1457 617 increases, or x is too large. If thst does not work, expand in the other 1458 618 direction. 1459 619 1460 XXX: 1461 This is F32 only.620 XXX: This is F32 only. Must add F64 support (actually, make the defaults F64, 621 and convert F32 vectors to F64). 1462 622 1463 XXX: 1464 output bracket vector should be an input as well. 623 XXX: output bracket vector should be an input as well. 1465 624 *****************************************************************************/ 1466 625 psVector *p_psDetermineBracket(psVector *params, … … 1716 875 XXX: This routine is not very efficient in terms of total evaluations of the 1717 876 function. 1718 XXX: This is F32 only 877 XXX: This is F32 only (make it F64). 1719 878 XXX: Since this is an internal function, many of the parameter checks are 1720 879 redundant. … … 1871 1030 1872 1031 XXX: The SDR is silent about data types. F32 is implemented here. 1873 1874 XXX: Check for F32 types? 1032 Reimplement in F64, convert F32 vectors to F64. 1875 1033 *****************************************************************************/ 1876 1034 #define PS_MINIMIZE_POWELL_LINEMIN_MAX_ITERATIONS 20 … … 2083 1241 This functions uses global variables to receive the function pointer, the 2084 1242 data values, and the data errors. 2085 XXX: This is F32 only 1243 XXX: This is F32 only. Must implement F64. 2086 1244 *****************************************************************************/ 2087 1245 static psF32 myPowellChi2Func(const psVector *params, … … 2149 1307 /****************************************************************************** 2150 1308 ****************************************************************************** 2151 ****************************************************************************** 2152 ****************************************************************************** 2153 EAM Code: 2154 ****************************************************************************** 2155 ****************************************************************************** 1309 Analytical 1-D fitting routines. 2156 1310 ****************************************************************************** 2157 1311 *****************************************************************************/ 2158 2159 static psVector *EAMBuildSums1D( 1312 // XXX: Make this a general type conversion macro, or function 1313 #define PS_VECTOR_GEN_F64_FROM_F32(VECF64, VECF32) \ 1314 VECF64 = psVectorAlloc(VECF32->n, PS_TYPE_F64); \ 1315 for (psS32 i = 0 ; i < VECF32->n ; i++) { \ 1316 VECF64->data.F64[i] = (psF64) VECF32->data.F32[i]; \ 1317 } \ 1318 1319 #define PS_VECTOR_GEN_CHEBY_INDEX(VECF64, SIZE) \ 1320 VECF64 = psVectorAlloc(SIZE, PS_TYPE_F64); \ 1321 for (psS32 i = 0 ; i < SIZE ; i++) { \ 1322 VECF64->data.F64[i] = ((2.0 / ((psF64) (SIZE - 1))) * ((psF64) i)) - 1.0; \ 1323 }\ 1324 /****************************************************************************** 1325 BuildSums1D(sums, x, polyOrder, sums): this routine calculates the powers of 1326 input parameter "x" between 0 and input parameter nTerms*2. The result is 1327 returned as a psVector sums. 1328 *****************************************************************************/ 1329 static psVector *BuildSums1D( 2160 1330 psVector* sums, 2161 1331 psF64 x, … … 2166 1336 2167 1337 // 2168 // XXX: Why do we multiply by 2 here? Better to do it outside and have the2169 // definition of this function remain sensible.1338 // XXX: Why do we multiply by 2 here? It's better to do it outside and 1339 // have the definition of this function remain sensible. 2170 1340 // 2171 1341 nSum = 2*nTerm; … … 2184 1354 } 2185 1355 2186 // XXX EAM : test version of 1d fitting 2187 psPolynomial1D* VectorFitPolynomial1DOrd_EAM( 1356 /****************************************************************************** 1357 BuildSums2D(sums, x, y, nXterm, nYterm): this routine calculates the powers of 1358 input parameter "x" and "y" between 0 and input parameter nXterms*2 and 1359 nYterm*2. The result is returned as a psImage sums. 1360 *****************************************************************************/ 1361 static psImage *BuildSums2D( 1362 psImage *sums, 1363 psF64 x, 1364 psF64 y, 1365 psS32 nXterm, 1366 psS32 nYterm) 1367 { 1368 psS32 nXsum = 0; 1369 psS32 nYsum = 0; 1370 psF64 xSum = 1.0; 1371 psF64 ySum = 1.0; 1372 1373 nXsum = 2*nXterm; 1374 nYsum = 2*nYterm; 1375 if (sums == NULL) { 1376 sums = psImageAlloc(nXsum, nYsum, PS_TYPE_F64); 1377 } 1378 if ((nXsum != sums->numCols) || (nYsum != sums->numRows)) { 1379 psFree (sums); 1380 sums = psImageAlloc(nXsum, nYsum, PS_TYPE_F64); 1381 } 1382 1383 ySum = 1.0; 1384 for (int j = 0; j < nYsum; j++) { 1385 xSum = ySum; 1386 for (int i = 0; i < nXsum; i++) { 1387 sums->data.F64[i][j] = xSum; 1388 xSum *= x; 1389 } 1390 ySum *= y; 1391 } 1392 return (sums); 1393 } 1394 1395 1396 /****************************************************************************** 1397 Polynomial2DEvalVectorD(myPoly, x, y): This routine takes as input two 1398 psVectors x and y, and evaluates myPoly for each pair of (x, y), and stores it 1399 in the output vector. This routine works on single-precision polynomials with 1400 double precision data. 1401 *****************************************************************************/ 1402 psVector *Polynomial2DEvalVectorD( 1403 const psPolynomial2D *myPoly, 1404 const psVector *x, 1405 const psVector *y) 1406 { 1407 PS_ASSERT_POLY_NON_NULL(myPoly, NULL); 1408 PS_ASSERT_VECTOR_NON_NULL(x, NULL); 1409 PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F64, NULL); 1410 PS_ASSERT_VECTOR_NON_NULL(y, NULL); 1411 PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F64, NULL); 1412 1413 // 1414 // Set the length of the output vector to the minimum of the x,y vectors. 1415 // 1416 psS32 vecLen=x->n; 1417 if (y->n < vecLen) { 1418 vecLen = y->n; 1419 } 1420 1421 // 1422 // Create output vector to return 1423 // 1424 psVector *tmp = psVectorAlloc(vecLen, PS_TYPE_F64); 1425 1426 // 1427 // Evaluate the polynomial at the specified points 1428 // 1429 for (psS32 i=0; i<vecLen; i++) { 1430 tmp->data.F64[i] = psPolynomial2DEval(myPoly, x->data.F64[i], y->data.F64[i]); 1431 } 1432 1433 return(tmp); 1434 } 1435 1436 /****************************************************************************** 1437 ****************************************************************************** 1438 1-D Vector Fitting Code. 1439 ****************************************************************************** 1440 *****************************************************************************/ 1441 1442 /****************************************************************************** 1443 vectorFitPolynomial1DCheb(): This routine will fit a Chebyshev polynomial of 1444 degree myPoly to the data points (x, y) and return the coefficients of that 1445 polynomial. 1446 1447 XXX: mask, maskValue, yErr are currently ignored. 1448 1449 XXX: Change arg order to that of the psLib function. 1450 *****************************************************************************/ 1451 static psPolynomial1D *vectorFitPolynomial1DCheby( 2188 1452 psPolynomial1D* myPoly, 2189 psVector *mask, 2190 const psVector *x, 2191 const psVector *y, 2192 const psVector *yErr) 2193 { 2194 // I think this is 1 dimension down 1453 const psVector *mask, 1454 psMaskType maskValue, 1455 const psVector* y, 1456 const psVector* yErr, 1457 const psVector* x) 1458 { 1459 // XXX: these ASSERTS are redundant. 1460 PS_ASSERT_POLY_NON_NULL(myPoly, NULL); 1461 PS_ASSERT_INT_NONNEGATIVE(myPoly->n, NULL); 1462 PS_ASSERT_VECTOR_NON_NULL(y, NULL); 1463 PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F64, NULL); 1464 if (yErr != NULL) { 1465 PS_ASSERT_VECTORS_SIZE_EQUAL(y, yErr, NULL); 1466 PS_ASSERT_VECTOR_TYPE(yErr, PS_TYPE_F64, NULL); 1467 } 1468 if (x != NULL) { 1469 PS_ASSERT_VECTORS_SIZE_EQUAL(y, x, NULL); 1470 PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F64, NULL); 1471 } 1472 1473 psS32 j; 1474 psS32 k; 1475 psS32 n = y->n; 1476 psF64 fac; 1477 psF64 sum; 1478 PS_VECTOR_GEN_STATIC_RECYCLED(f, n, PS_TYPE_F64); 1479 psScalar *fScalar; 1480 psScalar tmpScalar; 1481 tmpScalar.type.type = PS_TYPE_F64; 1482 1483 // XXX: These assignments appear too simple to warrant code and 1484 // variable declarations. I retain them here to maintain coherence 1485 // with the NR code. 1486 psF64 min = -1.0; 1487 psF64 max = 1.0; 1488 psF64 bma = 0.5 * (max-min); // 1 1489 psF64 bpa = 0.5 * (max+min); // 0 1490 1491 // In this loop, we first calculate the values of X for which the 1492 // Chebyshev polynomials are zero (see NR, section 5.4). Then we 1493 // calculate the value of the function we are fitting the Chebyshev 1494 // polynomials to at those values of X. This is a bit tricky since 1495 // we don't know that function. So, we instead do 3-order LaGrange 1496 // interpolation at the point X for the psVectors x,y for which we 1497 // are fitting this ChebyShev polynomial to. 1498 1499 for (psS32 i=0;i<n;i++) { 1500 // NR 5.8.4 1501 psF64 Y = cos(M_PI * (0.5 + ((psF32) i)) / ((psF32) n)); 1502 psF64 X = (Y + bma + bpa) - 1.0; 1503 tmpScalar.data.F64 = X; 1504 1505 // We interpolate against the tabluated x,y vectors to determine the 1506 // function value at X. 1507 fScalar = p_psVectorInterpolate((psVector *) x, 1508 (psVector *) y, 1509 3, 1510 &tmpScalar); 1511 1512 f->data.F64[i] = fScalar->data.F64; 1513 psFree(fScalar); 1514 1515 psTrace(".psLib.dataManip.vectorFitPolynomial1DCheby", 6, 1516 "(x, X, y, f(X)) is (%f, %f, %f, %f)\n", 1517 x->data.F64[i], X, y->data.F64[i], f->data.F64[i]); 1518 } 1519 1520 // We have the values for f() at the zero points, we now calculate the 1521 // coefficients of the Chebyshev polynomial: NR 5.8.7. 1522 1523 fac = 2.0/((psF32) n); 1524 // XXX: is this loop bound correct? 1525 for (j=0;j<myPoly->n;j++) { 1526 sum = 0.0; 1527 for (k=0;k<n;k++) { 1528 sum+= f->data.F64[k] * 1529 cos(M_PI * ((psF32) j) * (0.5 + ((psF32) k)) / ((psF32) n)); 1530 } 1531 1532 myPoly->coeff[j] = fac * sum; 1533 } 1534 1535 return(myPoly); 1536 } 1537 1538 /****************************************************************************** 1539 VectorFitPolynomial1DOrd(myPoly, *mask, maskValue, *y, *yErr, *x): This is a 1540 private routine which will fit a 1-D polynomial to a set of (x, f) pairs. The 1541 x and fErr vectors may be NULL. All non-NULL vectors must be of type 1542 PS_TYPE_F64. 1543 *****************************************************************************/ 1544 psPolynomial1D* VectorFitPolynomial1DOrd( 1545 psPolynomial1D* myPoly, 1546 const psVector *mask, 1547 psMaskType maskValue, 1548 const psVector *f, 1549 const psVector *fErr, 1550 const psVector *x) 1551 { 1552 // XXX: these ASSERTS are redundant. 1553 PS_ASSERT_POLY_NON_NULL(myPoly, NULL); 1554 PS_ASSERT_INT_NONNEGATIVE(myPoly->n, NULL); 1555 PS_ASSERT_VECTOR_NON_NULL(f, NULL); 1556 PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F64, NULL); 1557 if (mask != NULL) { 1558 PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL); 1559 PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL); 1560 } 1561 if (x != NULL) { 1562 PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL); 1563 PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F64, NULL); 1564 } 1565 if (fErr != NULL) { 1566 PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, NULL); 1567 PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F64, NULL); 1568 } 1569 2195 1570 psImage* A = NULL; 2196 1571 psVector* B = NULL; … … 2204 1579 2205 1580 if (psTraceGetLevel (".psLib.dataManip.VectorFitPolynomial1DOrd") >= 5) { 2206 FILE *f = fdopen((psTraceGetDestination ()), "a+"); 2207 fprintf (f, "VectorFitPolynomial1D()\n"); 2208 for (int i = 0; i < x->n; i++) { 2209 fprintf (f, "(x, y, yErr) is (%f, %f, %f)\n", x->data.F64[i], y->data.F64[i], yErr->data.F64[i]); 2210 } 2211 fclose(f); 1581 FILE *fp = fdopen((psTraceGetDestination ()), "a+"); 1582 fprintf(fp, "VectorFitPolynomial1D()\n"); 1583 for (int i = 0; i < f->n; i++) { 1584 fprintf(fp, "(x, f, fErr) is ("); 1585 if (x != NULL) { 1586 fprintf(fp, "%f, %f, ", x->data.F64[i], f->data.F64[i]); 1587 } else { 1588 fprintf(fp, "%f, %f, ", (psF64) i, f->data.F64[i]); 1589 } 1590 if (fErr != NULL) { 1591 fprintf(fp, "%f)\n", fErr->data.F64[i]); 1592 } else { 1593 fprintf(fp, "NULL)\n"); 1594 } 1595 } 1596 fclose(fp); 2212 1597 } 2213 1598 … … 2227 1612 // xSums look like: 1, x, x^2, ... x^(2n+1) 2228 1613 // Build the B and A data structs. 2229 for (int k = 0; k < x->n; k++) {1614 for (int k = 0; k < f->n; k++) { 2230 1615 if ((mask != NULL) && mask->data.U8[k]) 2231 1616 continue; 2232 xSums = EAMBuildSums1D(xSums, x->data.F64[k], nTerm); 2233 2234 if (yErr == NULL) { 1617 if (x != NULL) { 1618 xSums = BuildSums1D(xSums, x->data.F64[k], nTerm); 1619 } else { 1620 xSums = BuildSums1D(xSums, (psF64) k, nTerm); 1621 } 1622 1623 if (fErr == NULL) { 2235 1624 wt = 1.0; 2236 1625 } else { 2237 // this should filter yErr == 0 values2238 wt = 1.0 / PS_SQR( yErr->data.F64[k]);1626 // this should filter fErr == 0 values 1627 wt = 1.0 / PS_SQR(fErr->data.F64[k]); 2239 1628 } 2240 1629 for (int i = 0; i < nTerm; i++) { 2241 B->data.F64[i] += y->data.F64[k] * xSums->data.F64[i] * wt;1630 B->data.F64[i] += f->data.F64[k] * xSums->data.F64[i] * wt; 2242 1631 } 2243 1632 … … 2261 1650 myPoly->coeff[k] = B->data.F64[k]; 2262 1651 } 2263 } else 1652 } else { 2264 1653 // LUD version of the fit 2265 {2266 1654 psImage *ALUD = NULL; 2267 1655 psVector* outPerm = NULL; … … 2274 1662 myPoly->coeff[k] = coeffs->data.F64[k]; 2275 1663 } 1664 psFree(ALUD); 1665 psFree(coeffs); 1666 psFree(outPerm); 2276 1667 } 2277 1668 … … 2281 1672 2282 1673 psTrace(".psLib.dataManip.VectorFitPolynomial1DOrd", 4, 2283 "---- VectorFitPolynomial1DOrd() begin----\n");1674 "---- VectorFitPolynomial1DOrd() End ----\n"); 2284 1675 return (myPoly); 2285 1676 } 2286 1677 2287 // XXX EAM : this version uses the F64 vectors 2288 psVector *Polynomial2DEvalVectorD( 2289 const psPolynomial2D *myPoly, 1678 1679 /****************************************************************************** 1680 psVectorFitPolynomial1D(): This routine fits a polynomial of arbitrary degree 1681 (specified in poly) to the data points (x, y) and return that polynomial. 1682 Types F32 and F64 are supported, however, type F32 is done via vector 1683 conversion only. 1684 *****************************************************************************/ 1685 psPolynomial1D *psVectorFitPolynomial1D( 1686 psPolynomial1D *poly, 1687 const psVector *mask, 1688 psMaskType maskValue, 1689 const psVector *f, 1690 const psVector *fErr, 1691 const psVector *x) 1692 { 1693 // Internal pointers for possibly NULL or mis-typed vectors. 1694 psVector *x64 = NULL; 1695 psVector *f64 = NULL; 1696 psVector *fErr64 = NULL; 1697 1698 PS_ASSERT_POLY_NON_NULL(poly, NULL); 1699 PS_ASSERT_INT_NONNEGATIVE(poly->n, NULL); 1700 PS_ASSERT_VECTOR_NON_NULL(f, NULL); 1701 PS_ASSERT_VECTOR_NON_EMPTY(f, NULL); 1702 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, NULL); 1703 if (f->type.type != PS_TYPE_F64) { 1704 PS_VECTOR_GEN_F64_FROM_F32(f64, f); 1705 } else { 1706 f64 = (psVector *) f; 1707 } 1708 1709 if (mask != NULL) { 1710 PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL); 1711 PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL); 1712 } 1713 1714 if (x != NULL) { 1715 PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL); 1716 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(x, NULL); 1717 if (x->type.type != PS_TYPE_F64) { 1718 PS_VECTOR_GEN_F64_FROM_F32(x64, x); 1719 } else { 1720 x64 = (psVector *) x; 1721 } 1722 } 1723 1724 if (fErr != NULL) { 1725 PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, NULL); 1726 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(fErr, NULL); 1727 if (fErr->type.type != PS_TYPE_F64) { 1728 PS_VECTOR_GEN_F64_FROM_F32(fErr64, fErr); 1729 } else { 1730 fErr64 = (psVector *) fErr; 1731 } 1732 } 1733 1734 if (poly->type == PS_POLYNOMIAL_ORD) { 1735 poly = VectorFitPolynomial1DOrd(poly, mask, maskValue, f64, fErr64, x64); 1736 if (poly == NULL) { 1737 psError(PS_ERR_UNKNOWN, false, "Could not fit polynomial. Returning NULL.\n"); 1738 return(NULL); 1739 } 1740 } else if (poly->type == PS_POLYNOMIAL_CHEB) { 1741 if (mask != NULL) { 1742 psLogMsg(__func__, PS_LOG_WARN, "WARNING: ignoring mask and maskValue with Chebyshev polynomials.\n"); 1743 } 1744 if (x == NULL) { 1745 // If x==NULL, create an x64 vector with x values set to (-1:1). 1746 PS_VECTOR_GEN_CHEBY_INDEX(x64, f64->n); 1747 } 1748 // XXX: Change arg order. 1749 // XXX: Must modify this routine so that x64 or fErr64 can be NULL. 1750 poly = vectorFitPolynomial1DCheby(poly, NULL, 0, f64, fErr64, x64); 1751 if (x == NULL) { 1752 psFree(x64); 1753 } 1754 } else { 1755 psError(PS_ERR_UNKNOWN, true, "Incorrect polynomial type. Returning NULL.\n"); 1756 } 1757 1758 // Free psVectors that were created for NULL arguments. 1759 if (f->type.type != PS_TYPE_F64) { 1760 psFree(f64); 1761 } 1762 1763 if ((x != NULL) && (x->type.type != PS_TYPE_F64)) { 1764 psFree(x64); 1765 } 1766 1767 if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) { 1768 psFree(fErr64); 1769 } 1770 1771 return(NULL); 1772 } 1773 1774 1775 psPolynomial1D *psVectorClipFitPolynomial1D( 1776 psPolynomial1D *poly, 1777 psStats *stats, 1778 const psVector *mask, 1779 psMaskType maskValue, 1780 const psVector *f, 1781 const psVector *fErr, 1782 const psVector *x) 1783 { 1784 // Internal pointers for possibly NULL vectors. 1785 psVector *x32 = NULL; 1786 1787 PS_ASSERT_POLY_NON_NULL(poly, NULL); 1788 PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, NULL); 1789 PS_ASSERT_PTR_NON_NULL(stats, NULL); 1790 PS_ASSERT_VECTOR_NON_NULL(f, NULL); 1791 PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F32, NULL); 1792 if (mask != NULL) { 1793 PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL); 1794 PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL); 1795 } 1796 if (x != NULL) { 1797 PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL); 1798 PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F32, NULL); 1799 } 1800 if (fErr != NULL) { 1801 PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, NULL); 1802 PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F32, NULL); 1803 } 1804 1805 psLogMsg(__func__, PS_LOG_WARN, "WARNING: This function has not been implemented. Returning NULL.\n"); 1806 // Free psVectors that were created for NULL arguments. 1807 if (x == NULL) { 1808 psFree(x32); 1809 } 1810 return(NULL); 1811 } 1812 1813 1814 /****************************************************************************** 1815 ****************************************************************************** 1816 2-D Vector Fitting Code. 1817 ****************************************************************************** 1818 *****************************************************************************/ 1819 1820 /****************************************************************************** 1821 VectorFitPolynomial2DOrd(myPoly, *mask, maskValue, *f, *fErr, *x, *y): This is 1822 a private routine which will fit a 2-D polynomial to a set of (x, y)-(f) 1823 pairs. All non-NULL vectors must be of type PS_TYPE_F64. 1824 1825 // XXX: What about the maskValue? 1826 *****************************************************************************/ 1827 psPolynomial2D* VectorFitPolynomial2DOrd( 1828 psPolynomial2D* myPoly, 1829 const psVector* mask, 1830 psMaskType maskValue, 1831 const psVector *f, 1832 const psVector *fErr, 2290 1833 const psVector *x, 2291 1834 const psVector *y) 2292 1835 { 1836 // These ASSERTS are redundant. 2293 1837 PS_ASSERT_POLY_NON_NULL(myPoly, NULL); 1838 PS_ASSERT_INT_NONNEGATIVE(myPoly->nX, NULL); 1839 PS_ASSERT_INT_NONNEGATIVE(myPoly->nY, NULL); 1840 1841 PS_ASSERT_VECTOR_NON_NULL(f, NULL); 1842 PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F64, NULL); 1843 if (fErr != NULL) { 1844 PS_ASSERT_VECTORS_SIZE_EQUAL(y, fErr, NULL); 1845 PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F64, NULL); 1846 } 1847 PS_ASSERT_VECTOR_NON_NULL(y, NULL); 1848 PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F64, NULL); 1849 PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL); 2294 1850 PS_ASSERT_VECTOR_NON_NULL(x, NULL); 2295 1851 PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F64, NULL); 2296 PS_ASSERT_VECTOR_NON_NULL(y, NULL); 2297 PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F64, NULL); 2298 2299 psVector *tmp; 2300 psS32 vecLen=x->n; 2301 2302 // Determine the length of the output vector to by the minimum of the x,y vectors 2303 if (y->n < vecLen) { 2304 vecLen = y->n; 2305 } 2306 2307 // Create output vector to return 2308 tmp = psVectorAlloc(vecLen, PS_TYPE_F64); 2309 2310 // Evaluate the polynomial at the specified points 2311 for (psS32 i=0; i<vecLen; i++) { 2312 tmp->data.F64[i] = psPolynomial2DEval(myPoly, x->data.F64[i], y->data.F64[i]); 2313 } 2314 2315 // Return output vector 2316 return(tmp); 2317 } 2318 2319 // XXX EAM : EAMBuildSums2D in analogy with EAMBuildSums1D 2320 static psImage *EAMBuildSums2D( 2321 psImage *sums, 2322 psF64 x, 2323 psF64 y, 2324 psS32 nXterm, 2325 psS32 nYterm) 2326 { 2327 psS32 nXsum = 0; 2328 psS32 nYsum = 0; 2329 psF64 xSum = 1.0; 2330 psF64 ySum = 1.0; 2331 2332 nXsum = 2*nXterm; 2333 nYsum = 2*nYterm; 2334 if (sums == NULL) { 2335 sums = psImageAlloc(nXsum, nYsum, PS_TYPE_F64); 2336 } 2337 if ((nXsum != sums->numCols) || (nYsum != sums->numRows)) { 2338 psFree (sums); 2339 sums = psImageAlloc(nXsum, nYsum, PS_TYPE_F64); 2340 } 2341 2342 ySum = 1.0; 2343 for (int j = 0; j < nYsum; j++) { 2344 xSum = ySum; 2345 for (int i = 0; i < nXsum; i++) { 2346 sums->data.F64[i][j] = xSum; 2347 xSum *= x; 2348 } 2349 ySum *= y; 2350 } 2351 return (sums); 2352 } 2353 2354 // XXX EAM : test version of 2d fitting 2355 psPolynomial2D* VectorFitPolynomial2DOrd_EAM( 2356 psPolynomial2D* myPoly, 2357 psVector* mask, 2358 const psVector* x, 2359 const psVector* y, 2360 const psVector* z, 2361 const psVector* zErr) 2362 { 1852 PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL); 1853 if (mask != NULL) { 1854 PS_ASSERT_VECTORS_SIZE_EQUAL(y, mask, NULL); 1855 PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL); 1856 } 1857 2363 1858 // I think this is 1 dimension down 2364 1859 psImage* A = NULL; … … 2389 1884 if ((mask != NULL) && mask->data.U8[k]) 2390 1885 continue; 2391 Sums = EAMBuildSums2D(Sums, x->data.F64[k], y->data.F64[k], nXterm, nYterm);2392 2393 if ( zErr == NULL) {1886 Sums = BuildSums2D(Sums, x->data.F64[k], y->data.F64[k], nXterm, nYterm); 1887 1888 if (fErr == NULL) { 2394 1889 wt = 1.0; 2395 1890 } else { 2396 // XXX: this should probably by zErr^2 !!2397 // this should filter zErr == 0 values2398 // XXX: Why isn't this zErr^2?2399 wt = 1.0 / zErr->data.F64[k];1891 // XXX: this should probably by fErr^2 !! 1892 // this should filter fErr == 0 values 1893 // XXX: Why isn't this fErr^2? 1894 wt = 1.0 / fErr->data.F64[k]; 2400 1895 } 2401 1896 … … 2404 1899 for (int n = 0; n < nXterm; n++) { 2405 1900 for (int m = 0; m < nYterm; m++) { 2406 B->data.F64[n+m*nXterm] += z->data.F64[k] * Sums->data.F64[n][m] * wt;1901 B->data.F64[n+m*nXterm] += f->data.F64[k] * Sums->data.F64[n][m] * wt; 2407 1902 } 2408 1903 } … … 2447 1942 const psVector* x, 2448 1943 const psVector* y, 2449 const psVector* z,2450 const psVector* d z)1944 const psVector* f, 1945 const psVector* df) 2451 1946 { 2452 1947 psVector *X; … … 2455 1950 psVector *dZ; 2456 1951 2457 psVector * zFit = NULL;2458 psVector * zResid = NULL;1952 psVector *fFit = NULL; 1953 psVector *fResid = NULL; 2459 1954 psStats *stats = NULL; 2460 1955 2461 1956 X = psVectorCopy (NULL, x, PS_TYPE_F64); 2462 1957 Y = psVectorCopy (NULL, y, PS_TYPE_F64); 2463 Z = psVectorCopy (NULL, z, PS_TYPE_F64);2464 dZ = psVectorCopy (NULL, d z, PS_TYPE_F64);1958 Z = psVectorCopy (NULL, f, PS_TYPE_F64); 1959 dZ = psVectorCopy (NULL, df, PS_TYPE_F64); 2465 1960 2466 1961 for (int N = 0; N < 3; N++) { 2467 1962 // XXX EAM : this would be better defined with an element mask 2468 poly = VectorFitPolynomial2DOrd _EAM(poly, NULL, X, Y, Z, dZ);2469 zFit = Polynomial2DEvalVectorD(poly, x, y);2470 zResid = (psVector *) psBinaryOp(NULL, (void *) z, "-", (void *) zFit);1963 poly = VectorFitPolynomial2DOrd(poly, NULL, 0, X, Y, Z, dZ); 1964 fFit = Polynomial2DEvalVectorD(poly, x, y); 1965 fResid = (psVector *) psBinaryOp(NULL, (void *) f, "-", (void *) fFit); 2471 1966 2472 1967 stats = psStatsAlloc (PS_STAT_CLIPPED_MEAN | PS_STAT_CLIPPED_STDEV); 2473 stats = psVectorStats (stats, zResid, NULL, NULL, 0);1968 stats = psVectorStats (stats, fResid, NULL, NULL, 0); 2474 1969 psTrace (".psphot.RobustFit", 4, "residual stats for robust fit: %g +/- %g (%d pts)\n", stats->clippedMean, stats->clippedStdev, stats->clippedNvalues); 2475 1970 2476 1971 // re-create X, Y, Z, dZ if pts are valid 2477 1972 int n = 0; 2478 for (int i = 0; i < zResid->n; i++) {2479 if (fabs( zResid->data.F64[i] - stats->clippedMean) > 3*stats->clippedStdev) {1973 for (int i = 0; i < fResid->n; i++) { 1974 if (fabs(fResid->data.F64[i] - stats->clippedMean) > 3*stats->clippedStdev) { 2480 1975 continue; 2481 1976 } 2482 1977 X->data.F64[n] = x->data.F64[i]; 2483 1978 Y->data.F64[n] = y->data.F64[i]; 2484 Z->data.F64[n] = z->data.F64[i];2485 dZ->data.F64[n] = d z->data.F64[i];1979 Z->data.F64[n] = f->data.F64[i]; 1980 dZ->data.F64[n] = df->data.F64[i]; 2486 1981 n++; 2487 1982 } … … 2507 2002 2508 2003 psPolynomial2D* RobustFit2D(psPolynomial2D* poly, 2509 psVector* mask,2004 const psVector* mask, 2510 2005 const psVector* x, 2511 2006 const psVector* y, 2512 const psVector* z,2513 const psVector* d z)2007 const psVector* f, 2008 const psVector* df) 2514 2009 { 2515 2010 PS_ASSERT_VECTOR_NON_NULL(mask, NULL); 2516 2011 PS_ASSERT_VECTOR_NON_NULL(x, NULL); 2517 2012 PS_ASSERT_VECTOR_NON_NULL(y, NULL); 2518 PS_ASSERT_VECTOR_NON_NULL( z, NULL);2519 PS_ASSERT_VECTOR_NON_NULL(d z, NULL);2520 2521 psVector * zFit = NULL;2522 psVector * zResid = psVectorAlloc (x->n, PS_TYPE_F64);2013 PS_ASSERT_VECTOR_NON_NULL(f, NULL); 2014 PS_ASSERT_VECTOR_NON_NULL(df, NULL); 2015 2016 psVector *fFit = NULL; 2017 psVector *fResid = psVectorAlloc (x->n, PS_TYPE_F64); 2523 2018 psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_STDEV); 2524 2019 2525 2020 for (int N = 0; N < 3; N++) { 2526 poly = VectorFitPolynomial2DOrd _EAM (poly, mask, x, y, z, dz);2527 zFit = Polynomial2DEvalVectorD (poly, x, y);2528 zResid = (psVector *) psBinaryOp(zResid, (void *) z, "-", (void *) zFit);2529 2530 stats = psVectorStats (stats, zResid, NULL, mask, 1);2021 poly = VectorFitPolynomial2DOrd (poly, mask, 0, x, y, f, df); 2022 fFit = Polynomial2DEvalVectorD (poly, x, y); 2023 fResid = (psVector *) psBinaryOp(fResid, (void *) f, "-", (void *) fFit); 2024 2025 stats = psVectorStats (stats, fResid, NULL, mask, 1); 2531 2026 psTrace (".psphot.RobustFit", 4, "residual stats for robust fit: %g +/- %g\n", 2532 2027 stats->sampleMean, stats->sampleStdev); … … 2535 2030 // we are masking out any point which is out of range 2536 2031 // recovery is not allowed with this scheme 2537 for (int i = 0; i < zResid->n; i++) {2032 for (int i = 0; i < fResid->n; i++) { 2538 2033 if (mask->data.U8[i]) 2539 2034 continue; 2540 if (fabs( zResid->data.F64[i] - stats->sampleMean) > 3*stats->sampleStdev) {2035 if (fabs(fResid->data.F64[i] - stats->sampleMean) > 3*stats->sampleStdev) { 2541 2036 mask->data.U8[i] = 1; 2542 2037 continue; 2543 2038 } 2544 2039 } 2545 psFree ( zFit);2546 } 2547 psFree ( zResid);2040 psFree (fFit); 2041 } 2042 psFree (fResid); 2548 2043 psFree (stats); 2549 2044 return (poly); 2550 2045 } 2551 2046 2047 2552 2048 /****************************************************************************** 2553 ****************************************************************************** 2554 ****************************************************************************** 2555 ****************************************************************************** 2556 NEW Code: 2557 ****************************************************************************** 2558 ****************************************************************************** 2559 ****************************************************************************** 2049 psVectorFitPolynomial2D(): This routine fits a 2D polynomial of arbitrary 2050 degree (specified in poly) to the data points (x, y)-(f) and returns that 2051 polynomial. Types F32 and F64 are supported, however, type F32 is done via 2052 vector conversion only. 2560 2053 *****************************************************************************/ 2561 2562 #define PS_VECTOR_GEN_INDEX_F32(VEC, SIZE) \ 2563 VEC = psVectorAlloc(SIZE, PS_TYPE_F32); \ 2564 for (psS32 i = 0 ; i < SIZE ; i++) { \ 2565 VEC->data.F32[i] = (psF32) i; \ 2566 } \ 2567 2568 psPolynomial1D *psVectorFitPolynomial1D_NEW( 2569 psPolynomial1D *poly, 2570 const psVector *mask, 2571 psMaskType maskValue, 2572 const psVector *f, 2573 const psVector *fErr, 2574 const psVector *x) 2575 { 2576 // Internal pointers for possibly NULL vectors. 2577 psVector *x32 = NULL; 2578 psVector *fErr32 = NULL; 2579 2580 PS_ASSERT_POLY_NON_NULL(poly, NULL); 2581 PS_ASSERT_VECTOR_NON_NULL(f, NULL); 2582 PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F32, NULL); 2583 if (mask != NULL) { 2584 PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL); 2585 PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL); 2586 } 2587 if (x != NULL) { 2588 PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL); 2589 PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F32, NULL); 2590 } else { 2591 PS_VECTOR_GEN_INDEX_F32(x32, f->n); 2592 } 2593 2594 if (fErr != NULL) { 2595 PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, NULL); 2596 PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F32, NULL); 2597 } else { 2598 fErr = psVectorAlloc(f->n, PS_TYPE_F32); 2599 PS_VECTOR_SET_F32(fErr, 1.0); 2600 } 2601 2602 psLogMsg(__func__, PS_LOG_WARN, "WARNING: This function has not been implemented. Returning NULL.\n"); 2603 if (poly->type == PS_POLYNOMIAL_ORD) { 2604 // XXX: Call EAM code 2605 } else if (poly->type == PS_POLYNOMIAL_CHEB) { 2606 // XXX: Call my code 2607 } else { 2608 printf("XXX: ERROR: incorrect polynomial type.\n"); 2609 } 2610 2611 // Free psVectors that were created for NULL arguments. 2612 if (x == NULL) { 2613 psFree(x32); 2614 } 2615 if (fErr == NULL) { 2616 psFree(fErr32); 2617 } 2618 2619 return(NULL); 2620 } 2621 2622 2623 psPolynomial2D *psVectorFitPolynomial2D_NEW( 2624 psPolynomial1D *poly, 2054 psPolynomial2D *psVectorFitPolynomial2D( 2055 psPolynomial2D *poly, 2625 2056 const psVector *mask, 2626 2057 psMaskType maskValue, … … 2630 2061 const psVector *y) 2631 2062 { 2632 // Internal pointers for possibly NULL vectors. 2633 psVector *fErr32 = NULL; 2063 // Internal pointers for possibly NULL or mis-typed vectors. 2064 psVector *x64 = NULL; 2065 psVector *y64 = NULL; 2066 psVector *f64 = NULL; 2067 psVector *fErr64 = NULL; 2634 2068 2635 2069 PS_ASSERT_POLY_NON_NULL(poly, NULL); 2636 2070 PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, NULL); 2071 2072 // 2073 // f 2074 // 2075 PS_ASSERT_VECTOR_NON_NULL(f, NULL); 2076 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, NULL); 2077 if (f->type.type != PS_TYPE_F64) { 2078 PS_VECTOR_GEN_F64_FROM_F32(f64, f); 2079 } else { 2080 f64 = (psVector *) f; 2081 } 2082 if (mask != NULL) { 2083 PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL); 2084 PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL); 2085 } 2086 2087 // 2088 // x 2089 // 2090 PS_ASSERT_VECTOR_NON_NULL(x, NULL); 2091 PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL); 2092 if (x->type.type != PS_TYPE_F64) { 2093 PS_VECTOR_GEN_F64_FROM_F32(x64, x); 2094 } else { 2095 x64 = (psVector *) x; 2096 } 2097 2098 // 2099 // y 2100 // 2101 PS_ASSERT_VECTOR_NON_NULL(y, NULL); 2102 PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL); 2103 if (y->type.type != PS_TYPE_F64) { 2104 PS_VECTOR_GEN_F64_FROM_F32(y64, y); 2105 } else { 2106 y64 = (psVector *) y; 2107 } 2108 2109 // 2110 // fErr 2111 // 2112 if (fErr != NULL) { 2113 PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, NULL); 2114 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(fErr, NULL); 2115 if (fErr->type.type != PS_TYPE_F64) { 2116 PS_VECTOR_GEN_F64_FROM_F32(fErr64, fErr); 2117 } else { 2118 fErr64 = (psVector *) fErr; 2119 } 2120 } 2121 2122 if (poly->type == PS_POLYNOMIAL_ORD) { 2123 poly = VectorFitPolynomial2DOrd(poly, mask, maskValue, f64, fErr64, x64, y64); 2124 if (poly == NULL) { 2125 psError(PS_ERR_UNKNOWN, true, "Could not fit polynomial. Returning NULL.\n"); 2126 // Free psVectors that were created for NULL arguments. 2127 if (f->type.type != PS_TYPE_F64) { 2128 psFree(f64); 2129 } 2130 2131 if (x->type.type != PS_TYPE_F64) { 2132 psFree(x64); 2133 } 2134 2135 if (y->type.type != PS_TYPE_F64) { 2136 psFree(y64); 2137 } 2138 2139 if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) { 2140 psFree(fErr64); 2141 } 2142 return(NULL); 2143 } 2144 } else if (poly->type == PS_POLYNOMIAL_CHEB) { 2145 if (mask != NULL) { 2146 psLogMsg(__func__, PS_LOG_WARN, "WARNING: ignoring mask and maskValue with Chebyshev polynomials.\n"); 2147 } 2148 psLogMsg(__func__, PS_LOG_WARN, "WARNING: 2-D Chebyshev polynomial vector fitting has not been implemented. Returning NULL.\n"); 2149 psFree(poly); 2150 poly = NULL; 2151 } else { 2152 // Free psVectors that were created for NULL arguments. 2153 if (f->type.type != PS_TYPE_F64) { 2154 psFree(f64); 2155 } 2156 2157 if (x->type.type != PS_TYPE_F64) { 2158 psFree(x64); 2159 } 2160 2161 if (y->type.type != PS_TYPE_F64) { 2162 psFree(y64); 2163 } 2164 2165 if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) { 2166 psFree(fErr64); 2167 } 2168 psError(PS_ERR_UNKNOWN, true, "Incorrect polynomial type. Returning NULL.\n"); 2169 } 2170 2171 2172 // Free psVectors that were created for NULL arguments. 2173 if (f->type.type != PS_TYPE_F64) { 2174 psFree(f64); 2175 } 2176 2177 if (x->type.type != PS_TYPE_F64) { 2178 psFree(x64); 2179 } 2180 2181 if (y->type.type != PS_TYPE_F64) { 2182 psFree(y64); 2183 } 2184 2185 if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) { 2186 psFree(fErr64); 2187 } 2188 2189 return(poly); 2190 } 2191 2192 psPolynomial2D *psVectorClipFitPolynomial2D( 2193 psPolynomial2D *poly, 2194 psStats *stats, 2195 const psVector *mask, 2196 psMaskType maskValue, 2197 const psVector *f, 2198 const psVector *fErr, 2199 const psVector *x, 2200 const psVector *y) 2201 { 2202 PS_ASSERT_POLY_NON_NULL(poly, NULL); 2203 PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, NULL); 2204 PS_ASSERT_PTR_NON_NULL(stats, NULL); 2637 2205 PS_ASSERT_VECTOR_NON_NULL(f, NULL); 2638 2206 PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F32, NULL); … … 2648 2216 PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F32, NULL); 2649 2217 if (fErr != NULL) { 2650 PS_ASSERT_VECTORS_SIZE_EQUAL(f Err, mask, NULL);2218 PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, NULL); 2651 2219 PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F32, NULL); 2220 } 2221 2222 if (mask == NULL) { 2223 // XXX: Change argument order. 2224 poly = RobustFit2D_nomask(poly, x, y, f, fErr); 2652 2225 } else { 2653 fErr32 = psVectorAlloc(f->n, PS_TYPE_F32); 2654 PS_VECTOR_SET_F32(fErr32, 1.0); 2655 } 2656 2657 psLogMsg(__func__, PS_LOG_WARN, "WARNING: This function has not been implemented. Returning NULL.\n"); 2658 if (poly->type == PS_POLYNOMIAL_ORD) { 2659 psLogMsg(__func__, PS_LOG_WARN, "WARNING: 2-D polynomial vector fitting has not been implemented. Returning NULL.\n"); 2660 } else if (poly->type == PS_POLYNOMIAL_CHEB) { 2661 psLogMsg(__func__, PS_LOG_WARN, "WARNING: 2-D Chebyshev polynomial vector fitting has not been implemented. Returning NULL.\n"); 2662 } else { 2663 printf("XXX: ERROR: incorrect polynomial type.\n"); 2664 } 2665 if (fErr == NULL) { 2666 psFree(fErr32); 2667 } 2668 return(NULL); 2669 } 2670 2671 psPolynomial3D *psVectorFitPolynomial3D_NEW( 2672 psPolynomial1D *poly, 2226 // XXX: Use maskValue. 2227 // XXX: Change argument order. 2228 poly = RobustFit2D(poly, mask, x, y, f, fErr); 2229 } 2230 2231 if (poly == NULL) { 2232 psError(PS_ERR_UNKNOWN, true, "Could not fit a polynomial to the data. Returning NULL.\n"); 2233 return(NULL); 2234 } 2235 return(poly); 2236 } 2237 2238 /****************************************************************************** 2239 ****************************************************************************** 2240 3-D Vector Fitting Code. 2241 ****************************************************************************** 2242 *****************************************************************************/ 2243 2244 /****************************************************************************** 2245 VectorFitPolynomial3DOrd(myPoly, *mask, maskValue, *f, *fErr, *x, *y, *z): 2246 This is a private routine which will fit a 3-D polynomial to a set of (x, 2247 y, z)-(f) pairs. All non-NULL vectors must be of type PS_TYPE_F64. 2248 2249 XXX: This routine needs to be written. Currently, this is simply a shell. We 2250 can assume that all vectors have been converted to F64, that (f, x, y, z) are 2251 non-null and F64. fErr may be NULL, but will be F64 is not. 2252 *****************************************************************************/ 2253 psPolynomial3D* VectorFitPolynomial3DOrd( 2254 psPolynomial3D* myPoly, 2255 const psVector* mask, 2256 psMaskType maskValue, 2257 const psVector *f, 2258 const psVector *fErr, 2259 const psVector *x, 2260 const psVector *y, 2261 const psVector *z) 2262 { 2263 // These ASSERTS are redundant. 2264 PS_ASSERT_POLY_NON_NULL(myPoly, NULL); 2265 PS_ASSERT_INT_NONNEGATIVE(myPoly->nX, NULL); 2266 PS_ASSERT_INT_NONNEGATIVE(myPoly->nY, NULL); 2267 PS_ASSERT_INT_NONNEGATIVE(myPoly->nZ, NULL); 2268 2269 PS_ASSERT_VECTOR_NON_NULL(f, NULL); 2270 PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F64, NULL); 2271 if (fErr != NULL) { 2272 PS_ASSERT_VECTORS_SIZE_EQUAL(y, fErr, NULL); 2273 PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F64, NULL); 2274 } 2275 PS_ASSERT_VECTOR_NON_NULL(x, NULL); 2276 PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F64, NULL); 2277 PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL); 2278 PS_ASSERT_VECTOR_NON_NULL(y, NULL); 2279 PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F64, NULL); 2280 PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL); 2281 PS_ASSERT_VECTOR_NON_NULL(z, NULL); 2282 PS_ASSERT_VECTOR_TYPE(z, PS_TYPE_F64, NULL); 2283 PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, NULL); 2284 if (mask != NULL) { 2285 PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL); 2286 PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL); 2287 } 2288 2289 psError(PS_ERR_UNKNOWN, true, "3-D Polynomial Fitting is not Implemented.\n"); 2290 return (NULL); 2291 } 2292 2293 /****************************************************************************** 2294 psVectorFitPolynomial3D(): This routine fits a 3D polynomial of arbitrary 2295 degree (specified in poly) to the data points (x, y, z)-(f) and returns that 2296 polynomial. Types F32 and F64 are supported, however, type F32 is done via 2297 vector conversion only. 2298 *****************************************************************************/ 2299 psPolynomial3D *psVectorFitPolynomial3D( 2300 psPolynomial3D *poly, 2673 2301 const psVector *mask, 2674 2302 psMaskType maskValue, … … 2679 2307 const psVector *z) 2680 2308 { 2681 // Internal pointers for possibly NULL vectors. 2682 psVector *fErr32 = NULL; 2309 // Internal pointers for possibly NULL or mis-typed vectors. 2310 psVector *x64 = NULL; 2311 psVector *y64 = NULL; 2312 psVector *z64 = NULL; 2313 psVector *f64 = NULL; 2314 psVector *fErr64 = NULL; 2683 2315 2684 2316 PS_ASSERT_POLY_NON_NULL(poly, NULL); 2685 2317 PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, NULL); 2318 2319 // 2320 // f 2321 // 2322 PS_ASSERT_VECTOR_NON_NULL(f, NULL); 2323 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, NULL); 2324 if (f->type.type != PS_TYPE_F64) { 2325 PS_VECTOR_GEN_F64_FROM_F32(f64, f); 2326 } else { 2327 f64 = (psVector *) f; 2328 } 2329 if (mask != NULL) { 2330 PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL); 2331 PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL); 2332 } 2333 2334 // 2335 // x 2336 // 2337 PS_ASSERT_VECTOR_NON_NULL(x, NULL); 2338 PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL); 2339 if (x->type.type != PS_TYPE_F64) { 2340 PS_VECTOR_GEN_F64_FROM_F32(x64, x); 2341 } else { 2342 x64 = (psVector *) x; 2343 } 2344 2345 // 2346 // y 2347 // 2348 PS_ASSERT_VECTOR_NON_NULL(y, NULL); 2349 PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL); 2350 if (y->type.type != PS_TYPE_F64) { 2351 PS_VECTOR_GEN_F64_FROM_F32(y64, y); 2352 } else { 2353 y64 = (psVector *) y; 2354 } 2355 2356 // 2357 // z 2358 // 2359 PS_ASSERT_VECTOR_NON_NULL(z, NULL); 2360 PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, NULL); 2361 if (z->type.type != PS_TYPE_F64) { 2362 PS_VECTOR_GEN_F64_FROM_F32(y64, z); 2363 } else { 2364 z64 = (psVector *) z; 2365 } 2366 2367 // 2368 // fErr 2369 // 2370 if (fErr != NULL) { 2371 PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, NULL); 2372 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(fErr, NULL); 2373 if (fErr->type.type != PS_TYPE_F64) { 2374 PS_VECTOR_GEN_F64_FROM_F32(fErr64, fErr); 2375 } else { 2376 fErr64 = (psVector *) fErr; 2377 } 2378 } 2379 2380 if (poly->type == PS_POLYNOMIAL_ORD) { 2381 poly = VectorFitPolynomial3DOrd(poly, mask, maskValue, f64, fErr64, x64, y64, z64); 2382 if (poly == NULL) { 2383 psError(PS_ERR_UNKNOWN, true, "Could not fit polynomial. Returning NULL.\n"); 2384 // Free psVectors that were created for NULL arguments. 2385 if (f->type.type != PS_TYPE_F64) { 2386 psFree(f64); 2387 } 2388 2389 if (x->type.type != PS_TYPE_F64) { 2390 psFree(x64); 2391 } 2392 2393 if (y->type.type != PS_TYPE_F64) { 2394 psFree(y64); 2395 } 2396 2397 if (z->type.type != PS_TYPE_F64) { 2398 psFree(z64); 2399 } 2400 2401 if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) { 2402 psFree(fErr64); 2403 } 2404 return(NULL); 2405 } 2406 } else if (poly->type == PS_POLYNOMIAL_CHEB) { 2407 if (mask != NULL) { 2408 psLogMsg(__func__, PS_LOG_WARN, "WARNING: ignoring mask and maskValue with Chebyshev polynomials.\n"); 2409 } 2410 psLogMsg(__func__, PS_LOG_WARN, "WARNING: 3-D Chebyshev polynomial vector fitting has not been implemented. Returning NULL.\n"); 2411 psFree(poly); 2412 poly = NULL; 2413 } else { 2414 // Free psVectors that were created for NULL arguments. 2415 if (f->type.type != PS_TYPE_F64) { 2416 psFree(f64); 2417 } 2418 2419 if (x->type.type != PS_TYPE_F64) { 2420 psFree(x64); 2421 } 2422 2423 if (y->type.type != PS_TYPE_F64) { 2424 psFree(y64); 2425 } 2426 2427 if (z->type.type != PS_TYPE_F64) { 2428 psFree(z64); 2429 } 2430 2431 if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) { 2432 psFree(fErr64); 2433 } 2434 psError(PS_ERR_UNKNOWN, true, "Incorrect polynomial type. Returning NULL.\n"); 2435 } 2436 2437 2438 // Free psVectors that were created for NULL arguments. 2439 if (f->type.type != PS_TYPE_F64) { 2440 psFree(f64); 2441 } 2442 2443 if (x->type.type != PS_TYPE_F64) { 2444 psFree(x64); 2445 } 2446 2447 if (y->type.type != PS_TYPE_F64) { 2448 psFree(y64); 2449 } 2450 2451 if (z->type.type != PS_TYPE_F64) { 2452 psFree(z64); 2453 } 2454 2455 if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) { 2456 psFree(fErr64); 2457 } 2458 2459 return(poly); 2460 } 2461 2462 psPolynomial3D *psVectorClipFitPolynomial3D( 2463 psPolynomial3D *poly, 2464 psStats *stats, 2465 const psVector *mask, 2466 psMaskType maskValue, 2467 const psVector *f, 2468 const psVector *fErr, 2469 const psVector *x, 2470 const psVector *y, 2471 const psVector *z) 2472 { 2473 PS_ASSERT_POLY_NON_NULL(poly, NULL); 2474 PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, NULL); 2475 PS_ASSERT_PTR_NON_NULL(stats, NULL); 2686 2476 PS_ASSERT_VECTOR_NON_NULL(f, NULL); 2687 2477 PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F32, NULL); … … 2696 2486 PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL); 2697 2487 PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F32, NULL); 2698 PS_ASSERT_VECTOR_NON_NULL( z, NULL);2699 PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, NULL);2700 PS_ASSERT_VECTOR_TYPE( z, PS_TYPE_F32, NULL);2488 PS_ASSERT_VECTOR_NON_NULL(f, NULL); 2489 PS_ASSERT_VECTORS_SIZE_EQUAL(f, f, NULL); 2490 PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F32, NULL); 2701 2491 if (fErr != NULL) { 2702 2492 PS_ASSERT_VECTORS_SIZE_EQUAL(fErr, mask, NULL); 2703 2493 PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F32, NULL); 2704 } else {2705 fErr32 = psVectorAlloc(f->n, PS_TYPE_F32);2706 PS_VECTOR_SET_F32(fErr32, 1.0);2707 2494 } 2708 2495 2709 2496 psLogMsg(__func__, PS_LOG_WARN, "WARNING: This function has not been implemented. Returning NULL.\n"); 2710 if (poly->type == PS_POLYNOMIAL_ORD) {2711 psLogMsg(__func__, PS_LOG_WARN, "WARNING: 3-D polynomial vector fitting has not been implemented. Returning NULL.\n");2712 } else if (poly->type == PS_POLYNOMIAL_CHEB) {2713 psLogMsg(__func__, PS_LOG_WARN, "WARNING: 3-D Chebyshev polynomial vector fitting has not been implemented. Returning NULL.\n");2714 } else {2715 printf("XXX: ERROR: incorrect polynomial type.\n");2716 }2717 if (fErr == NULL) {2718 psFree(fErr32);2719 }2720 2497 return(NULL); 2721 2498 } 2722 2499 2723 psPolynomial4D *psVectorFitPolynomial4D_NEW( 2724 psPolynomial1D *poly, 2500 2501 /****************************************************************************** 2502 ****************************************************************************** 2503 4-D Vector Fitting Code. 2504 ****************************************************************************** 2505 *****************************************************************************/ 2506 /****************************************************************************** 2507 VectorFitPolynomial4DOrd(myPoly, *mask, maskValue, *f, *fErr, *x, *y, *z, *t): 2508 This is a private routine which will fit a 4-D polynomial to a set of (x, 2509 y, z, t)-(f) pairs. All non-NULL vectors must be of type PS_TYPE_F64. 2510 2511 XXX: This routine needs to be written. Currently, this is simply a shell. We 2512 can assume that all vectors have been converted to F64, that (f, x, y, z) are 2513 non-null and F64. fErr may be NULL, but will be F64 is not. 2514 *****************************************************************************/ 2515 psPolynomial4D* VectorFitPolynomial4DOrd( 2516 psPolynomial4D* myPoly, 2517 const psVector* mask, 2518 psMaskType maskValue, 2519 const psVector *f, 2520 const psVector *fErr, 2521 const psVector *x, 2522 const psVector *y, 2523 const psVector *z, 2524 const psVector *t) 2525 { 2526 // These ASSERTS are redundant. 2527 PS_ASSERT_POLY_NON_NULL(myPoly, NULL); 2528 PS_ASSERT_INT_NONNEGATIVE(myPoly->nX, NULL); 2529 PS_ASSERT_INT_NONNEGATIVE(myPoly->nY, NULL); 2530 PS_ASSERT_INT_NONNEGATIVE(myPoly->nZ, NULL); 2531 PS_ASSERT_INT_NONNEGATIVE(myPoly->nT, NULL); 2532 PS_ASSERT_VECTOR_NON_NULL(f, NULL); 2533 PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F64, NULL); 2534 if (fErr != NULL) { 2535 PS_ASSERT_VECTORS_SIZE_EQUAL(y, fErr, NULL); 2536 PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F64, NULL); 2537 } 2538 PS_ASSERT_VECTOR_NON_NULL(x, NULL); 2539 PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F64, NULL); 2540 PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL); 2541 PS_ASSERT_VECTOR_NON_NULL(y, NULL); 2542 PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F64, NULL); 2543 PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL); 2544 PS_ASSERT_VECTOR_NON_NULL(z, NULL); 2545 PS_ASSERT_VECTOR_TYPE(z, PS_TYPE_F64, NULL); 2546 PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, NULL); 2547 PS_ASSERT_VECTOR_NON_NULL(t, NULL); 2548 PS_ASSERT_VECTOR_TYPE(t, PS_TYPE_F64, NULL); 2549 PS_ASSERT_VECTORS_SIZE_EQUAL(f, t, NULL); 2550 if (mask != NULL) { 2551 PS_ASSERT_VECTORS_SIZE_EQUAL(y, mask, NULL); 2552 PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL); 2553 } 2554 2555 psError(PS_ERR_UNKNOWN, true, "4-D Polynomial Fitting is not Implemented.\n"); 2556 return (NULL); 2557 } 2558 2559 /****************************************************************************** 2560 psVectorFitPolynomial4D(): This routine fits a 4D polynomial of arbitrary 2561 degree (specified in poly) to the data points (x, y, z, t)-(f) and returns 2562 that polynomial. Types F32 and F64 are supported, however, type F32 is done 2563 via vector conversion only. 2564 *****************************************************************************/ 2565 psPolynomial4D *psVectorFitPolynomial4D( 2566 psPolynomial4D *poly, 2725 2567 const psVector *mask, 2726 2568 psMaskType maskValue, … … 2732 2574 const psVector *t) 2733 2575 { 2734 // Internal pointers for possibly NULL vectors. 2735 psVector *fErr32 = NULL; 2576 // Internal pointers for possibly NULL or mis-typed vectors. 2577 psVector *x64 = NULL; 2578 psVector *y64 = NULL; 2579 psVector *z64 = NULL; 2580 psVector *t64 = NULL; 2581 psVector *f64 = NULL; 2582 psVector *fErr64 = NULL; 2736 2583 2737 2584 PS_ASSERT_POLY_NON_NULL(poly, NULL); 2738 2585 PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, NULL); 2586 2587 // 2588 // f 2589 // 2739 2590 PS_ASSERT_VECTOR_NON_NULL(f, NULL); 2740 PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F32, NULL); 2591 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, NULL); 2592 if (f->type.type != PS_TYPE_F64) { 2593 PS_VECTOR_GEN_F64_FROM_F32(f64, f); 2594 } else { 2595 f64 = (psVector *) f; 2596 } 2741 2597 if (mask != NULL) { 2742 2598 PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL); 2743 2599 PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL); 2744 2600 } 2601 2602 // 2603 // x 2604 // 2745 2605 PS_ASSERT_VECTOR_NON_NULL(x, NULL); 2746 PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL); 2747 PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F32, NULL); 2606 PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL); 2607 if (x->type.type != PS_TYPE_F64) { 2608 PS_VECTOR_GEN_F64_FROM_F32(x64, x); 2609 } else { 2610 x64 = (psVector *) x; 2611 } 2612 2613 // 2614 // y 2615 // 2748 2616 PS_ASSERT_VECTOR_NON_NULL(y, NULL); 2749 2617 PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL); 2750 PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F32, NULL); 2618 if (y->type.type != PS_TYPE_F64) { 2619 PS_VECTOR_GEN_F64_FROM_F32(y64, y); 2620 } else { 2621 y64 = (psVector *) y; 2622 } 2623 2624 // 2625 // z 2626 // 2751 2627 PS_ASSERT_VECTOR_NON_NULL(z, NULL); 2752 2628 PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, NULL); 2753 PS_ASSERT_VECTOR_TYPE(z, PS_TYPE_F32, NULL); 2629 if (z->type.type != PS_TYPE_F64) { 2630 PS_VECTOR_GEN_F64_FROM_F32(y64, z); 2631 } else { 2632 z64 = (psVector *) z; 2633 } 2634 2635 // 2636 // t 2637 // 2754 2638 PS_ASSERT_VECTOR_NON_NULL(t, NULL); 2755 2639 PS_ASSERT_VECTORS_SIZE_EQUAL(f, t, NULL); 2756 PS_ASSERT_VECTOR_TYPE(t, PS_TYPE_F32, NULL); 2757 if (fErr != NULL) { 2758 PS_ASSERT_VECTORS_SIZE_EQUAL(fErr, mask, NULL); 2759 PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F32, NULL); 2640 if (t->type.type != PS_TYPE_F64) { 2641 PS_VECTOR_GEN_F64_FROM_F32(y64, t); 2760 2642 } else { 2761 fErr32 = psVectorAlloc(f->n, PS_TYPE_F32); 2762 PS_VECTOR_SET_F32(fErr32, 1.0); 2763 } 2764 2765 if (poly->type == PS_POLYNOMIAL_ORD) { 2766 psLogMsg(__func__, PS_LOG_WARN, "WARNING: 4-D polynomial vector fitting has not been implemented. Returning NULL.\n"); 2767 } else if (poly->type == PS_POLYNOMIAL_CHEB) { 2768 psLogMsg(__func__, PS_LOG_WARN, "WARNING: 4-D Chebyshev polynomial vector fitting has not been implemented. Returning NULL.\n"); 2769 } else { 2770 printf("XXX: ERROR: incorrect polynomial type.\n"); 2771 } 2772 if (fErr == NULL) { 2773 psFree(fErr32); 2774 } 2775 return(NULL); 2776 } 2777 2778 2779 psPolynomial1D *psVectorClipFitPolynomial1D_NEW( 2780 psPolynomial1D *poly, 2781 psStats *stats, 2782 const psVector *mask, 2783 psMaskType maskValue, 2784 const psVector *f, 2785 const psVector *fErr, 2786 const psVector *x) 2787 { 2788 // Internal pointers for possibly NULL vectors. 2789 psVector *x32 = NULL; 2790 psVector *fErr32 = NULL; 2791 2792 PS_ASSERT_POLY_NON_NULL(poly, NULL); 2793 PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, NULL); 2794 PS_ASSERT_VECTOR_NON_NULL(f, NULL); 2795 PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F32, NULL); 2796 if (mask != NULL) { 2797 PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL); 2798 PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL); 2799 } 2800 if (x != NULL) { 2801 PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL); 2802 PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F32, NULL); 2803 } 2643 t64 = (psVector *) t; 2644 } 2645 2646 // 2647 // fErr 2648 // 2804 2649 if (fErr != NULL) { 2805 2650 PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, NULL); 2806 PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F32, NULL); 2651 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(fErr, NULL); 2652 if (fErr->type.type != PS_TYPE_F64) { 2653 PS_VECTOR_GEN_F64_FROM_F32(fErr64, fErr); 2654 } else { 2655 fErr64 = (psVector *) fErr; 2656 } 2657 } 2658 2659 if (poly->type == PS_POLYNOMIAL_ORD) { 2660 poly = VectorFitPolynomial4DOrd(poly, mask, maskValue, f64, fErr64, x64, y64, z64, t64); 2661 if (poly == NULL) { 2662 psError(PS_ERR_UNKNOWN, true, "Could not fit polynomial. Returning NULL.\n"); 2663 // Free psVectors that were created for NULL arguments. 2664 if (f->type.type != PS_TYPE_F64) { 2665 psFree(f64); 2666 } 2667 2668 if (x->type.type != PS_TYPE_F64) { 2669 psFree(x64); 2670 } 2671 2672 if (y->type.type != PS_TYPE_F64) { 2673 psFree(y64); 2674 } 2675 2676 if (z->type.type != PS_TYPE_F64) { 2677 psFree(z64); 2678 } 2679 2680 if (t->type.type != PS_TYPE_F64) { 2681 psFree(t64); 2682 } 2683 2684 if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) { 2685 psFree(fErr64); 2686 } 2687 return(NULL); 2688 } 2689 } else if (poly->type == PS_POLYNOMIAL_CHEB) { 2690 if (mask != NULL) { 2691 psLogMsg(__func__, PS_LOG_WARN, "WARNING: ignoring mask and maskValue with Chebyshev polynomials.\n"); 2692 } 2693 psLogMsg(__func__, PS_LOG_WARN, "WARNING: 4-D Chebyshev polynomial vector fitting has not been implemented. Returning NULL.\n"); 2694 psFree(poly); 2695 poly = NULL; 2807 2696 } else { 2808 fErr32 = psVectorAlloc(f->n, PS_TYPE_F32); 2809 PS_VECTOR_SET_F32(fErr32, 1.0); 2810 } 2811 2812 psLogMsg(__func__, PS_LOG_WARN, "WARNING: This function has not been implemented. Returning NULL.\n"); 2697 // Free psVectors that were created for NULL arguments. 2698 if (f->type.type != PS_TYPE_F64) { 2699 psFree(f64); 2700 } 2701 2702 if (x->type.type != PS_TYPE_F64) { 2703 psFree(x64); 2704 } 2705 2706 if (y->type.type != PS_TYPE_F64) { 2707 psFree(y64); 2708 } 2709 2710 if (z->type.type != PS_TYPE_F64) { 2711 psFree(z64); 2712 } 2713 2714 if (t->type.type != PS_TYPE_F64) { 2715 psFree(t64); 2716 } 2717 2718 if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) { 2719 psFree(fErr64); 2720 } 2721 psError(PS_ERR_UNKNOWN, true, "Incorrect polynomial type. Returning NULL.\n"); 2722 } 2723 2724 2813 2725 // Free psVectors that were created for NULL arguments. 2814 if (x == NULL) { 2815 psFree(x32); 2816 } 2817 if (fErr == NULL) { 2818 psFree(fErr32); 2819 } 2820 return(NULL); 2821 } 2822 2823 psPolynomial2D *psVectorClipFitPolynomial2D_NEW( 2824 psPolynomial1D *poly, 2825 psStats *stats, 2826 const psVector *mask, 2827 psMaskType maskValue, 2828 const psVector *f, 2829 const psVector *fErr, 2830 const psVector *x, 2831 const psVector *y) 2832 { 2833 // Internal pointers for possibly NULL vectors. 2834 psVector *fErr32 = NULL; 2835 2836 PS_ASSERT_POLY_NON_NULL(poly, NULL); 2837 PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, NULL); 2838 PS_ASSERT_VECTOR_NON_NULL(f, NULL); 2839 PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F32, NULL); 2840 if (mask != NULL) { 2841 PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL); 2842 PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL); 2843 } 2844 PS_ASSERT_VECTOR_NON_NULL(x, NULL); 2845 PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL); 2846 PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F32, NULL); 2847 PS_ASSERT_VECTOR_NON_NULL(y, NULL); 2848 PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL); 2849 PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F32, NULL); 2850 if (fErr != NULL) { 2851 PS_ASSERT_VECTORS_SIZE_EQUAL(fErr, mask, NULL); 2852 PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F32, NULL); 2853 } else { 2854 fErr32 = psVectorAlloc(f->n, PS_TYPE_F32); 2855 PS_VECTOR_SET_F32(fErr32, 1.0); 2856 } 2857 2858 psLogMsg(__func__, PS_LOG_WARN, "WARNING: This function has not been implemented. Returning NULL.\n"); 2859 if (fErr == NULL) { 2860 psFree(fErr32); 2861 } 2862 return(NULL); 2863 } 2864 2865 psPolynomial3D *psVectorClipFitPolynomial3D_NEW( 2866 psPolynomial1D *poly, 2867 psStats *stats, 2868 const psVector *mask, 2869 psMaskType maskValue, 2870 const psVector *f, 2871 const psVector *fErr, 2872 const psVector *x, 2873 const psVector *y, 2874 const psVector *z) 2875 { 2876 // Internal pointers for possibly NULL vectors. 2877 psVector *fErr32 = NULL; 2878 2879 PS_ASSERT_POLY_NON_NULL(poly, NULL); 2880 PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, NULL); 2881 PS_ASSERT_VECTOR_NON_NULL(f, NULL); 2882 PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F32, NULL); 2883 if (mask != NULL) { 2884 PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL); 2885 PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL); 2886 } 2887 PS_ASSERT_VECTOR_NON_NULL(x, NULL); 2888 PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL); 2889 PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F32, NULL); 2890 PS_ASSERT_VECTOR_NON_NULL(y, NULL); 2891 PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL); 2892 PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F32, NULL); 2893 PS_ASSERT_VECTOR_NON_NULL(z, NULL); 2894 PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, NULL); 2895 PS_ASSERT_VECTOR_TYPE(z, PS_TYPE_F32, NULL); 2896 if (fErr != NULL) { 2897 PS_ASSERT_VECTORS_SIZE_EQUAL(fErr, mask, NULL); 2898 PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F32, NULL); 2899 } else { 2900 fErr32 = psVectorAlloc(f->n, PS_TYPE_F32); 2901 PS_VECTOR_SET_F32(fErr32, 1.0); 2902 } 2903 2904 psLogMsg(__func__, PS_LOG_WARN, "WARNING: This function has not been implemented. Returning NULL.\n"); 2905 if (fErr == NULL) { 2906 psFree(fErr32); 2907 } 2908 return(NULL); 2909 } 2910 2911 psPolynomial4D *psVectorClipFitPolynomial4D_NEW( 2912 psPolynomial1D *poly, 2726 if (f->type.type != PS_TYPE_F64) { 2727 psFree(f64); 2728 } 2729 2730 if (x->type.type != PS_TYPE_F64) { 2731 psFree(x64); 2732 } 2733 2734 if (y->type.type != PS_TYPE_F64) { 2735 psFree(y64); 2736 } 2737 2738 if (z->type.type != PS_TYPE_F64) { 2739 psFree(z64); 2740 } 2741 2742 if (t->type.type != PS_TYPE_F64) { 2743 psFree(t64); 2744 } 2745 2746 if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) { 2747 psFree(fErr64); 2748 } 2749 2750 return(poly); 2751 } 2752 2753 2754 psPolynomial4D *psVectorClipFitPolynomial4D( 2755 psPolynomial4D *poly, 2913 2756 psStats *stats, 2914 2757 const psVector *mask, … … 2921 2764 const psVector *t) 2922 2765 { 2923 // Internal pointers for possibly NULL vectors.2924 psVector *fErr32 = NULL;2925 2926 2766 PS_ASSERT_POLY_NON_NULL(poly, NULL); 2927 2767 PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, NULL); 2768 PS_ASSERT_PTR_NON_NULL(stats, NULL); 2928 2769 PS_ASSERT_VECTOR_NON_NULL(f, NULL); 2929 2770 PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F32, NULL); … … 2938 2779 PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL); 2939 2780 PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F32, NULL); 2940 PS_ASSERT_VECTOR_NON_NULL( z, NULL);2941 PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, NULL);2942 PS_ASSERT_VECTOR_TYPE( z, PS_TYPE_F32, NULL);2781 PS_ASSERT_VECTOR_NON_NULL(f, NULL); 2782 PS_ASSERT_VECTORS_SIZE_EQUAL(f, f, NULL); 2783 PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F32, NULL); 2943 2784 PS_ASSERT_VECTOR_NON_NULL(t, NULL); 2944 2785 PS_ASSERT_VECTORS_SIZE_EQUAL(f, t, NULL); … … 2947 2788 PS_ASSERT_VECTORS_SIZE_EQUAL(fErr, mask, NULL); 2948 2789 PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F32, NULL); 2949 } else {2950 fErr32 = psVectorAlloc(f->n, PS_TYPE_F32);2951 PS_VECTOR_SET_F32(fErr32, 1.0);2952 2790 } 2953 2791 2954 2792 psLogMsg(__func__, PS_LOG_WARN, "WARNING: This function has not been implemented. Returning NULL.\n"); 2955 if (fErr == NULL) { 2956 psFree(fErr32); 2957 } 2793 2958 2794 return(NULL); 2959 2795 } -
trunk/psLib/src/math/psMinimize.h
r4963 r4991 8 8 * @author GLG, MHPCC 9 9 * 10 * @version $Revision: 1.5 6$ $Name: not supported by cvs2svn $11 * @date $Date: 2005-09- 07 23:46:04$10 * @version $Revision: 1.57 $ $Name: not supported by cvs2svn $ 11 * @date $Date: 2005-09-11 22:18:40 $ 12 12 * 13 13 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 85 85 * @return psPolynomial1D* polynomial fit 86 86 */ 87 psPolynomial1D* psVectorFitPolynomial1D( 88 psPolynomial1D* poly, ///< Polynomial to fit 89 const psVector* x, ///< Ordinates (or NULL to just use the indices) 90 const psVector* y, ///< Coordinates 91 const psVector* yErr ///< Errors in coordinates, or NULL 92 ); 93 94 95 96 97 98 psPolynomial1D *psVectorFitPolynomial1D_NEW( 87 88 psPolynomial1D *psVectorFitPolynomial1D( 99 89 psPolynomial1D *poly, 100 90 const psVector *mask, … … 105 95 ); 106 96 107 psPolynomial2D *psVectorFitPolynomial2D _NEW(108 psPolynomial 1D *poly,97 psPolynomial2D *psVectorFitPolynomial2D( 98 psPolynomial2D *poly, 109 99 const psVector *mask, 110 100 psMaskType maskValue, … … 115 105 ); 116 106 117 psPolynomial3D *psVectorFitPolynomial3D _NEW(118 psPolynomial 1D *poly,107 psPolynomial3D *psVectorFitPolynomial3D( 108 psPolynomial3D *poly, 119 109 const psVector *mask, 120 110 psMaskType maskValue, … … 126 116 ); 127 117 128 psPolynomial4D *psVectorFitPolynomial4D _NEW(129 psPolynomial 1D *poly,118 psPolynomial4D *psVectorFitPolynomial4D( 119 psPolynomial4D *poly, 130 120 const psVector *mask, 131 121 psMaskType maskValue, … … 139 129 140 130 141 psPolynomial1D *psVectorClipFitPolynomial1D _NEW(131 psPolynomial1D *psVectorClipFitPolynomial1D( 142 132 psPolynomial1D *poly, 143 133 psStats *stats, … … 149 139 ); 150 140 151 psPolynomial2D *psVectorClipFitPolynomial2D _NEW(152 psPolynomial 1D *poly,141 psPolynomial2D *psVectorClipFitPolynomial2D( 142 psPolynomial2D *poly, 153 143 psStats *stats, 154 144 const psVector *mask, … … 160 150 ); 161 151 162 psPolynomial3D *psVectorClipFitPolynomial3D _NEW(163 psPolynomial 1D *poly,152 psPolynomial3D *psVectorClipFitPolynomial3D( 153 psPolynomial3D *poly, 164 154 psStats *stats, 165 155 const psVector *mask, … … 172 162 ); 173 163 174 psPolynomial4D *psVectorClipFitPolynomial4D _NEW(175 psPolynomial 1D *poly,164 psPolynomial4D *psVectorClipFitPolynomial4D( 165 psPolynomial4D *poly, 176 166 psStats *stats, 177 167 const psVector *mask, … … 183 173 const psVector *z, 184 174 const psVector *t 185 );186 187 188 189 190 /** Derive a one-dimensional spline fit.191 *192 * Given a psSpline1D data structure and a set of x,y vectors, this routine193 * generates the linear splines which satisfy those data points.194 *195 * @return psSpline1D*: the calculated one-dimensional splines196 */197 psSpline1D *psVectorFitSpline1D(198 psSpline1D *mySpline, ///< The spline which will be generated.199 const psVector* x, ///< Ordinates (or NULL to just use the indices)200 const psVector* y, ///< Coordinates201 const psVector* yErr ///< Errors in coordinates, or NULL202 );203 psSpline1D *psVectorFitSpline1DNEW(204 const psVector* x, ///< Ordinates (or NULL to just use the indices)205 const psVector* y, ///< Coordinates206 int nKnots207 175 ); 208 176 … … 233 201 const psVector *yErr, ///< Errors in the measurement coordinates 234 202 psMinimizeLMChi2Func func ///< Specified function 203 ); 204 205 bool psMinimizeGaussNewtonDelta ( 206 psVector *delta, 207 const psVector *params, 208 const psVector *paramMask, 209 const psArray *x, 210 const psVector *y, 211 const psVector *yErr, 212 psMinimizeLMChi2Func func 235 213 ); 236 214 -
trunk/psLib/src/math/psPolynomial.c
r4971 r4991 7 7 * polynomials. It also contains a Gaussian functions. 8 8 * 9 * @version $Revision: 1.1 19$ $Name: not supported by cvs2svn $10 * @date $Date: 2005-09- 08 00:14:31$9 * @version $Revision: 1.120 $ $Name: not supported by cvs2svn $ 10 * @date $Date: 2005-09-11 22:18:40 $ 11 11 * 12 12 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 564 564 of numbers with the specified mean and sigma. 565 565 566 XXX: It's possible to have a different seed ever utime. However, for now,566 XXX: It's possible to have a different seed everytime. However, for now, 567 567 for testability, we use a common seed. 568 568 *****************************************************************************/ -
trunk/psLib/src/math/psSpline.c
r4971 r4991 7 7 * splines. 8 8 * 9 * @version $Revision: 1.12 2$ $Name: not supported by cvs2svn $10 * @date $Date: 2005-09- 08 00:14:32$9 * @version $Revision: 1.123 $ $Name: not supported by cvs2svn $ 10 * @date $Date: 2005-09-11 22:18:40 $ 11 11 * 12 12 * … … 207 207 } 208 208 209 210 /***************************************************************************** 211 CalculateSecondDerivs(): Given a set of x/y vectors corresponding to a 212 tabulated function at n points, this routine calculates the second 213 derivatives of the interpolating cubic splines at those n points. 214 215 The first and second derivatives at the endpoints, undefined in the SDR, are 216 here defined to be 0.0. They can be modified via ypo and yp1. 217 218 This routine assumes that vectors x and y are of the appropriate types/sizes 219 (F32). 220 221 XXX: This algorithm is derived from the Numerical Recipes. 222 XXX: use recycled vectors for internal data. 223 XXX: do an F64 version? 224 *****************************************************************************/ 225 static psF32 *calculateSecondDerivs(const psVector* x, ///< Ordinates (or NULL to just use the indices) 226 const psVector* y) ///< Coordinates 227 { 228 psTrace(".psLib.dataManip.calculateSecondDerivs", 4, 229 "---- calculateSecondDerivs() begin ----\n"); 230 231 psS32 i; 232 psS32 k; 233 psF32 sig; 234 psF32 p; 235 psS32 n = y->n; 236 psF32 *u = (psF32 *) psAlloc(n * sizeof(psF32)); 237 psF32 *derivs2 = (psF32 *) psAlloc(n * sizeof(psF32)); 238 psF32 *X = (psF32 *) & (x->data.F32[0]); 239 psF32 *Y = (psF32 *) & (y->data.F32[0]); 240 psF32 qn; 241 242 // XXX: The second derivatives at the endpoints, undefined in the SDR, 243 // are set in psConstants.h: PS_LEFT_SPLINE_DERIV, PS_RIGHT_SPLINE_DERIV. 244 derivs2[0] = -0.5; 245 u[0]= (3.0/(X[1]-X[0])) * ((Y[1]-Y[0])/(X[1]-X[0]) - PS_LEFT_SPLINE_DERIV); 246 247 for (i=1;i<=(n-2);i++) { 248 sig = (X[i] - X[i-1]) / (X[i+1] - X[i-1]); 249 p = sig * derivs2[i-1] + 2.0; 250 derivs2[i] = (sig - 1.0) / p; 251 u[i] = ((Y[i+1] - Y[i])/(X[i+1]-X[i])) - ((Y[i]-Y[i-1])/(X[i]-X[i-1])); 252 u[i] = ((6.0 * u[i] / (X[i+1] - X[i-1])) - (sig * u[i-1])) / p; 253 254 psTrace(".psLib.dataManip.calculateSecondDerivs", 6, 255 "X[%d] is %f\n", i, X[i]); 256 psTrace(".psLib.dataManip.calculateSecondDerivs", 6, 257 "Y[%d] is %f\n", i, Y[i]); 258 psTrace(".psLib.dataManip.calculateSecondDerivs", 6, 259 "u[%d] is %f\n", i, u[i]); 260 } 261 262 qn = 0.5; 263 u[n-1] = (3.0/(X[n-1]-X[n-2])) * (PS_RIGHT_SPLINE_DERIV - (Y[n-1]-Y[n-2])/(X[n-1]-X[n-2])); 264 derivs2[n-1] = (u[n-1] - (qn * u[n-2])) / ((qn * derivs2[n-2]) + 1.0); 265 266 for (k=(n-2);k>=0;k--) { 267 derivs2[k] = derivs2[k] * derivs2[k+1] + u[k]; 268 269 psTrace(".psLib.dataManip.calculateSecondDerivs", 6, 270 "derivs2[%d] is %f\n", k, derivs2[k]); 271 } 272 273 psFree(u); 274 psTrace(".psLib.dataManip.calculateSecondDerivs", 4, 275 "---- calculateSecondDerivs() end ----\n"); 276 return(derivs2); 277 } 278 279 /*****************************************************************************/ 280 /* FUNCTION IMPLEMENTATION - PUBLIC */ 281 /*****************************************************************************/ 282 283 /***************************************************************************** 284 psVectorFitSpline1D(): given a psSpline1D data structure and a set of x/y 285 vectors, this routine generates the linear or cublic splines which satisfy 286 those data points. 287 288 The formula for calculating the spline polynomials is derived from Numerical 289 Recipes in C. The basic idea is that the polynomial is 290 (1) y = (A * y[0]) + 291 (2) (B * y[1]) + 292 (3) ((((A*A*A)-A) * mySpline->p_psDeriv2[0]) * H^2)/6.0 + 293 (4) ((((B*B*B)-B) * mySpline->p_psDeriv2[1]) * H^2)/6.0 294 Where: 295 H = x[1]-x[0] 296 A = (x[1]-x)/H 297 B = (x-x[0])/H 298 The bulk of the code in this routine is the expansion of the above equation 299 into a polynomial in terms of x, and then saving the coefficients of the 300 powers of x in the spline polynomials. This gets pretty complicated. 301 302 XXX: usage of yErr is not specified in IfA documentation. 303 304 XXX: Is the x argument redundant? What do we do if the x argument is 305 supplied, but does not equal the knots specified in mySpline? 306 307 XXX: can psSpline be NULL? 308 309 XXX: reimplement this assuming that mySpline is NULL? 310 311 XXX: What happens if X is NULL, then an index vector is generated for X, but 312 that index vector lies outside the range vectors in mySpline? 313 314 XXX: Assumes mySpline->knots is psF32. Must add psU32 and psF64. 315 *****************************************************************************/ 316 psSpline1D *psVectorFitSpline1D(psSpline1D *mySpline, ///< The spline which will be generated. 317 const psVector* x, ///< Ordinates (or NULL to just use the indices) 318 const psVector* y, ///< Coordinates 319 const psVector* yErr) ///< Errors in coordinates, or NULL 320 { 321 PS_ASSERT_VECTOR_NON_NULL(y, NULL); 322 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(y, NULL); 323 if (mySpline != NULL) { 324 PS_ASSERT_VECTOR_TYPE(mySpline->knots, PS_TYPE_F32, NULL); 325 } 326 psTrace(".psLib.dataManip.psVectorFitSpline1D", 4, 327 "---- psVectorFitSpline1D() begin ----\n"); 328 psS32 numSplines = (y->n)-1; 329 psF32 tmp; 330 psF32 H; 331 psS32 i; 332 psF32 slope; 333 psVector *x32 = NULL; 334 psVector *y32 = NULL; 335 psVector *yErr32 = NULL; 336 static psVector *x32Static = NULL; 337 static psVector *y32Static = NULL; 338 static psVector *yErr32Static = NULL; 339 340 PS_VECTOR_CONVERT_F64_TO_F32_STATIC(y, y32, y32Static); 341 342 // If yErr==NULL, set all errors equal. 343 if (yErr == NULL) { 344 PS_VECTOR_GEN_YERR_STATIC_F32(yErr32Static, y->n); 345 yErr32 = yErr32Static; 346 } else { 347 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(yErr, NULL); 348 PS_VECTOR_CONVERT_F64_TO_F32_STATIC(yErr, yErr32, yErr32Static); 349 } 350 351 // If x==NULL, create an x32 vector with x values set to (0:n). 352 if (x == NULL) { 353 PS_VECTOR_GEN_X_INDEX_STATIC_F32(x32Static, y->n); 354 x32 = x32Static; 355 } else { 356 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(x, NULL); 357 PS_VECTOR_CONVERT_F64_TO_F32_STATIC(x, x32, x32Static); 358 } 359 PS_ASSERT_VECTORS_SIZE_EQUAL(x32, y32, NULL); 360 PS_ASSERT_VECTORS_SIZE_EQUAL(yErr32, y32, NULL); 361 362 /* 363 XXX: 364 This can not be implemented until SDR states what order spline should be 365 created. 366 Should we error if mySpline is not NULL? 367 Should we error if mySPline is not NULL? 368 */ 369 if (mySpline == NULL) { 370 mySpline = psSpline1DAllocGeneric(x32, 3); 371 } 372 PS_ASSERT_PTR_NON_NULL(mySpline, NULL); 373 PS_ASSERT_INT_NONNEGATIVE(mySpline->n, NULL); 374 375 if (y32->n != (1 + mySpline->n)) { 376 psError(PS_ERR_BAD_PARAMETER_SIZE, true, 377 "data size / spline size mismatch (%d %d)\n", 378 y32->n, mySpline->n); 379 return(NULL); 380 } 381 382 // If these are linear splines, which means their polynomials will have 383 // two coefficients, then we do the simple calculation. 384 if (2 == (mySpline->spline[0])->n) { 385 for (i=0;i<mySpline->n;i++) { 386 slope = (y32->data.F32[i+1] - y32->data.F32[i]) / 387 (mySpline->knots->data.F32[i+1] - mySpline->knots->data.F32[i]); 388 (mySpline->spline[i])->coeff[0] = y32->data.F32[i] - 389 (slope * mySpline->knots->data.F32[i]); 390 391 (mySpline->spline[i])->coeff[1] = slope; 392 psTrace(".psLib.dataManip.psMinimize.psVectorFitSpline1D", 4, 393 "---- mySpline %d coeffs are (%f, %f)\n", i, 394 (mySpline->spline[i])->coeff[0], 395 (mySpline->spline[i])->coeff[1]); 396 } 397 psTrace(".psLib.dataManip.psMinimize.psVectorFitSpline1D", 4, 398 "---- Exiting psVectorFitSpline1D()()\n"); 399 return((psSpline1D *) mySpline); 400 } 401 402 // Check if these are cubic splines (n==4). If not, psError. 403 if (4 != (mySpline->spline[0])->n) { 404 psError(PS_ERR_BAD_PARAMETER_SIZE, true, 405 "Don't know how to generate %d-order splines.", 406 (mySpline->spline[0])->n-1); 407 return(NULL); 408 } 409 410 // If we get here, then we know these are cubic splines. We first 411 // generate the second derivatives at each data point. 412 mySpline->p_psDeriv2 = calculateSecondDerivs(x32, y32); 413 for (i=0;i<y32->n;i++) 414 psTrace(".psLib.dataManip.psVectorFitSpline1D", 6, 415 "Second deriv[%d] is %f\n", i, mySpline->p_psDeriv2[i]); 416 417 // We generate the coefficients of the spline polynomials. I can't 418 // concisely explain how this code works. See above function comments 419 // and Numerical Recipes in C. 420 for (i=0;i<numSplines;i++) { 421 H = x32->data.F32[i+1] - x32->data.F32[i]; 422 psTrace(".psLib.dataManip.psVectorFitSpline1D", 4, 423 "x data (%f - %f) (%f)\n", 424 x32->data.F32[i], 425 x32->data.F32[i+1], H); 426 // 427 // ******** Calculate 0-order term ******** 428 // 429 // From (1) 430 (mySpline->spline[i])->coeff[0] = (y32->data.F32[i] * x32->data.F32[i+1]/H); 431 // From (2) 432 ((mySpline->spline[i])->coeff[0])-= ((y32->data.F32[i+1] * x32->data.F32[i])/H); 433 // From (3) 434 tmp = (x32->data.F32[i+1] * x32->data.F32[i+1] * x32->data.F32[i+1]) / (H * H * H); 435 tmp-= (x32->data.F32[i+1] / H); 436 tmp*= (mySpline->p_psDeriv2)[i] * H * H / 6.0; 437 ((mySpline->spline[i])->coeff[0])+= tmp; 438 // From (4) 439 tmp = -(x32->data.F32[i] * x32->data.F32[i] * x32->data.F32[i]) / (H * H * H); 440 tmp+= (x32->data.F32[i] / H); 441 tmp*= (mySpline->p_psDeriv2)[i+1] * H * H / 6.0; 442 ((mySpline->spline[i])->coeff[0])+= tmp; 443 444 // 445 // ******** Calculate 1-order term ******** 446 // 447 // From (1) 448 (mySpline->spline[i])->coeff[1] = -(y32->data.F32[i]) / H; 449 // From (2) 450 ((mySpline->spline[i])->coeff[1])+= (y32->data.F32[i+1] / H); 451 // From (3) 452 tmp = -3.0 * (x32->data.F32[i+1] * x32->data.F32[i+1]) / (H * H * H); 453 tmp+= (1.0 / H); 454 tmp*= ((mySpline->p_psDeriv2)[i]) * H * H / 6.0; 455 ((mySpline->spline[i])->coeff[1])+= tmp; 456 // From (4) 457 tmp = 3.0 * (x32->data.F32[i] * x32->data.F32[i]) / (H * H * H); 458 tmp-= (1.0 / H); 459 tmp*= ((mySpline->p_psDeriv2)[i+1]) * H * H / 6.0; 460 ((mySpline->spline[i])->coeff[1])+= tmp; 461 462 // 463 // ******** Calculate 2-order term ******** 464 // 465 // From (3) 466 (mySpline->spline[i])->coeff[2] = ((mySpline->p_psDeriv2)[i]) * 3.0 * x32->data.F32[i+1] / (6.0 * H); 467 // From (4) 468 ((mySpline->spline[i])->coeff[2])-= (((mySpline->p_psDeriv2)[i+1]) * 3.0 * x32->data.F32[i] / (6.0 * H)); 469 470 // 471 // ******** Calculate 3-order term ******** 472 // 473 // From (3) 474 (mySpline->spline[i])->coeff[3] = -((mySpline->p_psDeriv2)[i]) / (6.0 * H); 475 // From (4) 476 ((mySpline->spline[i])->coeff[3])+= ((mySpline->p_psDeriv2)[i+1]) / (6.0 * H); 477 478 psTrace(".psLib.dataManip.psVectorFitSpline1D", 6, 479 "(mySpline->spline[%d])->coeff[0] is %f\n", i, (mySpline->spline[i])->coeff[0]); 480 psTrace(".psLib.dataManip.psVectorFitSpline1D", 6, 481 "(mySpline->spline[%d])->coeff[1] is %f\n", i, (mySpline->spline[i])->coeff[1]); 482 psTrace(".psLib.dataManip.psVectorFitSpline1D", 6, 483 "(mySpline->spline[%d])->coeff[2] is %f\n", i, (mySpline->spline[i])->coeff[2]); 484 psTrace(".psLib.dataManip.psVectorFitSpline1D", 6, 485 "(mySpline->spline[%d])->coeff[3] is %f\n", i, (mySpline->spline[i])->coeff[3]); 486 487 } 488 489 psTrace(".psLib.dataManip.psVectorFitSpline1D", 4, 490 "---- psVectorFitSpline1D() end ----\n"); 491 return(mySpline); 492 } 493 494 495 496 497 498 499 500 501 502 /***************************************************************************** 503 psVectorFitSpline1DNEW(): given a psSpline1D data structure and a set of x/y 504 505 xF32 and yF32 are internal psVectors which are used to hold the psF32 versions 506 of the input data, if necessary. xPtr and yPtr are pointers to either xF32 or 507 the x argument. All computation is done on xPtr and yPtr. xF32 and yF32 will 508 simply be psFree() at the end. 509 510 XXX: nKnots makes no sense. This number is always equal to the size of the x 511 an y vectors. 512 513 XXX: How do we specify the spline order? For now, order=3. 514 *****************************************************************************/ 515 #define PS_XXX_SPLINE_ORDER 3 516 psSpline1D *psVectorFitSpline1DNEW(const psVector* x, ///< Ordinates (or NULL to just use the indices) 517 const psVector* y, ///< Coordinates 518 int nKnots) 519 { 520 psTrace(".psLib.dataManip.psVectorFitSpline1D", 4, "---- psVectorFitSpline1DNEW() begin ----\n"); 521 PS_ASSERT_VECTOR_NON_NULL(y, NULL); 522 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(y, NULL); 523 // PS_ASSERT_INT_EQUAL(y->n, nKnots); 524 525 // 526 // The following code ensures that xPtr points to a psF32 version of the 527 // ordinate data. 528 // 529 psVector *xF32 = NULL; 530 psVector *xPtr = NULL; 531 if (x != NULL) { 532 PS_ASSERT_VECTORS_SIZE_EQUAL(x, y, NULL); 533 if (PS_TYPE_F64 == x->type.type) { 534 xF32 = psVectorAlloc(y->n, PS_TYPE_F32); 535 for (psS32 i = 0 ; i < x->n ; i++) { 536 xF32->data.F32[i] = (psF32) x->data.F64[i]; 537 } 538 xPtr = xF32; 539 } else if (PS_TYPE_F32 == x->type.type) { 540 xPtr = (psVector *) x; 541 } else { 542 psError(PS_ERR_UNKNOWN, true, "psVector x is wrong type.\n"); 543 return(NULL); 544 } 545 } else { 546 // If x==NULL, create an x32 vector with x values set to (0:n). 547 xF32 = psVectorAlloc(y->n, PS_TYPE_F32); 548 for (psS32 i = 0 ; i < x->n ; i++) { 549 xF32->data.F32[i] = (psF32) i; 550 } 551 xPtr = xF32; 552 } 553 554 // 555 // If y is of type psF64, then create a new vector yF32 and convert the 556 // y elements. Regardless of y's type, we create a yPtr which will be 557 // used in the remainder of this function. 558 // 559 psVector *yF32 = NULL; 560 psVector *yPtr = NULL; 561 if (PS_TYPE_F64 == y->type.type) { 562 yF32 = psVectorAlloc(y->n, PS_TYPE_F32); 563 for (psS32 i = 0 ; i < y->n ; i++) { 564 yF32->data.F32[i] = (psF32) y->data.F64[i]; 565 } 566 yPtr = yF32; 567 } else { 568 yPtr = (psVector *) y; 569 } 570 571 psSpline1D *mySpline = psSpline1DAllocGeneric(xPtr, PS_XXX_SPLINE_ORDER); 572 573 psS32 numSplines = nKnots - 1; 574 psF32 tmp; 575 psF32 H; 576 psS32 i; 577 psF32 slope; 578 // XXX: get rid of x32 and y32 (this is from old code) 579 psVector *x32 = xPtr; 580 psVector *y32 = yPtr; 581 582 // If these are linear splines, which means their polynomials will have 583 // two coefficients, then we do the simple calculation. 584 if (1 == PS_XXX_SPLINE_ORDER) { 585 for (i=0;i<mySpline->n;i++) { 586 slope = (y32->data.F32[i+1] - y32->data.F32[i]) / 587 (mySpline->knots->data.F32[i+1] - mySpline->knots->data.F32[i]); 588 (mySpline->spline[i])->coeff[0] = y32->data.F32[i] - 589 (slope * mySpline->knots->data.F32[i]); 590 591 (mySpline->spline[i])->coeff[1] = slope; 592 psTrace(".psLib.dataManip.psMinimize.psVectorFitSpline1D", 4, 593 "---- mySpline %d coeffs are (%f, %f)\n", i, 594 (mySpline->spline[i])->coeff[0], 595 (mySpline->spline[i])->coeff[1]); 596 } 597 psTrace(".psLib.dataManip.psMinimize.psVectorFitSpline1D", 4, 598 "---- Exiting psVectorFitSpline1D()()\n"); 599 return((psSpline1D *) mySpline); 600 } 601 602 // 603 // Check if these are cubic splines (n==4). If not, psError. 604 // 605 if (3 != PS_XXX_SPLINE_ORDER) { 606 psError(PS_ERR_BAD_PARAMETER_SIZE, true, 607 "Don't know how to generate %d-order splines.", PS_XXX_SPLINE_ORDER); 608 return(NULL); 609 } 610 611 // 612 // If we get here, then we know these are cubic splines. We first 613 // generate the second derivatives at each data point. 614 // 615 mySpline->p_psDeriv2 = calculateSecondDerivs(x32, y32); 616 for (i=0;i<y32->n;i++) 617 psTrace(".psLib.dataManip.psVectorFitSpline1D", 6, 618 "Second deriv[%d] is %f\n", i, mySpline->p_psDeriv2[i]); 619 620 // 621 // We generate the coefficients of the spline polynomials. I can't 622 // concisely explain how this code works. See above function comments 623 // and Numerical Recipes in C. 624 // 625 for (i=0;i<numSplines;i++) { 626 H = x32->data.F32[i+1] - x32->data.F32[i]; 627 psTrace(".psLib.dataManip.psVectorFitSpline1D", 4, 628 "x data (%f - %f) (%f)\n", 629 x32->data.F32[i], 630 x32->data.F32[i+1], H); 631 // 632 // ******** Calculate 0-order term ******** 633 // 634 // From (1) 635 (mySpline->spline[i])->coeff[0] = (y32->data.F32[i] * x32->data.F32[i+1]/H); 636 // From (2) 637 ((mySpline->spline[i])->coeff[0])-= ((y32->data.F32[i+1] * x32->data.F32[i])/H); 638 // From (3) 639 tmp = (x32->data.F32[i+1] * x32->data.F32[i+1] * x32->data.F32[i+1]) / (H * H * H); 640 tmp-= (x32->data.F32[i+1] / H); 641 tmp*= (mySpline->p_psDeriv2)[i] * H * H / 6.0; 642 ((mySpline->spline[i])->coeff[0])+= tmp; 643 // From (4) 644 tmp = -(x32->data.F32[i] * x32->data.F32[i] * x32->data.F32[i]) / (H * H * H); 645 tmp+= (x32->data.F32[i] / H); 646 tmp*= (mySpline->p_psDeriv2)[i+1] * H * H / 6.0; 647 ((mySpline->spline[i])->coeff[0])+= tmp; 648 649 // 650 // ******** Calculate 1-order term ******** 651 // 652 // From (1) 653 (mySpline->spline[i])->coeff[1] = -(y32->data.F32[i]) / H; 654 // From (2) 655 ((mySpline->spline[i])->coeff[1])+= (y32->data.F32[i+1] / H); 656 // From (3) 657 tmp = -3.0 * (x32->data.F32[i+1] * x32->data.F32[i+1]) / (H * H * H); 658 tmp+= (1.0 / H); 659 tmp*= ((mySpline->p_psDeriv2)[i]) * H * H / 6.0; 660 ((mySpline->spline[i])->coeff[1])+= tmp; 661 // From (4) 662 tmp = 3.0 * (x32->data.F32[i] * x32->data.F32[i]) / (H * H * H); 663 tmp-= (1.0 / H); 664 tmp*= ((mySpline->p_psDeriv2)[i+1]) * H * H / 6.0; 665 ((mySpline->spline[i])->coeff[1])+= tmp; 666 667 // 668 // ******** Calculate 2-order term ******** 669 // 670 // From (3) 671 (mySpline->spline[i])->coeff[2] = ((mySpline->p_psDeriv2)[i]) * 3.0 * x32->data.F32[i+1] / (6.0 * H); 672 // From (4) 673 ((mySpline->spline[i])->coeff[2])-= (((mySpline->p_psDeriv2)[i+1]) * 3.0 * x32->data.F32[i] / (6.0 * H)); 674 675 // 676 // ******** Calculate 3-order term ******** 677 // 678 // From (3) 679 (mySpline->spline[i])->coeff[3] = -((mySpline->p_psDeriv2)[i]) / (6.0 * H); 680 // From (4) 681 ((mySpline->spline[i])->coeff[3])+= ((mySpline->p_psDeriv2)[i+1]) / (6.0 * H); 682 683 psTrace(".psLib.dataManip.psVectorFitSpline1D", 6, 684 "(mySpline->spline[%d])->coeff[0] is %f\n", i, (mySpline->spline[i])->coeff[0]); 685 psTrace(".psLib.dataManip.psVectorFitSpline1D", 6, 686 "(mySpline->spline[%d])->coeff[1] is %f\n", i, (mySpline->spline[i])->coeff[1]); 687 psTrace(".psLib.dataManip.psVectorFitSpline1D", 6, 688 "(mySpline->spline[%d])->coeff[2] is %f\n", i, (mySpline->spline[i])->coeff[2]); 689 psTrace(".psLib.dataManip.psVectorFitSpline1D", 6, 690 "(mySpline->spline[%d])->coeff[3] is %f\n", i, (mySpline->spline[i])->coeff[3]); 691 692 } 693 694 psFree(xF32); 695 psFree(yF32); 696 697 psTrace(".psLib.dataManip.psVectorFitSpline1D", 4, 698 "---- psVectorFitSpline1D() end ----\n"); 699 700 return(mySpline); 701 } 702 703 704 705 706 209 707 /*****************************************************************************/ 210 708 /* FUNCTION IMPLEMENTATION - PUBLIC */ … … 283 781 } 284 782 } else { 285 p rintf("XXX: Generate an error here.\n");783 psError(PS_ERR_UNKNOWN, true, "psVector in has an incorrect type.\n"); 286 784 return(NULL); 287 785 } -
trunk/psLib/src/math/psSpline.h
r4969 r4991 10 10 * @author GLG, MHPCC 11 11 * 12 * @version $Revision: 1.5 4$ $Name: not supported by cvs2svn $13 * @date $Date: 2005-09- 08 00:02:48$12 * @version $Revision: 1.55 $ $Name: not supported by cvs2svn $ 13 * @date $Date: 2005-09-11 22:18:40 $ 14 14 * 15 15 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 118 118 ); 119 119 120 /** Derive a one-dimensional spline fit. 121 * 122 * Given a psSpline1D data structure and a set of x,y vectors, this routine 123 * generates the linear splines which satisfy those data points. 124 * 125 * @return psSpline1D*: the calculated one-dimensional splines 126 */ 127 psSpline1D *psVectorFitSpline1D( 128 psSpline1D *mySpline, ///< The spline which will be generated. 129 const psVector* x, ///< Ordinates (or NULL to just use the indices) 130 const psVector* y, ///< Coordinates 131 const psVector* yErr ///< Errors in coordinates, or NULL 132 ); 133 134 psSpline1D *psVectorFitSpline1DNEW( 135 const psVector* x, ///< Ordinates (or NULL to just use the indices) 136 const psVector* y, ///< Coordinates 137 int nKnots 138 ); 139 120 140 /** \} */ // End of MathGroup Functions 121 141 -
trunk/psLib/src/math/psStats.c
r4962 r4991 17 17 * 18 18 * 19 * @version $Revision: 1.14 4$ $Name: not supported by cvs2svn $20 * @date $Date: 2005-09- 07 21:40:09$19 * @version $Revision: 1.145 $ $Name: not supported by cvs2svn $ 20 * @date $Date: 2005-09-11 22:18:40 $ 21 21 * 22 22 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii … … 746 746 XXX: Write a general routine which smoothes a psVector. This routine should 747 747 call that. Is that possible? 748 749 XXX: This is, or will be, prettier than the previous 750 psVectorSmoothHistGaussian(). However, it is not being used, yet. 748 751 *****************************************************************************/ 749 752 psVector *p_psVectorSmoothHistGaussianNEW(psHistogram *histogram, … … 1549 1552 1550 1553 // Determine the coefficients of the polynomial. 1551 myPoly = psVectorFitPolynomial1D(myPoly, x, y, yErr); 1554 // myPoly = psVectorFitPolynomial1D(myPoly, x, y, yErr); 1555 myPoly = psVectorFitPolynomial1D(myPoly, NULL, 0, y, yErr, x); 1552 1556 if (myPoly == NULL) { 1553 1557 psError(PS_ERR_UNEXPECTED_NULL, … … 1825 1829 psPolynomial1D *tmpPoly = psPolynomial1DAlloc(3, PS_POLYNOMIAL_ORD); 1826 1830 // XXX: What about the NULL x argument? 1827 tmpPoly = psVectorFitPolynomial1D(tmpPoly, NULL, y, NULL);1831 tmpPoly = psVectorFitPolynomial1D(tmpPoly, NULL, 0, y, NULL, NULL); 1828 1832 if (tmpPoly == NULL) { 1829 1833 psLogMsg(__func__, PS_LOG_WARN, … … 1936 1940 } 1937 1941 } else { 1938 p rintf("XXX: Generate an error here.\n");1942 psError(PS_ERR_UNKNOWN, true, "Unallowable vector type.\n"); 1939 1943 return(NULL); 1940 1944 } … … 1950 1954 psVector *Fit1DGaussian(psVector *x, psVector*y) 1951 1955 { 1952 printf("XXX: Generate an error here.\n"); 1953 printf("XXX: Error: This function was previously part of psStats.c, was removed, was purged from CVS, and now needs to be retrieved from tape.\n"); 1956 psError(PS_ERR_UNKNOWN, true, "This code has not been implemented yet.\n"); 1957 // XXX: This function was previously part of psStats.c, was removed, was 1958 // purged from CVS, and now needs to be retrieved from tape. 1959 1954 1960 return(NULL); 1955 1961 } … … 2168 2174 stats->robustLQ = binLo25F32; 2169 2175 stats->robustUQ = binHi25F32; 2170 // XXX: No idea how to calculate stats->stdev2171 2176 2172 2177 // PS_BIN_MIDPOINT(robustHistogram, modeBinNum); 2173 2174 2178 // XXX: I think sumNfit == sumN50 here. 2175 2179 stats->robustNfit = -1;
Note:
See TracChangeset
for help on using the changeset viewer.
