Index: /trunk/psLib/pslib.kdevses
===================================================================
--- /trunk/psLib/pslib.kdevses	(revision 3736)
+++ /trunk/psLib/pslib.kdevses	(revision 3737)
@@ -2,5 +2,15 @@
 <!DOCTYPE KDevPrjSession>
 <KDevPrjSession>
- <DocsAndViews NumberOfDocuments="0" />
+ <DocsAndViews NumberOfDocuments="3" >
+  <Doc0 NumberOfViews="1" URL="file:///home/desonia/panstarrs/psLib/src/image/psImageManip.h" >
+   <View0 line="22" Type="Source" />
+  </Doc0>
+  <Doc1 NumberOfViews="1" URL="file:///home/desonia/panstarrs/psLib/src/image/psImageManip.c" >
+   <View0 line="1173" Type="Source" />
+  </Doc1>
+  <Doc2 NumberOfViews="1" URL="file:///home/desonia/panstarrs/psLib/src/image/psImage.h" >
+   <View0 line="159" Type="Source" />
+  </Doc2>
+ </DocsAndViews>
  <pluginList>
   <kdevdebugger>
Index: /trunk/psLib/src/collections/psCollectionsErrors.dat
===================================================================
--- /trunk/psLib/src/collections/psCollectionsErrors.dat	(revision 3736)
+++ /trunk/psLib/src/collections/psCollectionsErrors.dat	(revision 3737)
@@ -15,5 +15,5 @@
 psVector_NOT_A_VECTOR                  The input psVector must have a vector dimension type.
 psVector_SORT_NULL                     psVectorSort can not sort a NULL psVector.
-psVector_UNSUPPORTED_TYPE              Input psVector is an unsupported type (%d).
+psVector_UNSUPPORTED_TYPE              Input psVector is an unsupported type (0x%x).
 #
 psBitSet_ALLOC_NEG_SIZE                The number of bit in a psBitSet (%d) must be greater than zero.
Index: /trunk/psLib/src/collections/psCollectionsErrors.h
===================================================================
--- /trunk/psLib/src/collections/psCollectionsErrors.h	(revision 3736)
+++ /trunk/psLib/src/collections/psCollectionsErrors.h	(revision 3737)
@@ -7,6 +7,6 @@
  *  @author Robert DeSonia, MHPCC
  *
- *  @version $Revision: 1.11 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2005-02-17 19:26:23 $
+ *  @version $Revision: 1.12 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2005-04-21 21:18:23 $
  *
  *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -36,5 +36,5 @@
 #define PS_ERRORTEXT_psVector_NOT_A_VECTOR "The input psVector must have a vector dimension type."
 #define PS_ERRORTEXT_psVector_SORT_NULL "psVectorSort can not sort a NULL psVector."
-#define PS_ERRORTEXT_psVector_UNSUPPORTED_TYPE "Input psVector is an unsupported type (%d)."
+#define PS_ERRORTEXT_psVector_UNSUPPORTED_TYPE "Input psVector is an unsupported type (0x%x)."
 #define PS_ERRORTEXT_psBitSet_ALLOC_NEG_SIZE "The number of bit in a psBitSet (%d) must be greater than zero."
 #define PS_ERRORTEXT_psBitSet_SET_NULL "Can not operate on a NULL psBitSet."
Index: /trunk/psLib/src/collections/psVector.c
===================================================================
--- /trunk/psLib/src/collections/psVector.c	(revision 3736)
+++ /trunk/psLib/src/collections/psVector.c	(revision 3737)
@@ -9,6 +9,6 @@
 *  @author Robert DeSonia, MHPCC
 *
-*  @version $Revision: 1.38 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2005-04-08 17:58:57 $
+*  @version $Revision: 1.39 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2005-04-21 21:18:23 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -28,6 +28,12 @@
 #include "psCollectionsErrors.h"
 
+typedef struct
+{
+    p_psVectorData data; // need this first for psVectorSortIndex to work.
+    int index;
+}
+indexedVector;
+
 static void vectorFree(psVector* psVec);
-
 
 static void vectorFree(psVector* psVec)
@@ -297,4 +303,6 @@
                 PS_ERRORTEXT_psVector_UNSUPPORTED_TYPE,
                 inType);
+        psFree(outVector);
+        return NULL;
     }
 
