IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 19085


Ignore:
Timestamp:
Aug 16, 2008, 12:34:48 PM (18 years ago)
Author:
eugene
Message:

big re-write to make thread-efficient; the psPolynomialMD structure now carries several temp variables so it can be reused within a tight loop and avoid excessive malloc calls

Location:
trunk/psLib/src/math
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/psLib/src/math/psPolynomialMD.c

    r17447 r19085  
    2727    )
    2828{
     29    if (!poly) return;
    2930    psFree(poly->orders);
    3031    psFree(poly->coeff);
     32
     33    psFree(poly->fitMatrix);
     34    psFree(poly->fitVector);
     35    psFree(poly->tmpMatrix);
     36    psFree(poly->tmpVector);
     37
     38    psFree(poly->fitBuffer);
     39
     40    psFree(poly->ownMask);
     41    psFree(poly->deviations);
     42
     43    psFree(poly->LUperm);
     44    psFree(poly->LU);
     45   
    3146    return;
    3247}
     
    111126}
    112127
    113 // Accumulate and solve the least-squares equation
    114 static bool polynomialMDClipFit(psPolynomialMD *poly, // Polynomial
    115                                 psImage *matrix, // Least-squares matrix
    116                                 psVector *vector, // Least-squares vector
    117                                 psImage **lu, // LU-decomposed matrix
    118                                 psVector **perm, // Permutations vector
    119                                 const psArray *matrices, // Individual least-squares matrices
    120                                 const psArray *vectors, // Individual least-squares vectors
    121                                 const psVector *mask // Mask for values
    122     )
    123 {
    124     int numValues = vectors->n;         // Number of values
    125 
    126     // Accumulate the least-squares matrix and vector
    127     psImageInit(matrix, 0.0);
    128     psVectorInit(vector, 0.0);
    129     for (int i = 0; i < numValues; i++) {
    130         if (mask->data.U8[i]) {
    131             continue;
    132         }
    133 
    134         psImage *newMatrix = matrices->data[i]; // Matrix to accumulate
    135         psVector *newVector = vectors->data[i]; // Vector to accumulate
    136 
    137         polynomialMDAccumulate(matrix, vector, newMatrix, newVector);
    138     }
    139     polynomialMDFill(matrix);
    140 
    141     // Solve least-squares equation
    142     *lu = psMatrixLUD(*lu, perm, matrix);
    143     if (!*lu) {
    144         psError(PS_ERR_UNKNOWN, false, "Unable to LU-Decompose least-squares matrix.");
    145         return false;
    146     }
    147     poly->coeff = psMatrixLUSolve(poly->coeff, *lu, vector, *perm);
    148     if (!poly->coeff) {
    149         psError(PS_ERR_UNKNOWN, false, "Unable to solve least-squares equation.");
    150         return false;
    151     }
    152     return true;
    153 }
    154 
    155128// Calculate the standard deviation of the fit
    156129static void polynomialMDStdev(psPolynomialMD *poly, // Polynomial for which to measure stdev
     
    158131                              const psArray *coords, // Array of coordinates
    159132                              const psVector *values, // Measured values
    160                               const psVector *mask // Mask for values
     133                              const psVector *mask, // Mask for values
     134                              psMaskType maskVal
    161135                              )
    162136{
     
    169143    int numGood = numValues;            // Number of good values
    170144    for (int i = 0; i < numValues; i++) {
    171         if (mask && mask->data.U8[i]) {
     145        if (mask && (mask->data.U8[i] & maskVal)) {
    172146            numGood--;
    173147            continue;
     
    234208    poly->coeff = psVectorAlloc(numTerms, PS_TYPE_F64);
    235209
     210    // internal temporary variables so we can use this in a tight, threaded loop
     211    poly->fitMatrix = NULL;
     212    poly->fitVector = NULL;
     213    poly->tmpMatrix = NULL;
     214    poly->tmpVector = NULL;
     215
     216    poly->fitBuffer = NULL;
     217
     218    poly->ownMask = NULL;
     219    poly->deviations = NULL;
     220
     221    poly->LUperm = NULL;
     222    poly->LU = NULL;
     223
    236224    return poly;
    237225}
     
    288276    int numValues = values->n;          // Number of values
    289277    int numTerms = poly->coeff->n;      // Number of terms
    290     psImage *matrix = psImageAlloc(numTerms, numTerms, PS_TYPE_F64); // Least-squares matrix
    291     psImageInit(matrix, 0.0);
    292     psVector *vector = psVectorAlloc(numTerms, PS_TYPE_F64); // Least-squares vector
    293     psVectorInit(vector, 0.0);
    294 
    295     psImage *newMatrix = psImageAlloc(numTerms, numTerms, PS_TYPE_F64); // Least-squares matrix for each term
    296     psVector *newVector = psVectorAlloc(numTerms, PS_TYPE_F64); // Least-squares vector for each term
    297     psVector *buffer = psVectorAlloc(numTerms, PS_TYPE_F64); // Buffer for evaluations of polynomial stages
     278
     279    // we recycle matrices and vectors carried by poly to avoid alloc / threading hits
     280    poly->fitMatrix = psImageRecycle(poly->fitMatrix, numTerms, numTerms, PS_TYPE_F64); // Least-squares matrix
     281    poly->fitVector = psVectorRecycle(poly->fitVector, numTerms, PS_TYPE_F64); // Least-squares vector
     282
     283    psImageInit(poly->fitMatrix, 0.0);
     284    psVectorInit(poly->fitVector, 0.0);
     285
     286    poly->tmpMatrix = psImageRecycle (poly->tmpMatrix, numTerms, numTerms, PS_TYPE_F64); // Least-squares matrix for each term
     287    poly->tmpVector = psVectorRecycle(poly->tmpVector, numTerms, PS_TYPE_F64); // Least-squares vector for each term
     288    poly->fitBuffer = psVectorRecycle(poly->fitBuffer, numTerms, PS_TYPE_F64); // Buffer for evaluations of polynomial stages
    298289
    299290    for (int i = 0; i < numValues; i++) {
     
    307298        }
    308299
    309         polynomialMDLeastSquares(poly, newMatrix, newVector, coords, values->data.F32[i],
    310                                  errors ? errors->data.F32[i] : 0.0, buffer);
    311         polynomialMDAccumulate(matrix, vector, newMatrix, newVector);
    312     }
    313     polynomialMDFill(matrix);
    314 
    315     psFree(newMatrix);
    316     psFree(newVector);
    317     psFree(buffer);
    318 
    319     psVector *perm = NULL;              // Permutation vector
    320     psImage *lu = psMatrixLUD(NULL, &perm, matrix); // LU-decomposed matrix
    321     psFree(matrix);
    322     if (!lu) {
     300        float err = errors ? errors->data.F32[i] : 0.0;
     301        polynomialMDLeastSquares(poly, poly->tmpMatrix, poly->tmpVector, coords, values->data.F32[i], err, poly->fitBuffer);
     302        polynomialMDAccumulate(poly->fitMatrix, poly->fitVector, poly->tmpMatrix, poly->tmpVector);
     303    }
     304    polynomialMDFill(poly->fitMatrix);
     305
     306    poly->LU = psMatrixLUD(poly->LU, &poly->LUperm, poly->fitMatrix); // LU-decomposed matrix
     307    if (!poly->LU) {
    323308        psError(PS_ERR_UNKNOWN, false, "Unable to LU-Decompose least-squares matrix.");
    324         psFree(vector);
    325309        return false;
    326310    }
    327     poly->coeff = psMatrixLUSolve(poly->coeff, lu, vector, perm);
    328     psFree(vector);
    329     psFree(lu);
    330     psFree(perm);
     311
     312    poly->coeff = psMatrixLUSolve(poly->coeff, poly->LU, poly->fitVector, poly->LUperm);
    331313    if (!poly->coeff) {
    332314        psError(PS_ERR_UNKNOWN, false, "Unable to solve least-squares equation.");
     
    334316    }
    335317
    336     polynomialMDStdev(poly, NULL, coordsArray, values, NULL);
     318    polynomialMDStdev(poly, poly->deviations, coordsArray, values, mask, maskVal);
    337319
    338320    return true;
    339321}
     322
     323// XXX this function should take a (psMaskType markVal) argument
     324bool psPolynomialMDClipFit(psPolynomialMD *poly, const psVector *values, const psVector *errors,
     325                           const psVector *mask, psMaskType maskVal, const psArray *coordsArray,
     326                           int numIter, float rej)
     327{
     328
     329    PS_ASSERT_POLYNOMIALMD_NON_NULL(poly, false);
     330    PS_ASSERT_VECTOR_NON_NULL(values, false);
     331    PS_ASSERT_VECTOR_TYPE(values, PS_TYPE_F32, false);
     332    if (errors) {
     333        PS_ASSERT_VECTOR_NON_NULL(errors, false);
     334        PS_ASSERT_VECTOR_TYPE(errors, PS_TYPE_F32, false);
     335        PS_ASSERT_VECTORS_SIZE_EQUAL(values, errors, false);
     336    }
     337    if (maskVal == 0) {
     338        mask = NULL;
     339    }
     340    if (mask) {
     341        PS_ASSERT_VECTOR_NON_NULL(mask, false);
     342        PS_ASSERT_VECTOR_TYPE(mask, PS_TYPE_MASK, false);
     343        PS_ASSERT_VECTORS_SIZE_EQUAL(values, mask, false);
     344    }
     345    PS_ASSERT_ARRAY_NON_NULL(coordsArray, false);
     346    PS_ASSERT_ARRAY_SIZE(coordsArray, (long)values->n, false);
     347    PS_ASSERT_INT_NONNEGATIVE(numIter, false);
     348    PS_ASSERT_FLOAT_LARGER_THAN(rej, 0.0, false);
     349
     350    int numValues = values->n;          // Number of values
     351    int numTerms = poly->coeff->n;      // Number of terms
     352
     353    int numClipped = INT_MAX;           // Number of values clipped int an interation
     354    int numGood = numValues;            // Number of good values
     355
     356    // copy the input mask to a local temporary mask
     357    poly->ownMask = psVectorRecycle(poly->ownMask, numValues, PS_TYPE_U8); // Our own mask for input values
     358    psVectorInit(poly->ownMask, 0);
     359    for (int i = 0; mask && (i < numValues); i++) {
     360        if (mask->data.PS_TYPE_MASK_DATA[i] & maskVal) {
     361            poly->ownMask->data.U8[i] = 0xff;
     362            numGood--;
     363        }
     364    }
     365
     366    // make sure we have storage for the residuals
     367    poly->deviations = psVectorRecycle (poly->deviations, numValues, PS_TYPE_F32);
     368
     369    for (int iter = 0; (iter < numIter) && (numClipped > 0) && (numGood > numTerms); iter++) {
     370        numClipped = 0;
     371
     372        // XXX raise error?
     373        if (!psPolynomialMDFit(poly, values, errors, poly->ownMask, maskVal, coordsArray)) {
     374            return false;
     375        }
     376
     377        psTrace("psLib.math", 7, "RMS from %d points is %lf\n", numGood, poly->stdevFit);
     378
     379        // Reject
     380        float limit = rej * poly->stdevFit; // Rejection limit
     381        for (int i = 0; i < numValues; i++) {
     382
     383# if (0)
     384            fprintf (stderr, "coords: ");
     385            psVector *coords = coordsArray->data[i];
     386            for (int j = 0; j < coords->n; j++) {
     387                fprintf (stderr, "%f ", coords->data.F32[j]);
     388            }
     389# endif
     390           
     391            psTrace("psLib.math", 10, "point %d (%f,%f: %f > %f)\n",
     392                    i, values->data.F32[i], values->data.F32[i] - poly->deviations->data.F32[i], poly->deviations->data.F32[i], limit);
     393
     394            if (poly->ownMask->data.U8[i]) continue;
     395
     396            if (fabs(poly->deviations->data.F32[i]) > limit) {
     397                psTrace("psLib.math", 9, "Rejected point %d (%f,%f: %f > %f)\n",
     398                        i, values->data.F32[i], values->data.F32[i] + poly->deviations->data.F32[i],
     399                        poly->deviations->data.F32[i], limit);
     400                poly->ownMask->data.U8[i] = 0xff;
     401                numClipped++;
     402                numGood--;
     403            }
     404        }
     405        psTrace("psLib.math", 7, "Rejected %d points (%d remaining)\n", numClipped, numGood);
     406    }
     407
     408    if (numClipped > 0) {
     409        // Need to do a final re-evaluation of the fit
     410        if (!psPolynomialMDFit(poly, values, errors, poly->ownMask, maskVal, coordsArray)) {
     411            return false;
     412        }
     413    }
     414
     415    return true;
     416}
     417
     418// XXX EAM : This function was trying to save calculation time at the expense of a LOT of allocs.
     419# if (0)
     420// Accumulate and solve the least-squares equation
     421static bool polynomialMDClipFit(psPolynomialMD *poly, // Polynomial
     422                                psImage *matrix, // Least-squares matrix
     423                                psVector *vector, // Least-squares vector
     424                                psImage **lu, // LU-decomposed matrix
     425                                psVector **perm, // Permutations vector
     426                                const psArray *matrices, // Individual least-squares matrices
     427                                const psArray *vectors, // Individual least-squares vectors
     428                                const psVector *mask, // Mask for values
     429    )
     430{
     431    int numValues = vectors->n;         // Number of values
     432
     433    // Accumulate the least-squares matrix and vector
     434    psImageInit(matrix, 0.0);
     435    psVectorInit(vector, 0.0);
     436    for (int i = 0; i < numValues; i++) {
     437        if (mask->data.U8[i]) {
     438            continue;
     439        }
     440
     441        psImage *newMatrix = matrices->data[i]; // Matrix to accumulate
     442        psVector *newVector = vectors->data[i]; // Vector to accumulate
     443
     444        polynomialMDAccumulate(matrix, vector, newMatrix, newVector);
     445    }
     446    polynomialMDFill(matrix);
     447
     448    // Solve least-squares equation
     449    *lu = psMatrixLUD(*lu, perm, matrix);
     450    if (!*lu) {
     451        psError(PS_ERR_UNKNOWN, false, "Unable to LU-Decompose least-squares matrix.");
     452        return false;
     453    }
     454    poly->coeff = psMatrixLUSolve(poly->coeff, *lu, vector, *perm);
     455    if (!poly->coeff) {
     456        psError(PS_ERR_UNKNOWN, false, "Unable to solve least-squares equation.");
     457        return false;
     458    }
     459    return true;
     460}
     461
    340462
    341463bool psPolynomialMDClipFit(psPolynomialMD *poly, const psVector *values, const psVector *errors,
     
    471593    return true;
    472594}
    473 
     595# endif
  • trunk/psLib/src/math/psPolynomialMD.h

    r17147 r19085  
    1313    int numFit;                         ///< Number of values in fit
    1414    float stdevFit;                     ///< Standard deviation of fit
     15
     16    psImage  *fitMatrix;
     17    psVector *fitVector;
     18
     19    psImage  *tmpMatrix;
     20    psVector *tmpVector;
     21
     22    psVector *fitBuffer;
     23
     24    psVector *ownMask;
     25    psVector *deviations;
     26
     27    psVector *LUperm;
     28    psImage  *LU;
     29
    1530} psPolynomialMD;
    1631
Note: See TracChangeset for help on using the changeset viewer.