Bug 131: there was a problem with the test harness that caused 35 of
81 tests to fail.  It was a regex problem in the Perl code.

psMatrixVectorArithmetic:
// Conversion for degrees to radians
#define D2R 0.01745329252111111  /* PI/180 */
// Conversion for radians to degrees
#define R2D 57.29577950924861   /* 180.0/PI */

Instead of using M_PI etc.


Running gcov:

=============================================================================================================

 57.89% of 133 source lines executed in file psImage.c

L65:
         467        if (image == NULL) {
      ######            psAbort(__func__, " : Line %d - Failed to allocate memory", __LINE__);
		    }
L72:
         467        if (image->data.V == NULL) {
      ######            psAbort(__func__, " : Line %d - Failed to allocate memory", __LINE__);
		    }
L77:
         467        if (image->data.V[0] == NULL) {
      ######            psAbort(__func__, " : Line %d - Failed to allocate memory", __LINE__);
		    }
L100:
         455        if (image == NULL) {
      ######            return;
		    }

***L104:
         455        if (image->type.type == PS_TYPE_PTR) {
		        // 2-D array of pointers -- must
		        // dereference
      ######            unsigned int oldNumRows = image->numRows;
      ######            unsigned int oldNumCols = image->numCols;
      ######            psPTR* rowPtr;
		
      ######            for (unsigned int row = 0; row < oldNumRows; row++) {
      ######                rowPtr = image->data.PTR[row];
      ######                for (unsigned int col = 0; col < oldNumCols; col++) {
      ######                    psMemDecrRefCounter(rowPtr[col]);
		            }
		        }
		    }
L143:
         171        if (old->type.dimen != PS_DIMEN_IMAGE) {
         187            psError(__func__, "Can not realloc image because input is not an image.");
      ######            return NULL;
		    }
***L148:
         171        if (old->type.type == PS_TYPE_PTR) {
		        // 2-D array of pointers -- must
		        // dereference
      ######            unsigned int oldNumRows = old->numRows;
      ######            unsigned int oldNumCols = old->numCols;
      ######            psPTR* rowPtr;
		
      ######            for (unsigned int row = 0; row < oldNumRows; row++) {
      ######                rowPtr = old->data.PTR[row];
      ######                for (unsigned int col = 0; col < oldNumCols; col++) {
      ######                    psMemDecrRefCounter(rowPtr[col]);
      ######                    rowPtr[col] = NULL;
		            }
		        }
		    }
L191:
         456        if (image == NULL) {
      ######            return numFreed;
		    }
L222:
         162        if (input == NULL) {
         162            psError(__func__, "Image can not be NULL.");
      ######            return unexposedValue;
		    }
***L240:
         162        switch (input->type.type) {
      ######            PSIMAGE_PIXEL_INTERPOLATE_CASE(U8);
      ######            PSIMAGE_PIXEL_INTERPOLATE_CASE(U16);
      ######            PSIMAGE_PIXEL_INTERPOLATE_CASE(U32);
      ######            PSIMAGE_PIXEL_INTERPOLATE_CASE(U64);
      ######            PSIMAGE_PIXEL_INTERPOLATE_CASE(S8);
      ######            PSIMAGE_PIXEL_INTERPOLATE_CASE(S16);
      ######            PSIMAGE_PIXEL_INTERPOLATE_CASE(S32);
      ######            PSIMAGE_PIXEL_INTERPOLATE_CASE(S64);
         162            PSIMAGE_PIXEL_INTERPOLATE_CASE(F32);
      ######            PSIMAGE_PIXEL_INTERPOLATE_CASE(F64);
      ######            PSIMAGE_PIXEL_INTERPOLATE_CASE(C32);
      ######            PSIMAGE_PIXEL_INTERPOLATE_CASE(C64);
		    default:
      ######            psError(__func__, "Unsupported image datatype (%d)", input->type.type);
		    }

=============================================================================================================

 83.25% of 209 source lines executed in file psImageExtraction.c

L51:
          13        if (image->type.dimen != PS_DIMEN_IMAGE) {
      ######            psError(__func__, "Can not subset image because input image is not an image.");
      ######            return NULL;
		    }
L117:
          69        if (input == output) {
      ######            psError(__func__,
		                "Can not copy image because given input and output "
		                "parameter reference the same psImage struct.");
      ######            psFree(output);
      ######            return NULL;
		    }
L125:
          69        if (input->type.dimen != PS_DIMEN_IMAGE) {
      ######            psError(__func__, "Can not copy image because input image is not actually an image.");
      ######            psFree(output);
      ######            return NULL;
		    }
L137:
          69        if (inDatatype == PS_TYPE_PTR || type == PS_TYPE_PTR) {
      ######            psError(__func__, "Can not copy image to/from a void* matrix");
      ######            psFree(output);
      ######            return NULL;
		    }
***L201:
          57        switch (type) {
		    case PS_TYPE_S8:
           7            PSIMAGE_COPY_CASE(output, S8);
           7            break;
		    case PS_TYPE_S16:
           7            PSIMAGE_COPY_CASE(output, S16);
           7            break;
		    case PS_TYPE_S32:
           7            PSIMAGE_COPY_CASE(output, S32);
      ######            break;
		    case PS_TYPE_S64:
      ######            PSIMAGE_COPY_CASE(output, S64);
           7            break;
		    case PS_TYPE_U8:
           7            PSIMAGE_COPY_CASE(output, U8);
           7            break;
		    case PS_TYPE_U16:
           7            PSIMAGE_COPY_CASE(output, U16);
           7            break;
		    case PS_TYPE_U32:
           7            PSIMAGE_COPY_CASE(output, U32);
      ######            break;
		    case PS_TYPE_U64:
      ######            PSIMAGE_COPY_CASE(output, U64);
           7            break;
		    case PS_TYPE_F32:
           7            PSIMAGE_COPY_CASE(output, F32);
           7            break;
		    case PS_TYPE_F64:
           7            PSIMAGE_COPY_CASE(output, F64);
           1            break;
		    case PS_TYPE_C32:
           1            PSIMAGE_COPY_CASE(output, C32);
      ######            break;
		    case PS_TYPE_C64:
      ######            PSIMAGE_COPY_CASE(output, C64);
          57            break;
		    default:
          57            break;
		    }
          57        return output;
		}
L297:
          23        if (mask != NULL) {
          23            if (inRows != mask->numRows || inCols != mask->numCols) {
      ######                psError(__func__,
		                    "The mask and image dimensions did not match (%dx%d vs %dx%d)",
		                    mask->numCols, mask->numRows, in->numCols, in->numRows);
      ######                psFree(out);
		        }
          23            if (mask->type.type != PS_TYPE_MASK) {
      ######                psError(__func__, "The mask datatype (%d) must be %s.", mask->type.type, PS_TYPE_MASK_NAME);
      ######                psFree(out);
		        }
		    }
L386:
           8            switch (type) {
      ######                PSIMAGE_CUT_VERTICAL(U8);
      ######                PSIMAGE_CUT_VERTICAL(U16);
      ######                PSIMAGE_CUT_VERTICAL(U32);
      ######                PSIMAGE_CUT_VERTICAL(U64);
      ######                PSIMAGE_CUT_VERTICAL(S8);
      ######                PSIMAGE_CUT_VERTICAL(S16);
      ######                PSIMAGE_CUT_VERTICAL(S32);
      ######                PSIMAGE_CUT_VERTICAL(S64);
           8                PSIMAGE_CUT_VERTICAL(F32);
      ######                PSIMAGE_CUT_VERTICAL(F64);
      ######                PSIMAGE_CUT_VERTICAL(C32);
      ######                PSIMAGE_CUT_VERTICAL(C64);
		        default:
      ######                psError(__func__, "Unsupported datatype (%d)", type);
      ######                psFree(out);
      ######                out = NULL;
		        }

=============================================================================================================

 43.93% of 239 source lines executed in file psImageIO.c

LOTS

=============================================================================================================

 61.74% of 345 source lines executed in file psImageManip.c

***L110:
      ######            psImageClipCase(S64, "psS64")
***L114:
      ######            psImageClipCase(U64, "psU64")
L120:
		    default:
      ######            psError(__func__, "psImageClip does not support the given datatype (%d)", input->type.type);
***L156:
      ######            psImageClipNaNCase(C32)
      ######            psImageClipNaNCase(C64)
L181:
          42        if (op == NULL) {
      ######            psError(__func__, "Operation can not be NULL.");
      ######            return 1;
		    }
L188:
          42        if (type != overlay->type.type) {
      ######            psError(__func__, "Image and overlay datatypes must match. (%d vs %d)", type, overlay->type.type);
      ######            return 2;
		    }
L199:
          42        if (row0 < 0 || col0 < 0 || row0 >= imageNumRows || col0 >= imageNumCols) {
      ######            psError(__func__,
		                "Overlay origin of (%d,%d) is outside of the image dimensions (%d x %d).",
		                col0, row0, imageNumCols, imageNumRows);
      ######            return 3;
		    }