@@ -305,8 +313,5 @@
 {
     psS32 N = 0;
-    psVector* tmpVector = NULL;
-    psVector* checkVector = NULL;
     psElemType inType = 0;
-    psU32* outVec;
 
     if (inVector == NULL) {
@@ -320,17 +325,4 @@
     N = inVector->n;
 
-    if (outVector == NULL) {
-        outVector = psVectorAlloc(N, PS_TYPE_U32);
-    }
-
-    // check to see if output vector needs to be resized/retyped
-    if ( (N > outVector->nalloc) ||
-            (outVector->type.type != PS_TYPE_U32) ) {
-        // reshape the output vector to match the input vector's size/type.
-        outVector = psVectorRecycle(outVector,N,PS_TYPE_U32);
-    }
-    outVector->n = N;
-    outVec = outVector->data.U32;
-
     if (N == 0) {
         // no need to sort anything, as there are no elements in input vector.
@@ -338,60 +330,45 @@
     }
 
-    tmpVector = psVectorSort(tmpVector, inVector);
-
-    checkVector = psVectorAlloc(N,PS_TYPE_U8);
-    for(psS32 k=0; k<N; k++) {
-        checkVector->data.U8[k] = 0;
-    }
-
-    #define SORT_INDICES(TYPE,absfcn,maxError) {                              \
-        ps##TYPE* inVec = inVector->data.TYPE;                                \
-        ps##TYPE* tmpVec = tmpVector->data.TYPE;                              \
-        ps##TYPE  diff;                                                       \
-        for(psS32 i=0; i<N; i++) {                                              \
-            for(psS32 j=0; j<N; j++) {                                          \
-                if(checkVector->data.U8[j] == 0 ) {                                    \
-                    diff = absfcn(tmpVec[i] - inVec[j]);                          \
-                    if(diff < maxError) {                                         \
-                        outVec[i] = j;                                            \
-                        checkVector->data.U8[j] = 1; \
-                        break;                                                    \
-                    }                                                             \
-                } \
-            }                                                                 \
-        }                                                                     \
-    }
-
-    // Sort output vector
+    // ok, let's create a temporary indexed vector
+    indexedVector* idxVector = psAlloc(sizeof(indexedVector)*N);
+    int elSize = PSELEMTYPE_SIZEOF(inType);
+    for (int i = 0; i < N; i++) {
+        idxVector[i].data.U8 = inVector->data.U8+i*elSize;
+        idxVector[i].index = i;
+    }
+
+    // Sort indexed vector
+    // n.b., since first element in indexedVector is a pointer to the data,
+    // we can use the 'Ptr' version of the standard compare functions
     switch (inType) {
     case PS_TYPE_U8:
-        SORT_INDICES(U8,abs,1);
+        qsort(idxVector, N, sizeof(indexedVector), (psCompareFcn)psCompareU8Ptr);
         break;
     case PS_TYPE_U16:
-        SORT_INDICES(U16,abs,1);
+        qsort(idxVector, N, sizeof(indexedVector), (psCompareFcn)psCompareU16Ptr);
         break;
     case PS_TYPE_U32:
-        SORT_INDICES(U32,abs,1);
+        qsort(idxVector, N, sizeof(indexedVector), (psCompareFcn)psCompareU32Ptr);
         break;
     case PS_TYPE_U64:
-        SORT_INDICES(U64,abs,1);
+        qsort(idxVector, N, sizeof(indexedVector), (psCompareFcn)psCompareU64Ptr);
         break;
     case PS_TYPE_S8:
-        SORT_INDICES(S8,abs,1);
+        qsort(idxVector, N, sizeof(indexedVector), (psCompareFcn)psCompareS8Ptr);
         break;
     case PS_TYPE_S16:
-        SORT_INDICES(S16,abs,1);
+        qsort(idxVector, N, sizeof(indexedVector), (psCompareFcn)psCompareS16Ptr);
         break;
     case PS_TYPE_S32:
-        SORT_INDICES(S32,abs,1);
+        qsort(idxVector, N, sizeof(indexedVector), (psCompareFcn)psCompareS32Ptr);
         break;
     case PS_TYPE_S64:
-        SORT_INDICES(S64,abs,1);
+        qsort(idxVector, N, sizeof(indexedVector), (psCompareFcn)psCompareS64Ptr);
         break;
     case PS_TYPE_F32:
-        SORT_INDICES(F32,fabsf,FLT_EPSILON);
+        qsort(idxVector, N, sizeof(indexedVector), (psCompareFcn)psCompareF32Ptr);
         break;
     case PS_TYPE_F64:
-        SORT_INDICES(F64,fabs,DBL_EPSILON);
+        qsort(idxVector, N, sizeof(indexedVector), (psCompareFcn)psCompareF64Ptr);
         break;
     default:
@@ -399,9 +376,18 @@
                 PS_ERRORTEXT_psVector_UNSUPPORTED_TYPE,
                 inType);
+        psFree(idxVector);
+        psFree(outVector);
+        return NULL;
+    }
+
+    // extract the indices to the output vector
+    outVector = psVectorRecycle(outVector, N, PS_TYPE_U32);
+    psU32* outData = outVector->data.U32;
+    for (int i = 0; i < N; i++) {
+        outData[i] = idxVector[i].index;
     }
 
     // Free temp memory
-    psFree(tmpVector);
-    psFree(checkVector);
+    psFree(idxVector);
 
     return outVector;
Index: /trunk/psLib/src/collections/psVector.h
===================================================================
--- /trunk/psLib/src/collections/psVector.h	(revision 3736)
+++ /trunk/psLib/src/collections/psVector.h	(revision 3737)
@@ -11,6 +11,6 @@
  *  @author Ross Harman, MHPCC
  *
- *  @version $Revision: 1.31 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2005-04-08 17:58:57 $
+ *  @version $Revision: 1.32 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2005-04-21 21:18:23 $
  *
  *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -25,4 +25,20 @@
 /// @{
 
