IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Sep 28, 2004, 1:27:37 PM (22 years ago)
Author:
gusciora
Message:

Chebyshev polynomila fitting routines.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/psLib/src/dataManip/psMinimize.c

    r1907 r1921  
    99 *  @author George Gusciora, MHPCC
    1010 *
    11  *  @version $Revision: 1.49 $ $Name: not supported by cvs2svn $
    12  *  @date $Date: 2004-09-27 23:41:42 $
     11 *  @version $Revision: 1.50 $ $Name: not supported by cvs2svn $
     12 *  @date $Date: 2004-09-28 23:27:37 $
    1313 *
    1414 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    656656
    657657
    658 /*****************************************************************************
    659 CreateChebyshevPolys(n): this routine takes as input the required order n,
    660 and returns as output as a pointer to an array of n psPolynomial1D
    661 structures, corresponding to the first n Chebyshev polynomials.
    662  
    663 XXX: The output should be static since the Chebyshev polynomials might be
    664 used frequently and the data structure created here does not contain the
    665 outer coefficients of the Chebyshev polynomials.
     658/******************************************************************************
     659p_psVectorFitPolynomial1DCheb():  This routine will fit a Chebyshev
     660polynomial of degree myPoly to the data points (x, y) and return the
     661coefficients of that polynomial.
     662 
     663XXX: yErr is currently ignored.
     664 
     665XXX: must add type F32 (currently F64 only).
     666 
     667XXX: Use private name?
    666668 *****************************************************************************/
    667 static psPolynomial1D **CreateChebyshevPolys(int maxChebyPoly)
    668 {
    669     psPolynomial1D **chebPolys = NULL;
    670     int i = 0;
    671     int j = 0;
    672 
    673     chebPolys = (psPolynomial1D **) psAlloc(maxChebyPoly * sizeof(psPolynomial1D *));
    674     for (i = 0; i < maxChebyPoly; i++) {
    675         chebPolys[i] = psPolynomial1DAlloc(i + 1, PS_POLYNOMIAL_ORD);
    676     }
    677 
    678     // Create the Chebyshev polynomials.
    679     // Polynomial i has i-th order.
    680     chebPolys[0]->coeff[0] = 1;
    681     chebPolys[1]->coeff[1] = 1;
    682     for (i = 2; i < maxChebyPoly; i++) {
    683         for (j = 0; j < chebPolys[i - 1]->n; j++) {
    684             chebPolys[i]->coeff[j + 1] = 2 * chebPolys[i - 1]->coeff[j];
    685         }
    686         for (j = 0; j < chebPolys[i - 2]->n; j++) {
    687             chebPolys[i]->coeff[j] -= chebPolys[i - 2]->coeff[j];
    688         }
    689     }
    690 
    691     return (chebPolys);
    692 }
    693 
    694 
    695 
    696 psPolynomial1D* p_psVectorFitPolynomial1DCheby(psPolynomial1D* myPoly,
     669psPolynomial1D *p_psVectorFitPolynomial1DCheby(psPolynomial1D* myPoly,
    697670        const psVector* restrict x,
    698671        const psVector* restrict y,
     
    702675    int k;
    703676    int n = x->n;
    704     psPolynomial1D **chebPolys = CreateChebyshevPolys(myPoly->n);
    705     ;
    706     float fac;
    707     float sum;
    708     /*
    709         fac = 2.0/((float) n);
    710         for (j=0;j<n;j++) {
    711             sum = 0.0;
    712             for (k=0;k<n;k++) {
    713                 sum+= y->data.F64[k] *
    714                       cos(M_PI * ((float) j) * (0.5 + ((float) k)) / ((float) n));
    715     //            sum+= y->data.F64[k] *
    716     //                  cos(M_PI * ((float) j) * (-0.5 + ((float) k)) / ((float) n)) *
    717     //                  cos(M_PI * (-0.5 + ((float) k)) / ((float) n));
    718      
    719             }
    720             myPoly->coeff[j] = fac * sum;
    721      
    722         }
    723         return(myPoly);
    724     */
    725 
     677    psVector *f = psVectorAlloc(n, PS_TYPE_F64);
     678    double fac;
     679    double sum;
     680    // XXX: Use static memory here.
     681    psScalar *tmpScalar = psScalarAlloc(0.0, PS_TYPE_F32);
     682    psScalar *fScalar;
     683
     684
     685    // XXX: These assignments appear too simple to warrant code and
     686    // variable declarations.  I retain them here to maintain coherence
     687    // with the NR code.
     688    double min = -1.0;
     689    double max = 1.0;
     690    double bma = 0.5 * (max-min);  // 1
     691    double bpa = 0.5 * (max+min);  // 0
     692
     693    // XXX: Eliminate this later by generating a F64 version of the
     694    // LaGrange interpolation routines.
     695    PS_VECTOR_F64_TO_F32(x, x32);
     696    PS_VECTOR_F64_TO_F32(y, y32);
     697
     698    // In this loop, we first calculate the values of X for which the
     699    // Chebyshev polynomials are zero (see NR, section 5.4).  Then we
     700    // calculate the value of the function we are fitting the Chebyshev
     701    // polynomials to at those values of X.  This is a bit tricky since
     702    // we don't know that function.  So, we instead do 3-order LaGrange
     703    // interpolation at the point X for the psVectors x,y for which we
     704    // are fitting this ChebyShev polynomial to.
     705
     706    for (int i=0;i<n;i++) {
     707        // NR 5.8.4
     708        double Y = cos(M_PI * (0.5 + ((float) i)) / ((float) n));
     709        double X = (Y + bma + bpa) - 1.0;
     710        tmpScalar->data.F32 = (float) X;
     711
     712        // We interpolate against are tabluated x,y vectors to determine the
     713        // function value at X.
     714        fScalar = p_psVectorInterpolate((psVector *) x32, (psVector *) y32,
     715                                        3, tmpScalar);
     716        f->data.F64[i] = (double) fScalar->data.F32;
     717
     718        psTrace(".psLib.dataManip.p_psVectorFitPolynomial1DCheby", 6,
     719                "(x, X, y, f(X)) is (%f, %f, %f, %f)\n",
     720                x->data.F64[i], X, y->data.F64[i], f->data.F64[i]);
     721    }
     722
     723    // We have the values for f() at the zero points, we now calculate the
     724    // coefficients of the Chebyshev polynomial: NR 5.8.7.
    726725    fac = 2.0/((float) n);
    727     for (j=0;j<myPoly->n;j++) {
     726    for (j=0;j<n;j++) {
    728727        sum = 0.0;
    729         for (k=1;k<n;k++) {
    730             sum+= (y->data.F64[k] *
    731                    psPolynomial1DEval((float) x->data.F64[k], chebPolys[j]));
     728        for (k=0;k<n;k++) {
     729            sum+= f->data.F64[k] *
     730                  cos(M_PI * ((float) j) * (0.5 + ((float) k)) / ((float) n));
    732731        }
    733732        myPoly->coeff[j] = fac * sum;
    734733    }
     734
     735    // XXX: Must free memory.
     736    psFree(x32);
     737    psFree(y32);
     738    psFree(tmpScalar);
     739    psFree(fScalar);
    735740    return(myPoly);
    736741}
    737742
    738743/******************************************************************************
    739 psVectorFitPolynomial1D():  This routine must fit a polynomial of degree
    740 myPoly to the data points (x, y) and return the coefficients of that
    741 polynomial, as well as the error for each data point (yErr).
     744p_psVectorFitPolynomial1DOrd():  This routine will fit an ordinary
     745polynomial of degree myPoly to the data points (x, y) and return the
     746coefficients of that polynomial.
    742747 
    743748XXX: yErr is currently ignored.
     
    745750XXX: must add type F32 (currently F64 only).
    746751 
    747 XXX: Must do: if x==NULL, use the index vector (???).
    748  
    749 XXX: Must do: if yErr==NULL, set all errors equal.
    750  
    751 XXX: type is currently ignored.  Must implement this for Chebyshev
    752 polynomials.
     752XXX: Use private name?
    753753 *****************************************************************************/
    754 psPolynomial1D* psVectorFitPolynomial1D(psPolynomial1D* myPoly,
    755                                         const psVector* restrict x,
    756                                         const psVector* restrict y,
    757                                         const psVector* restrict yErr)
     754psPolynomial1D* p_psVectorFitPolynomial1DOrd(psPolynomial1D* myPoly,
     755        const psVector* restrict x,
     756        const psVector* restrict y,
     757        const psVector* restrict yErr)
    758758{
    759     // XXX: Create a p_psVectorFitPolynomial1DOrd() function.  Here, we
    760     // should only be calling that or the Cheby function.
    761 
    762     if (myPoly->type == PS_POLYNOMIAL_CHEB) {
    763         return(p_psVectorFitPolynomial1DCheby(myPoly, x, y, yErr));
    764     }
    765 
    766759    int polyOrder = myPoly->n;
    767760    psImage* A = NULL;
     
    783776    // }
    784777
     778    // XXX: Some of these are redundant.
    785779    PS_CHECK_NULL_1DPOLY(myPoly);
    786780    PS_CHECK_NULL_VECTOR(y);
    787781    PS_CHECK_EMPTY_VECTOR(y);
    788 
    789     // XXX: Verify that this is the correct action.
    790     if (x == NULL) {
    791         x = psVectorAlloc(y->n, PS_TYPE_F32);
    792         for (i=0;i<x->n;i++) {
    793             x->data.F32[i] = (float) i;
    794         }
    795     }
    796 
    797782    PS_CHECK_EMPTY_VECTOR(x);
    798783    PS_CHECK_NULL_VECTOR(yErr);
     
    863848    return (myPoly);
    864849}
     850
     851/******************************************************************************
     852psVectorFitPolynomial1D():  This routine must fit a polynomial of degree
     853myPoly to the data points (x, y) and return the coefficients of that
     854polynomial.
     855 
     856XXX: yErr is currently ignored.
     857 
     858XXX: must add type F32 (currently F64 only).
     859 *****************************************************************************/
     860psPolynomial1D* psVectorFitPolynomial1D(psPolynomial1D* myPoly,
     861                                        const psVector* restrict x,
     862                                        const psVector* restrict y,
     863                                        const psVector* restrict yErr)
     864{
     865    bool mustFreeMyYErr = false;
     866    bool mustFreemyX = false;
     867    int i;
     868    psPolynomial1D *tmpPoly;
     869    psVector *myX = NULL;
     870    psVector *myYErr = NULL;
     871
     872    PS_CHECK_NULL_1DPOLY(myPoly);
     873    PS_CHECK_NULL_VECTOR(y);
     874    PS_CHECK_EMPTY_VECTOR(y);
     875
     876    // If yErr==NULL, set all errors equal.
     877    if (yErr == NULL) {
     878        myYErr = psVectorAlloc(y->n, y->type.type);
     879        mustFreeMyYErr = true;
     880
     881        if (y->type.type == PS_TYPE_F32) {
     882            for (i=0;i<yErr->n;i++) {
     883                myYErr->data.F32[i] = 1.0;
     884            }
     885        } else if (y->type.type == PS_TYPE_F64) {
     886            for (i=0;i<yErr->n;i++) {
     887                myYErr->data.F64[i] = 1.0;
     888            }
     889        }
     890    } else {
     891        myYErr = (psVector *) yErr;
     892    }
     893
     894    // If x==NULL, create an myX vector with x values set to (0:n), and if
     895    // this is a CHebyshev polynomial, we must scale to (-1:1).
     896
     897    // XXX: Verify that this is the correct action.
     898    if (x == NULL) {
     899        myX = psVectorAlloc(y->n, y->type.type);
     900        mustFreemyX = true;
     901
     902        if (y->type.type == PS_TYPE_F32) {
     903            if (myPoly->type == PS_POLYNOMIAL_ORD) {
     904                for (i=0;i<yErr->n;i++) {
     905                    myX->data.F32[i] = (float) i;
     906                }
     907            } else if (myPoly->type == PS_POLYNOMIAL_CHEB) {
     908                float min = 0.0;
     909                float max = (float) (y->n - 1);
     910
     911                for (i=0;i<yErr->n;i++) {
     912                    myX->data.F32[i] = (((float) i) - 0.5 * (min + max)) /
     913                                       (0.5 * (max - min));
     914                }
     915            }
     916        } else if (y->type.type == PS_TYPE_F64) {
     917            if (myPoly->type == PS_POLYNOMIAL_ORD) {
     918                for (i=0;i<yErr->n;i++) {
     919                    myX->data.F64[i] = (float) i;
     920                }
     921            } else if (myPoly->type == PS_POLYNOMIAL_CHEB) {
     922                double min = 0.0;
     923                double max = (double) (y->n - 1);
     924
     925                for (i=0;i<yErr->n;i++) {
     926                    myX->data.F64[i] = (((float) i) - 0.5 * (min + max)) /
     927                                       (0.5 * (max - min));
     928                }
     929            }
     930        }
     931    } else {
     932        myX = (psVector *) x;
     933    }
     934
     935    PS_CHECK_VECTOR_SIZE_EQUAL(y, myX);
     936    PS_CHECK_VECTOR_SIZE_EQUAL(y, myYErr);
     937
     938    // Call the appropriate vector fitting routine.
     939    if (myPoly->type == PS_POLYNOMIAL_CHEB) {
     940        tmpPoly = p_psVectorFitPolynomial1DCheby(myPoly, myX, y, myYErr);
     941    } else if (myPoly->type == PS_POLYNOMIAL_ORD) {
     942        tmpPoly = p_psVectorFitPolynomial1DOrd(myPoly, myX, y, myYErr);
     943    } else {
     944        // XXX: psErrorMsg()
     945        return(NULL);
     946    }
     947
     948    // Free any allocated memory.
     949    if (mustFreeMyYErr == true) {
     950        psFree(myYErr);
     951    }
     952    if (mustFreemyX == true) {
     953        psFree(myX);
     954    }
     955
     956    return(myPoly);
     957}
     958
    865959
    866960
Note: See TracChangeset for help on using the changeset viewer.