Changeset 10848 for trunk/psLib/src/math/psMinimizePolyFit.c
- Timestamp:
- Dec 28, 2006, 6:38:42 PM (19 years ago)
- File:
-
- 1 edited
-
trunk/psLib/src/math/psMinimizePolyFit.c (modified) (72 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/math/psMinimizePolyFit.c
r10778 r10848 10 10 * @author EAM, IfA 11 11 * 12 * @version $Revision: 1.2 6$ $Name: not supported by cvs2svn $13 * @date $Date: 2006-12- 17 09:43:48$12 * @version $Revision: 1.27 $ $Name: not supported by cvs2svn $ 13 * @date $Date: 2006-12-29 04:38:42 $ 14 14 * 15 15 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 55 55 }\ 56 56 }\ 57 58 // free a local temporary F64 vector (TEMP) which is a copy of a non-F64 vector (ORIG) 59 # define PS_FREE_TEMP_F64_VECTOR(ORIG, TEMP) \ 60 if ((ORIG != NULL) && (ORIG->type.type != PS_TYPE_F64)) { psFree(TEMP); } 57 61 58 62 /*****************************************************************************/ … … 281 285 *****************************************************************************/ 282 286 283 284 287 /****************************************************************************** 285 288 ****************************************************************************** … … 288 291 *****************************************************************************/ 289 292 290 static psPolynomial1D* VectorFitPolynomial1DOrd(291 psPolynomial1D* myPoly,292 const psVector *mask,293 psMaskType maskValue,294 const psVector *f,295 const psVector *fErr,296 const psVector *x);297 298 293 /****************************************************************************** 299 294 vectorFitPolynomial1DCheb(): This routine will fit a Chebyshev … … 301 296 coefficients of that polynomial. 302 297 *****************************************************************************/ 303 static psPolynomial1D *vectorFitPolynomial1DCheb(298 static bool vectorFitPolynomial1DCheb( 304 299 psPolynomial1D* myPoly, 305 300 const psVector *mask, … … 404 399 if (!psMatrixGJSolve(A, B)) { 405 400 psError(PS_ERR_UNKNOWN, false, "Could not solve linear equations. Returning NULL.\n"); 406 psFree(myPoly); 407 myPoly = NULL; 401 goto escape_GJ; 408 402 } else { 409 403 // the first nTerm entries in B correspond directly to the desired … … 427 421 if (ALUD == NULL) { 428 422 psError(PS_ERR_UNKNOWN, false, "Could not do LUD decomposition on matrix. Returning NULL.\n"); 429 psFree(myPoly); 430 myPoly = NULL; 423 goto escape_LUD; 431 424 } else { 432 425 coeffs = psMatrixLUSolve(coeffs, ALUD, B, outPerm); 433 426 if (coeffs == NULL) { 434 427 psError(PS_ERR_UNKNOWN, false, "Could not solve LUD matrix. Returning NULL.\n"); 435 psFree(myPoly); 436 myPoly = NULL; 428 goto escape_LUD; 437 429 } else { 438 430 for (psS32 k = 0; k < numTerms; k++) { … … 441 433 } 442 434 } 443 444 445 435 psFree(ALUD); 446 436 psFree(coeffs); 447 437 psFree(outPerm); 448 438 } 449 450 439 psFree(A); 451 440 psFree(B); 452 453 return(myPoly); 441 return true; 442 443 escape_LUD: 444 // XXX drop the LUD version! 445 psFree(A); 446 psFree(B); 447 return false; 448 449 escape_GJ: 450 psFree(A); 451 psFree(B); 452 return false; 454 453 } 455 454 … … 459 458 x and fErr vectors may be NULL. All non-NULL vectors must be of type 460 459 PS_TYPE_F64. 461 *****************************************************************************/ 462 static psPolynomial1D* VectorFitPolynomial1DOrd( 460 461 XXX EAM : since this is a private function, can we drop the ASSERTS? 462 XXX EAM : can we drop the LUD version? it does not calculate coeffErr values!! 463 *****************************************************************************/ 464 static bool VectorFitPolynomial1DOrd( 463 465 psPolynomial1D* myPoly, 464 466 const psVector *mask, … … 469 471 { 470 472 psTrace("psLib.math", 4, "---- %s() begin ----\n", __func__); 471 PS_ASSERT_POLY_NON_NULL(myPoly, NULL);472 PS_ASSERT_VECTOR_NON_NULL(f, NULL);473 PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F64, NULL);473 PS_ASSERT_POLY_NON_NULL(myPoly, false); 474 PS_ASSERT_VECTOR_NON_NULL(f, false); 475 PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F64, false); 474 476 if (mask) { 475 PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL);476 PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL);477 PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, false); 478 PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false); 477 479 } 478 480 if (x) { 479 PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL);480 PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F64, NULL);481 PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, false); 482 PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F64, false); 481 483 } 482 484 if (fErr) { 483 PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, NULL);484 PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F64, NULL);485 PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, false); 486 PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F64, false); 485 487 } 486 488 … … 510 512 if (!psImageInit(A, 0.0) || !psVectorInit(B, 0.0)) { 511 513 psError(PS_ERR_UNKNOWN, false, "Could initialize data structures A, B. Returning NULL.\n"); 512 psFree(myPoly);513 514 psFree(A); 514 515 psFree(B); 515 516 psTrace("psLib.math", 4, "---- %s() End ----\n", __func__); 516 return (NULL);517 return false; 517 518 } 518 519 … … 596 597 if (!psMatrixGJSolve(A, B)) { 597 598 psError(PS_ERR_UNKNOWN, false, "Could not solve linear equations. Returning NULL.\n"); 598 psFree(myPoly); 599 myPoly = NULL; 599 goto escape_GJ; 600 600 } else { 601 601 // the first nTerm entries in B correspond directly to the desired … … 617 617 if (ALUD == NULL) { 618 618 psError(PS_ERR_UNKNOWN, false, "Could not do LUD decomposition on matrix. Returning NULL.\n"); 619 psFree(myPoly); 620 myPoly = NULL; 619 goto escape_LUD; 621 620 } else { 622 621 coeffs = psMatrixLUSolve(coeffs, ALUD, B, outPerm); 623 622 if (coeffs == NULL) { 624 623 psError(PS_ERR_UNKNOWN, false, "Could not solve LUD matrix. Returning NULL.\n"); 625 psFree(myPoly); 626 myPoly = NULL; 624 goto escape_LUD; 627 625 } else { 628 626 for (psS32 k = 0; k < nTerm; k++) { … … 632 630 } 633 631 } 634 635 632 psFree(ALUD); 636 633 psFree(coeffs); 637 634 psFree(outPerm); 638 635 } 639 640 641 636 psFree(A); 642 637 psFree(B); 643 638 644 639 psTrace("psLib.math", 4, "---- %s() End ----\n", __func__); 645 return (myPoly); 640 return true; 641 642 escape_LUD: 643 psFree(A); 644 psFree(B); 645 return false; 646 647 escape_GJ: 648 psFree(A); 649 psFree(B); 650 return false; 646 651 } 647 652 … … 653 658 conversion only. 654 659 *****************************************************************************/ 655 psPolynomial1D *psVectorFitPolynomial1D(660 bool psVectorFitPolynomial1D( 656 661 psPolynomial1D *poly, 657 662 const psVector *mask, … … 661 666 const psVector *x) 662 667 { 663 // Internal pointers for possibly NULL or mis-typed vectors. 668 PS_ASSERT_POLY_NON_NULL(poly, false); 669 PS_ASSERT_INT_NONNEGATIVE(poly->nX, false); 670 671 PS_ASSERT_VECTOR_NON_NULL(f, false); 672 PS_ASSERT_VECTOR_NON_EMPTY(f, false); 673 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, false); 674 if (mask != NULL) { 675 PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, false); 676 PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false); 677 } 678 if (fErr != NULL) { 679 PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, false); 680 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(fErr, false); 681 } 682 if (x != NULL) { 683 PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, false); 684 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(x, false); 685 } 686 687 // Convert input vectors to F64 if necessary. 688 psVector *f64 = (f->type.type == PS_TYPE_F64) ? (psVector *) f : psVectorCopy (NULL, f, PS_TYPE_F64); 664 689 psVector *x64 = NULL; 665 psVector *f64 = NULL; 690 if (x != NULL) { 691 x64 = (x->type.type == PS_TYPE_F64) ? (psVector *) x : psVectorCopy (NULL, x, PS_TYPE_F64); 692 } 666 693 psVector *fErr64 = NULL; 667 668 PS_ASSERT_POLY_NON_NULL(poly, NULL);669 //PS_ASSERT_INT_NONNEGATIVE(poly->nX, NULL);670 PS_ASSERT_VECTOR_NON_NULL(f, NULL);671 PS_ASSERT_VECTOR_NON_EMPTY(f, NULL);672 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, NULL);673 if (mask != NULL) {674 PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL);675 PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL);676 }677 if (x != NULL) {678 PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL);679 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(x, NULL);680 }681 694 if (fErr != NULL) { 682 PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, NULL); 683 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(fErr, NULL); 684 } 685 686 f64 = (f->type.type == PS_TYPE_F64) ? (psVector *) f : psVectorCopy(NULL, f, PS_TYPE_F64); 687 688 if (x != NULL) { 689 x64 = (x->type.type == PS_TYPE_F64) ? (psVector *) x : psVectorCopy(NULL, x, PS_TYPE_F64); 690 } 691 692 if (fErr != NULL) { 693 fErr64 = (fErr->type.type == PS_TYPE_F64) ? (psVector *) fErr : psVectorCopy(NULL, fErr, PS_TYPE_F64); 694 } 695 fErr64 = (fErr->type.type == PS_TYPE_F64) ? (psVector *) fErr : psVectorCopy (NULL, fErr, PS_TYPE_F64); 696 } 697 698 bool result = true; 695 699 696 700 switch (poly->type) { 697 701 case PS_POLYNOMIAL_ORD: 698 poly= VectorFitPolynomial1DOrd(poly, mask, maskValue, f64, fErr64, x64);699 if ( poly == NULL) {702 result = VectorFitPolynomial1DOrd(poly, mask, maskValue, f64, fErr64, x64); 703 if (!result) { 700 704 psError(PS_ERR_UNKNOWN, false, "Could not fit polynomial. Returning NULL.\n"); 701 705 } … … 703 707 case PS_POLYNOMIAL_CHEB: 704 708 if (mask != NULL) { 705 //psLogMsg(__func__, PS_LOG_WARN, "WARNING: ignoring mask and maskValue with Chebyshev polynomials.\n");709 psLogMsg(__func__, PS_LOG_WARN, "WARNING: ignoring mask and maskValue with Chebyshev polynomials.\n"); 706 710 } 707 711 if (fErr != NULL) { … … 713 717 } 714 718 715 poly = vectorFitPolynomial1DCheb(poly, mask, maskValue, f64, fErr64, x64); 719 result = vectorFitPolynomial1DCheb(poly, mask, maskValue, f64, fErr64, x64); 720 if (!result) { 721 psError(PS_ERR_UNKNOWN, false, "Could not fit polynomial. Returning NULL.\n"); 722 } 716 723 717 724 if (x == NULL) { … … 721 728 default: 722 729 psError(PS_ERR_UNKNOWN, true, "Incorrect polynomial type (%d). Returning NULL.\n", poly->type); 723 poly = NULL;730 result = false; 724 731 break; 725 732 } 726 733 727 734 // Free psVectors that were created for NULL arguments. 728 if (f->type.type != PS_TYPE_F64) { 729 psFree(f64); 730 } 731 732 if ((x != NULL) && (x->type.type != PS_TYPE_F64)) { 733 psFree(x64); 734 } 735 736 if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) { 737 psFree(fErr64); 738 } 739 740 return(poly); 735 PS_FREE_TEMP_F64_VECTOR (f, f64); 736 PS_FREE_TEMP_F64_VECTOR (x, x64); 737 PS_FREE_TEMP_F64_VECTOR (fErr, fErr64); 738 739 return result; 741 740 } 742 741 743 742 // This function accepts F32 and F64 input vectors. 744 psPolynomial1D *psVectorClipFitPolynomial1D(743 bool psVectorClipFitPolynomial1D( 745 744 psPolynomial1D *poly, 746 745 psStats *stats, … … 752 751 { 753 752 psTrace("psLib.math", 3, "---- %s() begin ----\n", __func__); 754 PS_ASSERT_POLY_NON_NULL(poly, NULL); 755 PS_ASSERT_PTR_NON_NULL(stats, NULL); 756 PS_ASSERT_VECTOR_NON_NULL(f, NULL); 757 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, NULL); 758 PS_ASSERT_VECTOR_NON_NULL(mask, NULL); 759 PS_ASSERT_VECTORS_SIZE_EQUAL(mask, f, NULL); 760 PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL); 753 PS_ASSERT_POLY_NON_NULL(poly, false); 754 PS_ASSERT_PTR_NON_NULL(stats, false); 755 PS_ASSERT_VECTOR_NON_NULL(f, false); 756 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, false); 757 PS_ASSERT_VECTOR_NON_NULL(mask, false); 758 PS_ASSERT_VECTORS_SIZE_EQUAL(mask, f, false); 759 PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false); 760 761 761 if (fErr != NULL) { 762 PS_ASSERT_VECTORS_SIZE_EQUAL(fErr, f, NULL);763 PS_ASSERT_VECTOR_TYPE(fErr, f->type.type, NULL);762 PS_ASSERT_VECTORS_SIZE_EQUAL(fErr, f, false); 763 PS_ASSERT_VECTOR_TYPE(fErr, f->type.type, false); 764 764 } 765 765 … … 767 767 psVector *x = NULL; 768 768 if (xIn != NULL) { 769 PS_ASSERT_VECTORS_SIZE_EQUAL(xIn, f, NULL);770 PS_ASSERT_VECTOR_TYPE(xIn, f->type.type, NULL);769 PS_ASSERT_VECTORS_SIZE_EQUAL(xIn, f, false); 770 PS_ASSERT_VECTOR_TYPE(xIn, f->type.type, false); 771 771 x = (psVector *) xIn; 772 772 } else { … … 781 781 } else { 782 782 psError(PS_ERR_UNKNOWN, true, "Error, bad poly type.\n"); 783 return(NULL); 784 } 783 return false; 784 } 785 } 786 787 // the user supplies one of various stats option pairs, 788 // determine the desired mean and stdev STATS options: 789 // XXX enforce consistency? 790 // XXX psStatsGetValue() probably has inverted precedence 791 psStatsOptions meanOption = stats->options & (PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_MEDIAN | PS_STAT_ROBUST_MEDIAN | PS_STAT_CLIPPED_MEAN | PS_STAT_FITTED_MEAN | PS_STAT_FITTED_MEAN_V2); 792 psStatsOptions stdevOption = stats->options & (PS_STAT_SAMPLE_STDEV | PS_STAT_ROBUST_STDEV | PS_STAT_CLIPPED_STDEV | PS_STAT_FITTED_STDEV | PS_STAT_FITTED_STDEV_V2); 793 if (!meanOption) { 794 psError(PS_ERR_UNKNOWN, true, "no valid mean stats option selected"); 795 return false; 796 } 797 if (!stdevOption) { 798 psError(PS_ERR_UNKNOWN, true, "no valid stdev stats option selected"); 799 return false; 785 800 } 786 801 … … 798 813 minClipSigma = fabs(stats->clipSigma); 799 814 } 800 801 psVector *fit = NULL;802 815 psVector *resid = psVectorAlloc(f->n, PS_TYPE_F64); 803 816 804 // eventual expansion: user supplies one of various stats option pairs,805 // eg (SAMPLE_MEAN | SAMPLE_STDEV) and the correct pair is used to806 // evaluate the clipping sigma807 // for now, for the SAMPLE_MEDIAN and SAMPLE_STDEV to be used808 stats->options |= (PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV);809 stats->options |= (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);810 817 psTrace("psLib.math", 4, "stats->clipIter is %d\n", stats->clipIter); 811 818 psTrace("psLib.math", 4, "(minClipSigma, maxClipSigma) is (%.2f, %.2f)\n", minClipSigma, maxClipSigma); … … 822 829 } 823 830 } 824 poly = psVectorFitPolynomial1D(poly, mask, maskValue, f, fErr, x); 825 if (poly == NULL) { 826 psError(PS_ERR_UNKNOWN, false, "Could not fit polynomial. Returning NULL.\n"); 831 if (!psVectorFitPolynomial1D(poly, mask, maskValue, f, fErr, x)) { 832 psError(PS_ERR_UNKNOWN, false, "Could not fit polynomial. Returning false.\n"); 827 833 if (xIn == NULL) { 828 834 psFree(x); 829 835 } 830 return (NULL);831 } 832 833 fit = psPolynomial1DEvalVector(poly, x);836 return false; 837 } 838 839 psVector *fit = psPolynomial1DEvalVector(poly, x); 834 840 if (fit == NULL) { 835 psError(PS_ERR_UNKNOWN, false, "Could not call psPolynomial3DEvalVector(). Returning NULL.\n");841 psError(PS_ERR_UNKNOWN, false, "Could not call psPolynomial3DEvalVector(). Returning false.\n"); 836 842 psFree(resid); 837 return (NULL);843 return false; 838 844 } 839 845 for (psS32 i = 0 ; i < f->n ; i++) { … … 856 862 857 863 if (!psVectorStats(stats, resid, NULL, mask, maskValue)) { 858 psError(PS_ERR_UNKNOWN, false, "Could not compute statistics on the resid vector. Returning NULL.\n"); 859 psFree(resid) 860 psFree(fit) 861 return(NULL); 862 } 863 # if (USE_ROBUST_STATS_FOR_CLIPPING) 864 psTrace("psLib.math", 5, "Median is %f\n", stats->robustMedian); 865 psTrace("psLib.math", 5, "Stdev is %f\n", stats->robustStdev); 866 psF32 minClipValue = -minClipSigma*stats->robustStdev; 867 psF32 maxClipValue = +maxClipSigma*stats->robustStdev; 868 psF32 clipMedian = stats->robustMedian; 869 # else 870 871 psTrace("psLib.math", 5, "Median is %f\n", stats->sampleMedian); 872 psTrace("psLib.math", 5, "Stdev is %f\n", stats->sampleStdev); 873 psF32 minClipValue = -minClipSigma*stats->robustStdev; 874 psF32 maxClipValue = +maxClipSigma*stats->robustStdev; 875 psF32 clipMedian = stats->sampleMedian; 876 # endif 864 psError(PS_ERR_UNKNOWN, false, "Could not compute statistics on the resid vector. Returning false.\n"); 865 psFree(resid); 866 psFree(fit); 867 return false; 868 } 869 870 double meanValue = psStatsGetValue (stats, meanOption); 871 double stdevValue = psStatsGetValue (stats, stdevOption); 872 873 psTrace("psLib.math", 5, "Mean is %f\n", meanValue); 874 psTrace("psLib.math", 5, "Stdev is %f\n", stdevValue); 875 psF32 minClipValue = -minClipSigma*stdevValue; 876 psF32 maxClipValue = +maxClipSigma*stdevValue; 877 877 878 878 // set mask if pts are not valid … … 884 884 } 885 885 886 if ((resid->data.F64[i] - clipMedian > maxClipValue) || (resid->data.F64[i] - clipMedian< minClipValue)) {886 if ((resid->data.F64[i] - meanValue > maxClipValue) || (resid->data.F64[i] - meanValue < minClipValue)) { 887 887 if (f->type.type == PS_TYPE_F64) { 888 888 psTrace("psLib.math", 6, "Masking element %d (%f). resid->data.F64[%d] is %f\n", … … 906 906 // 907 907 psTrace("psLib.math", 6, "keeping %d of %ld pts for fit\n", Nkeep, x->n); 908 stats->clippedNvalues = Nkeep; 908 909 psFree(fit); 909 910 } … … 917 918 918 919 psTrace("psLib.math", 3, "---- %s() end ----\n", __func__); 919 return (poly);920 return true; 920 921 } 921 922 … … 933 934 934 935 *****************************************************************************/ 935 static psPolynomial2D*VectorFitPolynomial2DOrd(936 static bool VectorFitPolynomial2DOrd( 936 937 psPolynomial2D* myPoly, 937 938 const psVector* mask, … … 943 944 { 944 945 psTrace("psLib.math", 4, "---- %s() begin ----\n", __func__); 945 PS_ASSERT_POLY_NON_NULL(myPoly, NULL);946 PS_ASSERT_INT_NONNEGATIVE(myPoly->nX, NULL);947 PS_ASSERT_INT_NONNEGATIVE(myPoly->nY, NULL);948 PS_ASSERT_VECTOR_NON_NULL(f, NULL);949 PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F64, NULL);946 PS_ASSERT_POLY_NON_NULL(myPoly, false); 947 PS_ASSERT_INT_NONNEGATIVE(myPoly->nX, false); 948 PS_ASSERT_INT_NONNEGATIVE(myPoly->nY, false); 949 PS_ASSERT_VECTOR_NON_NULL(f, false); 950 PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F64, false); 950 951 if (fErr != NULL) { 951 PS_ASSERT_VECTORS_SIZE_EQUAL(y, fErr, NULL);952 PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F64, NULL);953 } 954 PS_ASSERT_VECTOR_NON_NULL(x, NULL);955 PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F64, NULL);956 PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL);957 PS_ASSERT_VECTOR_NON_NULL(y, NULL);958 PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F64, NULL);959 PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL);952 PS_ASSERT_VECTORS_SIZE_EQUAL(y, fErr, false); 953 PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F64, false); 954 } 955 PS_ASSERT_VECTOR_NON_NULL(x, false); 956 PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F64, false); 957 PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, false); 958 PS_ASSERT_VECTOR_NON_NULL(y, false); 959 PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F64, false); 960 PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, false); 960 961 if (mask != NULL) { 961 PS_ASSERT_VECTORS_SIZE_EQUAL(y, mask, NULL);962 PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL);962 PS_ASSERT_VECTORS_SIZE_EQUAL(y, mask, false); 963 PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false); 963 964 } 964 965 … … 974 975 if (!psImageInit(A, 0.0) || !psVectorInit(B, 0.0)) { 975 976 psError(PS_ERR_UNKNOWN, false, "Could initialize data structures A, B. Returning NULL.\n"); 976 psFree(myPoly);977 977 psFree(A); 978 978 psFree(B); 979 979 psTrace("psLib.math", 4, "---- %s() End ----\n", __func__); 980 return (NULL);980 return false; 981 981 } 982 982 … … 1040 1040 if (!psMatrixGJSolve(A, B)) { 1041 1041 psError(PS_ERR_UNKNOWN, false, "Could not solve linear equations. Returning NULL.\n"); 1042 psFree( myPoly);1043 myPoly = NULL;1044 } else {1045 // select the appropriate solution entries1046 for (int i = 0; i < nTerm; i++) { 1047 int l = i / nYterm; // x index1048 int m = i % nYterm; // y index1049 myPoly->coeff[l][m] = B->data.F64[i];1050 myPoly->coeffErr[l][m] = sqrt(A->data.F64[i][i]);1051 }1052 }1053 1042 psFree(A); 1043 psFree(B); 1044 return false; 1045 } 1046 1047 // select the appropriate solution entries 1048 for (int i = 0; i < nTerm; i++) { 1049 int l = i / nYterm; // x index 1050 int m = i % nYterm; // y index 1051 myPoly->coeff[l][m] = B->data.F64[i]; 1052 myPoly->coeffErr[l][m] = sqrt(A->data.F64[i][i]); 1053 } 1054 1054 psFree(A); 1055 1055 psFree(B); 1056 1056 1057 1057 psTrace("psLib.math", 4, "---- %s() end ----\n", __func__); 1058 return (myPoly);1058 return true; 1059 1059 } 1060 1060 … … 1065 1065 vector conversion only. 1066 1066 *****************************************************************************/ 1067 psPolynomial2D *psVectorFitPolynomial2D(1067 bool psVectorFitPolynomial2D( 1068 1068 psPolynomial2D *poly, 1069 1069 const psVector *mask, … … 1074 1074 const psVector *y) 1075 1075 { 1076 // Internal pointers for possibly NULL or mis-typed vectors. 1077 psVector *x64 = NULL; 1078 psVector *y64 = NULL; 1079 psVector *f64 = NULL; 1076 PS_ASSERT_POLY_NON_NULL(poly, false); 1077 PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, false); 1078 1079 PS_ASSERT_VECTOR_NON_NULL(f, false); 1080 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, false); 1081 PS_ASSERT_VECTOR_NON_NULL(x, false); 1082 PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, false); 1083 PS_ASSERT_VECTOR_NON_NULL(y, false); 1084 PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, false); 1085 if (mask != NULL) { 1086 PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, false); 1087 PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false); 1088 } 1089 if (fErr != NULL) { 1090 PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, false); 1091 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(fErr, false); 1092 } 1093 1094 // Convert input vectors to F64 if necessary. 1095 psVector *f64 = (f->type.type == PS_TYPE_F64) ? (psVector *) f : psVectorCopy(NULL, f, PS_TYPE_F64); 1096 psVector *x64 = (x->type.type == PS_TYPE_F64) ? (psVector *) x : psVectorCopy(NULL, x, PS_TYPE_F64); 1097 psVector *y64 = (y->type.type == PS_TYPE_F64) ? (psVector *) y : psVectorCopy(NULL, y, PS_TYPE_F64); 1098 1080 1099 psVector *fErr64 = NULL; 1081 1082 PS_ASSERT_POLY_NON_NULL(poly, NULL);1083 PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, NULL);1084 1085 PS_ASSERT_VECTOR_NON_NULL(f, NULL);1086 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, NULL);1087 1088 if (mask != NULL) {1089 PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL);1090 PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL);1091 }1092 PS_ASSERT_VECTOR_NON_NULL(x, NULL);1093 PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL);1094 PS_ASSERT_VECTOR_NON_NULL(y, NULL);1095 PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL);1096 1100 if (fErr != NULL) { 1097 PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, NULL); 1098 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(fErr, NULL); 1099 } 1100 1101 // 1102 // Convert input vectors to F64 if necessary. 1103 // 1104 if (f->type.type != PS_TYPE_F64) { 1105 f64 = psVectorCopy(NULL, f, PS_TYPE_F64); 1106 } else { 1107 f64 = (psVector *) f; 1108 } 1109 1110 if (x->type.type != PS_TYPE_F64) { 1111 x64 = psVectorCopy(NULL, x, PS_TYPE_F64); 1112 } else { 1113 x64 = (psVector *) x; 1114 } 1115 1116 if (y->type.type != PS_TYPE_F64) { 1117 y64 = psVectorCopy(NULL, y, PS_TYPE_F64); 1118 } else { 1119 y64 = (psVector *) y; 1120 } 1121 1122 // 1123 // fErr 1124 // 1125 if (fErr != NULL) { 1126 if (fErr->type.type != PS_TYPE_F64) { 1127 fErr64 = psVectorCopy(NULL, fErr, PS_TYPE_F64); 1128 } else { 1129 fErr64 = (psVector *) fErr; 1130 } 1131 } 1132 1133 if (poly->type == PS_POLYNOMIAL_ORD) { 1134 poly = VectorFitPolynomial2DOrd(poly, mask, maskValue, f64, fErr64, x64, y64); 1135 if (poly == NULL) { 1101 fErr64 = (fErr->type.type == PS_TYPE_F64) ? (psVector *) fErr : psVectorCopy(NULL, fErr, PS_TYPE_F64); 1102 } 1103 1104 bool result = true; 1105 1106 switch (poly->type) { 1107 case PS_POLYNOMIAL_ORD: 1108 result = VectorFitPolynomial2DOrd(poly, mask, maskValue, f64, fErr64, x64, y64); 1109 if (!result) { 1136 1110 psError(PS_ERR_UNKNOWN, true, "Could not fit polynomial. Returning NULL.\n"); 1137 // Free psVectors that were created for NULL arguments. 1138 if (f->type.type != PS_TYPE_F64) { 1139 psFree(f64); 1140 } 1141 1142 if (x->type.type != PS_TYPE_F64) { 1143 psFree(x64); 1144 } 1145 1146 if (y->type.type != PS_TYPE_F64) { 1147 psFree(y64); 1148 } 1149 1150 if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) { 1151 psFree(fErr64); 1152 } 1153 return(NULL); 1154 } 1155 } else if (poly->type == PS_POLYNOMIAL_CHEB) { 1111 } 1112 break; 1113 case PS_POLYNOMIAL_CHEB: 1156 1114 if (mask != NULL) { 1157 1115 psLogMsg(__func__, PS_LOG_WARN, "WARNING: ignoring mask and maskValue with Chebyshev polynomials.\n"); 1158 1116 } 1159 psLogMsg(__func__, PS_LOG_WARN, "WARNING: 2-D Chebyshev polynomial vector fitting has not been implemented. Returning NULL.\n"); 1160 psFree(poly); 1161 poly = NULL; 1162 } else { 1163 // Free psVectors that were created for NULL arguments. 1164 if (f->type.type != PS_TYPE_F64) { 1165 psFree(f64); 1166 } 1167 1168 if (x->type.type != PS_TYPE_F64) { 1169 psFree(x64); 1170 } 1171 1172 if (y->type.type != PS_TYPE_F64) { 1173 psFree(y64); 1174 } 1175 1176 if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) { 1177 psFree(fErr64); 1178 } 1117 psError(PS_ERR_UNKNOWN, true, "2-D Chebyshev polynomial vector fitting has not been implemented. Returning NULL.\n"); 1118 result = false; 1119 break; 1120 default: 1179 1121 psError(PS_ERR_UNKNOWN, true, "Incorrect polynomial type. Returning NULL.\n"); 1180 } 1181 1122 result = false; 1123 break; 1124 } 1182 1125 1183 1126 // Free psVectors that were created for NULL arguments. 1184 if (f->type.type != PS_TYPE_F64) { 1185 psFree(f64); 1186 } 1187 1188 if (x->type.type != PS_TYPE_F64) { 1189 psFree(x64); 1190 } 1191 1192 if (y->type.type != PS_TYPE_F64) { 1193 psFree(y64); 1194 } 1195 1196 if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) { 1197 psFree(fErr64); 1198 } 1199 1200 return(poly); 1127 PS_FREE_TEMP_F64_VECTOR (f, f64); 1128 PS_FREE_TEMP_F64_VECTOR (x, x64); 1129 PS_FREE_TEMP_F64_VECTOR (y, y64); 1130 PS_FREE_TEMP_F64_VECTOR (fErr, fErr64); 1131 1132 return result; 1201 1133 } 1202 1134 1203 psPolynomial2D *psVectorClipFitPolynomial2D(1135 bool psVectorClipFitPolynomial2D( 1204 1136 psPolynomial2D *poly, 1205 1137 psStats *stats, … … 1212 1144 { 1213 1145 psTrace("psLib.math", 3, "---- %s() begin ----\n", __func__); 1214 PS_ASSERT_POLY_NON_NULL(poly, NULL);1215 PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, NULL);1216 PS_ASSERT_PTR_NON_NULL(stats, NULL);1217 PS_ASSERT_VECTOR_NON_NULL(mask, NULL);1218 PS_ASSERT_VECTOR_NON_NULL(f, NULL);1219 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, NULL);1220 if (mask != NULL) { 1221 PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL);1222 PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL);1223 }1224 PS_ASSERT_VECTOR_NON_NULL(x, NULL); 1225 PS_ASSERT_VECTOR S_SIZE_EQUAL(f, x, NULL);1226 PS_ASSERT_VECTOR _TYPE(x, f->type.type, NULL);1227 1228 PS_ASSERT_VECTOR_NON_NULL(y, NULL); 1229 PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL);1230 PS_ASSERT_VECTOR_TYPE( y, f->type.type, NULL);1146 PS_ASSERT_POLY_NON_NULL(poly, false); 1147 PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, false); 1148 PS_ASSERT_PTR_NON_NULL(stats, false); 1149 PS_ASSERT_VECTOR_NON_NULL(mask, false); 1150 PS_ASSERT_VECTOR_NON_NULL(f, false); 1151 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, false); 1152 1153 PS_ASSERT_VECTOR_NON_NULL(x, false); 1154 PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, false); 1155 PS_ASSERT_VECTOR_TYPE(x, f->type.type, false); 1156 1157 PS_ASSERT_VECTOR_NON_NULL(y, false); 1158 PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, false); 1159 PS_ASSERT_VECTOR_TYPE(y, f->type.type, false); 1160 1161 PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, false); 1162 PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false); 1231 1163 1232 1164 if (fErr != NULL) { 1233 PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, NULL); 1234 PS_ASSERT_VECTOR_TYPE(fErr, f->type.type, NULL); 1165 PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, false); 1166 PS_ASSERT_VECTOR_TYPE(fErr, f->type.type, false); 1167 } 1168 1169 // the user supplies one of various stats option pairs, 1170 // determine the desired mean and stdev STATS options: 1171 // XXX enforce consistency? 1172 // XXX psStatsGetValue() probably has inverted precedence 1173 psStatsOptions meanOption = stats->options & (PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_MEDIAN | PS_STAT_ROBUST_MEDIAN | PS_STAT_CLIPPED_MEAN | PS_STAT_FITTED_MEAN | PS_STAT_FITTED_MEAN_V2); 1174 psStatsOptions stdevOption = stats->options & (PS_STAT_SAMPLE_STDEV | PS_STAT_ROBUST_STDEV | PS_STAT_CLIPPED_STDEV | PS_STAT_FITTED_STDEV | PS_STAT_FITTED_STDEV_V2); 1175 if (!meanOption) { 1176 psError(PS_ERR_UNKNOWN, true, "no valid mean stats option selected"); 1177 return false; 1178 } 1179 if (!stdevOption) { 1180 psError(PS_ERR_UNKNOWN, true, "no valid stdev stats option selected"); 1181 return false; 1235 1182 } 1236 1183 … … 1250 1197 psVector *resid = psVectorAlloc(f->n, PS_TYPE_F64); 1251 1198 1252 // eventual expansion: user supplies one of various stats option pairs,1253 // eg (SAMPLE_MEAN | SAMPLE_STDEV) and the correct pair is used to1254 // evaluate the clipping sigma1255 // for now, for the SAMPLE_MEDIAN and SAMPLE_STDEV to be used1256 stats->options |= (PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV);1257 stats->options |= (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);1258 1199 psTrace("psLib.math", 4, "stats->clipIter is %d\n", stats->clipIter); 1259 1200 psTrace("psLib.math", 4, "(minClipSigma, maxClipSigma) is (%.2f, %.2f)\n", minClipSigma, maxClipSigma); … … 1270 1211 } 1271 1212 1272 poly = psVectorFitPolynomial2D(poly, mask, maskValue, f, fErr, x, y); 1273 if (poly == NULL) { 1274 psError(PS_ERR_UNKNOWN, false, "Could not fit a polynomial to the data. Returning NULL.\n"); 1213 if (!psVectorFitPolynomial2D(poly, mask, maskValue, f, fErr, x, y)) { 1214 psError(PS_ERR_UNKNOWN, false, "Could not fit a polynomial to the data. Returning false.\n"); 1275 1215 psFree(resid) 1276 return (NULL);1216 return false; 1277 1217 } 1278 1218 … … 1281 1221 psError(PS_ERR_UNKNOWN, false, "Could not call psPolynomial3DEvalVector(). Returning NULL.\n"); 1282 1222 psFree(resid) 1283 return (NULL);1223 return false; 1284 1224 } 1285 1225 … … 1307 1247 psFree(resid) 1308 1248 psFree(fit) 1309 return(NULL); 1310 } 1311 # if (USE_ROBUST_STATS_FOR_CLIPPING) 1312 psTrace("psLib.math", 5, "Median is %f\n", stats->robustMedian); 1313 psTrace("psLib.math", 5, "Stdev is %f\n", stats->robustStdev); 1314 psTrace("psLib.math", 5, "Sample Median is %f\n", stats->sampleMedian); 1315 psTrace("psLib.math", 5, "Sample Stdev is %f\n", stats->sampleStdev); 1316 psF32 minClipValue = -minClipSigma*stats->robustStdev; 1317 psF32 maxClipValue = +maxClipSigma*stats->robustStdev; 1318 psF32 clipMedian = stats->robustMedian; 1319 # else 1320 1321 psTrace("psLib.math", 5, "Median is %f\n", stats->sampleMedian); 1322 psTrace("psLib.math", 5, "Stdev is %f\n", stats->sampleStdev); 1323 psTrace("psLib.math", 5, "Robust Median is %f\n", stats->robustMedian); 1324 psTrace("psLib.math", 5, "Robust Stdev is %f\n", stats->robustStdev); 1325 psF32 minClipValue = -minClipSigma*stats->robustStdev; 1326 psF32 maxClipValue = +maxClipSigma*stats->robustStdev; 1327 psF32 clipMedian = stats->sampleMedian; 1328 # endif 1249 return false; 1250 } 1251 1252 double meanValue = psStatsGetValue (stats, meanOption); 1253 double stdevValue = psStatsGetValue (stats, stdevOption); 1254 1255 psTrace("psLib.math", 5, "Mean is %f\n", meanValue); 1256 psTrace("psLib.math", 5, "Stdev is %f\n", stdevValue); 1257 psF32 minClipValue = -minClipSigma*stdevValue; 1258 psF32 maxClipValue = +maxClipSigma*stdevValue; 1329 1259 1330 1260 // set mask if pts are not valid … … 1336 1266 } 1337 1267 1338 if ((resid->data.F64[i] - clipMedian > maxClipValue) || (resid->data.F64[i] - clipMedian< minClipValue)) {1268 if ((resid->data.F64[i] - meanValue > maxClipValue) || (resid->data.F64[i] - meanValue < minClipValue)) { 1339 1269 if (fit->type.type == PS_TYPE_F64) { 1340 1270 psTrace("psLib.math", 6, "Masking element %d (%f). resid->data.F64[%d] is %f\n", … … 1352 1282 Nkeep++; 1353 1283 } 1354 1355 1284 psTrace("psLib.math", 4, "keeping %d of %ld pts for fit\n", Nkeep, x->n); 1285 stats->clippedNvalues = Nkeep; 1356 1286 psFree(fit); 1357 1287 } … … 1359 1289 psFree(resid); 1360 1290 1361 if (poly == NULL) {1362 psError(PS_ERR_UNKNOWN, true, "Could not fit a polynomial to the data. Returning NULL.\n");1363 return(NULL);1364 }1365 1366 1291 psTrace("psLib.math", 3, "---- %s() end ----\n", __func__); 1367 return (poly);1292 return true; 1368 1293 } 1369 1294 … … 1381 1306 1382 1307 *****************************************************************************/ 1383 static psPolynomial3D*VectorFitPolynomial3DOrd(1308 static bool VectorFitPolynomial3DOrd( 1384 1309 psPolynomial3D* myPoly, 1385 1310 const psVector* mask, … … 1392 1317 { 1393 1318 psTrace("psLib.math", 4, "---- %s() begin ----\n", __func__); 1394 PS_ASSERT_POLY_NON_NULL(myPoly, NULL);1395 PS_ASSERT_INT_NONNEGATIVE(myPoly->nX, NULL);1396 PS_ASSERT_INT_NONNEGATIVE(myPoly->nY, NULL);1397 PS_ASSERT_INT_NONNEGATIVE(myPoly->nZ, NULL);1398 1399 PS_ASSERT_VECTOR_NON_NULL(f, NULL);1400 PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F64, NULL);1319 PS_ASSERT_POLY_NON_NULL(myPoly, false); 1320 PS_ASSERT_INT_NONNEGATIVE(myPoly->nX, false); 1321 PS_ASSERT_INT_NONNEGATIVE(myPoly->nY, false); 1322 PS_ASSERT_INT_NONNEGATIVE(myPoly->nZ, false); 1323 1324 PS_ASSERT_VECTOR_NON_NULL(f, false); 1325 PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F64, false); 1401 1326 if (fErr != NULL) { 1402 PS_ASSERT_VECTORS_SIZE_EQUAL(y, fErr, NULL);1403 PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F64, NULL);1404 } 1405 PS_ASSERT_VECTOR_NON_NULL(x, NULL);1406 PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F64, NULL);1407 PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL);1408 PS_ASSERT_VECTOR_NON_NULL(y, NULL);1409 PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F64, NULL);1410 PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL);1411 PS_ASSERT_VECTOR_NON_NULL(z, NULL);1412 PS_ASSERT_VECTOR_TYPE(z, PS_TYPE_F64, NULL);1413 PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, NULL);1327 PS_ASSERT_VECTORS_SIZE_EQUAL(y, fErr, false); 1328 PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F64, false); 1329 } 1330 PS_ASSERT_VECTOR_NON_NULL(x, false); 1331 PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F64, false); 1332 PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, false); 1333 PS_ASSERT_VECTOR_NON_NULL(y, false); 1334 PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F64, false); 1335 PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, false); 1336 PS_ASSERT_VECTOR_NON_NULL(z, false); 1337 PS_ASSERT_VECTOR_TYPE(z, PS_TYPE_F64, false); 1338 PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, false); 1414 1339 if (mask != NULL) { 1415 PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL); 1416 PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL); 1417 } 1418 1340 PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, false); 1341 PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false); 1342 } 1419 1343 1420 1344 int nXterm = 1 + myPoly->nX; // Number of x terms … … 1429 1353 if (!psImageInit(A, 0.0) || !psVectorInit(B, 0.0)) { 1430 1354 psError(PS_ERR_UNKNOWN, false, "Could initialize data structures A, B. Returning NULL.\n"); 1431 psFree(myPoly);1432 1355 psFree(A); 1433 1356 psFree(B); 1434 1357 psTrace("psLib.math", 4, "---- %s() End ----\n", __func__); 1435 return (NULL);1358 return false; 1436 1359 } 1437 1360 … … 1511 1434 // The matrices were overflowing, so I switched to LUD. 1512 1435 if (!psMatrixGJSolve(A, B)) { 1513 psFree(A);1514 psFree(B);1515 1436 psError(PS_ERR_UNKNOWN, false, "Failed to perform GaussJordan elimination.\n"); 1516 return(NULL);1437 goto escape_GJ; 1517 1438 } 1518 1439 // select the appropriate solution entries … … 1534 1455 if (ALUD == NULL) { 1535 1456 psError(PS_ERR_UNKNOWN, false, "Could not do LUD decomposition on matrix. Returning NULL.\n"); 1536 psFree(myPoly); 1537 myPoly = NULL; 1457 goto escape_LUD; 1538 1458 } else { 1539 1459 coeffs = psMatrixLUSolve(coeffs, ALUD, B, outPerm); 1540 1460 if (coeffs == NULL) { 1541 1461 psError(PS_ERR_UNKNOWN, false, "Could not solve LUD matrix. Returning NULL.\n"); 1542 psFree(myPoly); 1543 myPoly = NULL; 1462 goto escape_LUD; 1544 1463 } else { 1545 1464 // select the appropriate solution entries … … 1565 1484 1566 1485 psTrace("psLib.math", 4, "---- %s() end ----\n", __func__); 1567 return (myPoly); 1486 return true; 1487 1488 escape_LUD: 1489 psFree(A); 1490 psFree(B); 1491 return false; 1492 1493 escape_GJ: 1494 1495 psFree(A); 1496 psFree(B); 1497 return false; 1568 1498 } 1569 1499 … … 1574 1504 vector conversion only. 1575 1505 *****************************************************************************/ 1576 psPolynomial3D *psVectorFitPolynomial3D(1506 bool psVectorFitPolynomial3D( 1577 1507 psPolynomial3D *poly, 1578 1508 const psVector *mask, … … 1584 1514 const psVector *z) 1585 1515 { 1586 // Internal pointers for possibly NULL or mis-typed vectors. 1587 psVector *x64 = NULL; 1588 psVector *y64 = NULL; 1589 psVector *z64 = NULL; 1590 psVector *f64 = NULL; 1516 PS_ASSERT_POLY_NON_NULL(poly, false); 1517 PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, false); 1518 1519 PS_ASSERT_VECTOR_NON_NULL(f, false); 1520 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, false); 1521 PS_ASSERT_VECTOR_NON_NULL(x, false); 1522 PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, false); 1523 PS_ASSERT_VECTOR_NON_NULL(y, false); 1524 PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, false); 1525 PS_ASSERT_VECTOR_NON_NULL(z, false); 1526 PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, false); 1527 if (mask != NULL) { 1528 PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, false); 1529 PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false); 1530 } 1531 if (fErr != NULL) { 1532 PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, false); 1533 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(fErr, false); 1534 } 1535 1536 // Convert input vectors to F64 if necessary. 1537 psVector *f64 = (f->type.type == PS_TYPE_F64) ? (psVector *) f : psVectorCopy(NULL, f, PS_TYPE_F64); 1538 psVector *x64 = (x->type.type == PS_TYPE_F64) ? (psVector *) x : psVectorCopy(NULL, x, PS_TYPE_F64); 1539 psVector *y64 = (y->type.type == PS_TYPE_F64) ? (psVector *) y : psVectorCopy(NULL, y, PS_TYPE_F64); 1540 psVector *z64 = (z->type.type == PS_TYPE_F64) ? (psVector *) z : psVectorCopy(NULL, z, PS_TYPE_F64); 1541 1591 1542 psVector *fErr64 = NULL; 1592 1593 PS_ASSERT_POLY_NON_NULL(poly, NULL);1594 PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, NULL);1595 1596 PS_ASSERT_VECTOR_NON_NULL(f, NULL);1597 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, NULL);1598 if (mask != NULL) {1599 PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL);1600 PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL);1601 }1602 PS_ASSERT_VECTOR_NON_NULL(x, NULL);1603 PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL);1604 PS_ASSERT_VECTOR_NON_NULL(y, NULL);1605 PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL);1606 PS_ASSERT_VECTOR_NON_NULL(z, NULL);1607 PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, NULL);1608 1543 if (fErr != NULL) { 1609 PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, NULL); 1610 // PS_ASSERT_VECTOR_TYPE(fErr, f->type.type, NULL); 1611 } 1612 1613 // 1614 // Convert input vectors to F64 if necessary. 1615 // 1616 if (f->type.type != PS_TYPE_F64) { 1617 f64 = psVectorCopy(NULL, f, PS_TYPE_F64); 1618 } else { 1619 f64 = (psVector *) f; 1620 } 1621 if (x->type.type != PS_TYPE_F64) { 1622 x64 = psVectorCopy(NULL, x, PS_TYPE_F64); 1623 } else { 1624 x64 = (psVector *) x; 1625 } 1626 if (y->type.type != PS_TYPE_F64) { 1627 y64 = psVectorCopy(NULL, y, PS_TYPE_F64); 1628 } else { 1629 y64 = (psVector *) y; 1630 } 1631 1632 if (z->type.type != PS_TYPE_F64) { 1633 z64 = psVectorCopy(NULL, z, PS_TYPE_F64); 1634 } else { 1635 z64 = (psVector *) z; 1636 } 1637 1638 if (fErr != NULL) { 1639 if (fErr->type.type != PS_TYPE_F64) { 1640 fErr64 = psVectorCopy(NULL, fErr, PS_TYPE_F64); 1641 } else { 1642 fErr64 = (psVector *) fErr; 1643 } 1644 } 1645 1646 if (poly->type == PS_POLYNOMIAL_ORD) { 1647 poly = VectorFitPolynomial3DOrd(poly, mask, maskValue, f64, fErr64, x64, y64, z64); 1648 if (poly == NULL) { 1544 fErr64 = (fErr->type.type == PS_TYPE_F64) ? (psVector *) fErr : psVectorCopy(NULL, fErr, PS_TYPE_F64); 1545 } 1546 1547 bool result = true; 1548 1549 switch (poly->type) { 1550 case PS_POLYNOMIAL_ORD: 1551 result = VectorFitPolynomial3DOrd(poly, mask, maskValue, f64, fErr64, x64, y64, z64); 1552 if (!result) { 1649 1553 psError(PS_ERR_UNKNOWN, true, "Could not fit polynomial. Returning NULL.\n"); 1650 // Free psVectors that were created for NULL arguments. 1651 if (f->type.type != PS_TYPE_F64) { 1652 psFree(f64); 1653 } 1654 1655 if (x->type.type != PS_TYPE_F64) { 1656 psFree(x64); 1657 } 1658 1659 if (y->type.type != PS_TYPE_F64) { 1660 psFree(y64); 1661 } 1662 1663 if (z->type.type != PS_TYPE_F64) { 1664 psFree(z64); 1665 } 1666 1667 if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) { 1668 psFree(fErr64); 1669 } 1670 return(NULL); 1671 } 1672 } else if (poly->type == PS_POLYNOMIAL_CHEB) { 1554 } 1555 break; 1556 case PS_POLYNOMIAL_CHEB: 1673 1557 if (mask != NULL) { 1674 1558 psLogMsg(__func__, PS_LOG_WARN, "WARNING: ignoring mask and maskValue with Chebyshev polynomials.\n"); 1675 1559 } 1676 psLogMsg(__func__, PS_LOG_WARN, "WARNING: 3-D Chebyshev polynomial vector fitting has not been implemented. Returning NULL.\n"); 1677 psFree(poly); 1678 poly = NULL; 1679 } else { 1680 // Free psVectors that were created for NULL arguments. 1681 if (f->type.type != PS_TYPE_F64) { 1682 psFree(f64); 1683 } 1684 1685 if (x->type.type != PS_TYPE_F64) { 1686 psFree(x64); 1687 } 1688 1689 if (y->type.type != PS_TYPE_F64) { 1690 psFree(y64); 1691 } 1692 1693 if (z->type.type != PS_TYPE_F64) { 1694 psFree(z64); 1695 } 1696 1697 if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) { 1698 psFree(fErr64); 1699 } 1560 psError(PS_ERR_UNKNOWN, true, "3-D Chebyshev polynomial vector fitting has not been implemented. Returning NULL.\n"); 1561 result = false; 1562 break; 1563 default: 1700 1564 psError(PS_ERR_UNKNOWN, true, "Incorrect polynomial type. Returning NULL.\n"); 1701 } 1702 1565 result = false; 1566 break; 1567 } 1703 1568 1704 1569 // Free psVectors that were created for NULL arguments. 1705 if (f->type.type != PS_TYPE_F64) { 1706 psFree(f64); 1707 } 1708 1709 if (x->type.type != PS_TYPE_F64) { 1710 psFree(x64); 1711 } 1712 1713 if (y->type.type != PS_TYPE_F64) { 1714 psFree(y64); 1715 } 1716 1717 if (z->type.type != PS_TYPE_F64) { 1718 psFree(z64); 1719 } 1720 1721 if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) { 1722 psFree(fErr64); 1723 } 1724 1725 return(poly); 1570 PS_FREE_TEMP_F64_VECTOR (f, f64); 1571 PS_FREE_TEMP_F64_VECTOR (x, x64); 1572 PS_FREE_TEMP_F64_VECTOR (y, y64); 1573 PS_FREE_TEMP_F64_VECTOR (z, z64); 1574 PS_FREE_TEMP_F64_VECTOR (fErr, fErr64); 1575 1576 return result; 1726 1577 } 1727 1578 1728 psPolynomial3D *psVectorClipFitPolynomial3D(1579 bool psVectorClipFitPolynomial3D( 1729 1580 psPolynomial3D *poly, 1730 1581 psStats *stats, … … 1738 1589 { 1739 1590 psTrace("psLib.math", 3, "---- %s() begin ----\n", __func__); 1740 PS_ASSERT_POLY_NON_NULL(poly, NULL);1741 PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, NULL);1742 PS_ASSERT_PTR_NON_NULL(stats, NULL);1743 PS_ASSERT_VECTOR_NON_NULL(mask, NULL);1744 PS_ASSERT_VECTOR_NON_NULL(f, NULL);1745 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, NULL);1746 if (mask != NULL) { 1747 PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL);1748 PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL);1749 }1750 PS_ASSERT_VECTOR_NON_NULL(x, NULL); 1751 PS_ASSERT_VECTOR S_SIZE_EQUAL(f, x, NULL);1752 PS_ASSERT_VECTOR _TYPE(x, f->type.type, NULL);1753 1754 PS_ASSERT_VECTOR_NON_NULL(y, NULL); 1755 PS_ASSERT_VECTOR S_SIZE_EQUAL(f, y, NULL);1756 PS_ASSERT_VECTOR _TYPE(y, f->type.type, NULL);1757 1758 PS_ASSERT_VECTOR_NON_NULL(z, NULL); 1759 PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, NULL);1760 PS_ASSERT_VECTOR_TYPE( z, f->type.type, NULL);1591 PS_ASSERT_POLY_NON_NULL(poly, false); 1592 PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, false); 1593 PS_ASSERT_PTR_NON_NULL(stats, false); 1594 PS_ASSERT_VECTOR_NON_NULL(mask, false); 1595 PS_ASSERT_VECTOR_NON_NULL(f, false); 1596 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, false); 1597 1598 PS_ASSERT_VECTOR_NON_NULL(x, false); 1599 PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, false); 1600 PS_ASSERT_VECTOR_TYPE(x, f->type.type, false); 1601 1602 PS_ASSERT_VECTOR_NON_NULL(y, false); 1603 PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, false); 1604 PS_ASSERT_VECTOR_TYPE(y, f->type.type, false); 1605 1606 PS_ASSERT_VECTOR_NON_NULL(z, false); 1607 PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, false); 1608 PS_ASSERT_VECTOR_TYPE(z, f->type.type, false); 1609 1610 PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, false); 1611 PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false); 1761 1612 1762 1613 if (fErr != NULL) { 1763 PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, NULL); 1764 PS_ASSERT_VECTOR_TYPE(fErr, f->type.type, NULL); 1614 PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, false); 1615 PS_ASSERT_VECTOR_TYPE(fErr, f->type.type, false); 1616 } 1617 1618 // the user supplies one of various stats option pairs, 1619 // determine the desired mean and stdev STATS options: 1620 // XXX enforce consistency? 1621 // XXX psStatsGetValue() probably has inverted precedence 1622 psStatsOptions meanOption = stats->options & (PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_MEDIAN | PS_STAT_ROBUST_MEDIAN | PS_STAT_CLIPPED_MEAN | PS_STAT_FITTED_MEAN | PS_STAT_FITTED_MEAN_V2); 1623 psStatsOptions stdevOption = stats->options & (PS_STAT_SAMPLE_STDEV | PS_STAT_ROBUST_STDEV | PS_STAT_CLIPPED_STDEV | PS_STAT_FITTED_STDEV | PS_STAT_FITTED_STDEV_V2); 1624 if (!meanOption) { 1625 psError(PS_ERR_UNKNOWN, true, "no valid mean stats option selected"); 1626 return false; 1627 } 1628 if (!stdevOption) { 1629 psError(PS_ERR_UNKNOWN, true, "no valid stdev stats option selected"); 1630 return false; 1765 1631 } 1766 1632 … … 1778 1644 minClipSigma = fabs(stats->clipSigma); 1779 1645 } 1780 psVector *fit = NULL;1781 1646 psVector *resid = psVectorAlloc(f->n, PS_TYPE_F64); 1782 1647 1783 // eventual expansion: user supplies one of various stats option pairs,1784 // eg (SAMPLE_MEAN | SAMPLE_STDEV) and the correct pair is used to1785 // evaluate the clipping sigma1786 // for now, for the SAMPLE_MEDIAN and SAMPLE_STDEV to be used1787 stats->options |= (PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV);1788 stats->options |= (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);1789 1648 psTrace("psLib.math", 4, "stats->clipIter is %d\n", stats->clipIter); 1790 1649 psTrace("psLib.math", 4, "(minClipSigma, maxClipSigma) is (%.2f, %.2f)\n", minClipSigma, maxClipSigma); … … 1801 1660 } 1802 1661 1803 poly = psVectorFitPolynomial3D(poly, mask, maskValue, f, fErr, x, y, z); 1804 if (poly == NULL) { 1662 if (!psVectorFitPolynomial3D(poly, mask, maskValue, f, fErr, x, y, z)) { 1805 1663 psError(PS_ERR_UNKNOWN, false, "Could not fit a polynomial to the data. Returning NULL.\n"); 1806 1664 psFree(resid) 1807 psFree(fit) 1808 return(NULL); 1809 } 1810 fit = psPolynomial3DEvalVector(poly, x, y, z); 1665 return false; 1666 } 1667 psVector *fit = psPolynomial3DEvalVector(poly, x, y, z); 1811 1668 if (fit == NULL) { 1812 1669 psError(PS_ERR_UNKNOWN, false, "Could not call psPolynomial3DEvalVector(). Returning NULL.\n"); 1813 1670 psFree(resid) 1814 return (NULL);1671 return false; 1815 1672 } 1816 1673 for (psS32 i = 0 ; i < f->n ; i++) { … … 1837 1694 psFree(resid) 1838 1695 psFree(fit) 1839 return(NULL); 1840 } 1841 1842 # if (USE_ROBUST_STATS_FOR_CLIPPING) 1843 psTrace("psLib.math", 5, "Median is %f\n", stats->robustMedian); 1844 psTrace("psLib.math", 5, "Stdev is %f\n", stats->robustStdev); 1845 psF32 minClipValue = -minClipSigma*stats->robustStdev; 1846 psF32 maxClipValue = +maxClipSigma*stats->robustStdev; 1847 psF32 clipMedian = stats->robustMedian; 1848 # else 1849 1850 psTrace("psLib.math", 5, "Median is %f\n", stats->sampleMedian); 1851 psTrace("psLib.math", 5, "Stdev is %f\n", stats->sampleStdev); 1852 psF32 minClipValue = -minClipSigma*stats->robustStdev; 1853 psF32 maxClipValue = +maxClipSigma*stats->robustStdev; 1854 psF32 clipMedian = stats->sampleMedian; 1855 # endif 1696 return false; 1697 } 1698 1699 double meanValue = psStatsGetValue (stats, meanOption); 1700 double stdevValue = psStatsGetValue (stats, stdevOption); 1701 1702 psTrace("psLib.math", 5, "Mean is %f\n", meanValue); 1703 psTrace("psLib.math", 5, "Stdev is %f\n", stdevValue); 1704 psF32 minClipValue = -minClipSigma*stdevValue; 1705 psF32 maxClipValue = +maxClipSigma*stdevValue; 1856 1706 1857 1707 // set mask if pts are not valid … … 1863 1713 } 1864 1714 1865 if ((resid->data.F64[i] - clipMedian > maxClipValue) || (resid->data.F64[i] - clipMedian< minClipValue)) {1715 if ((resid->data.F64[i] - meanValue > maxClipValue) || (resid->data.F64[i] - meanValue < minClipValue)) { 1866 1716 if (f->type.type == PS_TYPE_F64) { 1867 1717 psTrace("psLib.math", 6, "Masking element %d (%f). resid->data.F64[%d] is %f\n", … … 1879 1729 Nkeep++; 1880 1730 } 1881 1882 1731 psTrace("psLib.math", 6, "keeping %d of %ld pts for fit\n", Nkeep, x->n); 1732 stats->clippedNvalues = Nkeep; 1883 1733 psFree(fit); 1884 1734 } … … 1886 1736 psFree(resid); 1887 1737 1888 if (poly == NULL) {1889 psError(PS_ERR_UNKNOWN, true, "Could not fit a polynomial to the data. Returning NULL.\n");1890 return(NULL);1891 }1892 1893 1738 psTrace("psLib.math", 3, "---- %s() end ----\n", __func__); 1894 return (poly);1739 return true; 1895 1740 } 1896 1741 … … 1906 1751 1907 1752 *****************************************************************************/ 1908 static psPolynomial4D*VectorFitPolynomial4DOrd(1753 static bool VectorFitPolynomial4DOrd( 1909 1754 psPolynomial4D* myPoly, 1910 1755 const psVector* mask, … … 1918 1763 { 1919 1764 psTrace("psLib.math", 4, "---- %s() begin ----\n", __func__); 1920 PS_ASSERT_POLY_NON_NULL(myPoly, NULL);1921 PS_ASSERT_INT_NONNEGATIVE(myPoly->nX, NULL);1922 PS_ASSERT_INT_NONNEGATIVE(myPoly->nY, NULL);1923 PS_ASSERT_INT_NONNEGATIVE(myPoly->nZ, NULL);1924 PS_ASSERT_INT_NONNEGATIVE(myPoly->nT, NULL);1925 PS_ASSERT_VECTOR_NON_NULL(f, NULL);1926 PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F64, NULL);1765 PS_ASSERT_POLY_NON_NULL(myPoly, false); 1766 PS_ASSERT_INT_NONNEGATIVE(myPoly->nX, false); 1767 PS_ASSERT_INT_NONNEGATIVE(myPoly->nY, false); 1768 PS_ASSERT_INT_NONNEGATIVE(myPoly->nZ, false); 1769 PS_ASSERT_INT_NONNEGATIVE(myPoly->nT, false); 1770 PS_ASSERT_VECTOR_NON_NULL(f, false); 1771 PS_ASSERT_VECTOR_TYPE(f, PS_TYPE_F64, false); 1927 1772 if (fErr != NULL) { 1928 PS_ASSERT_VECTORS_SIZE_EQUAL(y, fErr, NULL);1929 PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F64, NULL);1930 } 1931 PS_ASSERT_VECTOR_NON_NULL(x, NULL);1932 PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F64, NULL);1933 PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL);1934 PS_ASSERT_VECTOR_NON_NULL(y, NULL);1935 PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F64, NULL);1936 PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL);1937 PS_ASSERT_VECTOR_NON_NULL(z, NULL);1938 PS_ASSERT_VECTOR_TYPE(z, PS_TYPE_F64, NULL);1939 PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, NULL);1940 PS_ASSERT_VECTOR_NON_NULL(t, NULL);1941 PS_ASSERT_VECTOR_TYPE(t, PS_TYPE_F64, NULL);1942 PS_ASSERT_VECTORS_SIZE_EQUAL(f, t, NULL);1773 PS_ASSERT_VECTORS_SIZE_EQUAL(y, fErr, false); 1774 PS_ASSERT_VECTOR_TYPE(fErr, PS_TYPE_F64, false); 1775 } 1776 PS_ASSERT_VECTOR_NON_NULL(x, false); 1777 PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_F64, false); 1778 PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, false); 1779 PS_ASSERT_VECTOR_NON_NULL(y, false); 1780 PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_F64, false); 1781 PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, false); 1782 PS_ASSERT_VECTOR_NON_NULL(z, false); 1783 PS_ASSERT_VECTOR_TYPE(z, PS_TYPE_F64, false); 1784 PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, false); 1785 PS_ASSERT_VECTOR_NON_NULL(t, false); 1786 PS_ASSERT_VECTOR_TYPE(t, PS_TYPE_F64, false); 1787 PS_ASSERT_VECTORS_SIZE_EQUAL(f, t, false); 1943 1788 if (mask) { 1944 PS_ASSERT_VECTORS_SIZE_EQUAL(y, mask, NULL);1945 PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL);1789 PS_ASSERT_VECTORS_SIZE_EQUAL(y, mask, false); 1790 PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false); 1946 1791 } 1947 1792 … … 1959 1804 if (!psImageInit(A, 0.0) || !psVectorInit(B, 0.0)) { 1960 1805 psError(PS_ERR_UNKNOWN, false, "Could initialize data structures A, B. Returning NULL.\n"); 1961 psFree(myPoly);1962 1806 psFree(A); 1963 1807 psFree(B); 1964 1808 psTrace("psLib.math", 4, "---- %s() End ----\n", __func__); 1965 return (NULL);1809 return false; 1966 1810 } 1967 1811 … … 2051 1895 // The GaussJordan version was overflowing, so I'm using LUD. 2052 1896 if (!psMatrixGJSolve(A, B)) { 2053 psFree(A);2054 psFree(B);2055 1897 psError(PS_ERR_UNKNOWN, false, "Failed to perform GaussJordan elimination.\n"); 2056 return(NULL);1898 goto escape_GJ; 2057 1899 } 2058 1900 … … 2076 1918 if (ALUD == NULL) { 2077 1919 psError(PS_ERR_UNKNOWN, false, "Could not do LUD decomposition on matrix. Returning NULL.\n"); 2078 psFree(myPoly); 2079 myPoly = NULL; 1920 goto escape_LUD; 2080 1921 } else { 2081 1922 coeffs = psMatrixLUSolve(coeffs, ALUD, B, outPerm); 2082 1923 if (coeffs == NULL) { 2083 1924 psError(PS_ERR_UNKNOWN, false, "Could not solve LUD matrix. Returning NULL.\n"); 2084 psFree(myPoly); 2085 myPoly = NULL; 1925 goto escape_LUD; 2086 1926 } else { 2087 1927 // select the appropriate solution entries … … 2100 1940 } 2101 1941 } 2102 2103 1942 psFree(ALUD); 2104 1943 psFree(coeffs); 2105 1944 psFree(outPerm); 2106 2107 } 2108 1945 } 2109 1946 psFree(A); 2110 1947 psFree(B); 2111 1948 2112 1949 psTrace("psLib.math", 4, "---- %s() end ----\n", __func__); 2113 return (myPoly); 1950 return true; 1951 1952 escape_LUD: 1953 psFree(A); 1954 psFree(B); 1955 return false; 1956 1957 escape_GJ: 1958 psFree(A); 1959 psFree(B); 1960 return false; 2114 1961 } 2115 1962 … … 2120 1967 via vector conversion only. 2121 1968 *****************************************************************************/ 2122 psPolynomial4D *psVectorFitPolynomial4D(1969 bool psVectorFitPolynomial4D( 2123 1970 psPolynomial4D *poly, 2124 1971 const psVector *mask, … … 2131 1978 const psVector *t) 2132 1979 { 2133 // Internal pointers for possibly NULL or mis-typed vectors. 2134 psVector *x64 = NULL; 2135 psVector *y64 = NULL; 2136 psVector *z64 = NULL; 2137 psVector *t64 = NULL; 2138 psVector *f64 = NULL; 1980 PS_ASSERT_POLY_NON_NULL(poly, false); 1981 PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, false); 1982 1983 PS_ASSERT_VECTOR_NON_NULL(f, false); 1984 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, false); 1985 PS_ASSERT_VECTOR_NON_NULL(x, false); 1986 PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, false); 1987 PS_ASSERT_VECTOR_NON_NULL(y, false); 1988 PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, false); 1989 PS_ASSERT_VECTOR_NON_NULL(z, false); 1990 PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, false); 1991 PS_ASSERT_VECTOR_NON_NULL(t, false); 1992 PS_ASSERT_VECTORS_SIZE_EQUAL(f, t, false); 1993 if (mask) { 1994 PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, false); 1995 PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false); 1996 } 1997 if (fErr != NULL) { 1998 PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, false); 1999 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(fErr, false); 2000 } 2001 2002 // Convert input vectors to F64 if necessary. 2003 psVector *f64 = (f->type.type == PS_TYPE_F64) ? (psVector *) f : psVectorCopy(NULL, f, PS_TYPE_F64); 2004 psVector *x64 = (x->type.type == PS_TYPE_F64) ? (psVector *) x : psVectorCopy(NULL, x, PS_TYPE_F64); 2005 psVector *y64 = (y->type.type == PS_TYPE_F64) ? (psVector *) y : psVectorCopy(NULL, y, PS_TYPE_F64); 2006 psVector *z64 = (z->type.type == PS_TYPE_F64) ? (psVector *) z : psVectorCopy(NULL, z, PS_TYPE_F64); 2007 psVector *t64 = (t->type.type == PS_TYPE_F64) ? (psVector *) t : psVectorCopy(NULL, t, PS_TYPE_F64); 2008 2139 2009 psVector *fErr64 = NULL; 2140 2141 PS_ASSERT_POLY_NON_NULL(poly, NULL);2142 PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, NULL);2143 2144 PS_ASSERT_VECTOR_NON_NULL(f, NULL);2145 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, NULL);2146 if (mask) {2147 PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL);2148 PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL);2149 }2150 PS_ASSERT_VECTOR_NON_NULL(x, NULL);2151 PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, NULL);2152 PS_ASSERT_VECTOR_NON_NULL(y, NULL);2153 PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, NULL);2154 PS_ASSERT_VECTOR_NON_NULL(z, NULL);2155 PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, NULL);2156 PS_ASSERT_VECTOR_NON_NULL(t, NULL);2157 PS_ASSERT_VECTORS_SIZE_EQUAL(f, t, NULL);2158 2010 if (fErr != NULL) { 2159 PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, NULL); 2160 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(fErr, NULL); 2161 } 2162 2163 2164 // 2165 // Convert input vector to F64 if necessary. 2166 // 2167 if (f->type.type != PS_TYPE_F64) { 2168 f64 = psVectorCopy(NULL, f, PS_TYPE_F64); 2169 } else { 2170 f64 = (psVector *) f; 2171 } 2172 if (x->type.type != PS_TYPE_F64) { 2173 x64 = psVectorCopy(NULL, x, PS_TYPE_F64); 2174 } else { 2175 x64 = (psVector *) x; 2176 } 2177 if (y->type.type != PS_TYPE_F64) { 2178 y64 = psVectorCopy(NULL, y, PS_TYPE_F64); 2179 } else { 2180 y64 = (psVector *) y; 2181 } 2182 if (z->type.type != PS_TYPE_F64) { 2183 z64 = psVectorCopy(NULL, z, PS_TYPE_F64); 2184 } else { 2185 z64 = (psVector *) z; 2186 } 2187 if (t->type.type != PS_TYPE_F64) { 2188 t64 = psVectorCopy(NULL, t, PS_TYPE_F64); 2189 } else { 2190 t64 = (psVector *) t; 2191 } 2192 // 2193 // fErr 2194 // 2195 if (fErr != NULL) { 2196 if (fErr->type.type != PS_TYPE_F64) { 2197 fErr64 = psVectorCopy(NULL, fErr, PS_TYPE_F64); 2198 } else { 2199 fErr64 = (psVector *) fErr; 2200 } 2201 } 2202 2203 if (poly->type == PS_POLYNOMIAL_ORD) { 2204 poly = VectorFitPolynomial4DOrd(poly, mask, maskValue, f64, fErr64, x64, y64, z64, t64); 2205 if (poly == NULL) { 2011 fErr64 = (fErr->type.type == PS_TYPE_F64) ? (psVector *) fErr : psVectorCopy(NULL, fErr, PS_TYPE_F64); 2012 } 2013 2014 bool result = true; 2015 2016 switch (poly->type) { 2017 case PS_POLYNOMIAL_ORD: 2018 result = VectorFitPolynomial4DOrd(poly, mask, maskValue, f64, fErr64, x64, y64, z64, t64); 2019 if (!result) { 2206 2020 psError(PS_ERR_UNKNOWN, true, "Could not fit polynomial. Returning NULL.\n"); 2207 // Free psVectors that were created for NULL arguments. 2208 if (f->type.type != PS_TYPE_F64) { 2209 psFree(f64); 2210 } 2211 2212 if (x->type.type != PS_TYPE_F64) { 2213 psFree(x64); 2214 } 2215 2216 if (y->type.type != PS_TYPE_F64) { 2217 psFree(y64); 2218 } 2219 2220 if (z->type.type != PS_TYPE_F64) { 2221 psFree(z64); 2222 } 2223 2224 if (t->type.type != PS_TYPE_F64) { 2225 psFree(t64); 2226 } 2227 2228 if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) { 2229 psFree(fErr64); 2230 } 2231 return(NULL); 2232 } 2233 } else if (poly->type == PS_POLYNOMIAL_CHEB) { 2021 } 2022 break; 2023 case PS_POLYNOMIAL_CHEB: 2234 2024 if (mask != NULL) { 2235 2025 psLogMsg(__func__, PS_LOG_WARN, "WARNING: ignoring mask and maskValue with Chebyshev polynomials.\n"); 2236 2026 } 2237 psLogMsg(__func__, PS_LOG_WARN, "WARNING: 4-D Chebyshev polynomial vector fitting has not been implemented. Returning NULL.\n"); 2238 psFree(poly); 2239 poly = NULL; 2240 } else { 2241 // Free psVectors that were created for NULL arguments. 2242 if (f->type.type != PS_TYPE_F64) { 2243 psFree(f64); 2244 } 2245 2246 if (x->type.type != PS_TYPE_F64) { 2247 psFree(x64); 2248 } 2249 2250 if (y->type.type != PS_TYPE_F64) { 2251 psFree(y64); 2252 } 2253 2254 if (z->type.type != PS_TYPE_F64) { 2255 psFree(z64); 2256 } 2257 2258 if (t->type.type != PS_TYPE_F64) { 2259 psFree(t64); 2260 } 2261 2262 if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) { 2263 psFree(fErr64); 2264 } 2027 psError(PS_ERR_UNKNOWN, true, "4-D Chebyshev polynomial vector fitting has not been implemented. Returning NULL.\n"); 2028 result = false; 2029 break; 2030 default: 2265 2031 psError(PS_ERR_UNKNOWN, true, "Incorrect polynomial type. Returning NULL.\n"); 2266 } 2267 2032 result = false; 2033 break; 2034 } 2268 2035 2269 2036 // Free psVectors that were created for NULL arguments. 2270 if (f->type.type != PS_TYPE_F64) { 2271 psFree(f64); 2272 } 2273 2274 if (x->type.type != PS_TYPE_F64) { 2275 psFree(x64); 2276 } 2277 2278 if (y->type.type != PS_TYPE_F64) { 2279 psFree(y64); 2280 } 2281 2282 if (z->type.type != PS_TYPE_F64) { 2283 psFree(z64); 2284 } 2285 2286 if (t->type.type != PS_TYPE_F64) { 2287 psFree(t64); 2288 } 2289 2290 if ((fErr != NULL) && (fErr->type.type != PS_TYPE_F64)) { 2291 psFree(fErr64); 2292 } 2293 2294 return(poly); 2037 PS_FREE_TEMP_F64_VECTOR (f, f64); 2038 PS_FREE_TEMP_F64_VECTOR (x, x64); 2039 PS_FREE_TEMP_F64_VECTOR (y, y64); 2040 PS_FREE_TEMP_F64_VECTOR (z, z64); 2041 PS_FREE_TEMP_F64_VECTOR (t, t64); 2042 PS_FREE_TEMP_F64_VECTOR (fErr, fErr64); 2043 2044 return result; 2295 2045 } 2296 2046 2297 2047 2298 psPolynomial4D *psVectorClipFitPolynomial4D(2048 bool psVectorClipFitPolynomial4D( 2299 2049 psPolynomial4D *poly, 2300 2050 psStats *stats, … … 2309 2059 { 2310 2060 psTrace("psLib.math", 3, "---- %s() begin ----\n", __func__); 2311 PS_ASSERT_POLY_NON_NULL(poly, NULL);2312 PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, NULL);2313 PS_ASSERT_PTR_NON_NULL(stats, NULL);2314 PS_ASSERT_VECTOR_NON_NULL(mask, NULL);2315 PS_ASSERT_VECTOR_NON_NULL(f, NULL);2316 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, NULL);2317 if (mask) { 2318 PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, NULL);2319 PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, NULL);2320 }2321 PS_ASSERT_VECTOR_NON_NULL(x, NULL); 2322 PS_ASSERT_VECTOR S_SIZE_EQUAL(f, x, NULL);2323 PS_ASSERT_VECTOR _TYPE(x, f->type.type, NULL);2324 2325 PS_ASSERT_VECTOR_NON_NULL(y, NULL); 2326 PS_ASSERT_VECTOR S_SIZE_EQUAL(f, y, NULL);2327 PS_ASSERT_VECTOR _TYPE(y, f->type.type, NULL);2328 2329 PS_ASSERT_VECTOR_NON_NULL(z, NULL); 2330 PS_ASSERT_VECTOR S_SIZE_EQUAL(f, z, NULL);2331 PS_ASSERT_VECTOR _TYPE(z, f->type.type, NULL);2332 2333 PS_ASSERT_VECTOR_NON_NULL(t, NULL); 2334 PS_ASSERT_VECTORS_SIZE_EQUAL(f, t, NULL);2335 PS_ASSERT_VECTOR_TYPE( t, f->type.type, NULL);2061 PS_ASSERT_POLY_NON_NULL(poly, false); 2062 PS_ASSERT_POLY_TYPE(poly, PS_POLYNOMIAL_ORD, false); 2063 PS_ASSERT_PTR_NON_NULL(stats, false); 2064 PS_ASSERT_VECTOR_NON_NULL(mask, false); 2065 PS_ASSERT_VECTOR_NON_NULL(f, false); 2066 PS_ASSERT_VECTOR_TYPE_F32_OR_F64(f, false); 2067 2068 PS_ASSERT_VECTOR_NON_NULL(x, false); 2069 PS_ASSERT_VECTORS_SIZE_EQUAL(f, x, false); 2070 PS_ASSERT_VECTOR_TYPE(x, f->type.type, false); 2071 2072 PS_ASSERT_VECTOR_NON_NULL(y, false); 2073 PS_ASSERT_VECTORS_SIZE_EQUAL(f, y, false); 2074 PS_ASSERT_VECTOR_TYPE(y, f->type.type, false); 2075 2076 PS_ASSERT_VECTOR_NON_NULL(z, false); 2077 PS_ASSERT_VECTORS_SIZE_EQUAL(f, z, false); 2078 PS_ASSERT_VECTOR_TYPE(z, f->type.type, false); 2079 2080 PS_ASSERT_VECTOR_NON_NULL(t, false); 2081 PS_ASSERT_VECTORS_SIZE_EQUAL(f, t, false); 2082 PS_ASSERT_VECTOR_TYPE(t, f->type.type, false); 2083 2084 PS_ASSERT_VECTORS_SIZE_EQUAL(f, mask, false); 2085 PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_U8, false); 2336 2086 2337 2087 if (fErr != NULL) { 2338 PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, NULL); 2339 PS_ASSERT_VECTOR_TYPE(fErr, f->type.type, NULL); 2088 PS_ASSERT_VECTORS_SIZE_EQUAL(f, fErr, false); 2089 PS_ASSERT_VECTOR_TYPE(fErr, f->type.type, false); 2090 } 2091 2092 // the user supplies one of various stats option pairs, 2093 // determine the desired mean and stdev STATS options: 2094 // XXX enforce consistency? 2095 // XXX psStatsGetValue() probably has inverted precedence 2096 psStatsOptions meanOption = stats->options & (PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_MEDIAN | PS_STAT_ROBUST_MEDIAN | PS_STAT_CLIPPED_MEAN | PS_STAT_FITTED_MEAN | PS_STAT_FITTED_MEAN_V2); 2097 psStatsOptions stdevOption = stats->options & (PS_STAT_SAMPLE_STDEV | PS_STAT_ROBUST_STDEV | PS_STAT_CLIPPED_STDEV | PS_STAT_FITTED_STDEV | PS_STAT_FITTED_STDEV_V2); 2098 if (!meanOption) { 2099 psError(PS_ERR_UNKNOWN, true, "no valid mean stats option selected"); 2100 return false; 2101 } 2102 if (!stdevOption) { 2103 psError(PS_ERR_UNKNOWN, true, "no valid stdev stats option selected"); 2104 return false; 2340 2105 } 2341 2106 … … 2353 2118 minClipSigma = fabs(stats->clipSigma); 2354 2119 } 2355 psVector *fit = NULL;2356 2120 psVector *resid = psVectorAlloc(f->n, PS_TYPE_F64); 2357 2121 2358 // eventual expansion: user supplies one of various stats option pairs,2359 // eg (SAMPLE_MEAN | SAMPLE_STDEV) and the correct pair is used to2360 // evaluate the clipping sigma2361 // for now, for the SAMPLE_MEDIAN and SAMPLE_STDEV to be used2362 stats->options |= (PS_STAT_SAMPLE_MEDIAN | PS_STAT_SAMPLE_STDEV);2363 stats->options |= (PS_STAT_ROBUST_MEDIAN | PS_STAT_ROBUST_STDEV);2364 2122 psTrace("psLib.math", 4, "stats->clipIter is %d\n", stats->clipIter); 2365 2123 psTrace("psLib.math", 4, "(minClipSigma, maxClipSigma) is (%.2f, %.2f)\n", minClipSigma, maxClipSigma); … … 2376 2134 } 2377 2135 2378 poly = psVectorFitPolynomial4D (poly, mask, maskValue, f, fErr, x, y, z, t); 2379 if (poly == NULL) { 2136 if (!psVectorFitPolynomial4D (poly, mask, maskValue, f, fErr, x, y, z, t)) { 2380 2137 psError(PS_ERR_UNKNOWN, false, "Could not fit a polynomial to the data. Returning NULL.\n"); 2381 2138 psFree(resid) 2382 psFree(fit) 2383 return(NULL); 2384 } 2385 2386 fit = psPolynomial4DEvalVector (poly, x, y, z, t); 2139 return false; 2140 } 2141 2142 psVector *fit = psPolynomial4DEvalVector (poly, x, y, z, t); 2387 2143 if (fit == NULL) { 2388 2144 psError(PS_ERR_UNKNOWN, false, "Could not call psPolynomial4DEvalVector(). Returning NULL.\n"); 2389 2145 psFree(resid) 2390 return (NULL);2146 return false; 2391 2147 } 2392 2148 for (psS32 i = 0 ; i < f->n ; i++) { … … 2413 2169 psFree(resid) 2414 2170 psFree(fit) 2415 return(NULL); 2416 } 2417 # if (USE_ROBUST_STATS_FOR_CLIPPING) 2418 psTrace("psLib.math", 5, "Median is %f\n", stats->robustMedian); 2419 psTrace("psLib.math", 5, "Stdev is %f\n", stats->robustStdev); 2420 psF32 minClipValue = -minClipSigma*stats->robustStdev; 2421 psF32 maxClipValue = +maxClipSigma*stats->robustStdev; 2422 psF32 clipMedian = stats->robustMedian; 2423 # else 2424 2425 psTrace("psLib.math", 5, "Median is %f\n", stats->sampleMedian); 2426 psTrace("psLib.math", 5, "Stdev is %f\n", stats->sampleStdev); 2427 psF32 minClipValue = -minClipSigma*stats->robustStdev; 2428 psF32 maxClipValue = +maxClipSigma*stats->robustStdev; 2429 psF32 clipMedian = stats->sampleMedian; 2430 # endif 2171 return false; 2172 } 2173 2174 double meanValue = psStatsGetValue (stats, meanOption); 2175 double stdevValue = psStatsGetValue (stats, stdevOption); 2176 2177 psTrace("psLib.math", 5, "Mean is %f\n", meanValue); 2178 psTrace("psLib.math", 5, "Stdev is %f\n", stdevValue); 2179 psF32 minClipValue = -minClipSigma*stdevValue; 2180 psF32 maxClipValue = +maxClipSigma*stdevValue; 2431 2181 2432 2182 // set mask if pts are not valid … … 2438 2188 } 2439 2189 2440 if ((resid->data.F64[i] - clipMedian > maxClipValue) || (resid->data.F64[i] - clipMedian< minClipValue)) {2190 if ((resid->data.F64[i] - meanValue > maxClipValue) || (resid->data.F64[i] - meanValue < minClipValue)) { 2441 2191 if (f->type.type == PS_TYPE_F64) { 2442 2192 psTrace("psLib.math", 6, "Masking element %d (%f). resid->data.F64[%d] is %f\n", … … 2452 2202 continue; 2453 2203 } 2454 2455 2204 Nkeep++; 2456 2205 } 2457 2458 2206 psTrace("psLib.math", 6, "keeping %d of %ld pts for fit\n", Nkeep, x->n); 2207 stats->clippedNvalues = Nkeep; 2459 2208 psFree (fit); 2460 2209 } … … 2462 2211 psFree (resid); 2463 2212 2464 if (poly == NULL) {2465 psError(PS_ERR_UNKNOWN, true, "Could not fit a polynomial to the data. Returning NULL.\n");2466 return(NULL);2467 }2468 2469 2213 psTrace("psLib.math", 3, "---- %s() end ----\n", __func__); 2470 return (poly);2214 return true; 2471 2215 }
Note:
See TracChangeset
for help on using the changeset viewer.