+///< Union of psVector data types.
+typedef union {
+    psU8* U8;               ///< Unsigned 8-bit integer data.
+    psU16* U16;             ///< Unsigned 16-bit integer data.
+    psU32* U32;             ///< Unsigned 32-bit integer data.
+    psU64* U64;             ///< Unsigned 64-bit integer data.
+    psS8* S8;               ///< Signed 8-bit integer data.
+    psS16* S16;             ///< Signed 16-bit integer data.
+    psS32* S32;             ///< Signed 32-bit integer data.
+    psS64* S64;             ///< Signed 64-bit integer data.
+    psF32* F32;             ///< Single-precision float data.
+    psF64* F64;             ///< Double-precision float data.
+    psC32* C32;             ///< Single-precision complex data.
+    psC64* C64;             ///< Double-precision complex data.
+} p_psVectorData;
+
 /** An vector to support primitive types.
  *
@@ -35,19 +51,5 @@
     int n;                      ///< Number of elements in use.
     const int nalloc;           ///< Total number of elements available.
-
-    union {
-        psU8* U8;               ///< Unsigned 8-bit integer data.
-        psU16* U16;             ///< Unsigned 16-bit integer data.
-        psU32* U32;             ///< Unsigned 32-bit integer data.
-        psU64* U64;             ///< Unsigned 64-bit integer data.
-        psS8* S8;               ///< Signed 8-bit integer data.
-        psS16* S16;             ///< Signed 16-bit integer data.
-        psS32* S32;             ///< Signed 32-bit integer data.
-        psS64* S64;             ///< Signed 64-bit integer data.
-        psF32* F32;             ///< Single-precision float data.
-        psF64* F64;             ///< Double-precision float data.
-        psC32* C32;             ///< Single-precision complex data.
-        psC64* C64;             ///< Double-precision complex data.
-    } data;                     ///< Union for data types.
+    p_psVectorData data;        ///< Union for data types.
 }
 psVector;
Index: /trunk/psLib/src/image/Makefile.am
===================================================================
--- /trunk/psLib/src/image/Makefile.am	(revision 3736)
+++ /trunk/psLib/src/image/Makefile.am	(revision 3737)
@@ -18,5 +18,6 @@
 	psImageStats.c \
 	psImageFFT.c \
-	psImageConvolve.c
+	psImageConvolve.c \
+	psPixels.c
 
 BUILT_SOURCES = psImageErrors.h
Index: /trunk/psLib/src/image/psImageManip.c
===================================================================
--- /trunk/psLib/src/image/psImageManip.c	(revision 3736)
+++ /trunk/psLib/src/image/psImageManip.c	(revision 3737)
@@ -10,6 +10,6 @@
  *  @author Ross Harman, MHPCC
  *
- *  @version $Revision: 1.38 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2005-03-22 21:52:49 $
+ *  @version $Revision: 1.39 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2005-04-21 21:18:23 $
  *
  *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -19,4 +19,6 @@
 #include <stdlib.h>
 #include <string.h>                        // for memcpy, etc.
+
+#include "psImageManip.h"
 
 #include "psError.h"
@@ -1082,2 +1084,3 @@
     return NULL;
 }
+
Index: /trunk/psLib/src/image/psImageManip.h
===================================================================
--- /trunk/psLib/src/image/psImageManip.h	(revision 3736)
+++ /trunk/psLib/src/image/psImageManip.h	(revision 3737)
@@ -1,3 +1,2 @@
-
 /** @file  psImageManip.h
  *
@@ -11,6 +10,6 @@
  *  @author Ross Harman, MHPCC
  *
- *  @version $Revision: 1.19 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2005-03-22 21:52:49 $
+ *  @version $Revision: 1.20 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2005-04-21 21:18:23 $
  *
  *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -21,4 +20,5 @@
 #include "psImage.h"
 #include "psCoord.h"
+#include "psStats.h"
 
 /// @addtogroup Image
Index: /trunk/psLib/src/image/psPixels.c
===================================================================
--- /trunk/psLib/src/image/psPixels.c	(revision 3737)
+++ /trunk/psLib/src/image/psPixels.c	(revision 3737)
@@ -0,0 +1,343 @@
+/** @file  psPixels.c
+ *
+ *  @brief Contains psPixel related functions
+ *
+ *  @ingroup Image
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2005-04-21 21:18:23 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "psPixels.h"
+#include "psMemory.h"
+
+typedef struct
+{
+    psS32 x;
+    psS32 y;
+}
+p_psPixelCoord;
+
+typedef int(*qsortCompareFcn)(const void *, const void *);
+
+static void pixelsFree(psPixels* pixels)
+{
+    if (pixels != NULL) {
+        psFree(pixels->x);
+        psFree(pixels->y);
+    }
+}
+
+// for use by qsort, etc.
+static int comparePixelCoord(p_psPixelCoord* coord1, p_psPixelCoord* coord2)
+{
+    // check row first
+    if (coord1->y < coord2->y) {
+        return -1;
+    }
+
+    if (coord1->y > coord2->y) {
+        return 1;
+    }
+
+    // rows are the same, so check column
+    if (coord1->x < coord2->x) {
+        return -1;
+    }
+
+    if (coord1->x > coord2->x) {
+        return 1;
+    }
+
+    return 0;
+}
+
+psPixels* psPixelsAlloc(int size)
+{
+    psPixels* out = psAlloc(sizeof(psPixels));
+
+    if (size > 0) {
+        out->x = psVectorAlloc(size, PS_TYPE_S32);
+        out->y = psVectorAlloc(size, PS_TYPE_S32);
+    } else {
+        out->x = NULL;
+        out->y = NULL;
+    }
+
+    psMemSetDeallocator(out, (psFreeFcn)pixelsFree);
+
+    return NULL;
+}
+
+psPixels* psPixelsRealloc(psPixels* pixels, int size)
+{
+    if (pixels == NULL) {
+        return psPixelsAlloc(size);
+    }
+
+    pixels->x = psVectorRealloc(pixels->x, size);
+    pixels->y = psVectorRealloc(pixels->y, size);
+
+    return pixels;
+}
+
+psImage *psPixelsToMask(psImage *out, const psPixels *pixels, const psRegion *region, unsigned int maskVal)
+{
+    // check that the input pixel vector is valid
+    if (pixels == NULL) {
+        // XXX: Error message
+        psFree(out);
+        return NULL;
+    }
+    psVector* xVec = pixels->x;
+    psVector* yVec = pixels->y;
+    if (xVec == NULL || yVec == NULL) {
+        // XXX: Error message
+        psFree(out);
+        return NULL;
+    }
+    if (xVec->type.type != PS_TYPE_S32) {
+        // XXX: Error message
+        psFree(out);
+        return NULL;
+    }
+    if (yVec->type.type != PS_TYPE_S32) {
+        // XXX: Error message
+        psFree(out);
+        return NULL;
+    }
+
+    // check if the input region is valid
+    if (region == NULL) {
+        // XXX: Error message
+        psFree(out);
+        return NULL;
+    }
+    int x0 = region->x0;
+    int x1 = region->x1;
+    int y0 = region->y0;
+    int y1 = region->y1;
+
+    // determine the output image size
+    int numRows = x1-x0;
+    int numCols = y1-y0;
+    if (numRows < 1 || numCols < 1) {
+        // XXX: Error message
+        psFree(out);
+        return NULL;
+    }
+
+    //  allocate the output image
+    out = psImageRecycle(out, numCols, numRows, PS_TYPE_MASK);
+    if (out == NULL) {
+        // XXX: Error message
+        return NULL;
+    }
+    *(psS32*)&out->row0 = x0;
+    *(psS32*)&out->col0 = y0;
+
+    // initialize image to all zeros
+    int columnByteSize = sizeof(PS_TYPE_MASK)*numCols;
+    for (int row = 0; row < numRows; row++) {
+        memset(out->data.U8[row],0,columnByteSize);
+    }
+
+    // determine the length of the pixel vector
+    int length = pixels->x->n;
+    if (pixels->y->n != length) {
+        // XXX: warning message
+        if (pixels->y->n < length) {
+            length = pixels->y->n;
+        }
+    }
+
+    // cycle through the vector of pixels and insert pixels into image
+    psMaskType** outData = out->data.PS_TYPE_MASK_DATA;
+    for (int p = 0; p < length; p++) {
+        psS32 x = xVec->data.S32[p];
+        psS32 y = yVec->data.S32[p];
+        // pixel in region?
+        if (x >= x0 && x < x1 && y >= y0 && y < y1) {
+            outData[x-x0][y-y0] |= maskVal;
+        }
+    }
+
+    return out;
+}
+
+psPixels *psMaskToPixels(psPixels *out, const psImage *mask, unsigned int maskVal)
+{
+    if (mask == NULL) {
+        // XXX: Error message
+        psFree(out);
+        return NULL;
+    }
+    if (mask->type.type != PS_TYPE_MASK) {
+        // XXX: Error message
+        psFree(out);
+        return NULL;
+    }
+    int numRows = mask->numRows;
+    int numCols = mask->numCols;
+
+    // assumption: number of masked pixels is relatively small compared to
+    // total pixels, so it is best to just start with a guess and resize if
+    // necessary
+    int minPixels = numRows*numCols/100; // initial guess, 1% of pixels masked
+    if (minPixels < 32) { // enforce a minimum size
+        minPixels = 32;
+    }
+    if (out == NULL) {
+        out = psPixelsAlloc(minPixels);
+    }
+    psVector* xVec = out->x;
+    psVector* yVec = out->y;
+
+    // check the x and y vector validity (type/minimum size)
+    if (xVec == NULL || xVec->type.type != PS_TYPE_S32 || xVec->nalloc < minPixels) {
+        xVec = psVectorRecycle(xVec,minPixels,PS_TYPE_S32);
+    }
+    if (yVec == NULL || yVec->type.type != PS_TYPE_S32 || yVec->nalloc < minPixels) {
+        yVec = psVectorRecycle(yVec, minPixels,PS_TYPE_S32);
+    }
+
+    // start with a blank list of pixels
+    xVec->n = 0;
+    yVec->n = 0;
+
+    // find the mask pixels in the image
+    int numPixels = 0;
+    for (int row=0; row<numRows; row++) {
+        psMaskType* maskRow = mask->data.PS_TYPE_MASK_DATA[row];
+        for (int col=0; col<numCols; col++) {
+            if ( (maskRow[col] | maskVal) != 0 ) {
+                // check the vector sizes, and expand if necessary
+                if (xVec->nalloc >= numPixels) {
+                    xVec = psVectorRealloc(xVec, 2*xVec->nalloc);
+                }
+                if (yVec->nalloc >= numPixels) {
+                    yVec = psVectorRealloc(yVec, 2*yVec->nalloc);
+                }
+
+                xVec->data.S32[numPixels] = col;
+                yVec->data.S32[numPixels] = row;
+                numPixels++;
+            }
+        }
+    }
+
+    // return the vectors to the psPixels struct
+    // (n.b., not assuming psVectorRealloc/psVectorRecycle, etc., didn't
+    //  relocate the vectors)
+    out->x = xVec;
+    out->y = yVec;
+
+    return out;
+}
+
+psPixels* psPixelsConcatenate(psPixels *out,const psPixels *pixels)
+{
+    if (pixels == NULL) {
+        // XXX: Error message
+        return NULL;
+    }
+    psVector* xPixels = pixels->x;
+    psVector* yPixels = pixels->y;
+
+    // verify that pixels has well formed vectors (type)
+    if (xPixels->type.type != PS_TYPE_S32 ||
+            yPixels->type.type != PS_TYPE_S32) {
+        // XXX: Error message
+        return NULL;
+    }
+
+    // determine the length of the pixel vector
+    int pixelsLen = xPixels->n;
+    if (yPixels->n != pixelsLen) {
+        // XXX: warning message
+        if (yPixels->n < pixelsLen) {
+            pixelsLen = yPixels->n;
+        }
+    }
+
+    if (out == NULL) {
+        // simple copy of pixels
+        out = psPixelsAlloc(0); // let psVectorCopy allocate the vector
+        out->x = psVectorCopy(out->x,pixels->x,PS_TYPE_S32);
+        out->y = psVectorCopy(out->y,pixels->y,PS_TYPE_S32);
+
+        return out;
+    }
+
+    // make sure the out vectors are allocated
+    psVector* xVec = out->x;
+    psVector* yVec = out->y;
+    if (xVec == NULL) {
+        out->x = xVec = psVectorAlloc(pixelsLen,PS_TYPE_S32);
+        xVec->n = 0;
+    }
+    if (yVec == NULL) {
+        out->y = yVec = psVectorAlloc(pixelsLen,PS_TYPE_S32);
+        yVec->n = 0;
+    }
+
+    // verify that out has well formed vectors (type/size)
+    if (xVec->type.type != PS_TYPE_S32 ||
+            yVec->type.type != PS_TYPE_S32) {
+        // XXX: Error message
+        return NULL;
+    }
+    if (xVec->n != yVec->n) {
+        // XXX: Error message
+        return NULL;
+    }
+    int outLen = xVec->n;
+
+
+    // populate an array of psPixelCoord structs with the out values
+    p_psPixelCoord* coordinates = psAlloc(sizeof(p_psPixelCoord)*(pixelsLen+outLen));
+    psS32* outXData = xVec->data.S32;
+    psS32* outYData = yVec->data.S32;
+    for (int n = 0; n < outLen; n++) {
+        coordinates[n].x = outXData[n];
+        coordinates[n].y = outYData[n];
+    }
+
+    // sort the coordinates array
+    qsort(coordinates, sizeof(p_psPixelCoord), outLen,
+          (qsortCompareFcn)comparePixelCoord);
+
+    // search out for coordinates in pixels
+    int end = outLen;
+    psS32* pixelsXData = xPixels->data.S32;
+    psS32* pixelsYData = yPixels->data.S32;
+    p_psPixelCoord pCoord;
+    for (int n = 0; n < pixelsLen; n++) {
+        pCoord.x = pixelsXData[n];
+        pCoord.y = pixelsYData[n];
+        if (bsearch(&pCoord, coordinates, sizeof(p_psPixelCoord), outLen,
+                    (qsortCompareFcn)comparePixelCoord) == NULL) {
+            coordinates[end++] = pCoord;
+        }
+    }
+
+    // transfer the coordinates data back to psPixels
+    out = psPixelsRealloc(out, end);
+    outXData = xVec->data.S32;
+    outYData = yVec->data.S32;
+    for (int n = 0; n < end; n++) {
+        outXData[n] = coordinates[n].x;
+        outYData[n] = coordinates[n].y;
+    }
+
+    psFree(coordinates);
+
+    return out;
+}
Index: /trunk/psLib/src/image/psPixels.h
===================================================================
--- /trunk/psLib/src/image/psPixels.h	(revision 3737)
+++ /trunk/psLib/src/image/psPixels.h	(revision 3737)
@@ -0,0 +1,107 @@
+/** @file  psPixels.h
+ *
+ *  @brief Contains psPixel related functions
+ *
+ *  @ingroup Image
+ *
+ *  @author Robert DeSonia, MHPCC
+ *
+ *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2005-04-21 21:18:23 $
+ *
+ *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ */
+#ifndef PS_PIXELS_H
+#define PS_PIXELS_H
+
+#include "psImage.h"
+#include "psVector.h"
+
+/// @addtogroup Image
+/// @{
+
+/** list of pixel coordinates
+ *
+ *  Usually an image mask is the best way to carry information about what
+ *  pixels mean what. However, in the case where the number of pixels in which
+ *  we are interested is limited, it is more efï¬cient to simply carry a list
+ *  of pixels. An example of this is in the image combination code, where we
+ *  want to perform an operation on a relatively small fraction of pixels, and
+ *  it is inefï¬cient to go through an entire mask image checking each pixel.
+ *
+ */
+typedef struct
+{
+    psVector *x;                       ///< x coordinate
+    psVector *y;                       ///< y coordinate
+}
+psPixels;
+
+
+/** Allocates a new psPixels structure
+ *
+ *  @return psPixels*   new psPixels
+ */
+psPixels* psPixelsAlloc(
+    int size                           ///< the size of the coordinate vectors
+);
+
+/** resizes a psPixels structure
+ *
+ *  @return psPixels*   resized psPixels
+ */
+psPixels* psPixelsRealloc(
+    psPixels* pixels,                  ///< psPixels to resize, or NULL to create new psPixels
+    int size                           ///< the size of the coordinate vectors
+);
+
+/** Generate a psImage from a psPixels
+ *
+ *  psPixelsToMask shall return an image of type U8 with the pixels lying
+ *  within the speciï¬ed region set to the maskVal. The out image shall be
+ *  modiï¬ed if supplied, or allocated and returned if NULL. The size of the
+ *  output image shall be region->x1 - region->x0 by region->y1 - region->y0,
+ *  with out->x0 = region->x0 and out->y0 = region->y0. In the event that
+ *  either of pixels or region are NULL, the function shall generate an
+ *  error and return NULL.
+ *
+ *  @return psImage*    generated mask image
+ */
+psImage* psPixelsToMask(
+    psImage* out,                      ///< psImage to recycle, or NULL
+    const psPixels* pixels,            ///< list of pixels to use
+    const psRegion* region,            ///< region to define the output mask image
+    unsigned int maskVal               ///< the mask bit-values to act upon
+);
+
+/** Generate a psPixels from a mask psImage
+ *
+ *  psMaskToPixels shall return a psPixels consisting of the coordinates in
+ *  the mask that match the maskVal. The out pixel list shall be modiï¬ed if
+ *  supplied, or allocated and returned if NULL. In hte event that mask is
+ *  NULL, the function shall generate an error and return NULL.
+ *
+ *  @return psPixels*   generated psPixels pixel list
+ */
+psPixels* psMaskToPixels(
+    psPixels *out,                     ///< psPixels to recycle, or NULL
+    const psImage *mask,               ///< the input mask psImage
+    unsigned int maskVal               ///< the mask bit-values to act upon
+);
+
+/** Concatenates two psPixels
+ *
+ *  psPixelsConcatenate shall concatenate pixels onto out. In the event that
+ *  out is NULL, a new psPixels shall be allocated, and the contents of
+ *  pixels simply copied in. If pixels is NULL, the function shall generate
+ *  an error and return NULL. The function shall take care to ensure that
+ *  there are no duplicate pixels in out.
+ *
+ *  @return psPixels         Concatenated psPixel list
+ */
+psPixels* psPixelsConcatenate(
+    psPixels *out,                     ///< psPixels to recycle, or NULL
+    const psPixels *pixels             ///< psPixels to append to OUT
+);
+
+#endif
Index: /trunk/psLib/src/mathtypes/psVector.c
===================================================================
--- /trunk/psLib/src/mathtypes/psVector.c	(revision 3736)
+++ /trunk/psLib/src/mathtypes/psVector.c	(revision 3737)
@@ -9,6 +9,6 @@
 *  @author Robert DeSonia, MHPCC
 *