***L249:
           5            psImageOverlayCase(U8);
           5            psImageOverlayCase(U16);
      ######            psImageOverlayCase(U32);
      ######            psImageOverlayCase(U64);
           5            psImageOverlayCase(S8);
           5            psImageOverlayCase(S16);
      ######            psImageOverlayCase(S32);
      ######            psImageOverlayCase(S64);
           6            psImageOverlayCase(F32);
           5            psImageOverlayCase(F64);
           5            psImageOverlayCase(C32);
           5            psImageOverlayCase(C64);
L262:
		    default:
      ######            psError(__func__, "Can not operate on type %d.", type);
		    }
L335:
		    default:
      ######            psError(__func__, "psImageClip does not support the given datatype (%d)", input->type.type);
		    }
***L421:
           2        switch (in->type.type) {
      ######            PS_IMAGE_REBIN_CASE(U8);
      ######            PS_IMAGE_REBIN_CASE(U16);
      ######            PS_IMAGE_REBIN_CASE(U32);
      ######            PS_IMAGE_REBIN_CASE(U64);
      ######            PS_IMAGE_REBIN_CASE(S8);
      ######            PS_IMAGE_REBIN_CASE(S16);
      ######            PS_IMAGE_REBIN_CASE(S32);
      ######            PS_IMAGE_REBIN_CASE(S64);
           2            PS_IMAGE_REBIN_CASE(F32);
      ######            PS_IMAGE_REBIN_CASE(F64);
      ######            PS_IMAGE_REBIN_CASE(C32);
      ######            PS_IMAGE_REBIN_CASE(C64);
		    default:
      ######            psError(__func__, "Input image type not supported.");
      ######            psFree(out);
      ######            out = NULL;
		    }

***psImageResample

***L588:
           2            switch (type) {
      ######                PSIMAGE_ROTATE_LEFT_90(U8);
      ######                PSIMAGE_ROTATE_LEFT_90(U16);
      ######                PSIMAGE_ROTATE_LEFT_90(U32);
      ######                PSIMAGE_ROTATE_LEFT_90(U64);
      ######                PSIMAGE_ROTATE_LEFT_90(S8);
           1                PSIMAGE_ROTATE_LEFT_90(S16);
      ######                PSIMAGE_ROTATE_LEFT_90(S32);
      ######                PSIMAGE_ROTATE_LEFT_90(S64);
           1                PSIMAGE_ROTATE_LEFT_90(F32);
      ######                PSIMAGE_ROTATE_LEFT_90(F64);
      ######                PSIMAGE_ROTATE_LEFT_90(C32);
      ######                PSIMAGE_ROTATE_LEFT_90(C64);
L601:
		        default:
      ######                psError(__func__, "Unsupported type (%d)", type);
      ######                psFree(out);
      ######                return NULL;
		        }
***L628:
           4            switch (type) {
      ######                PSIMAGE_ROTATE_180_CASE(U8);
      ######                PSIMAGE_ROTATE_180_CASE(U16);
      ######                PSIMAGE_ROTATE_180_CASE(U32);
      ######                PSIMAGE_ROTATE_180_CASE(U64);
      ######                PSIMAGE_ROTATE_180_CASE(S8);
           2                PSIMAGE_ROTATE_180_CASE(S16);
      ######                PSIMAGE_ROTATE_180_CASE(S32);
      ######                PSIMAGE_ROTATE_180_CASE(S64);
           2                PSIMAGE_ROTATE_180_CASE(F32);
      ######                PSIMAGE_ROTATE_180_CASE(F64);
      ######                PSIMAGE_ROTATE_180_CASE(C32);
      ######                PSIMAGE_ROTATE_180_CASE(C64);
L641:
		        default:
      ######                psError(__func__, "Unsupported type (%d)", type);
      ######                psFree(out);
      ######                return NULL;
		        }

***L667:
           2            switch (type) {
      ######                PSIMAGE_ROTATE_RIGHT_90(U8);
      ######                PSIMAGE_ROTATE_RIGHT_90(U16);
      ######                PSIMAGE_ROTATE_RIGHT_90(U32);
      ######                PSIMAGE_ROTATE_RIGHT_90(U64);
      ######                PSIMAGE_ROTATE_RIGHT_90(S8);
           1                PSIMAGE_ROTATE_RIGHT_90(S16);
      ######                PSIMAGE_ROTATE_RIGHT_90(S32);
      ######                PSIMAGE_ROTATE_RIGHT_90(S64);
           1                PSIMAGE_ROTATE_RIGHT_90(F32);
      ######                PSIMAGE_ROTATE_RIGHT_90(F64);
      ######                PSIMAGE_ROTATE_RIGHT_90(C32);
      ######                PSIMAGE_ROTATE_RIGHT_90(C64);
L680:
		        default:
      ######                psError(__func__, "Unsupported type (%d)", type);
      ######                psFree(out);
      ######                return NULL;
		        }

***L797:
      ######                PSIMAGE_ROTATE_ARBITRARY_CASE(BILINEAR);
L798:
		        default:
      ######                psError(__func__, "Unsupported interpolation mode (%d)", mode);
      ######                psFree(out);
      ######                out = NULL;
		        }

psImageShift

=============================================================================================================

 96.07% of 178 source lines executed in file psImageStats.c

L71:
           6            if (mask->type.type != PS_TYPE_MASK) {
      ######                psError(__func__, "Expected the mask image type not found (type=%x)", mask->type.type);
      ######                psFree(junkData);
      ######                return NULL;
		        }
L118:
           6            if (mask->type.type != PS_TYPE_MASK) {
          15                psError(__func__, "Expected the mask image type not found (type=%x)", mask->type.type);
      ######                psFree(junkData);
      ######                return NULL;
		        }
L257:
           1        if (coeffs->nY > coeffs->nX) {
      ######            maxChebyPoly = coeffs->nY;
		    }
L365:
           1        if (coeffs->nY > coeffs->nX) {
      ######            maxChebyPoly = coeffs->nY;
		    }

=============================================================================================================

  0.00% of 6 source lines executed in file psAbort.c

gcov claims these haven't been exercised, but I'm sure that they have.

=============================================================================================================

100.00% of 4 source lines executed in file psError.c

=============================================================================================================

 90.98% of 133 source lines executed in file psLogMsg.c

L69:
          43        if ((level < MIN_LOG_LEVEL) || (level > MAX_LOG_LEVEL)) {
      ######            psLogMsg("logmsg", PS_LOG_WARN, "Attempt to set invalid logMsg level: %d", level);
      ######            level = (level < MIN_LOG_LEVEL) ? MIN_LOG_LEVEL : MAX_LOG_LEVEL;
		    }
L116:
           1                if (logDest != NULL && logDest != stderr && logDest != stdout) {
      ######                    fclose(logDest);
		            }
L123:
           1                if (logDest != NULL && logDest != stderr && logDest != stdout) {
      ######                    fclose(logDest);
		            }
L129:
      ######            psError(__func__, "The location, %s, for protocol 'dest' is invalid.", location);
      ######            return 1;
L138:
           1            if (logDest != NULL && logDest != stderr && logDest != stdout) {
      ######                fclose(logDest);
		        }
L145:
      ######        psError(__func__, "Do not know how to handle the protocol '%s'.", protocol);
      ######        return false;
L288:
		    default:
      ######            psTrace("utils.logMsg", 2, "Invalid logMsg level: %d (%s)\n", level, fmt);
      ######            level = (level < 0) ? 0 : 9;
         395            break;
		    }


=============================================================================================================

 76.72% of 262 source lines executed in file psMemory.c

static void *memExhaustedCallbackDefault
psMemExhaustedCallback psMemExhaustedCallbackSet
static void memProblemCallbackDefault
L117:
           2        if (func != NULL) {
           2            memProblemCallback = func;
		    } else {
      ######            memProblemCallback = memProblemCallbackDefault;
		    }

static psMemoryId memAllocateCallbackDefault
static psMemoryId memFreeCallbackDefault

L182:
           1        if (func != NULL) {
           1            memAllocateCallback = func;
		    } else {
      ######            memAllocateCallback = memAllocateCallbackDefault;
		    }
L195:
           1        if (func != NULL) {
           1            memFreeCallback = func;
		    } else {
      ######            memFreeCallback = memFreeCallbackDefault;
		    }
L229:
       47465        if (m == NULL) {
      ######            psError(funcName, "Memory Corruption: NULL memory block found.");
      ######            return 1;
		    }
L244:
       47464        if (*(void **)((int8_t *) (m + 1) + m->userMemorySize) != P_PS_MEMMAGIC) {
      ######            psError(funcName, "Memory Corruption: memory block %ld is corrupted (buffer overflow)", m->id);
      ######            return 1;
		    }
L265 (possibly gcov wrong):
           1                if (abort_on_error) {
		                // release the lock on the memblock list
      ######                    pthread_mutex_unlock(&memBlockListMutex);
      ######                    psAbort(__func__, "Detected memory corruption");
      ######                    return nbad;
		            }
L315 (something funky with gcov):
        1814            if (ptr == NULL) {
      ######                ptr = memExhaustedCallback(size);
      ######                if (ptr == NULL) {
       30851                    psAbort(__func__, "Failed to allocate %u bytes at %s:%d", size, file, lineno);
		            }
		        }
