IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 15711


Ignore:
Timestamp:
Nov 28, 2007, 4:56:01 PM (18 years ago)
Author:
Paul Price
Message:

Removing heap sort code that was straight out of Numerical Recipes.
Replacing with heap sort code from GNU Scientific Library,
reformatted. Advantage of reformatting is that the direct sort and
index sort are now implemented using the same code, with different
functions for comparison and swapping. Code passes tests in
tap_psVectorSort and tap_psVectorSortIndex.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/psLib/src/mathtypes/psVector.c

    r15406 r15711  
    1010*  @author Joshua Hoblitt, University of Hawaii
    1111*
    12 *  @version $Revision: 1.99 $ $Name: not supported by cvs2svn $
    13 *  @date $Date: 2007-10-29 20:35:31 $
     12*  @version $Revision: 1.100 $ $Name: not supported by cvs2svn $
     13*  @date $Date: 2007-11-29 02:56:01 $
    1414*
    1515*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     
    344344// XXX since the key size is fixed (same number of bits) a Radix sort could be
    345345// a big win here -- someone should benchmark this -JH
    346 #define PSVECTOR_SORT_CASE(NAME) \
    347 case PS_TYPE_##NAME: { \
    348     ps##NAME temp; \
    349     ps##NAME *value = vector->data.NAME; \
    350     for (;;) { \
    351         if (l > 0) { \
    352             temp = value[--l]; \
     346
     347// The following sort code is based on gsl_heapsort from GSL-1.8 (www.gnu.org/software/gsl), file
     348// gsl-1.8/sort/sort.c, which is distributed under the GNU General Public License, version 2.
     349//
     350// Implement Heap sort -- direct and indirect sorting
     351// Based on descriptions in Sedgewick "Algorithms in C"
     352//
     353// Copyright (C) 1999  Thomas Walter
     354//
     355// 18 February 2000: Modified for GSL by Brian Gough
     356
     357// Comparison and swap functions for sorting values directly
     358#define PSVECTOR_SORT_COMPARE_DIRECT(A,B) (value[A] < value[B])
     359#define PSVECTOR_SORT_SWAP_DIRECT(TYPE,A,B) { \
     360    if (A != B) { \
     361        ps##TYPE temp = value[A]; \
     362        value[A] = value[B]; \
     363        value[B] = temp; \
     364    } \
     365}
     366
     367// Comparison and swap functions for sorting vector indices
     368#define PSVECTOR_SORT_COMPARE_INDEX(A,B) (value[index[A]] < value[index[B]])
     369#define PSVECTOR_SORT_SWAP_INDEX(TYPE,A,B) { \
     370    if (A != B) { \
     371        ps##TYPE temp = index[A]; \
     372        index[A] = index[B]; \
     373        index[B] = temp; \
     374    } \
     375}
     376
     377// Sort the heap
     378#define PSVECTOR_SORT_DOWNHEAP(SWAPTYPE, COMPAREFUNC, SWAPFUNC, K) { \
     379    unsigned long k = K; /* Local version of k --- so the higher-level version isn't modified */ \
     380    while (k <= N / 2) { \
     381        unsigned long j = 2 * k; \
     382        if (j < N && COMPAREFUNC(j, j + 1)) { \
     383            j++; \
     384        } \
     385        if (COMPAREFUNC(k, j)) { \
     386            SWAPFUNC(SWAPTYPE, j, k); \
    353387        } else { \
    354             temp = value[ir]; \
    355             value[ir] = value[0]; \
    356             if (--ir == 0) { \
    357                 value[0] = temp; \
    358                 return true; \
    359             } \
     388            break; \
    360389        } \
    361         int i = l; \
    362         int j = (l << 1) + 1; \
    363         while (j <= ir) { \
    364             if (j < ir && value[j] < value[j+1]) \
    365                 ++j; \
    366             if (temp < value[j]) { \
    367                 value[i]=value[j]; \
    368                 j += (i=j) + 1; \
    369             } else { \
    370                 j = ir + 1; \
    371             } \
    372         } \
    373         value[i] = temp; \
     390        k = j; \
    374391    } \
    375 } \
    376 break;
     392}
     393
     394// Driver for heap sort
     395#define PSVECTOR_SORT_CASE(ELEMTYPE, SWAPTYPE, COMPAREFUNC, SWAPFUNC) \
     396case PS_TYPE_##ELEMTYPE: { \
     397    ps##ELEMTYPE *value = vector->data.ELEMTYPE; \
     398    unsigned long N = vector->n - 1; /* Index of last element */ \
     399    unsigned long i = N / 2 + 1; /* Adding one to compensate for i-- below */ \
     400    do { \
     401        i--; \
     402        PSVECTOR_SORT_DOWNHEAP(SWAPTYPE, COMPAREFUNC, SWAPFUNC, i); \
     403    } while (i > 0); \
     404    while (N > 0) { \
     405        SWAPFUNC(SWAPTYPE, 0, N); /* Swap elements */ \
     406        /* Process the heap */ \
     407        N--; \
     408        PSVECTOR_SORT_DOWNHEAP(SWAPTYPE, COMPAREFUNC, SWAPFUNC, 0); \
     409    } \
     410    break; \
     411}
     412// END of heap sort code from GSL
    377413
    378414bool psVectorSortInPlace(const psVector *vector)
     
    380416    PS_ASSERT_VECTOR_NON_NULL(vector, false);
    381417
    382     long N = vector->n;                    // Number of elements
    383     if (N < 2) {
     418    if (vector->n < 2) {
     419        // Already sorted!
    384420        return true;
    385421    }
    386     long l = N >> 1;
    387     long ir = N - 1;
     422
    388423    switch (vector->type.type) {
    389         PSVECTOR_SORT_CASE(U8);
    390         PSVECTOR_SORT_CASE(U16);
    391         PSVECTOR_SORT_CASE(U32);
    392         PSVECTOR_SORT_CASE(U64);
    393         PSVECTOR_SORT_CASE(S8);
    394         PSVECTOR_SORT_CASE(S16);
    395         PSVECTOR_SORT_CASE(S32);
    396         PSVECTOR_SORT_CASE(S64);
    397         PSVECTOR_SORT_CASE(F32);
    398         PSVECTOR_SORT_CASE(F64);
     424        PSVECTOR_SORT_CASE(U8 , U8 , PSVECTOR_SORT_COMPARE_DIRECT, PSVECTOR_SORT_SWAP_DIRECT);
     425        PSVECTOR_SORT_CASE(U16, U16, PSVECTOR_SORT_COMPARE_DIRECT, PSVECTOR_SORT_SWAP_DIRECT);
     426        PSVECTOR_SORT_CASE(U32, U32, PSVECTOR_SORT_COMPARE_DIRECT, PSVECTOR_SORT_SWAP_DIRECT);
     427        PSVECTOR_SORT_CASE(U64, U64, PSVECTOR_SORT_COMPARE_DIRECT, PSVECTOR_SORT_SWAP_DIRECT);
     428        PSVECTOR_SORT_CASE(S8 , S8 , PSVECTOR_SORT_COMPARE_DIRECT, PSVECTOR_SORT_SWAP_DIRECT);
     429        PSVECTOR_SORT_CASE(S16, S16, PSVECTOR_SORT_COMPARE_DIRECT, PSVECTOR_SORT_SWAP_DIRECT);
     430        PSVECTOR_SORT_CASE(S32, S32, PSVECTOR_SORT_COMPARE_DIRECT, PSVECTOR_SORT_SWAP_DIRECT);
     431        PSVECTOR_SORT_CASE(S64, S64, PSVECTOR_SORT_COMPARE_DIRECT, PSVECTOR_SORT_SWAP_DIRECT);
     432        PSVECTOR_SORT_CASE(F32, F32, PSVECTOR_SORT_COMPARE_DIRECT, PSVECTOR_SORT_SWAP_DIRECT);
     433        PSVECTOR_SORT_CASE(F64, F64, PSVECTOR_SORT_COMPARE_DIRECT, PSVECTOR_SORT_SWAP_DIRECT);
    399434    default:
    400435        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
     
    436471}
    437472
    438 // Heap sort of the index array
    439 #define PSVECTOR_SORT_INDEX_CASE(NAME) \
    440 case PS_TYPE_##NAME: { \
    441     psS32 temp; \
    442     psS32 *index = out->data.S32; \
    443     ps##NAME *value = inVector->data.NAME; \
    444     for (;;) { \
    445         if (l > 0) { \
    446             temp = index[--l]; \
    447         } else { \
    448             temp = index[ir]; \
    449             index[ir] = index[0]; \
    450             if (--ir == 0) { \
    451                 index[0] = temp; \
    452                 return out; \
    453             } \
    454         } \
    455         long i = l; \
    456         long j = (l << 1) + 1; \
    457         while (j <= ir) { \
    458             if (j < ir && value[index[j]] < value[index[j+1]]) \
    459                 ++j; \
    460             if (value[temp ] < value[index[j]]) { \
    461                 index[i]=index[j]; \
    462                 j += (i=j) + 1; \
    463             } else { \
    464                 j = ir + 1; \
    465             } \
    466         } \
    467         index[i] = temp; \
    468     } \
    469 } \
    470 break;
    471 
    472 psVector* psVectorSortIndex(psVector* outVector,
    473                             const psVector* inVector)
    474 {
    475     if (inVector == NULL) {
    476         psError(PS_ERR_BAD_PARAMETER_NULL, true,
    477                 _("psVectorSort can not sort a NULL psVector."));
    478         psFree(outVector);
    479         return NULL;
    480     }
    481 
    482     // XXX isn't this line a waste of space?
    483     psVector *out = psVectorRecycle(outVector, inVector->n, PS_TYPE_S32); // Vector for output
    484     out = psVectorCreate(out, 0, inVector->n, 1, PS_TYPE_S32);
    485     long N = out->n;                    // Number of elements
    486     if (N < 2) {
    487         return out;
    488     }
    489     long l = N >> 1;
    490     long ir = N - 1;
    491     switch (inVector->type.type) {
    492         PSVECTOR_SORT_INDEX_CASE(U8);
    493         PSVECTOR_SORT_INDEX_CASE(U16);
    494         PSVECTOR_SORT_INDEX_CASE(U32);
    495         PSVECTOR_SORT_INDEX_CASE(U64);
    496         PSVECTOR_SORT_INDEX_CASE(S8);
    497         PSVECTOR_SORT_INDEX_CASE(S16);
    498         PSVECTOR_SORT_INDEX_CASE(S32);
    499         PSVECTOR_SORT_INDEX_CASE(S64);
    500         PSVECTOR_SORT_INDEX_CASE(F32);
    501         PSVECTOR_SORT_INDEX_CASE(F64);
     473psVector* psVectorSortIndex(psVector *out,
     474                            const psVector *vector)
     475{
     476    PS_ASSERT_VECTOR_NON_NULL(vector, NULL);
     477
     478    psVector *indexVector = psVectorCreate(out, 0, vector->n, 1, PS_TYPE_S32); // Array of indices
     479    psS32 *index = indexVector->data.S32; // Dereference for convenience
     480
     481    if (vector->n < 2) {
     482        // Already sorted
     483        return indexVector;
     484    }
     485    switch (vector->type.type) {
     486        PSVECTOR_SORT_CASE(U8 , S32, PSVECTOR_SORT_COMPARE_INDEX, PSVECTOR_SORT_SWAP_INDEX);
     487        PSVECTOR_SORT_CASE(U16, S32, PSVECTOR_SORT_COMPARE_INDEX, PSVECTOR_SORT_SWAP_INDEX);
     488        PSVECTOR_SORT_CASE(U32, S32, PSVECTOR_SORT_COMPARE_INDEX, PSVECTOR_SORT_SWAP_INDEX);
     489        PSVECTOR_SORT_CASE(U64, S32, PSVECTOR_SORT_COMPARE_INDEX, PSVECTOR_SORT_SWAP_INDEX);
     490        PSVECTOR_SORT_CASE(S8 , S32, PSVECTOR_SORT_COMPARE_INDEX, PSVECTOR_SORT_SWAP_INDEX);
     491        PSVECTOR_SORT_CASE(S16, S32, PSVECTOR_SORT_COMPARE_INDEX, PSVECTOR_SORT_SWAP_INDEX);
     492        PSVECTOR_SORT_CASE(S32, S32, PSVECTOR_SORT_COMPARE_INDEX, PSVECTOR_SORT_SWAP_INDEX);
     493        PSVECTOR_SORT_CASE(S64, S32, PSVECTOR_SORT_COMPARE_INDEX, PSVECTOR_SORT_SWAP_INDEX);
     494        PSVECTOR_SORT_CASE(F32, S32, PSVECTOR_SORT_COMPARE_INDEX, PSVECTOR_SORT_SWAP_INDEX);
     495        PSVECTOR_SORT_CASE(F64, S32, PSVECTOR_SORT_COMPARE_INDEX, PSVECTOR_SORT_SWAP_INDEX);
    502496    default:
    503497        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
    504498                _("Input psVector is an unsupported type (0x%x)."),
    505                 inVector->type.type);
    506         psFree(outVector);
    507         return NULL;
    508     }
    509     return out;
     499                vector->type.type);
     500        psFree(indexVector);
     501        return NULL;
     502    }
     503
     504    return indexVector;
    510505}
    511506
Note: See TracChangeset for help on using the changeset viewer.