-*  @version $Revision: 1.38 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2005-04-08 17:58:57 $
+*  @version $Revision: 1.39 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2005-04-21 21:18:23 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -28,6 +28,12 @@
 #include "psCollectionsErrors.h"
 
+typedef struct
+{
+    p_psVectorData data; // need this first for psVectorSortIndex to work.
+    int index;
+}
+indexedVector;
+
 static void vectorFree(psVector* psVec);
-
 
 static void vectorFree(psVector* psVec)
@@ -297,4 +303,6 @@
                 PS_ERRORTEXT_psVector_UNSUPPORTED_TYPE,
                 inType);
+        psFree(outVector);
+        return NULL;
     }
 
@@ -305,8 +313,5 @@
 {
     psS32 N = 0;
-    psVector* tmpVector = NULL;
-    psVector* checkVector = NULL;
     psElemType inType = 0;
-    psU32* outVec;
 
     if (inVector == NULL) {
@@ -320,17 +325,4 @@
     N = inVector->n;
 
-    if (outVector == NULL) {
-        outVector = psVectorAlloc(N, PS_TYPE_U32);
-    }
-
-    // check to see if output vector needs to be resized/retyped
-    if ( (N > outVector->nalloc) ||
-            (outVector->type.type != PS_TYPE_U32) ) {
-        // reshape the output vector to match the input vector's size/type.
-        outVector = psVectorRecycle(outVector,N,PS_TYPE_U32);
-    }
-    outVector->n = N;
-    outVec = outVector->data.U32;
-
     if (N == 0) {
         // no need to sort anything, as there are no elements in input vector.
@@ -338,60 +330,45 @@
     }
 
-    tmpVector = psVectorSort(tmpVector, inVector);
-
-    checkVector = psVectorAlloc(N,PS_TYPE_U8);
-    for(psS32 k=0; k<N; k++) {
-        checkVector->data.U8[k] = 0;
-    }
-
-    #define SORT_INDICES(TYPE,absfcn,maxError) {                              \
-        ps##TYPE* inVec = inVector->data.TYPE;                                \
-        ps##TYPE* tmpVec = tmpVector->data.TYPE;                              \
-        ps##TYPE  diff;                                                       \
-        for(psS32 i=0; i<N; i++) {                                              \
-            for(psS32 j=0; j<N; j++) {                                          \
-                if(checkVector->data.U8[j] == 0 ) {                                    \
-                    diff = absfcn(tmpVec[i] - inVec[j]);                          \
-                    if(diff < maxError) {                                         \
-                        outVec[i] = j;                                            \
-                        checkVector->data.U8[j] = 1; \
-                        break;                                                    \
-                    }                                                             \
-                } \
-            }                                                                 \
-        }                                                                     \
-    }
-
-    // Sort output vector
+    // ok, let's create a temporary indexed vector
+    indexedVector* idxVector = psAlloc(sizeof(indexedVector)*N);
+    int elSize = PSELEMTYPE_SIZEOF(inType);
+    for (int i = 0; i < N; i++) {
+        idxVector[i].data.U8 = inVector->data.U8+i*elSize;
+        idxVector[i].index = i;
+    }
+
+    // Sort indexed vector
+    // n.b., since first element in indexedVector is a pointer to the data,
+    // we can use the 'Ptr' version of the standard compare functions
     switch (inType) {
     case PS_TYPE_U8:
-        SORT_INDICES(U8,abs,1);
+        qsort(idxVector, N, sizeof(indexedVector), (psCompareFcn)psCompareU8Ptr);
         break;
     case PS_TYPE_U16:
-        SORT_INDICES(U16,abs,1);
+        qsort(idxVector, N, sizeof(indexedVector), (psCompareFcn)psCompareU16Ptr);
         break;
     case PS_TYPE_U32:
-        SORT_INDICES(U32,abs,1);
+        qsort(idxVector, N, sizeof(indexedVector), (psCompareFcn)psCompareU32Ptr);
         break;
     case PS_TYPE_U64:
-        SORT_INDICES(U64,abs,1);
+        qsort(idxVector, N, sizeof(indexedVector), (psCompareFcn)psCompareU64Ptr);
         break;
     case PS_TYPE_S8:
-        SORT_INDICES(S8,abs,1);
+        qsort(idxVector, N, sizeof(indexedVector), (psCompareFcn)psCompareS8Ptr);
         break;
     case PS_TYPE_S16:
-        SORT_INDICES(S16,abs,1);
+        qsort(idxVector, N, sizeof(indexedVector), (psCompareFcn)psCompareS16Ptr);
         break;
     case PS_TYPE_S32:
-        SORT_INDICES(S32,abs,1);
+        qsort(idxVector, N, sizeof(indexedVector), (psCompareFcn)psCompareS32Ptr);
         break;
     case PS_TYPE_S64:
-        SORT_INDICES(S64,abs,1);
+        qsort(idxVector, N, sizeof(indexedVector), (psCompareFcn)psCompareS64Ptr);
         break;
     case PS_TYPE_F32:
-        SORT_INDICES(F32,fabsf,FLT_EPSILON);
+        qsort(idxVector, N, sizeof(indexedVector), (psCompareFcn)psCompareF32Ptr);
         break;
     case PS_TYPE_F64:
-        SORT_INDICES(F64,fabs,DBL_EPSILON);
+        qsort(idxVector, N, sizeof(indexedVector), (psCompareFcn)psCompareF64Ptr);
         break;
     default:
@@ -399,9 +376,18 @@
                 PS_ERRORTEXT_psVector_UNSUPPORTED_TYPE,
                 inType);
+        psFree(idxVector);
+        psFree(outVector);
+        return NULL;
+    }
+
+    // extract the indices to the output vector
+    outVector = psVectorRecycle(outVector, N, PS_TYPE_U32);
+    psU32* outData = outVector->data.U32;
+    for (int i = 0; i < N; i++) {
+        outData[i] = idxVector[i].index;
     }
 
     // Free temp memory