L368(gcov):
         521            if (checkMemBlock(ptr, __func__) != 0) {
      ######                memProblemCallback(ptr, file, lineno);
      ######                psAbort(file, "Realloc detected a memory corruption (id %ld @ %s:%d).",
		                    ptr->id, ptr->file, ptr->lineno);
		        }
L477:
         160        if (checkMemBlock(ptr, __func__) != 0) {
      ######            memProblemCallback(ptr, __func__, __LINE__);
		    }
L499:
         756        if (checkMemBlock(ptr, __func__)) {
      ######            memProblemCallback(ptr, file, lineno);
		    }
L519:
       62686        if (checkMemBlock(ptr, __func__) != 0) {
      ######            memProblemCallback(ptr, file, lineno);
      ######            return NULL;
		    }
L611:
       29356        if (checkMemBlock(ptr, __func__) != 0) {
      ######            memProblemCallback(ptr, __func__, __LINE__);
		    }

psFreeFcn p_psMemGetDeallocator

=============================================================================================================

100.00% of 11 source lines executed in file psString.c

=============================================================================================================

 84.92% of 126 source lines executed in file psTrace.c

static void componentFree
void psTraceFree
L158:
          55        if (addNodeName[0] != '.') {
      ######            printf("ERROR: failed to add %s to the root component tree.\n", addNodeName);
      ######            exit(1);
		    }
L309:
          11        if (comp->name[0] == '\0') {
      ######            printf("%*s%-*s %d\n", depth, "", 20 - depth,
		               "(root)", (comp->level == PS_UNKNOWN_TRACE_LEVEL) ? 0 : comp->level);
		    } else {
          11            if (comp->level == PS_UNKNOWN_TRACE_LEVEL) {
      ######                printf("%*s%-*s %s\n", depth, "", 20 - depth, comp->name, ".");
		        } else {


=============================================================================================================

 83.33% of 42 source lines executed in file psArray.c

L71:
           2        if (in == NULL) {
      ######            psError(__func__, "Null input vector\n");
      ######            return NULL;

=============================================================================================================

 90.40% of 125 source lines executed in file psBitSet.c

L109:
          26        if (newObj == NULL) {
      ######            psAbort(__func__, " : Line %d - Failed to allocate memory", __LINE__);
		    }
L118:
          26        if (newObj->bits == NULL) {
      ######            psAbort(__func__, " : Line %d - Failed to allocate memory", __LINE__);
		    }
L195:
           9        if (operator == NULL) {
      ######            psError(__func__, " : Line %d - Null input operator\n", __LINE__);
      ######            return outBitSet;
		    }
L200:
           9        if (inBitSet2 == NULL) {
      ######            psError(__func__, " : Line %d - Null psBitSet for inBitSet2 argument", __LINE__);
      ######            return outBitSet;
		    }
L257:
           3        if (n == 0) {
      ######            psError(__func__, " : Line %d - No elements in inBitSet", __LINE__);
      ######            return outBitSet;
		    }
L265:
           3        if (inBitSet->n != outBitSet->n) {
      ######            psError(__func__, " : Line %d - psBitSet sizes not the same", __LINE__);
      ######            return outBitSet;
		    }

=============================================================================================================

 12.50% of 40 source lines executed in file psCompare.c

Need to do all the macros.

=============================================================================================================

 87.18% of 117 source lines executed in file psHash.c

L96
          55        if (data == NULL) {
		        // NOTE: Should we flag a warning message?
      ######            bucket->data = NULL;
		    } else {
          55            bucket->data = psMemIncrRefCounter(data);
		    }
L246:
         132        if ((hash < 0) || (hash >= table->nbucket)) {
      ######            psAbort(__func__, "Internal hash function out of range (%d)", hash);
		    }
***L304:
          65            while (ptr != NULL) {
          10                if (strcmp(key, ptr->key) == 0) {
		                // We have found this key in the hash table.
		
      ######                    psTrace("utils.hash.insert", 3, "Replacing data for %s\n", key);
		
		                // NOTE: I have changed this behavior from the originally
		                // supplied code.  Formerly, if itemFree was NULL, then
		                // the new data was not inserted into the hash table.
		
      ######                    psFree(ptr->data);
		
      ######                    ptr->data = psMemIncrRefCounter(data);
      ######                    return data;
		            }
          10                ptr = ptr->next;
		        }
L402:
          14        if (data != NULL) {
          14            retVal = true;
		    } else {
      ######            retVal = false;
		    }

=============================================================================================================

 98.21% of 224 source lines executed in file psList.c

L137:
          19            if (position == NULL) {
      ######                psError(__func__, "%s failed to move cursor to specified location (%d)", __func__, where);
      ######                position = list->head;         // since we no list->size != 0, this must be non-NULL
		        }

=============================================================================================================

 36.96% of 46 source lines executed in file psScalar.c

psScalar* psScalarCopy
void psScalarFree

All the different cases.

=============================================================================================================

 67.08% of 161 source lines executed in file psVector.c

L147:
          13        if (nalloc < 1) {
          42            psError(__func__, "Invalid value for nalloc (%d)\n", nalloc);
      ######            psFree(in);
      ######            return NULL;
		    }
**L181:
        6622        if (outVector == NULL) {
      ######            outVector = psVectorAlloc(inN, inType);
      ######            outVector->n = inVector->n;
		    }
L201:
        6620        if (inN == 0) {
      ######            psError(__func__, " : Line %d - No elements in use for input vector\n", __LINE__);
      ######            return outVector;
		    }
		
        6620        if (outN == 0) {
      ######            psError(__func__, " : Line %d - No elements in use for output vector\n", __LINE__);
      ######            return outVector;
		    }
***L214:
        6620        switch (inType) {
		    case PS_TYPE_U8:
      ######            qsort(outVec, inN, elSize, psCompareU8);
      ######            break;
		    case PS_TYPE_U16:
      ######            qsort(outVec, inN, elSize, psCompareU16);
      ######            break;
		    case PS_TYPE_U32:
      ######            qsort(outVec, inN, elSize, psCompareU32);
      ######            break;
		    case PS_TYPE_U64:
      ######            qsort(outVec, inN, elSize, psCompareU64);
      ######            break;
		    case PS_TYPE_S8:
      ######            qsort(outVec, inN, elSize, psCompareS8);
      ######            break;
		    case PS_TYPE_S16:
      ######            qsort(outVec, inN, elSize, psCompareS16);
      ######            break;
		    case PS_TYPE_S32:
      ######            qsort(outVec, inN, elSize, psCompareS32);
      ######            break;
		    case PS_TYPE_S64:
      ######            qsort(outVec, inN, elSize, psCompareS64);
      ######            break;
		    case PS_TYPE_F32:
        6620            qsort(outVec, inN, elSize, psCompareF32);
        6620            break;
		    case PS_TYPE_F64:
      ######            qsort(outVec, inN, elSize, psCompareF64);
      ######            break;
		    default:
      ######            psError(__func__, " : Line %d - Invalid psType\n", __LINE__);
		    }
L292:
           1        if (inN != outN) {
      ######            psError(__func__, " : Line %d - Input and output vector sizes are not equal: in=%d out=%d\n",
		                __LINE__, inN, outN);
      ######            return outVector;
		    }
		
           1        if (outVector->type.type != PS_TYPE_U32) {
      ######            psError(__func__, " : Line %d - Output vector is not of type U32: out=%d\n",
		                __LINE__, outVector->type.type);
      ######            return outVector;
		    }
***L309:
           1        switch (inType) {
		    case PS_TYPE_U8:
      ######            SORT_INDICES(U8);
      ######            break;
		    case PS_TYPE_U16:
      ######            SORT_INDICES(U16);
      ######            break;
		    case PS_TYPE_U32:
      ######            SORT_INDICES(U32);
      ######            break;
		    case PS_TYPE_U64:
      ######            SORT_INDICES(U64);
      ######            break;
		    case PS_TYPE_S8:
      ######            SORT_INDICES(S8);
      ######            break;
		    case PS_TYPE_S16:
      ######            SORT_INDICES(S16);
      ######            break;
		    case PS_TYPE_S32:
      ######            SORT_INDICES(S32);
      ######            break;
		    case PS_TYPE_S64:
      ######            SORT_INDICES(S64);
           1            break;
		    case PS_TYPE_F32:
           1            SORT_INDICES(F32);
      ######            break;
		    case PS_TYPE_F64:
      ######            SORT_INDICES(F64);
      ######            break;
		    default:
      ######            psError(__func__, " : Line %d - Invalid psType\n", __LINE__);
		    }


=============================================================================================================

 63.49% of 430 source lines executed in file psFFT.c

L38:
           2        if (in == NULL) {
      ######            psFree(out);
      ######            return NULL;
		    }
L45 (gcov?):
           2        if ((type != PS_TYPE_F32) && (type != PS_TYPE_C32)) {
           2            psError(__func__, "Input image must be a 32-bit float or complex image (type=%d)", type);
      ######            psFree(out);
      ######            return NULL;
		    }
		
           2        if (type != PS_TYPE_C32 && direction == PS_FFT_REVERSE) {
      ######            psError(__func__, "Input image must be complex image for reverse FFT (type=%d).", type);
      ######            psFree(out);
      ######            return NULL;
		
		    }
		
           2        if (type != PS_TYPE_F32 && direction == PS_FFT_FORWARD) {
      ######            psError(__func__, "Input image must be real image for forward FFT (type=%d).", type);
      ######            psFree(out);
      ######            return NULL;
		    }
L80:
           2        if (plan == NULL) {
      ######            psError(__func__, "Failed to create FFTW plan.");
      ######            psFree(out);
      ######            return NULL;
		    }
L101:
           1        if (in == NULL) {
      ######            psFree(out);
      ######            return NULL;
		    }
***L131:
      ######        } else if (type == PS_TYPE_C64) {
      ######            psF64* outRow;
      ######            psC64* inRow;
		
      ######            out = psImageRecycle(out, numCols, numRows, PS_TYPE_F64);
      ######            for (unsigned int row = 0; row < numRows; row++) {
      ######                outRow = out->data.F64[row];
      ######                inRow = in->data.C64[row];
		
      ######                for (unsigned int col = 0; col < numCols; col++) {
      ######                    outRow[col] = creal(inRow[col]);
		            }
		        }
		    } else {
      ######            psError(__func__, "Can not extract real component from given image type (%d).", type);
      ######            psFree(out);
      ######            return NULL;
		    }
L159:
           1        if (in == NULL) {
      ######            psFree(out);
      ######            return NULL;
		    }
L169 (gcov?):
           1        if (!PS_IS_PSELEMTYPE_COMPLEX(type)) {
		        // Warn user, as this is probably not expected
           1            psLogMsg(__func__, PS_LOG_WARN, "Imaginary portion of a non-Complex type called for. "
		                 "A zero image was returned.");
      ######            out = psImageRecycle(out, numCols, numRows, type);
      ######            memset(out->data.V[0], 0, PSELEMTYPE_SIZEOF(type) * numCols * numRows);
      ######            return out;
		    }
***L191:
      ######        } else if (type == PS_TYPE_C64) {
      ######            psF64* outRow;
      ######            psC64* inRow;
		
      ######            out = psImageRecycle(out, numCols, numRows, PS_TYPE_F64);
      ######            for (unsigned int row = 0; row < numRows; row++) {
      ######                outRow = out->data.F64[row];
      ######                inRow = in->data.C64[row];
		
      ######                for (unsigned int col = 0; col < numCols; col++) {
      ######                    outRow[col] = cimag(inRow[col]);
		            }
		        }
		    } else {
      ######            psError(__func__, "Can not extract imaginary component from given image type (%d).", type);
      ######            psFree(out);
      ######            return NULL;
		    }
L219:
           3        if (real == NULL || imag == NULL) {
      ######            psFree(out);
      ######            return NULL;
		    }
L240:
           1        if (PS_IS_PSELEMTYPE_COMPLEX(type)) {
      ######            psError(__func__, "The inputs to psImageComplex can not be complex.");
      ######            psFree(out);
      ######            return NULL;
		    }
L246:
           1        if (type != PS_TYPE_F32 && type != PS_TYPE_F64) {
      ######            psError(__func__, "The input type to psImageComplex must be a floating point.");
      ######            psFree(out);
      ######            return NULL;
		    }
***L268:
      ######        } else if (type == PS_TYPE_F64) {
      ######            psC64* outRow;
      ######            psF64* realRow;
      ######            psF64* imagRow;
		
      ######            out = psImageRecycle(out, numCols, numRows, PS_TYPE_C64);
      ######            for (unsigned int row = 0; row < numRows; row++) {
      ######                outRow = out->data.C64[row];
      ######                realRow = real->data.F64[row];
      ######                imagRow = imag->data.F64[row];
		
      ######                for (unsigned int col = 0; col < numCols; col++) {
      ######                    outRow[col] = realRow[col] + I * imagRow[col];
		            }
		        }
		    } else {
      ######            psError(__func__, "Can not merge real and imaginary portions for given image type (%d).", type);
      ######            psFree(out);
      ######            return NULL;
		    }
L298:
           1        if (in == NULL) {
      ######            psFree(out);
      ######            return NULL;
		    }
***L328:
      ######        } else if (type == PS_TYPE_C64) {
      ######            psC64* outRow;
      ######            psC64* inRow;
		
      ######            out = psImageRecycle(out, numCols, numRows, PS_TYPE_C64);
      ######            for (unsigned int row = 0; row < numRows; row++) {
      ######                outRow = out->data.C64[row];
      ######                inRow = in->data.C64[row];
		
      ######                for (unsigned int col = 0; col < numCols; col++) {
      ######                    outRow[col] = creal(inRow[col]) - I * cimag(inRow[col]);
		            }
		        }
		    } else {
      ######            psError(__func__, "Can not compute complex conjugate for given image type (%d).", type);
      ######            psFree(out);
      ######            return NULL;
		    }
L357:
           1        if (in == NULL) {
      ######            psFree(out);
      ######            return NULL;
		    }
L368 (gcov?):
           1        if (!PS_IS_PSELEMTYPE_COMPLEX(type)) {
           1            psError(__func__, "Power Spectrum for non-complex inputs is not implemented.");
      ######            psFree(out);
      ######            return NULL;
		    }
***L391:
      ######        } else if (type == PS_TYPE_C64) {
      ######            psF64* outRow;
      ######            psC64* inRow;
      ######            psF64 real;
      ######            psF64 imag;
		
      ######            out = psImageRecycle(out, numCols, numRows, PS_TYPE_F64);
      ######            for (unsigned int row = 0; row < numRows; row++) {
      ######                outRow = out->data.F64[row];
      ######                inRow = in->data.C64[row];
		
      ######                for (unsigned int col = 0; col < numCols; col++) {
      ######                    real = crealf(inRow[col]);
      ######                    imag = cimagf(inRow[col]);
      ######                    outRow[col] = real * real + imag * imag / numElementsSquared;
		            }
		        }
		    } else {
      ######            psError(__func__, "Can not power spectrum for given image type (%d).", type);
      ######            psFree(out);
      ######            return NULL;
		    }
L427:
           2        if (in == NULL) {
      ######            psFree(out);
      ######            return NULL;
		    }
L434:
           2        if ((type != PS_TYPE_F32) && (type != PS_TYPE_C32)) {
           2            psError(__func__, "Input image must be a 32-bit float or complex image (type=%d)", type);
      ######            psFree(out);
      ######            return NULL;
		    }
L440:
           2        if ((type != PS_TYPE_C32) && (direction == PS_FFT_REVERSE)) {
      ######            psError(__func__, "Input image must be complex image for reverse FFT (type=%d).", type);
      ######            psFree(out);
      ######            return NULL;
		
		    }
L447:
           2        if ((type != PS_TYPE_F32) && (direction == PS_FFT_FORWARD)) {
      ######            psError(__func__, "Input image must be real image for forward FFT (type=%d).", type);
      ######            psFree(out);
      ######            return NULL;
		    }
L486:
           2        if (plan == NULL) {
      ######            psError(__func__, "Failed to create FFTW plan.");
      ######            psFree(out);
      ######            return NULL;
		    }
L505:
           1        if (in == NULL) {
      ######            psFree(out);
      ######            return NULL;
		    }
***L514:
           1        if (!PS_IS_PSELEMTYPE_COMPLEX(type)) {
		        // Warn user, as this is probably not expected
           1            psLogMsg(__func__, PS_LOG_WARN, "Real portion of a non-Complex type called called for. "
		                 "Just a vector copy was performed.");
      ######            out = psVectorRecycle(out, numElements, type);
      ######            out->n = numElements;
      ######            memcpy(out->data.V, in->data.V, numElements * PSELEMTYPE_SIZEOF(type));
      ######            return out;
		    }
L535:
		    } else {
      ######            psError(__func__, "Can not extract real component from given vector type (%d).", type);
      ######            psFree(out);
      ######            return NULL;
		    }
L549:
           1        if (in == NULL) {
      ######            psFree(out);
      ######            return NULL;
		    }
***L558:
           1        if (!PS_IS_PSELEMTYPE_COMPLEX(type)) {
		        // Warn user, as this is probably not expected
           1            psLogMsg(__func__, PS_LOG_WARN, "Imaginary portion of a non-Complex type called for. "
		                 "A zeroed vector was returned.");
      ######            out = psVectorRecycle(out, numElements, type);
      ######            out->n = numElements;
      ######            memset(out->data.V, 0, PSELEMTYPE_SIZEOF(type) * numElements);
      ######            return out;
		    }
L579:
		    } else {
      ######            psError(__func__, "Can not extract imaginary component from given vector type (%d).", type);
      ######            psFree(out);
      ######            return NULL;
		    }
L593:
           3        if (real == NULL || imag == NULL) {
      ######            psFree(out);
      ######            return NULL;
		    }
L611:
           2        if (PS_IS_PSELEMTYPE_COMPLEX(type)) {
      ######            psError(__func__, "The inputs to psVectorComplex can not be complex.");
      ######            psFree(out);
      ######            return NULL;
		    }
L629:
		    } else {
      ######            psError(__func__, "Can not merge real and imaginary portions for given vector type (%d).", type);
      ######            psFree(out);
      ######            return NULL;
		    }