-    psFree(tmpVector);
-    psFree(checkVector);
+    psFree(idxVector);
 
     return outVector;
Index: /trunk/psLib/src/mathtypes/psVector.h
===================================================================
--- /trunk/psLib/src/mathtypes/psVector.h	(revision 3736)
+++ /trunk/psLib/src/mathtypes/psVector.h	(revision 3737)
@@ -11,6 +11,6 @@
  *  @author Ross Harman, MHPCC
  *
- *  @version $Revision: 1.31 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2005-04-08 17:58:57 $
+ *  @version $Revision: 1.32 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2005-04-21 21:18:23 $
  *
  *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -25,4 +25,20 @@
 /// @{
 
+///< Union of psVector data types.
+typedef union {
+    psU8* U8;               ///< Unsigned 8-bit integer data.
+    psU16* U16;             ///< Unsigned 16-bit integer data.
+    psU32* U32;             ///< Unsigned 32-bit integer data.
+    psU64* U64;             ///< Unsigned 64-bit integer data.
+    psS8* S8;               ///< Signed 8-bit integer data.
+    psS16* S16;             ///< Signed 16-bit integer data.
+    psS32* S32;             ///< Signed 32-bit integer data.
+    psS64* S64;             ///< Signed 64-bit integer data.
+    psF32* F32;             ///< Single-precision float data.
+    psF64* F64;             ///< Double-precision float data.
+    psC32* C32;             ///< Single-precision complex data.
+    psC64* C64;             ///< Double-precision complex data.
+} p_psVectorData;
+
 /** An vector to support primitive types.
  *
@@ -35,19 +51,5 @@
     int n;                      ///< Number of elements in use.
     const int nalloc;           ///< Total number of elements available.
-
-    union {
-        psU8* U8;               ///< Unsigned 8-bit integer data.
-        psU16* U16;             ///< Unsigned 16-bit integer data.
-        psU32* U32;             ///< Unsigned 32-bit integer data.
-        psU64* U64;             ///< Unsigned 64-bit integer data.
-        psS8* S8;               ///< Signed 8-bit integer data.
-        psS16* S16;             ///< Signed 16-bit integer data.
-        psS32* S32;             ///< Signed 32-bit integer data.
-        psS64* S64;             ///< Signed 64-bit integer data.
-        psF32* F32;             ///< Single-precision float data.
-        psF64* F64;             ///< Double-precision float data.
-        psC32* C32;             ///< Single-precision complex data.
-        psC64* C64;             ///< Double-precision complex data.
-    } data;                     ///< Union for data types.
+    p_psVectorData data;        ///< Union for data types.
 }
 psVector;
Index: /trunk/psLib/test/collections/tst_psVectorSort_01.c
===================================================================
--- /trunk/psLib/test/collections/tst_psVectorSort_01.c	(revision 3736)
+++ /trunk/psLib/test/collections/tst_psVectorSort_01.c	(revision 3737)
@@ -7,11 +7,11 @@
  *     B)  Sort input float vector into itself
  *     C)  Attempt to sort vector with invalid type (i.e. PS_TYPE_BOOL)
- *     D)  Sort input vector with zero items 
+ *     D)  Sort input vector with zero items
  *     C)  Free float vectors
  *
  *  @author  Ross Harman, MHPCC
  *
- *  @version $Revision: 1.8 $  $Name: not supported by cvs2svn $
- *  @date  $Date: 2005-04-07 20:27:41 $
+ *  @version $Revision: 1.9 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2005-04-21 21:18:23 $
  *
  *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -142,9 +142,8 @@
     psLogMsg(__func__,PS_LOG_INFO,"Following should generate an error messgae");
     tempVec = psVectorSort(out,in);
-    if(tempVec != out) {
-        psError(PS_ERR_UNKNOWN,true,"Did not return the specified output vector");
+    if(tempVec != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL on error or didn't error?");
         return 33;
     }
-    psFree(out);
     printFooter(stdout,"psVectorSort","Invalid vector type",true);
 
Index: /trunk/psLib/test/collections/tst_psVectorSort_02.c
===================================================================
--- /trunk/psLib/test/collections/tst_psVectorSort_02.c	(revision 3736)
+++ /trunk/psLib/test/collections/tst_psVectorSort_02.c	(revision 3737)
@@ -14,6 +14,6 @@
  *  @author  Ross Harman, MHPCC
  *
- *  @version $Revision: 1.8 $  $Name: not supported by cvs2svn $
- *  @date  $Date: 2005-04-07 20:27:41 $
+ *  @version $Revision: 1.9 $  $Name: not supported by cvs2svn $
+ *  @date  $Date: 2005-04-21 21:18:23 $
  *
  *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
@@ -155,11 +155,10 @@
     psLogMsg(__func__,PS_LOG_INFO,"Following should generate two error messages(psVectorSort,psVectorSortIndex)");
     out = psVectorSortIndex(out,in);
-    if( out != tempVect) {
-        psError(PS_ERR_UNKNOWN,true,"Did not return the same output vector");
+    if( out != NULL) {
+        psError(PS_ERR_UNKNOWN,true,"Did not return NULL on error or didn't error?");
         return 119;
     }
     in->type.type = PS_TYPE_U8;
     psFree(in);
-    psFree(out);
     printFooter(stdout,"psVectorSortIndex","Attempt to sort with invalid type",true);
 
Index: /trunk/psLib/test/collections/verified/tst_psVectorSort_01.stderr
===================================================================
--- /trunk/psLib/test/collections/verified/tst_psVectorSort_01.stderr	(revision 3736)
+++ /trunk/psLib/test/collections/verified/tst_psVectorSort_01.stderr	(revision 3737)
@@ -2,3 +2,3 @@
     Following should generate an error messgae
 <DATE><TIME>|<HOST>|E|psVectorSort (FILE:LINENO)
-    Input psVector is an unsupported type (4865).
+    Input psVector is an unsupported type (0x1301).
Index: /trunk/psLib/test/collections/verified/tst_psVectorSort_02.stderr
===================================================================
--- /trunk/psLib/test/collections/verified/tst_psVectorSort_02.stderr	(revision 3736)
+++ /trunk/psLib/test/collections/verified/tst_psVectorSort_02.stderr	(revision 3737)
@@ -5,6 +5,4 @@
 <DATE><TIME>|<HOST>|I|main
     Following should generate two error messages(psVectorSort,psVectorSortIndex)
-<DATE><TIME>|<HOST>|E|psVectorSort (FILE:LINENO)
-    Input psVector is an unsupported type (4865).
 <DATE><TIME>|<HOST>|E|psVectorSortIndex (FILE:LINENO)
-    Input psVector is an unsupported type (4865).
+    Input psVector is an unsupported type (0x1301).