L643:
           1        if (in == NULL) {
      ######            psFree(out);
      ######            return NULL;
		    }
***L652:
           1        if (!PS_IS_PSELEMTYPE_COMPLEX(type)) {
		        // Warn user, as this is probably not expected
           1            psLogMsg(__func__, PS_LOG_WARN, "Complex Conjugate of a non-Complex type called for. "
		                 "Vector copy was performed instead.");
		
      ######            out = psVectorRecycle(out, numElements, type);
      ######            out->n = numElements;
      ######            memcpy(out->data.V, in->data.V, PSELEMTYPE_SIZEOF(type) * numElements);
      ######            return out;
		    }
L674:
		    } else {
      ######            psError(__func__, "Can not compute complex conjugate for given vector type (%d).", type);
      ######            psFree(out);
      ######            return NULL;
		    }
L691:
           1        if (in == NULL) {
      ######            psFree(out);
      ######            return NULL;
		    }
L703 (gcov?):
           1        if (!PS_IS_PSELEMTYPE_COMPLEX(type)) {
           1            psError(__func__, "Power Spectrum for non-complex inputs is not implemented.");
      ######            psFree(out);
      ######            return NULL;
		    }
L733:
		    } else {
      ######            psError(__func__, "Can not power spectrum for given vector type (%d).", type);
      ######            psFree(out);
      ######            return NULL;
		    }

=============================================================================================================

 99.32% of 438 source lines executed in file psFunctions.c

L372:
     1056799        if (myPoly->n == 0) {
      ######            return (1.0);
		    }
L376:
     1056799        if (NULL == myPoly->coeff) {
      ######            psAbort(__func__, "psPolynomial1DEval(): myPoly->coeff is NULL\n");
		    }
L682:
           1        if (myPoly->n == 0) {
      ######            return (1.0);
		    }

=============================================================================================================

 94.57% of 258 source lines executed in file psMatrix.c

L507:
           1            if (outVector->n == 0) {
      ######                outVector->n = inImage->numRows;
		        }
L511:
           1            if (outVector->n != inImage->numRows) {
      ######                psError(__func__, "Image and vector sizes differ: (%d vs %d).", inImage->numRows, outVector->n);
      ######                return outVector;
		        }
L521:
           1            if (outVector->n == 0) {
      ######                outVector->n = inImage->numCols;
		        }
L525:
           1            if (outVector->n != inImage->numCols) {
      ######                psError(__func__, "Image and vector sizes differ: (%d vs %d).", inImage->numCols, outVector->n);
      ######                return outVector;
		        }
L550:
           1            if (outImage->numCols > 1) {
      ######                psError(__func__, "Image has more than 1 column: numCols = %d.", outImage->numCols);
      ######                return outImage;
           1            } else if (outImage->numRows != inVector->n) {
      ######                psError(__func__, "Image and vector sizes differ: (%d vs %d).", outImage->numRows, inVector->n);
      ######                return outImage;
		        }
L565:
           1            if (outImage->numRows > 1) {
      ######                psError(__func__, "Image has more than 1 row: numRows = %d.", outImage->numRows);
      ######                return outImage;
           1            } else if (outImage->numCols != inVector->n) {
      ######                psError(__func__, "Image and vector sizes differ: (%d vs %d).", outImage->numCols, inVector->n);
      ######                return outImage;
		        }

=============================================================================================================

 80.30% of 132 source lines executed in file psMatrixVectorArithmetic.c

L451:
          58        if (dim1 == PS_DIMEN_OTHER || dim2 == PS_DIMEN_OTHER || dimOut == PS_DIMEN_OTHER) {
      ######            psError(__func__, ": Line %d - PS_DIMEN_OTHER not allowed for arguments: (%d, %d, %d)", __LINE__,
		                dim1, dim2, dimOut);
      ######            return out;
		    }
L457:
          58        if (dim1 == PS_DIMEN_VECTOR) {
           1            if (((psVector* ) in1)->n == 0) {
      ######                psError(__func__, ": Line %d - Vector contains zero elements");
		        }
          57        } else if (dim1 == PS_DIMEN_IMAGE) {
          56            if (((psImage* ) in1)->numCols == 0 || ((psImage* ) in1)->numRows == 0) {
      ######                psError(__func__, ": Line %d - Image contains zero length row or cols");
		        }
		    }
L467:
          58        if (dim2 == PS_DIMEN_VECTOR) {
          17            if (((psVector* ) in2)->n == 0) {
      ######                psError(__func__, ": Line %d - Vector contains zero elements");
		        }
          41        } else if (dim2 == PS_DIMEN_IMAGE) {
          24            if (((psImage* ) in2)->numCols == 0 || ((psImage* ) in2)->numRows == 0) {
      ######                psError(__func__, ": Line %d - Image contains zero length row or cols");
		        }
		    }
***L477:
          58        if (dim1 == PS_DIMEN_SCALAR) {
      ######            if (dim2 == PS_DIMEN_SCALAR) {
      ######                BINARY_OP(SCALAR, SCALAR, out, psType1, op, psType2);       // scalar op scalar
      ######            } else if (dim2 == PS_DIMEN_VECTOR || dim2 == PS_DIMEN_TRANSV) {
      ######                BINARY_OP(SCALAR, VECTOR, out, psType1, op, psType2);       // scalar op vector
      ######            } else if (dim2 == PS_DIMEN_IMAGE) {
      ######                BINARY_OP(SCALAR, IMAGE, out, psType1, op, psType2);        // scalar op image
		        } else {
      ######                psError(__func__, ": Line %d - Invalid dimensionality for in2 arg: %d", __LINE__, dim2);
		        }
          58        } else if (dim1 == PS_DIMEN_VECTOR || dim1 == PS_DIMEN_TRANSV) {
           2            if (dim2 == PS_DIMEN_SCALAR) {
      ######                BINARY_OP(VECTOR, SCALAR, out, psType1, op, psType2);       // vector op scalar
           2            } else if (dim2 == PS_DIMEN_VECTOR || dim2 == PS_DIMEN_TRANSV) {
      ######                BINARY_OP(VECTOR, VECTOR, out, psType1, op, psType2);       // vector op vector
           2            } else if (dim2 == PS_DIMEN_IMAGE) {
           2                BINARY_OP(VECTOR, IMAGE, out, psType1, op, psType2);        // vector op image
		        } else {
      ######                psError(__func__, ": Line %d - Invalid dimensionality for in2 arg: %d", __LINE__, dim2);
L504:
		        } else {
      ######                psError(__func__, ": Line %d - Invalid dimensionality for in2 arg: %d", __LINE__, dim2);
		        }
		    } else {
      ######            psError(__func__, ": Line %d - Invalid dimensionality for in1 arg: %d", __LINE__, dim1);
		    }
L757:
         138        if (dimIn == PS_DIMEN_OTHER || dimOut == PS_DIMEN_OTHER) {
      ######            psError(__func__, ": Line %d - PS_DIMEN_OTHER not allowed for arguments: (%d, %d)", __LINE__,
		                dimIn, dimOut);
      ######            return out;
		    }
L763:
         138        if (dimIn == PS_DIMEN_VECTOR) {
          68            if (((psVector* ) in)->n == 0) {
      ######                psError(__func__, ": Line %d - Vector contains zero elements");
		        }
          70        } else if (dimIn == PS_DIMEN_IMAGE) {
          70            if (((psImage* ) in)->numCols == 0 || ((psImage* ) in)->numRows == 0) {
      ######                psError(__func__, ": Line %d - Image contains zero length row or cols");
		        }
		    }
L773:
         138        if (dimOut == PS_DIMEN_VECTOR) {
          68            if (((psVector* ) out)->n == 0) {
      ######                psError(__func__, ": Line %d - Vector contains zero elements");
		        }
          70        } else if (dimOut == PS_DIMEN_IMAGE) {
          70            if (((psImage* ) out)->numCols == 0 || ((psImage* ) out)->numRows == 0) {
      ######                psError(__func__, ": Line %d - Image contains zero length row or cols");
		        }
		    }
***L783:
         138        if (dimIn == PS_DIMEN_SCALAR) {
      ######            UNARY_OP(SCALAR, out, psTypeIn, op);    // scalar
L789:
		    } else {
      ######            psError(__func__, ": Line %d - Invalid dimensionality for in arg: %d", __LINE__, dimIn);
		    }

=============================================================================================================

 74.93% of 371 source lines executed in file psMinimize.c

IGNORED: Subject to change.  Will test in next release.

=============================================================================================================

 69.71% of 746 source lines executed in file psStats.c

L130:
		    case PS_STAT_SAMPLE_STDEV:
      ######            *value = stats->sampleStdev;
      ######            return true;
		
		    case PS_STAT_ROBUST_MEAN:
      ######            *value = stats->robustMean;
      ######            return true;
		
		    case PS_STAT_ROBUST_MEDIAN:
      ######            *value = stats->robustMedian;
      ######            return true;
		
		    case PS_STAT_ROBUST_MODE:
      ######            *value = stats->robustMode;
      ######            return true;
		
		    case PS_STAT_ROBUST_STDEV:
      ######            *value = stats->robustStdev;
      ######            return true;
		
		    case PS_STAT_CLIPPED_MEAN:
      ######            *value = stats->clippedMean;
      ######            return true;
		
		    case PS_STAT_CLIPPED_STDEV:
      ######            *value = stats->clippedStdev;
      ######            return true;
		
		    case PS_STAT_MAX:
          37            *value = stats->max;
          37            return true;
		
		    case PS_STAT_MIN:
      ######            *value = stats->min;
      ######            return true;

void p_psVectorPrint unused, but comment says it's for debugging: fair enough.

***L231:
          36        if (stats->options & PS_STAT_USE_RANGE) {
      ######            rangeMin = stats->min;
      ######            rangeMax = stats->max;
      ######            if (maskVector != NULL) {
      ######                for (i = 0; i < myVector->n; i++) {
		                // Check if the data is with the specified range
      ######                    if (!(maskVal & maskVector->data.U8[i]) &&
		                        (rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
      ######                        mean += myVector->data.F32[i];
      ######                        count++;
		                }
		            }
      ######                mean /= (float)count;
		        } else {
      ######                for (i = 0; i < myVector->n; i++) {
      ######                    if ((rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
      ######                        mean += myVector->data.F32[i];
      ######                        count++;
		                }
		            }
      ######                mean /= (float)count;
		        }
***L293:
          39        if (stats->options & PS_STAT_USE_RANGE) {
      ######            rangeMin = stats->min;
      ######            rangeMax = stats->max;
      ######            if (maskVector != NULL) {
      ######                for (i = 0; i < myVector->n; i++) {
      ######                    if (!(maskVal & maskVector->data.U8[i])) {
      ######                        if ((myVector->data.F32[i] > max) &&
		                            (rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
      ######                            max = myVector->data.F32[i];
		                    }
		                }
		            }
		        } else {
      ######                for (i = 0; i < myVector->n; i++) {
      ######                    if ((myVector->data.F32[i] > max) &&
		                        (rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
      ######                        max = myVector->data.F32[i];
		                }
		            }
		        }
		    } else {
***L353:
           3        if (stats->options & PS_STAT_USE_RANGE) {
      ######            rangeMin = stats->min;
      ######            rangeMax = stats->max;
      ######            if (maskVector != NULL) {
      ######                for (i = 0; i < myVector->n; i++) {
      ######                    if (!(maskVal & maskVector->data.U8[i])) {
      ######                        if ((myVector->data.F32[i] < min) &&
		                            (rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
      ######                            min = myVector->data.F32[i];
		                    }
		                }
		            }
		        } else {
      ######                for (i = 0; i < myVector->n; i++) {
      ######                    if ((myVector->data.F32[i] < min) &&
		                        (rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
      ######                        min = myVector->data.F32[i];
		                }
		            }
		        }
		    } else {
***L414:
        6617        if (stats->options & PS_STAT_USE_RANGE) {
      ######            rangeMin = stats->min;
      ######            rangeMax = stats->max;
      ######            if (maskVector != NULL) {
      ######                for (i = 0; i < myVector->n; i++) {
      ######                    if (!(maskVal & maskVector->data.U8[i]) &&
		                        (rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
      ######                        numData++;
		                }
		            }
		        } else {
      ######                for (i = 0; i < myVector->n; i++) {
      ######                    if ((rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
      ######                        numData++;
		                }
		            }
		        }
		    } else {
***L502:
        6613        if (stats->options & PS_STAT_USE_RANGE) {
      ######            rangeMin = stats->min;
      ######            rangeMax = stats->max;
		
		        // Store all non-masked data points within the min/max range
		        // into the temporary vectors.
      ######            count = 0;
      ######            if (maskVector != NULL) {
      ######                for (i = 0; i < myVector->n; i++) {
      ######                    if (!(maskVal & maskVector->data.U8[i]) &&
		                        (rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
      ######                        unsortedVector->data.F32[count++] = maskVector->data.F32[i];
		                }
		            }
		        } else {
      ######                for (i = 0; i < myVector->n; i++) {
      ######                    if ((rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
      ######                        unsortedVector->data.F32[count++] = myVector->data.F32[i];
		                }
		            }
		        }
		    } else {
***L596:
		        } else {
		            /* If sigma equals zero (all pixels have the same value) the above code will divide by zero.
		             * Therefore, we don't need to smooth the data. */
      ######                for (i = 0; i < robustHistogram->nums->n; i++) {
      ######                    smooth->data.F32[i] = (float)robustHistogram->nums->data.S32[i];
		            }
      ######                return (smooth);
		        }
***L652:
           4        if (stats->options & PS_STAT_USE_RANGE) {
      ######            rangeMin = stats->min;
      ######            rangeMax = stats->max;
		        // Store all non-masked data points within the min/max range
		        // into the temporary vectors.
      ######            count = 0;
      ######            if (maskVector != NULL) {
      ######                for (i = 0; i < myVector->n; i++) {
      ######                    if (!(maskVal & maskVector->data.U8[i]) &&
		                        (rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
      ######                        unsortedVector->data.F32[count++] = myVector->data.F32[i];
		                }
		            }
		        } else {
      ######                for (i = 0; i < myVector->n; i++) {
      ######                    if ((rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
      ######                        unsortedVector->data.F32[count++] = myVector->data.F32[i];
		                }
		            }
		        }
		    } else {
***L732:
        3605        if (stats->options & PS_STAT_USE_RANGE) {
      ######            if (maskVector != NULL) {
      ######                for (i = 0; i < myVector->n; i++) {
      ######                    if (!(maskVal & maskVector->data.U8[i]) &&
		                        (rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
      ######                        diff = myVector->data.F32[i] - mean;
      ######                        sumSquares += (diff * diff);
      ######                        sumDiffs += diff;
      ######                        countInt++;
		                }
		            }
		        } else {
      ######                for (i = 0; i < myVector->n; i++) {
      ######                    if ((rangeMin <= myVector->data.F32[i]) && (myVector->data.F32[i] <= rangeMax)) {
      ######                        diff = myVector->data.F32[i] - mean;
      ######                        sumSquares += (diff * diff);
      ######                        sumDiffs += diff;
      ######                        countInt++;
		                }
		            }
      ######                countInt = myVector->n;
		        }
		    } else {
L813:
           3        if (!((CLIPPED_SIGMA_LB <= stats->clipSigma) && (stats->clipSigma <= CLIPPED_SIGMA_UB))) {
      ######            psAbort(__func__, "Unallowed value for clipSigma (%f).\n", stats->clipSigma);
		    }

void p_psNormalizeVector, float p_psGaussian, float p_psGaussianDeriv,
float p_psQuadratic, float p_psQuadraticDeriv unexercised, but are
private (should be "static").

L1009:
          30            if (fabs(midpoint - oldMidpoint) <= FLT_EPSILON) {
      ######                return (midpoint);
		        }
L1016:
          30            if (fabs(f - getThisValue) <= FLT_EPSILON) {
      ######                return (midpoint);
		        }

float p_psFitQuadratic not exercised, comment says "unused".

*L1150:
           1        if (fabs(binSize) <= FLT_EPSILON) {
      ######            if (stats->options & PS_STAT_ROBUST_MEAN) {
      ######                stats->robustMean = stats->clippedMean;
		        }
      ######            if (stats->options & PS_STAT_ROBUST_MEDIAN) {
      ######                stats->robustMedian = stats->clippedMean;
		        }
      ######            if (stats->options & PS_STAT_ROBUST_MODE) {
      ######                stats->robustMode = stats->clippedMean;
		        }
      ######            if (stats->options & PS_STAT_ROBUST_STDEV) {
      ######                stats->robustStdev = 0.0;
		        }
      ######            if (stats->options & PS_STAT_ROBUST_QUARTILE) {
      ######                stats->robustUQ = stats->clippedMean;
      ######                stats->robustLQ = stats->clippedMean;
		        }
		        // XXX: Set these to the number of unmasked data points?
      ######            stats->robustNfit = 0.0;
      ######            stats->robustN50 = 0.0;
      ######            psFree(tmpStats);
      ######            return;
		    }
L1338:
           1                if (!((y->data.F64[0] <= cumulativeMedian) && (cumulativeMedian <= y->data.F64[2]))) {
      ######                    printf("((%f), %f, %f)\n", cumulativeMedian, y->data.F64[0], y->data.F64[2]);
      ######                    psAbort(__func__, "p_psVectorRobustStats(1): midpoint not within y-range\n");
		            }
*L1354:
		        } else {
		            // If the mode is the first/last histogram bin, then simply use
		            // the midpoint of that bin.
      ######                stats->robustMedian = 0.5 * (robustHistogram->bounds->data.F32[maxBinNum + 1] +
		                                         robustHistogram->bounds->data.F32[maxBinNum]);
		        }
L1384:
           1                if (!((y->data.F64[0] <= (countFloat / 4.0)) && ((countFloat / 4.0) <= y->data.F64[2]))) {
      ######                    psAbort(__func__, "p_psVectorRobustStats(2): midpoint not within y-range\n");
		            }
*L1395:
		        } else {
		            // If the LQ is the first/last histogram bin, then simply use
		            // the midpoint of that bin.
      ######                stats->robustLQ = 0.5 * (robustHistogram->bounds->data.F32[LQBinNum + 1] +
		                                     robustHistogram->bounds->data.F32[LQBinNum]);
		        }
L1417:
           1                if (!((y->data.F64[0] <= (3.0 * countFloat / 4.0)) &&
		                    ((3.0 * countFloat / 4.0) <= y->data.F64[2]))) {
      ######                    psAbort(__func__, "p_psVectorRobustStats(3): midpoint not within y-range\n");
		            }
*L1429:
		        } else {
		            // If the UQ is the first/last histogram bin, then simply use
		            // the midpoint of that bin.
      ######                stats->robustUQ = 0.5 * (robustHistogram->bounds->data.F32[UQBinNum + 1] +
		                                     robustHistogram->bounds->data.F32[UQBinNum]);
		        }
L1557:
          28        if (n == 0) {
      ######            return (NULL);
		    }
*****Allocator returning NULL.

L1613:
           4        if (bounds == NULL) {
		        // psAbort(__func__, "psHistogram requested with NULL bounds");
      ######            return (NULL);
		    }
L1618:
           4        if (bounds->n <= 1) {
		        // psAbort(__func__, "psHistogram requested with NULL bounds");
      ######            return (NULL);
		    }
L1623:
           4        if (bounds->type.type != PS_TYPE_F32) {
		        // psAbort(__func__, "psHistogram request a bound which is not type F32");
      ######            return (NULL);
		    }
L1691:
          22        if (out->nums->type.type != PS_TYPE_U32) {
      ######            psAbort(__func__, "Only data type PS_TYPE_U32 for output.nums member.");
		    }
L1699:
          21        if (in->type.type != PS_TYPE_F32) {
      ######            psAbort(__func__, "Only data type PS_TYPE_F32 is currently supported (0x%x).", in->type.type);
		    }
L1703:
          21        if (mask != NULL) {
          10            if (in->n != mask->n) {
      ######                psAbort(__func__, "Vector data and vector mask are of different sizes.");
		        }
          10            if (mask->type.type != PS_TYPE_U8) {
      ######                psAbort(__func__, "Vector mask must be type PS_TYPE_U8");
		        }
		    }
***L1720:
       69415                if (in->data.F32[i] < out->bounds->data.F32[0]) {
      ######                    out->minNum++;
		                // Check if this pixel is above the maximum value, and if so
		                // count it, then skip it.
       69415                } else if (in->data.F32[i] > out->bounds->data.F32[numBins]) {
      ######                    out->maxNum++;
		            } else {
L1736:
       69415                        if (binNum >= out->nums->n) {
      ######                            binNum = out->nums->n - 1;
		                    }
***L1744:
		                } else {
		                    // NOTE: This is slow.  Put a smarter algorithm here to
		                    // find the correct bin number (bin search, probably)
      ######                        for (j = 0; j < (out->bounds->n) - 1; j++) {
      ######                            if ((out->bounds->data.S32[j] <= in->data.F32[i]) &&
		                                (in->data.F32[i] <= out->bounds->data.S32[j + 1])) {
      ######                                (out->nums->data.S32[j])++;
		                        }
		                    }
		                }
*L1774: Looks to be temporary
        3091        if (in->type.type == PS_TYPE_S32) {
      ######            tmp = psVectorAlloc(in->n, PS_TYPE_F32);
      ######            for (i = 0; i < in->n; i++) {
      ######                tmp->data.F32[i] = (float)in->data.S32[i];
		        }
        3091        } else if (in->type.type == PS_TYPE_U32) {
      ######            tmp = psVectorAlloc(in->n, PS_TYPE_F32);
      ######            for (i = 0; i < in->n; i++) {
      ######                tmp->data.F32[i] = (float)in->data.U32[i];
		        }
        3091        } else if (in->type.type == PS_TYPE_F64) {
      ######            tmp = psVectorAlloc(in->n, PS_TYPE_F32);
      ######            for (i = 0; i < in->n; i++) {
      ######                tmp->data.F32[i] = (float)in->data.F64[i];
		        }
        3091        } else if (in->type.type == PS_TYPE_F32) {
L1884:
        3091        if (mustFreeTmp == 1) {
      ######            psFree(inF32);
		    }


=============================================================================================================

  0.00% of 289 source lines executed in file psAstrometry.c
  0.00% of 212 source lines executed in file psCoord.c

These probably not part of the release.

=============================================================================================================

 75.88% of 369 source lines executed in file psMetadata.c

L137 (gcov?):
          52        if (metadataItem == NULL) {
      ######            psAbort(__func__, "Failed to allocate memory");
		    }
L213 (gcov?):
           8        if (list == NULL) {
      ######            psAbort(__func__, "Failed to allocate list");
		    }
L218 (gcov?):
           8        if (table == NULL) {
      ######            psAbort(__func__, "Failed to allocate table");
		    }
L250:
          42        if(mdTable == NULL) {
      ######            psError( __func__, "Null metadata table not allowed" );
      ######            return false;
		    }
L256:
          42        if(mdList == NULL) {
      ######            psError( __func__, "Null metadata list not allowed");
      ######            return false;
		    }
L262:
          42        if(key == NULL) {
      ######            psError(__func__, "Null key item not allowed");
      ######            return false;
		    }
L274:
           3                if(!psListAdd(existingEntry->items, metadataItem, PS_LIST_TAIL)) {
      ######                    psError( __func__, "Couldn't add metadata item to items list. Name: %s",
		                         metadataItem->name );
      ######                    return false;
		            }
L284:
           4                if(!psListAdd(newFolderEntry->items, existingEntry, PS_LIST_TAIL)) {
      ######                    psError( __func__, "Couldn't add metadata item to items list. Name: %s", key);
      ######                    psFree(newFolderEntry);
      ######                    return false;
		            }
L290:
           4                if(!psListAdd(newFolderEntry->items, metadataItem, PS_LIST_TAIL)) {
      ######                    psError( __func__, "Couldn't add metadata item to items list. Name: %s", key);
      ######                    psFree(newFolderEntry);
      ######                    return false;
		            }
L296:
           4                if(!psHashRemove(mdTable, key)) {
      ######                    psError( __func__, "Couldn't remove metadata item from metadata table. Name: %s", key);
      ######                    psFree(newFolderEntry);
      ######                    return false;
		            }
L302:
           4                if(!psHashAdd(mdTable, key, newFolderEntry)) {
      ######                    psError( __func__, "Couldn't add metadata item to metadata table. Name: %s", key);
      ######                    psFree(newFolderEntry);
      ######                    return false;
		            }
L313:
           1                if(!psListAdd(metadataItem->items, existingEntry, PS_LIST_TAIL)) {
      ######                    psError( __func__, "Couldn't add metadata item to items list. Name: %s", key);
      ######                    return false;
		            }
L318:
           1                if(!psHashRemove(mdTable, key)) {
      ######                    psError( __func__, "Couldn't remove metadata item from metadata table. Name: %s", key);
      ######                    return false;
		            }
L323:
           1                if(!psHashAdd(mdTable, key, metadataItem)) {
      ######                    psError( __func__, "Couldn't add metadata item to metadata table. Name: %s", key);
      ######                    return false;
		            }
L331:
          34            if(!psHashAdd(mdTable, key, metadataItem)) {
      ######                psError( __func__, "Couldn't add metadata item to metadata table. Name: %s", key);
      ######                return false;
		        }
L338:
          42        if(!psListAdd( mdList, metadataItem, where )) {
      ######            psError( __func__, "Couldn't add metadata item to metadata collection list. Name: %s",
		                 metadataItem->name );
      ######            return false;
		    }
L363 (gcov):
          25        if (!psMetadataAddItem(md, where, metadataItem)) {
          25            psError(__func__, "Couldn't add metadata item to metadata collection list. Name: %s",
		                metadataItem->name);
      ######            psFree(metadataItem);
      ######            return false;
		    }
L387:
           9        if (mdList == NULL) {
      ######            psError(__func__, "Null metadata list not allowed");
      ######            return false;
		    }
L393:
           9        if (mdTable == NULL) {
      ######            psError(__func__, "Null metadata table not allowed");
      ######            return false;
		    }
L414:
           2                    if (!psListRemove(mdList, entryChild, PS_LIST_UNKNOWN)) {
      ######                        psError(__func__, "Couldn't remove metadata item from list. Name: %s", key);
      ######                        return false;
		                }
L423:
           4                if (!psListRemove(mdList, entry, PS_LIST_UNKNOWN)) {
      ######                    psError(__func__, "Couldn't remove metadata item from list. Name: %s", key);
      ######                    return false;
		            }
L429:
           5            if (!psHashRemove(mdTable, key)) {
      ######                psError(__func__, "Couldn't remove metadata item from table. Name: %s", key);
      ######                return false;
		        }
L443:
           2            if (key == NULL) {
      ######                psError(__func__, "Null key name not allowed. Index: %d", where);
      ######                return false;
		        }
L466:
           3        if (mdTable == NULL) {
      ######            psError(__func__, "Null metadata table not allowed");
      ######            return NULL;
		    }
L497:
           2        if (mdList == NULL) {
      ######            psError(__func__, "Null metadata list not allowed");
      ######            return NULL;
		    }
L521:
           1        if (mdList == NULL) {
      ######            psError(__func__, "Null metadata list not allowed");
      ######            return false;
		    }
L543:
           2        if (mdList == NULL) {
      ######            psError(__func__, "Null metadata list not allowed");
      ######            return NULL;
		    }
L564:
      ######        if (entry == NULL) {
      ######            psError(__func__, "Couldn't find metadata item");
		    }
**L591:
           1            if(match != NULL) {
      ######                if (!strncmp(match, entry->name, strlen(match))) {
		
		                // Match found
      ######                    return entry;
		            }
      ######                entry = psListGetPrevious(mdList);
		        } else {
L604:
      ######        if (entry == NULL) {
      ######            psError(__func__, "Couldn't find metadata item", match);
		    }
**L632:
           1        switch (type) {
		    case PS_META_BOOL:
      ######            fprintf(fd, format, metadataItem->data.B);
      ######            break;
		    case PS_META_S32:
           1            fprintf(fd,format, metadataItem->data.S32);
           1            break;
		    case PS_META_F32:
      ######            fprintf(fd, format, metadataItem->data.F32);
      ######            break;
		    case PS_META_F64:
      ######            fprintf(fd, format, metadataItem->data.F64);
      ######            break;
		    case PS_META_STR:
      ######            fprintf(fd, format, metadataItem->data.V);
      ######            break;
		    case PS_META_ITEM_SET:
		    case PS_META_IMG:
		    case PS_META_JPEG:
		    case PS_META_PNG:
		    case PS_META_ASTROM:
		    case PS_META_UNKNOWN:
		    default:
      ######            psError(__func__, " Invalid psMetadataType to print: %d", type);
		    }
L683:
           5        } else if (extName && extNum) {
      ######            psError(__func__, "Both extName and extNum arguments should not have non zero values.");
      ######            return NULL;
		    }
L703:
           3        if (fits_get_hdrpos(fd, &numKeys, &keyNum, &status) != 0) {
      ######            FITS_ERROR("FITS error while reading key %d: %s", keyNum);
		    }
L708:
          25            if (fits_read_keyn(fd, i, keyName, keyValue, keyComment, &status) != 0) {
      ######                FITS_ERROR("FITS error while reading key %d: %s", keyNum);
		        }
L713:
           7                if (status != VALUE_UNDEFINED) {
      ######                    FITS_ERROR("FITS error while determining key %d type: %s", keyNum);
		            } else {
*L730:
		        case 'F':
      ######                metadataItemType = PS_META_F64;
      ######                success =
		                psMetadataAdd(output, PS_LIST_TAIL, keyName, metadataItemType, keyComment,
		                              atof(keyValue));
      ######                break;
L749:
		        default:
      ######                psError(__func__, "Invalid psMetadataType: %c", keyType);
      ######                return output;
		        }
L754:
          25            if (!success) {
      ######                psError(__func__, "Failed to add metadata item. Name: %s", keyName);
      ######                return output;
		        }

=============================================================================================================

 98.09% of 209 source lines executed in file psTime.c

L236:
           1        if (!strftime(tempString, MAX_TIME_STRING_LENGTH, "%Y/%m/%d,%H:%M:%S", tmTime)) {
      ######            psError(__func__, " : Line %d - Failed strftime conversion", __LINE__);
		    }
L240:
           1        if (snprintf(timeString, MAX_TIME_STRING_LENGTH, "%s.%3.3d", tempString, ms) < 0) {
      ######            psError(__func__, " : Line %d - Failed snprintf conversion", __LINE__);
		    }

=============================================================================================================

Compiling on nkfb0 was annoying: must have taken several hours.

There were a few problems:

* Installing SLALIB was difficult, because they want to use programs
(like uudecode, pax) that people don't use anyone, so they weren't
installed.

* It seems that some of the files aren't coming out of CVS.  Perhaps I
was trying to install over the top of an old copy which caused CVS to
do some funky stuff.  I just tried it on my own machine, and
psFFT.[ch] has disappeared from the release.  After some digging
around, it seems that psFFT.[ch] have been renamed topsVectorFFT.[ch],
which was done in the repository instead of the(orthodox but, I'll
admit, annoying) CVS dance with "remove old" and"add new".  This had
the effect of breaking the rel2 release, since allthe other files have
#include "psFFT.h" --- the name of the file (evenif updated on the
mainline) isn't updated in the release because thefiles are tagged,
and because psFFT.h no longer exists, the release hasbeen broken.

* In order to link in SLALib (written in Fortran), it was necessary to
add "-DFORTRAN_DOUBLE_UNDERSCORE_SUFFIX" to CFLAGS in the
Makefile.Globals, and to edit "slalib.h", which was using the illegal
"#elseif" instead of "#elif" (--> bug 141).  I discovered that I
needed the double underscore suffix by doing "nm slalib.a" and noting
that the functions of interest had no prefix underscores, but a double
suffix on this system.

=============================================================================================================

Attempting to put in a test for PS_TYPE_PTR in psImage has been
annoying.  I put in a test in tst_psImage.c similar to the other
lines, which causes the test to fail with a core dump somewhere in
psMemory: it can't access the refCounter.  I can't trace through the
program, I think because gdb won't trace through a shared library.
==> BUG #176.


Many instances of multiple types not being tested.  Each usage of a
#define MACRO should be tested.

Here are the major code segments that aren't being exercised, which
should be:

psImage.c:
L240 psImagePixelInterpolate on U8,U16,U32,U64,S8,S16,S32,S64,F64,C32,C64

psImageExtraction.c:
L201 psImageCopy on S16,U64,C64
L386 psImageSlice on U8,U16,U32,U64,S8,S16,S32,S64,F64,C32,C64

psImageIO.c:
L142 psImageReadSection on U8,S8,U16,U32,S32,S64,F64
L229 psImageWriteSection on U8,S8,U16,U32,S32,S64,F64

psImageManip.c:
L110 psImageClip on S64,U64
L156 psImageClipNaN on C32,C64
L249 psImageOverlaySection on U32,U64,S32,S64
L421 psImageRebin on U8,U16,U32,U64,S8,S16,S32,S64,F64,C32,C64
psImageResample Not tested at all
L588 psImageRotate for 90, 180, 270 on U8,U16,U32,U64,S8,S32,S64,F64,C32,C64
L797 psImageRotate using bilinear

psHash.c:
L304 Replacing a key

psScalar.c:
psScalarCopy
psScalarFree

psVector.c:
L214 psVectorSort on U8,U16,U32,U64,S8,S16,S32,S64,F64,C32,C64
L309 psVectorSortIndex on U8,U16,U32,U64,S8,S16,S32,S64,F64,C32,C64

psFFT.c:
L131 psImageReal on C64
L191 psImageImaginary on C64
L268 psImageComplex on F64
L328 psImageConjugate on C64
L391 psImagePowerSpectrum on C64
L514 psVectorReal on real vector
L558 psVectorImaginary on real vector
L652 psVectorConjugate on real vector

psMatrixVectorArithmetic.c:
L477 First operand is scalar; or second operand is scalar or vector
L783 Unary operator on a scalar

psStats.c:
L231 Vector sample mean with PS_STAT_USE_RANGE
L293 Vector max with PS_STAT_USE_RANGE
L353 Vector min with PS_STAT_USE_RANGE
L414 Vector nValues PS_STAT_USE_RANGE
L502 Vector sample median with PS_STAT_USE_RANGE
L596 Smoothing a histogram when the vector is single-valued
L652 Vector quartiles with PS_STAT_USE_RANGE
L732 Vector SD with PS_STAT_USE_RANGE
L1354 Robust mode in first/last bin
L1395 LQ in first/last bin
L1429 UQ in first/last/bin
L1720 minNum, maxNum
L1744 Non-uniform histogram bins

=============================================================================================================

To get psLogMsg output to stderr, you need to specify:
        psLogSetDestination("dest:stderr");
Similarly for stdout.  I can see where they got it from (the SDRS
entry could easily be misinterpreted), but I don't think this is the
behaviour we expected.

psTrace:

* Each "facility" must commence with a dot: e.g.,
".IPP.debias.overscan", which I think is really annoying because it's
easy to forget.

* You must set every level for each node on the trace tree explicitly if
you intend it to be used.  For example, the call
        psTraceSetLevel(".IPP.debias.overscan", 5)
will produce the following setup:
.                    0
 IPP                 5
 debias              5
 overscan            5
Note how each of those is in the same level, so that the hierarchy
hasn't been built up?  Of course, this is a bug because it does
something completely unexpected, but I would appreciate confirmation
of my expectation that a 4-deep heirarchy (".", ".A", ".A.B",
".A.B.C") should be formed from simply specifying a level for
".A.B.C".

* I would have thought that the property of inheritance that we
specified implied that if I hadn't explicitly set the level for
".A.B", but I have set the level for ".A", then printing a trace
message on component ".A.B" would depend on comparing the level to the
set level of ".A"; but in the implementation, it would be ignored
completely.
