Index: /trunk/doc/pslib/psLibSDRS.tex
===================================================================
--- /trunk/doc/pslib/psLibSDRS.tex	(revision 702)
+++ /trunk/doc/pslib/psLibSDRS.tex	(revision 703)
@@ -1,3 +1,3 @@
-%%% $Id: psLibSDRS.tex,v 1.44 2004-05-15 02:41:00 price Exp $
+%%% $Id: psLibSDRS.tex,v 1.45 2004-05-16 04:50:56 eugene Exp $
 \documentclass[panstarrs]{panstarrs}
 
@@ -99,4 +99,6 @@
 example, the function which copies an image (of type \code{psImage})
 is called \code{psImageCopy()}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 \subsection{External Libraries}
@@ -129,5 +131,7 @@
 \subsection{Threads}
 
-\tbd{discussion of thread safe?}
+Pan-STARRS does not have a strong requirement for multithreading
+capability.  The memory management functions, defined below, must be
+written to be thread-safe.  
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -537,10 +541,10 @@
     /* No operation if object is NULL */
     if (myType == NULL) {
-	return;
+        return;
     }
     /* Only call psFree if reference counter is 1 */
     if (psMemGetRefCounter(myType) == 1) {
-	psFree(myType);
-	return;
+        psFree(myType);
+        return;
     }
     /* Otherwise, decrement the reference counter only */
@@ -1202,16 +1206,16 @@
 \begin{verbatim}
 typedef enum {
-    PS_TYPE_S8,				///< Character
-    PS_TYPE_S16,			///< Short integer
-    PS_TYPE_S32,			///< Integer
-    PS_TYPE_S64,			///< Long integer
-    PS_TYPE_U8,				///< Unsigned character
-    PS_TYPE_U16,			///< Unsigned short integer
-    PS_TYPE_U32,			///< Unsigned integer
-    PS_TYPE_U64,			///< Unsigned long integer
-    PS_TYPE_F32,			///< Floating point
-    PS_TYPE_F64,			///< Double-precision floating point
-    PS_TYPE_C32,			///< Complex numbers consisting of floating point
-    PS_TYPE_OTHER,			///< Something else that's not supported for arithmetic
+    PS_TYPE_S8,                         ///< Character
+    PS_TYPE_S16,                        ///< Short integer
+    PS_TYPE_S32,                        ///< Integer
+    PS_TYPE_S64,                        ///< Long integer
+    PS_TYPE_U8,                         ///< Unsigned character
+    PS_TYPE_U16,                        ///< Unsigned short integer
+    PS_TYPE_U32,                        ///< Unsigned integer
+    PS_TYPE_U64,                        ///< Unsigned long integer
+    PS_TYPE_F32,                        ///< Floating point
+    PS_TYPE_F64,                        ///< Double-precision floating point
+    PS_TYPE_C32,                        ///< Complex numbers consisting of floating point
+    PS_TYPE_OTHER,                      ///< Something else that's not supported for arithmetic
 } psElemType;
 \end{verbatim}
@@ -1228,21 +1232,21 @@
 \begin{verbatim}
 typedef struct {
-    psType type; 			///< vector data type and dimension
-    const int n;			///< size of vector 
-    const int nalloc;			///< data region relative to parent 
+    psType type;                        ///< vector data type and dimension
+    const int n;                        ///< size of vector 
+    const int nalloc;                   ///< data region relative to parent 
     union {
-	psF32 *arr;			///< Pointers to floating-point data (default)
-	psS8  *arr_S8;			///< Pointers to short-integer data
-	psS16 *arr_S16;			///< Pointers to short-integer data
-	psS32 *arr_S32;			///< Pointers to integer data
-	psS64 *arr_S64;			///< Pointers to long-integer data
-	psU8  *arr_U18;			///< Pointers to unsigned-short-integer data
-	psU16 *arr_U16;			///< Pointers to unsigned-short-integer data
-	psU32 *arr_U32;			///< Pointers to unsigned-integer data
-	psU64 *arr_U64;			///< Pointers to unsigned-long-integer data
-	psF32 *arr_F32;			///< Pointers to floating-point data
-	psF64 *arr_F64;		        ///< Pointers to double-precision data
-	psF32 *arr_C32;			///< Pointers to complex floating-point data
-	void **arr_v;
+        psF32 *arr;                     ///< Pointers to floating-point data (default)
+        psS8  *arr_S8;                  ///< Pointers to short-integer data
+        psS16 *arr_S16;                 ///< Pointers to short-integer data
+        psS32 *arr_S32;                 ///< Pointers to integer data
+        psS64 *arr_S64;                 ///< Pointers to long-integer data
+        psU8  *arr_U18;                 ///< Pointers to unsigned-short-integer data
+        psU16 *arr_U16;                 ///< Pointers to unsigned-short-integer data
+        psU32 *arr_U32;                 ///< Pointers to unsigned-integer data
+        psU64 *arr_U64;                 ///< Pointers to unsigned-long-integer data
+        psF32 *arr_F32;                 ///< Pointers to floating-point data
+        psF64 *arr_F64;                 ///< Pointers to double-precision data
+        psF32 *arr_C32;                 ///< Pointers to complex floating-point data
+        void **arr_v;
     } arr;
 } psVector;
@@ -1323,24 +1327,24 @@
 \begin{verbatim}
 typedef struct psImage {
-    psType type; 			///< image data type and dimension
-    const int ncols, nrows;		///< size of image 
-    const int x0, y0;			///< data region relative to parent 
+    psType type;                        ///< image data type and dimension
+    const int ncols, nrows;             ///< size of image 
+    const int x0, y0;                   ///< data region relative to parent 
     union {
-	psF32 **rows;			///< Pointers to floating-point data (default)
-	psS8  **rows_S8;		///< Pointers to char data
-	psS16 **rows_S16;		///< Pointers to short-integer data
-	psS32 **rows_S32;		///< Pointers to integer data
-	psS64 **rows_S64;		///< Pointers to long-integer data
-	psU8  **rows_U8;		///< Pointers to unsigned-char data
-	psU16 **rows_U16;		///< Pointers to unsigned-short-integer data
-	psU32 **rows_U32;		///< Pointers to unsigned-integer data
-	psU64 **rows_U64;		///< Pointers to unsigned-long-integer data
-	psF32 **rows_F32;		///< Pointers to floating-point data
-	psF64 **rows_F64;		///< Pointers to double-precision data
-	psC32 **rows_C32;		///< Pointers to complex floating-point data
+        psF32 **rows;                   ///< Pointers to floating-point data (default)
+        psS8  **rows_S8;                ///< Pointers to char data
+        psS16 **rows_S16;               ///< Pointers to short-integer data
+        psS32 **rows_S32;               ///< Pointers to integer data
+        psS64 **rows_S64;               ///< Pointers to long-integer data
+        psU8  **rows_U8;                ///< Pointers to unsigned-char data
+        psU16 **rows_U16;               ///< Pointers to unsigned-short-integer data
+        psU32 **rows_U32;               ///< Pointers to unsigned-integer data
+        psU64 **rows_U64;               ///< Pointers to unsigned-long-integer data
+        psF32 **rows_F32;               ///< Pointers to floating-point data
+        psF64 **rows_F64;               ///< Pointers to double-precision data
+        psC32 **rows_C32;               ///< Pointers to complex floating-point data
     } rows;
-    const struct psImage *parent;	///< parent, if a subimage 
-    int Nchildren;			///< number of subimages 
-    struct psImage **children;		///< children of this region; array of Nchildren pointers
+    const struct psImage *parent;       ///< parent, if a subimage 
+    int Nchildren;                      ///< number of subimages 
+    struct psImage **children;          ///< children of this region; array of Nchildren pointers
 } psImage;
 \end{verbatim}
@@ -1637,8 +1641,6 @@
 array.  Also note that the constructor is passed the number of
 required bits, which implies that \code{ceil(n / 8)} bytes must be
-allocated.
-
-\begin{verbatim}
-/** A bitset of arbitrary length. */
+allocated.  The bitset structure is define by:
+\begin{verbatim}
 typedef struct {
     int n;                              ///< Number of chars that form the bitset
@@ -1648,14 +1650,9 @@
 
 We also require the corresponding constructor and destructor:
-
-\begin{verbatim}
-/** Constructor */
-psBitset *psBitsetAlloc(int n         ///< Number of bits required
-    );
- 
-/** Destructor */
-void psBitsetFree(psBitset *restrict myBits ///< bitset to destroy
-    );
-\end{verbatim}
+\begin{verbatim}
+psBitset *psBitsetAlloc(int n);
+void psBitsetFree(psBitset *restrict myBits);
+\end{verbatim}
+where \code{n} is the requested number of bits.
 
 Four basic operations on bitsets are required:
@@ -1665,12 +1662,14 @@
 \item \code{OR}, \code{AND} and \code{XOR} two bitsets.
 \end{itemize}
-The corresponding APIs are defined below.
-
-\begin{verbatim}
-/** Set a bitset */
-psBitset *
-psBitsetSet(psBitset *restrict myBits, ///< Input bitset
-            int bit                    ///< Bit to set
-    );
+The corresponding APIs are defined below:
+
+\begin{verbatim}
+psBitset *psBitsetSet(psBitset *restrict myBits, int bit);
+psBitset *psBitsetOp(psBitset *outBits, 
+                     const psBitset *restrict inBits1,
+                     char *operator, 
+                     const psBitset *restrict inBits2);
+psBitset *psBitsetNot(psBitset *out, psBitset *in);
+int psBitsetTest(const psBitset *restrict checkBits, int bit);
 \end{verbatim}
 
@@ -1679,38 +1678,16 @@
 will be modified.
 
-\begin{verbatim}
-/** Check a bitset.  Returns true or false */
-int
-psBitsetTest(const psBitset *restrict checkBits, ///< bitset to check
-              int bit                   ///< Bit to check
-    );
-\end{verbatim}
-
-\code{psBitsetTest} returns a true value if the specified \code{bit}
-is set; otherwise, it returns a false value.
-
-\begin{verbatim}
-/** apply the given operator to two bitsets */
-psBitset *
-psBitsetOp(psBitset *outBits,         ///< Output bitset or NULL
-            const psBitset *restrict inBits1, ///< Input bitset 1
-            char *operator,             ///< bitset operator (AND, OR, XOR)
-            const psBitset *restrict inBits2 ///< Input bitset 2
-    );
-\end{verbatim}
-
 \code{psBitsetOp} returns the \code{psBitset} that is the result of
 performing the specified \code{operator} (one of \code{"AND"},
 \code{"OR"}, or \code{"XOR"}) on \code{inBits1} and \code{inBits2}.
-
-Finally, \code{psBitsetNot} applies a unary \code{NOT} to a bitset:
-
-\begin{verbatim}
-/** Apply unary NOT to a bitset */
-psBitset *
-psBitsetNot(psBitset *out,		///< Output bitset, or NULL
-	    psBitset *in		///< Input bitset to be NOT-ed
-    );
-\end{verbatim}
+If the output bitset \code{outBits} is \code{NULL}, it is created by
+the function.
+
+\code{psBitsetNot} applies a unary \code{NOT} to a bitset, placing the
+answer in the bitset \code{out}, or creating a new bitset if
+\code{out} is \code{NULL}.
+
+Finally, \code{psBitsetTest} returns a true value if the specified
+\code{bit} is set; otherwise, it returns a false value.
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1721,14 +1698,11 @@
 following function returns the array, sorted from the smallest (i.e.\
 most negative) value in the first element, and the largest (i.e.\ most
-positive) value in the last element.  The input array, \code{myArray},
-may be sorted in-place if it is also specified as the \code{out}
-array.
-
-\begin{verbatim}
-/** Sort an array. Inputs not restrict-ed to allow sort in place */
-psFloatArray *
-psSort(psFloatArray *out,               ///< Sorted array to return. May be NULL
-       const psFloatArray *restrict myArray      ///< Array to sort
-    );
+positive) value in the last element.  The input array, \code{in}, may
+be sorted in-place if it is also specified as the \code{out}
+array. This function is specified for input types \code{psU8, psU16,
+psF32, psF64}.  The input and output vectors must have the same type.
+
+\begin{verbatim}
+psVector *psSort(psVector *out, const psVector *restrict in);
 \end{verbatim}
 
@@ -1737,20 +1711,17 @@
 in \code{x}.  In order to facilitate this, we will have a sort
 function return an array containing the indices for the unsorted list
-in the order appropriate for the sorted array:
-
-\begin{verbatim}
-/** Sort an array, along with some other stuff.  Returns an index array */
-psIntArray *
-psSortIndex(psIntArray *restrict out;   ///< Output index array (may be NULL)
-            const psFloatArray *restrict myArray ///< Array to sort
-    );
-\end{verbatim}
-
-Then the sorted arrays may be accessed in the following manner:
-
+in the order appropriate for the sorted array.  The output vector must
+be of type \code{psU32}.  This function is specified for input types
+\code{psU8, psU16, psF32, psF64}.
+
+\begin{verbatim}
+psVector *psSortIndex(psVector *restrict out; const psVector *restrict in);
+\end{verbatim}
+
+The sorted arrays may be accessed in the following manner:
 \begin{verbatim}
 indexArray = psSortIndex(NULL, x);
 for (int i = 0; i < indexArray.n; i++) {
-    doMyFunc(x[indexArray[i]], y[indexArray[i]]);
+    doMyFunc(x[indexArray.arr.arr_U32[i]], y[indexArray[i].arr.arr_U32]);
 }
 \end{verbatim}
@@ -1788,18 +1759,15 @@
 
 \begin{verbatim}
-/** Do Statistics on an array.  Returns a status value. \ingroup MathGroup */
-psStats *
-psArrayStats(const psFloatArray *restrict myArray, ///< Array to be analysed
-             const psIntArray *restrict maskArray, ///< Ignore elements where (maskArray & maskVal) != 0
-                                                   ///< May be NULL
-             unsigned int maskVal,      ///< Only mask elements with one of these bits set in maskArray
-             psStats *stats             ///< stats structure defines stats to be calculated and how
-    );
-\end{verbatim}
-%
-This function takes the input data in \code{myArray} (with optional
-masking in \code{maskArray}, so that the user may explicitly reject
-specific entries) and a \code{psStats} structure, which will be
-altered and returned.
+psStats *psArrayStats(const psVector *restrict in, 
+                      const psVector *restrict mask, 
+                      unsigned int maskVal, 
+                      psStats *stats);
+\end{verbatim}
+%
+This function takes the input data in \code{in} (with optional masking
+in \code{mask}, so that the user may explicitly reject specific
+entries) and a \code{psStats} structure, which will be altered and
+returned.  The input vector may be of type \code{psU8}, \code{psU16},
+\code{psF32}, \code{psF64}; the mask must be of type \code{psU8}.
 
 The \code{psStats} structure is defined with entries for each of the
@@ -1814,11 +1782,11 @@
     double sampleUQ;                    ///< upper quartile of sample
     double sampleLQ;                    ///< lower quartile of sample
-    double robustMean;                  ///< robust mean of array
+    double robustMean;                  ///< robust mean of data
     int    robustMeanNvalues;           ///< number of measurements used for robust mean
-    double robustMedian;                ///< robust median of array
+    double robustMedian;                ///< robust median of data
     int    robustMedianNvalues;         ///< number of measurements used for robust median
-    double robustMode;                  ///< Robust mode of array
+    double robustMode;                  ///< Robust mode of data
     int    robustModeNvalues;           ///< Number of measurements used for robust mode
-    double robustStdev;                 ///< robust standard deviation of array
+    double robustStdev;                 ///< robust standard deviation of data
     double robustUQ;                    ///< robust upper quartile
     double robustLQ;                    ///< robust lower quartile
@@ -1828,7 +1796,7 @@
     double clipSigma;                   ///< Nsigma used for clipping; user input
     int    clipIter;                    ///< Number of clipping iterations; user input
-    double min;                         ///< minimum data value in array
-    double max;                         ///< maximum data value in array
-    int    nValues;                     ///< number of data values in array
+    double min;                         ///< minimum data value in data
+    double max;                         ///< maximum data value in data
+    int    nValues;                     ///< number of data values in data
     psStatsOptions options;             ///< bitmask of calculated values
 } psStats;
@@ -1867,15 +1835,7 @@
 
 \begin{verbatim}
-/** Constructor */
-psStats *
-psStatsAlloc(psStatsOptions options     ///< Statistics to measure
-    );
-
-/** Destructor */
-void
-psStatsFree(psStats *restrict stats     ///< Stats structure to destroy
-    );
-\end{verbatim}
-
+psStats *psStatsAlloc(psStatsOptions options);
+void psStatsFree(psStats *restrict stats);
+\end{verbatim}
 
 \subsubsection{Histograms}
@@ -1883,16 +1843,21 @@
 
 We also require to be able to generate histograms, given a list of
-upper and lower bounds for each of the bins.
-
-\begin{verbatim}
-/** Histograms  */
+upper and lower bounds for each of the bins.  We define the following
+data structure to represent a histogram:
+\begin{verbatim}
 typedef struct {
-    const psFloatArray *restrict bounds; ///< Bounds for the bins
-    psIntArray *nums;			///< Number in each of the bins
-    const float minVal, maxVal;		///< Minimum and maximum values
-    int minNum, maxNum;			///< Number below the minimum and above the maximum
-    int uniform;			///< Is it a uniform distribution?
+    const psVector *restrict bounds;    ///< Bounds for the bins
+    psVector *nums;                     ///< Number in each of the bins
+    int minNum, maxNum;                 ///< Number below the minimum and above the maximum
+    int uniform;                        ///< Is it a uniform distribution?
 } psHistogram;
 \end{verbatim}
+In this structure, the vector \code{bounds} specifies the boundaries
+of the histogram bins, and must of type \code{psF32}, while
+\code{nums} specifies the number of entries in the bin, and must of
+type \code{psU32}.  The value of \code{bounds.n} must therefore be 1
+greater than than \code{nums.n}.  The two values \code{minNum} and
+\code{maxNum} are the number of data values which fell below the lower
+limit bound or above the upper limit bound, respectively.
 
 The constructors and destructor follow.  We specify two constructors,
@@ -1902,41 +1867,32 @@
 
 \begin{verbatim}
-/** Constructor */
-psHistogram *
-psHistogramAlloc(float lower,		///< Lower limit for the bins
-		 float upper,		///< Upper limit for the bins
-		 int n			///< Number of the bins
-    );
-\end{verbatim}
-
-\begin{verbatim}
-/** Generic constructor */
-psHistogram *
-psHistogramAllocGeneric(const psFloatArray *restrict bounds, ///< Bounds for the bins
-                        float minVal,   ///< Minimum value
-                        float maxVal    ///< Maximum value
-    );
-\end{verbatim}
-
-\begin{verbatim}
-/** Destructor */
-void
-psHistogramFree(psHistogram *restrict myHist ///< Histogram to destroy
-    );
+psHistogram *psHistogramAlloc(float lower, float upper, int n);
+\end{verbatim}
+where \code{lower} specifies the lower bound of the histogram range,
+\code{upper} specified the upper bound of the histogram range, and
+\code{n} is the number of bins desired across the range.  This
+constructor sets the value of \code{uniform} to be true.
+
+A histogram with a more flexible bin set may be constructed with the
+following constructor:
+\begin{verbatim}
+psHistogram *psHistogramAllocGeneric(const psVector *restrict bounds);
+\end{verbatim}
+where the \code{psVector *bounds} (of type \code{psF32}) is defined by
+the user to specify the boundaries of the histogram bins. This
+constructor sets the value of \code{uniform} to be false.
+
+A histogram is free with the destructor:
+\begin{verbatim}
+void psHistogramFree(psHistogram *restrict myHist);
 \end{verbatim}
 
 The following function populates the histogram bins from the specified
-array (\code{myArray}), the number of entries less than \code{minVal}
-(\code{minNum}), and the number of entries greater than \code{maxVal}
-(\code{maxNum}).  It alters and returns the \code{psHistogram}
-structure.
-
-\begin{verbatim}
-/** Calculate a histogram \ingroup MathGroup **/
-psHistogram *
-psGetArrayHistogram(psHistogram *restrict myHist, ///< Histogram data
-                    const psFloatArray *restrict myArray ///< Array to analyse
-    );
-\end{verbatim}
+vector (\code{in}).  It alters and returns the histogram \code{out}
+structure.  
+\begin{verbatim}
+psHistogram *psHistogramVector(psHistogram *restrict out, const psVector *restrict in);
+\end{verbatim}
+The input vector may be of types \code{psU8, psU16, psF32, psF64}.
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1947,8 +1903,6 @@
 (\S\ref{sec:arithmetic}), we also require the ability to perform basic
 linear algebra on matrices, in order to solve equations.  We use
-\code{psImage} as a matrix, since it has the correct form; similarly,
-we define a vector, \code{psVector} to be an array of floating-point
-numbers, \code{psFloatArray}.  We define the following basic matrix
-operations:
+\code{psImage} as a matrix, since it has the correct form.  We define
+the following basic matrix operations:
 \begin{itemize}
 \item $LU$ Decompose a matrix, and solve for $x$ in $Ax = b$;
@@ -1963,46 +1917,30 @@
 
 \begin{verbatim}
-/** LU Decomposition of a matrix */
-psImage *
-psMatrixLUD(psImage *out,               ///< Matrix to return, or NULL
-            psImage *myMatrix           ///< Matrix to decompose
-            );
-
-/** LU Solution.  Solves for and returns x in the equation Ax = b */
-psVector *
-psMatrixLUSolve(psVector *out,          ///< Vector to return, or NULL
-                const psImage *luMatrix, ///< LU-decomposed matrix
-                const psVector *rhsVector ///< right-hand-side of the equation
-                ); 
-\end{verbatim}
-
-The above functions decompose a matrix, \code{myMatrix}, into its $LU$
+psImage *psMatrixLUD(psImage *out, psImage *in);
+psVector *psMatrixLUSolve(psVector *out, const psImage *LU, const psVector *RHS);
+\end{verbatim}
+The above functions decompose a matrix, \code{in}, into its $LU$
 representation (\code{psMatrixLUD}, which returns the decomposed
 matrix), and uses the decomposed matrix to solve for $x$ in the
 equation $Ax = b$.  In this case, the $LU$ decomposed matrix $A$ is
-specified as \code{luMatrix}, and $b$ is \code{rhsVector}; the
-solution for $x$ is returned.
-
-\begin{verbatim}
-/** Invert matrix.  Not using restrict, to allow inversion to be done in-place */
-psImage *
-psMatrixInvert(psImage *out,           ///< Matrix to return, or NULL
-               const psImage *myMatrix, ///< Matrix to be inverted
-               float *restrict determinant ///< Determinant to return, or NULL
-    );
-\end{verbatim}
-
+specified as \code{LU}, and $b$ is \code{RHS}; the solution vector for
+$x$ is returned.  These functions are specified for data types
+\code{psF32, psF64}.  The output and input vectors and images must all
+have the same data type.
+
+\begin{verbatim}
+psImage *psMatrixInvert(psImage *out, const psImage *in, float *restrict determinant);
+\end{verbatim}
 \code{psMatrixInvert} returns the inverse of the specified matrix
-(\code{myMatrix}), along with the \code{determinant}, if non-NULL.
+(\code{in}), along with the \code{determinant}, if the \code{float}
+pointer is non-NULL.  The input and output images must have the same
+type.  This function is specified for data types \code{psF32, psF64}.
 
 The matrix determinant may be calculated using
 \code{psMatrixDeterminant}, which simply returns the determinant for
-the specified matrix, \code{myMatrix}.
-
-\begin{verbatim}
-/** Matrix determinant */
-float
-psMatrixDeterminant(const psImage *restrict myMatrix //!< Matrix to get determinant for
-                    );
+the specified matrix, \code{in}.  This function is specified for data
+types \code{psF32, psF64}.
+\begin{verbatim}
+float psMatrixDeterminant(const psImage *restrict in);
 \end{verbatim}
 
@@ -2014,55 +1952,36 @@
 \code{psMatrixOp} are identical to that for \code{psBinaryOp} (since
 that is how matrix addition is defined).  Matrix division is not
-defined.
-
-\begin{verbatim}
-/** Matrix operations */
-psImage *
-psMatrixOp(psImage *out,               ///< Matrix to return, or NULL
-           const psImage *matrix1,     ///< Matrix 1
-           const char *op,              ///< Operation to perform: "+", "-", "*"
-           const psImage *matrix2      ///< Matrix 2
-           );
-\end{verbatim}
-
-The transpose of an input matrix, \code{myMatrix}, is returned by
-\code{psMatrixTranspose}.
-
-\begin{verbatim}
-/** Transpose Matrix */
-psImage *
-psMatrixTranspose(psImage *out,        ///< Matrix to return, or NULL
-                  const psImage *myMatrix ///< Matrix to transpose
-                  );
-\end{verbatim}
-
-Eigenvectors of a matrix are calculated by \code{psMatrixEigenvectors}:
-
-\begin{verbatim}
-/** Eigenvectors of a matrix */
-psVector *
-psMatrixEigenvectors(psImage *myMatrix	///< Matrix to get eigenvectors for
-    );
+defined.  \tbd{why specify addition as an operator? why not only
+define operators which are different for matrices?}.  This function is
+specified for data types \code{psF32, psF64}.
+
+\begin{verbatim}
+psImage *psMatrixOp(psImage *out, const psImage *in1, const char *op, const psImage *in2);
+\end{verbatim}
+
+The transpose of an input matrix, \code{in}, is returned by
+\code{psMatrixTranspose}, optionally into the provided matrix
+\code{out}.  This function is specified for data types \code{psF32,psF64}.
+\begin{verbatim}
+psImage *psMatrixTranspose(psImage *out, const psImage *in);
+\end{verbatim}
+
+Eigenvectors of a matrix are calculated by
+\code{psMatrixEigenvectors}.  This function is specified for data
+types \code{psF32, psF64}.  Input and output data types should match.
+\begin{verbatim}
+psVector *psMatrixEigenvectors(psImage *in);
 \end{verbatim}
 
 Finally, we specify two functions to convert between matrices and
-vectors.  This allows the use of vectors in matrix arithmetic, since
-a vector can be converted to a matrix, utilised, and the result can
-be converted back to a vector if required.
-
-\begin{verbatim}
-/** Convert matrix to vector.  Intended for a 1-d matrix. */
-psVector *
-psMatrixToVector(psVector *out,         ///< Vector to return, or NULL
-                 psImage *myMatrix      ///< Matrix to convert
-    );
-
-/** Convert vector to matrix. */
-psImage *
-psVectorToMatrix(psImage *out,          //!< Matrix to return, or NULL
-                 psVector *myVector     //!< Vector to convert
-    );
-\end{verbatim}
-
+vectors.  This allows the use of vectors in matrix arithmetic, since a
+vector can be converted to a matrix, utilised, and the result can be
+converted back to a vector if required.  This function is specified
+for data types \code{psF32, psF64}.  Input and output data types
+should match.
+\begin{verbatim}
+psVector *psMatrixToVector(psVector *out, psImage *in);
+psImage *psVectorToMatrix(psImage *out, psVector *in);
+\end{verbatim}
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -2071,87 +1990,49 @@
 
 We require the ability to calculate the (fast) fourier transforms of
-floating-point two-dimensional images and one-dimensional arrays.  We
+floating-point one-dimensional vectors and two-dimensional images.  We
 expect that these will be implemented through wrapping an external
-library.
-
-The forward and reverse Fourier transforms may be calculated using the
-following APIs:
-
-\begin{verbatim}
-/** Forward FFT an image.  Returns a complex float image. */
-psImage *
-psImageFFT(const psImage *image		///< Image to transform
-    );
-
-/** Forward FFT an array of floating-point numbers. */
-psFloatArray *
-psFloatArrayFFT(const psFloatArray *arr	///< Array to transform
-    );
-
-/** Inverse FFT an image. */
-psImage *
-psImageInverseFFT(const psImage *fftImage ///< FFT-ed image to inverse-transform
-    );
-
-/** Inverse FFT an array of complex floating-point numbers */
-psComplexArray *
-psComplexArrayInverseFFT(const psComplexArray *fftArray ///< FFT-ed array to inverse-transform
-    );
-\end{verbatim}
-
-Neither the forward or inverse transforms shall multiply by $1/N$ (or
-$1/N^{1/2}$), and so it falls to the responsibility of the user to
-multiply an image that has been forward- and reverse-transformed by
-$1/N$.
-
-The \code{psImage}s output by \code{psImageFFT} and
-\code{psImageInverseFFT} should be of complex floating-point type.  Following
-an inverse transform, therefore, the user will likely want to extract the
-real parts:
-
-\begin{verbatim}
-/** Get the real part of an image */
-psImage *
-psImageReal(psImage *out,		///< Image for output (or NULL)
-	    const psImage *in		///< Image to get the real part of
-	    );
-
-/** Get the real part of an array of complex floating-point numbers */
-psFloatArray *
-psComplexArrayReal(psFloatArray *out,	///< Array for output (or NULL)
-		   const psComplexArray *in ///< Array to get the real part of
-    );
-\end{verbatim}
-
-To aid operations on FFT-ed images or arrays, we also specify
-functions to return the complex conjugate of an image or array:
-
-\begin{verbatim}
-/** Get the complex conjugate of an image */
-psImage *
-psImageConjugate(psImage *out,		///< Image for output (or NULL)
-		 const psImage *in	///< Image to get the complex conjugate of
-    );
-
-/** Get the complex conjugate of an array of complex floating-point numbers */
-psComplexArray *
-psComplexArrayConjugate(psComplexArray *out, ///< Array for output (or NULL)
-			const psComplexArray *in ///< Array to get the complex conjugate of
-    );
-\end{verbatim}
-
-Finally, the power spectrum may be calculated directly from the
-original image or array:
-
-\begin{verbatim}
-/** Calculate power spectrum of an image */
-psImage *
-psImagePowerSpectrum(const psImage *image ///< Image to obtain power spectrum of
-    );
-
-/** Calculate power spectrum of an array of floating-point numbers */
-psFloatArray *
-psFloatArrayPowerSpectrum(const psFloatArray *arr ///< Array to obtain power spectrum of
-    );
+library.  We define the following APIs to support FFT operations on vectors:
+
+\begin{verbatim}
+psVector *psVectorFFT(const psVector *in, int direction);
+psVector *psVectorReal(psVector *out, const psVector *in);
+psVector *psVectorImaginary(psVector *out, const psVector *in);
+psVector *psVectorComplex(psVector *real, psVector *imag);
+psVector *psVectorConjugate(psVector *out, const psVector *in);
+psVector *psVectorPowerSpectrum(const psVector *in);
+\end{verbatim}
+
+The forward and reverse FFT is calculated using \code{psVectorFFT},
+which takes as input the vector of interest (\code{in}) and the
+direction (\code{direction}; 1 is forward, -1 is reverse).  The input
+vector may be of type \code{psF32} or \code{psC32}, the result is
+always \code{psC32}.  If the input vector is \code{psF32}, the
+direction must be forward.  Neither the forward or inverse transforms
+shall multiply by $1/N$ (or $1/N^{1/2}$), and so it falls to the
+responsibility of the user to multiply a vector that has been forward-
+and reverse-transformed by $1/N$.
+
+Conversions between complex and real vectors requires the functions
+\code{psVectorReal}, which returns the real part (\code{psF32}) of the
+complex vector \code{in}, \code{psVectorImaginary}, which returns the
+the magnitude of the imaginary part (\code{psF32}) of the complex
+vector \code{in}, and \code{psVectorComplex}, which constructs a
+complex vector (\code{psC32}) from the real and imaginary components
+\code{real} and \code{imag}, both of type \code{psF32}.
+
+We also specify the additional utility functions
+\code{psVectorConjuagte} and \code{psVectorPowerSpectrum} which
+construct the complex conjugate (\code{psC32}) and the magnitude
+(\code{psF32}) vectors of the input complex vector (\code{psC32}).
+
+In analogy with the vector FFT operations, we also define matching
+image operations as follows:
+\begin{verbatim}
+psImage *psImageFFT(const psImage *image, int direction);
+psImage *psImagePowerSpectrum(const psImage *image);
+psImage *psImageReal(psImage *out, const psImage *in);
+psImage *psImageReal(psImage *out, const psImage *in);
+psImage *psImageReal(psImage *out, const psImage *in);
+psImage *psImageConjugate(psImage *out, const psImage *in);
 \end{verbatim}
 
@@ -2161,17 +2042,14 @@
 
 We require two types of general functions which will be used in fitting:
-Gaussians and Polynomials.  The Gaussian is easily defined:
-
-\begin{verbatim}
-/** Evaluate a non-normalized Gaussian with the given mean and sigma at the given coordianate.  Note that this
- *  is not a Gaussian deviate.  The evaluated Gaussian is:
- *  \f[ 1/(\sqrt(2\pi)\sigma) exp(-\frac{(x-mean)^2}{2\sigma^2}) \f]
- */
-float
-psGaussian(float x,                     ///< Value at which to evaluate
-           float mean,                  ///< Mean for the Gaussian
-           float stddev                 ///< Standard deviation for the Gaussian
-           );
-\end{verbatim}
+Gaussians and Polynomials.  The Gaussian is defined as:
+\begin{verbatim}
+float psGaussian(float x, float mean, float stdev);
+\end{verbatim}
+
+which evaluates a non-normalized Gaussian with the given mean and
+sigma at the given coordianate.  Note that this is not a Gaussian
+deviate.  The evaluated Gaussian is: 
+
+\[ 1/(\sqrt(2\pi)\sigma) exp(-\frac{(x-mean)^2}{2\sigma^2}) \]
 
 For the polynomial, \PS{} astrometry requirements lead us to specify
@@ -2232,20 +2110,13 @@
 The constructor and destructor are:
 \begin{verbatim}
-psDPolynomial2D *psDPolynomial2DAlloc(int nX, int nY ///< Number of terms in x and y
-    );
-void psDPolynomial2DFree(psDPolynomial2D *restrict myPoly ///< Polynomial to destroy
-    );
-\end{verbatim}
-
-And the polynomials may be evaluated, returning the value of the
-polynomial at the specified coordinates:
-
-\begin{verbatim}
-/** Evaluate 2D polynomial (double precision) */
-double
-psEvalDPolynomial2D(double x,           ///< Value x at which to evaluate
-                    double y,           ///< Value y at which to evaluate
-                    const psDPolynomial2D *restrict myPoly ///< Coefficients for the polynomial
-                    );
+psDPolynomial2D *psDPolynomial2DAlloc(int nX, int nY);
+void psDPolynomial2DFree(psDPolynomial2D *restrict myPoly);
+\end{verbatim}
+where \code{nX} and \code{nY} are the number of terms in x and y
+respectively.
+
+To evaluate the polynomials at specific coordinates, we define:
+\begin{verbatim}
+double psEvalDPolynomial2D(double x, double y, const psDPolynomial2D *restrict myPoly);
 \end{verbatim}
 
@@ -2255,40 +2126,42 @@
 
 \subsection{Minimization and fitting routines}
+
+\tbd{I am concerned the minimization functions defined here are
+  missing details - gene}
 
 We require a general minimization routine, a routine that will
 specifically minimize $\chi^2$ given a list of data with associated
 errors, and a function that will analytically determine the best
-polynomial fit by minimizing $\chi^2$.  The APIs are:
-
-\begin{verbatim}
-/** Find the minimum of a particular non-linear function */
-psFloatArray *
-psMinimize(psFloatArray *restrict initialGuess,	///< Initial guess and answer
-	   float (*myFunction)(const psFloatArray *restrict), ///< Function to minimize
-	   float (*myFuncDeriv)(const psFloatArray *restrict), ///< Derivatives of function, or NULL
-	   const psIntArray *restrict paramMask //!< 1 = fit for parameter, 0 = hold parameter constant
-	   );
-\end{verbatim}
-
-\code{psMinimize} determines and returns the parameters that minimizes
-the specified function.  It takes as input a function,
-\code{myFunction}, an initial guess for the parameters that minimize
-the function, \code{initialGuess} which is returned with the best-fit
-parameters, and an optional mask for the parameters to minimize,
-\code{paramMask} (all parameters are fit if \code{NULL}).
-
-\begin{verbatim}
-/** Minimize chi^2 for input data */
-psFloatArray *
-psMinimizeChi2(psFloatArray *restrict initialGuess, ///< Initial guess and answer
-	       float (*evalModel)(const psFloatArray *restrict,
-				  const psFloatArray *restrict), ///< Model to fit; (domain and params)
-	       const psFloatArray *restrict domain, ///< The domain values for the corresponding measurements
-	       const psFloatArray *restrict data, ///< Data to fit
-	       const psFloatArray *restrict errors, ///< Errors in the data
-	       const psIntArray *restrict paramMask ///< 1 = fit for parameter, 0 = hold parameter constant
-    );
-\end{verbatim}
-
+polynomial fit by minimizing $\chi^2$.  
+
+First, we define \code{psMinimize}, which returns the vector which
+minimizes the specified function, which is itself a function of a
+single vector.  The returned vector must be the same length as the
+vector argument to the input function.  
+\begin{verbatim}
+psVector *psMinimize(psVector *restrict initialGuess, 
+                     float (*myFunction)(const psVector *restrict),
+                     float (*myFuncDeriv)(const psVector *restrict),
+                     const psVector *restrict paramMask);
+\end{verbatim}
+
+\code{psMinimize} determines and returns the vector that minimizes the
+specified function.  It takes as input a function, \code{myFunction},
+an initial guess for the vector that minimizes the function,
+\code{initialGuess}, and an optional mask for the vector elements
+(function parameters) to minimize, \code{paramMask} (all parameters
+are fit if \code{NULL}).  Note that \code{paramMask} must be of type
+\code{psU8}, while \tbd{what are valid types for the function
+parameter lists?}.  The optional function, \code{myFuncDeriv} returns
+the derivative of the function.  \tbd{is this sufficient? clear?}
+
+\begin{verbatim}
+psVector *psMinimizeChi2(psVector *restrict initialGuess,
+                         float (*evalModel)(const psVector *restrict, const psVector *restrict),
+                         const psVector *restrict domain,
+                         const psVector *restrict data,
+                         const psVector *restrict errors,
+                         const psVector *restrict paramMask);
+\end{verbatim}
 \code{psMinimizeChi2} fits a model to observations by minimizing
 $\chi^2$, returing the best-fit parameters.  The input parameters are
@@ -2297,25 +2170,24 @@
 \code{data}, and \code{errors}); an initial guess at the best-fit
 parameters, \code{initialGuess} which is returned with the best-fit
-parameters, and an optional mask specifying which parameters are to be
-fit, \code{paramMask} (all parameters are fit if \code{NULL}).
-
-\begin{verbatim}
-/** Derive a polynomial fit by chi^2 minimisation --- can be done analytically */
-psPolynomial1D *
-psGetArrayPolynomial(psPolynomial1D myPoly, ///< Polynomial to fit
-                     const psFloatArray *restrict x, ///< Ordinates (or NULL to just use the indices)
-                     const psFloatArray *restrict y, ///< Coordinates
-                     const psFloatArray *restrict yErr ///< Errors in coordinates, or NULL
-    );
-\end{verbatim}
-
-\code{psGetArrayPolynomial} calculates analytically and returns the
-polynomial that best fits the observations.  The input parameters are
-a polynomial that specifies the fit order, \code{myPoly}, which will
-be altered and returned with the best-fit coefficients; and the
-observations, \code{x}, \code{y} and \code{yErr}.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+parameters \tbd{how? unclear!}, and an optional mask specifying which
+parameters are to be fit, \code{paramMask}, which must be of type
+\code{psU8}.  All parameters are fit if this vector is \code{NULL}.
+
+\begin{verbatim}
+psPolynomial1D *psGetArrayPolynomial(psPolynomial1D myPoly, 
+                                     const psVector *restrict x,
+                                     const psVector *restrict y,
+                                     const psVector *restrict yErr);
+\end{verbatim}
+\code{psGetArrayPolynomial} returns the polynomial that best fits the
+observations.  The input parameters are a polynomial that specifies
+the fit order, \code{myPoly}, which will be altered and returned with
+the best-fit coefficients; and the observations, \code{x}, \code{y}
+and \code{yErr}.  The independent variable list, \code{x} may be
+\code{NULL}, in which case the vector index is used.  The dependent
+variable error, \code{yErr} may be null, in which case the solution is
+determined in the assumption that all data errors are equal.
+\tbd{valid types?}
+
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
@@ -2339,5 +2211,8 @@
 starting pixel of the subraster.  The entire subraster must be
 contained within the raster of the parent image.  Note that the
-\code{refCounter} for the parent should be incremented.
+\code{refCounter} for the parent should be incremented.  This function
+must be defined for the following types: \code{psU8}, \code{psU16},
+\code{psS8}, \code{psS16}, \code{psF32}, \code{psF64}, \code{psC32},
+\code{psC64}.
 
 Create a copy of the specified image, converting the type in the
@@ -2345,5 +2220,7 @@
 in the specified structure.  The output image data must be allocated
 as a single, contiguous block of memory.  The output image may not be
-the input image.
+the input image.  This function must be defined for the following
+types: \code{psU8}, \code{psU16}, \code{psS8}, \code{psS16},
+\code{psF32}, \code{psF64}, \code{psC32}, \code{psC64}.
 \begin{verbatim}
 psImage *psImageCopy(psImage *output, const psImage *input, psElemType type);
@@ -2359,7 +2236,8 @@
 is derived from the statistics of the pixels at that direction
 coordinate.  The statistic used to derive the output vector value is
-specified by \code{stats}.
-\begin{verbatim}
-psFloatArray *psImageSlice(psFloatArray *out, const psImage *input, int x, int y, int nx, int ny, 
+specified by \code{stats}.  This function must be defined for the
+following types: \code{psU8}, \code{psU16}, \code{psF32}, \code{psF64}.
+\begin{verbatim}
+psVector *psImageSlice(psVector *out, const psImage *input, int x, int y, int nx, int ny, 
                            int direction, const psStats *stats);
 \end{verbatim}
@@ -2373,7 +2251,8 @@
 statistics of the pixels interpolated along the perpendicular
 direction.  The statistic used to derive the output vector value is
-specified by \code{stats}.
-\begin{verbatim}
-psFloatArray *psImageCut(psFloatArray *out, const psImage *input, float xs, float ys, float xe, float ye, 
+specified by \code{stats}.  This function must be defined for the
+following types: \code{psU8}, \code{psU16}, \code{psF32}, \code{psF64}
+\begin{verbatim}
+psVector *psImageCut(psVector *out, const psImage *input, float xs, float ys, float xe, float ye, 
                          float dw, const psStats *stats);
 \end{verbatim}
@@ -2384,8 +2263,9 @@
 the image pixel coordinate \code{x,y}, and have width \code{dr}.  The
 number of annuli is $radius / dr$.  The statistic used to derive the
-output vector value is specified by \code{stats}
-\begin{verbatim}
-psFloatArray *psImageRadialCut(psFloatArray *out, const psImage *input, float x, float y,
-                               const psFloatArray *radii, const psStats *stats);
+output vector value is specified by \code{stats}.  This function must be defined for the
+following types: \code{psU8}, \code{psU16}, \code{psF32}, \code{psF64}.
+\begin{verbatim}
+psVector *psImageRadialCut(psVector *out, const psImage *input, float x, float y,
+                               const psVector *radii, const psStats *stats);
 \end{verbatim}
 
@@ -2398,5 +2278,7 @@
 Each pixel in the output image is derived from the statistics of the
 corresponding set of input image pixels based on the statistics
-specified by \code{stats}.
+specified by \code{stats}.  This function must be defined for the following
+types: \code{psU8}, \code{psU16}, \code{psS8}, \code{psS16},
+\code{psF32}, \code{psF64}, \code{psC32}, \code{psC64}.
 \begin{verbatim}
 psImage *psImageRebin(psImage *out, const psImage *input, float scale, const psStats *stats);
@@ -2408,5 +2290,7 @@
 pixels should be set to \tbd{value}.  The center of rotation is always
 the center pixel of the image.  The rotation is specified in the sense
-that a positive angle is an anti-clockwise rotation.  
+that a positive angle is an anti-clockwise rotation.    This function must be defined for the following
+types: \code{psU8}, \code{psU16}, \code{psS8}, \code{psS16},
+\code{psF32}, \code{psF64}, \code{psC32}, \code{psC64}.
 \begin{verbatim}
 psImage *psImageRotate(psImage *out, const psImage *input, float angle);
@@ -2418,5 +2302,7 @@
 image has the same dimensions as the input image.  Pixels which fall
 off the edge of the output image are lost.  Newly exposed pixels are
-set to the value given by \code{exposed}.  
+set to the value given by \code{exposed}.    This function must be defined for the following
+types: \code{psU8}, \code{psU16}, \code{psS8}, \code{psS16},
+\code{psF32}, \code{psF64}, \code{psC32}, \code{psC64}.
 \begin{verbatim}
 psImage *psImageShift(psImage *out, const psImage *input, float dx, float dy, float exposed);
@@ -2425,5 +2311,7 @@
 Roll image by an integer number of pixels (\code{dx,dy}) in either
 direction.  The output image is the same dimensions as the input
-image.  Edge pixels wrap to the other side (no values are lost).
+image.  Edge pixels wrap to the other side (no values are lost).  This function must be defined for the following
+types: \code{psU8}, \code{psU16}, \code{psS8}, \code{psS16},
+\code{psF32}, \code{psF64}, \code{psC32}, \code{psC64}.
 \begin{verbatim}
 psImage *psImageRoll(psImage *out, const psImage *input, int dx, int dy);
@@ -2433,5 +2321,6 @@
 
 Determine statistics for image (or subimage).  The statistics to be
-determined are specified by \code{stats}.
+determined are specified by \code{stats}.  This function must be defined for the
+following types: \code{psU8}, \code{psU16}, \code{psF32}, \code{psF64}.
 \begin{verbatim}
 psStats *psImageGetStats(psStats *stats, const psImage *input);
@@ -2440,5 +2329,6 @@
 Construct a histogram from an image (or subimage).  The histogram to
 generate is specified by \code{psHistogram hist} (see
-section~\ref{sec:histograms}).
+section~\ref{sec:histograms}).  This function must be defined for the
+following types: \code{psU8}, \code{psU16}, \code{psF32}, \code{psF64}.
 \begin{verbatim}
 psHistogram *psImageHistogram(psHistogram *hist, const psImage *input);
@@ -2447,5 +2337,6 @@
 Fit a 2-D Chebychev polynomial surface to an image.  The input
 structure \code{coeffs} contains the desired order and terms of
-interest.
+interest.  This function must be defined for the
+following types: \code{psU8}, \code{psU16}, \code{psF32}, \code{psF64}.
 \begin{verbatim}
 psPolynomial2D *psImageFitPolynomial(psPolynomial2D *coeffs, const psImage *input);
@@ -2454,5 +2345,6 @@
 Evaluate a 2-D polynomial surface for the image pixels.  Given the
 input polynomial coefficients, set the image pixel values on the basis
-of the polynomial function.
+of the polynomial function.  This function must be defined for the
+following types: \code{psU8}, \code{psU16}, \code{psF32}, \code{psF64}.
 \begin{verbatim}
 psImage *psImageEvalPolynomial(psImage *input, const psPolynomial2D *coeffs);
@@ -2516,6 +2408,6 @@
 \end{verbatim}
 
-Read header data from a FITS image file descriptor into a \code{psMetaData}
-structure.  
+Read header data from a FITS image file descriptor into a
+\code{psMetaData} structure.
 \begin{verbatim}
 psMetadata *psImageFReadHeader(psMetadata *output, const char *extname, int extnum, FILE *f);
@@ -2527,5 +2419,7 @@
 values \code{< min} are set to the value \code{vmin}. All pixels with
 values \code{> max} are set to the value \code{vmax}. Returns the
-number of clipped pixels.
+number of clipped pixels.  This function must be defined for the
+following types: \code{psU8}, \code{psU16}, \code{psS8}, \code{psS16},
+\code{psF32}, \code{psF64}, \code{psC32}, \code{psC64}.
 \begin{verbatim}
 int psImageClip(psImage *input, float min, float vmin, float max, float vmax);
@@ -2534,5 +2428,7 @@
 Clip \code{NaN} image pixels to given value.  Pixels with \code{NaN},
 \code{+Inf} or \code{-Inf} values are set to the specified value.
-Returns the number of clipped pixels.
+Returns the number of clipped pixels.  This function must be defined
+for the following types: \code{psU8}, \code{psU16}, \code{psS8},
+\code{psS16}, \code{psF32}, \code{psF64}, \code{psC32}, \code{psC64}.
 \begin{verbatim}
 int psImageClipNaN(psImage *input, float value);
@@ -2546,4 +2442,7 @@
 image value), \code{-} (subtract overlay from image), \code{*}
 (multiply overlay times image), \code{/} (divide image by overlay).
+This function must be defined for the following types: \code{psU8},
+\code{psU16}, \code{psS8}, \code{psS16}, \code{psF32}, \code{psF64},
+\code{psC32}, \code{psC64}.
 \begin{verbatim}
 int psImageOverlaySection(psImage *image, const psImage *overlay, int x0, int y0, const char *op);
@@ -2573,5 +2472,5 @@
 pre-processor macros to perform the onerous task of creating the
 loops.  Also note that \code{psVector} is equivalent to
-\code{psFloatArray}.  An attempt to perform an arithmetic operation on
+\code{psVector}.  An attempt to perform an arithmetic operation on
 an object of dimension \code{PS_DIMEN_OTHER} should produce an error.
 
@@ -3036,6 +2935,6 @@
 /// get the next item in the sequence
 psMetadataItem *psMetadataGetNext(psMetadata *restrict md, ///< metadata to get from
-				  const char *restrict match, ///< Match this
-				  int which ///< Which iterator to use
+                                  const char *restrict match, ///< Match this
+                                  int which ///< Which iterator to use
     );
 \end{verbatim}
@@ -3074,16 +2973,16 @@
 /** A point in 2-D space, with errors. */
 typedef struct {
-    double x;				///< x position
-    double y;				///< y position
-    double xErr;			///< Error in x position
-    double yErr;			///< Error in y position
+    double x;                           ///< x position
+    double y;                           ///< y position
+    double xErr;                        ///< Error in x position
+    double yErr;                        ///< Error in y position
 } psPlaneCoord;
 
 /** A point on the surface of a sphere, with errors */
 typedef struct {
-    double r;				///< RA
-    double d;				///< Dec
-    double rErr;			///< Error in RA
-    double dErr;			///< Error in Dec
+    double r;                           ///< RA
+    double d;                           ///< Dec
+    double rErr;                        ///< Error in RA
+    double dErr;                        ///< Error in Dec
 } psSphereCoord;
 \end{verbatim}
@@ -3188,14 +3087,14 @@
 /** apply the coordinate transformation to the given coordinate */
 psPlaneCoord *psPlaneCoordXformApply (psPlaneCoord *out, ///< Output coordinates, or NULL
-				      const psPlaneCoordXform *frame, ///< coordinate transformation
-				      const psPlaneCoord *coords ///< input coordiate
+                                      const psPlaneCoordXform *frame, ///< coordinate transformation
+                                      const psPlaneCoord *coords ///< input coordiate
     );
 
 /** apply the optical distortion to the given coordinate, magnitude, color */
 psPlaneCoord *psPlaneDistortionApply (psPlaneCoord *out, ///< Output coordinates, or NULL
-				      const psPlaneDistortion *pattern, ///< optical distortion pattern
-				      const psPlaneCoord *coords, ///< input coordinate
-				      float mag, ///< magnitude of object
-				      float color ///< color of object
+                                      const psPlaneDistortion *pattern, ///< optical distortion pattern
+                                      const psPlaneCoord *coords, ///< input coordinate
+                                      float mag, ///< magnitude of object
+                                      float color ///< color of object
     );
 \end{verbatim}
@@ -3232,6 +3131,6 @@
 psSphereCoordTransformation *
 psSphereCoordTransformationAlloc(double pole1, ///< First location of pole
-				 double pole2, ///< Second location of pole
-				 double rotation ///< Rotation between systems
+                                 double pole2, ///< Second location of pole
+                                 double rotation ///< Rotation between systems
     );
 
@@ -3248,5 +3147,5 @@
 psSphereCoord *
 psSphereCoordTransform(const psSphereCoord *coord, ///< Coordinates to convert
-		       psSphereCoordSystem *sys	///< System to use to convert
+                       psSphereCoordSystem *sys ///< System to use to convert
     );
 \end{verbatim}
@@ -3291,5 +3190,5 @@
 psPlaneCoord *
 psCoordProject(const psSphereCoord *coord, ///< Spherical coordinates to project
-	       const char *projection	///< Projection to use
+               const char *projection   ///< Projection to use
     );
 
@@ -3297,5 +3196,5 @@
 psSphereCoord *
 psCoordDeproject(const psPlaneCoord *coord, ///< Plane coordinates to deproject
-		 const char *projection	///< Projection to use
+                 const char *projection ///< Projection to use
     );
 \end{verbatim}
@@ -3310,7 +3209,7 @@
 psSphereCoord *
 psSphereCoordGetOffset(const psSphereCoord *restrict position1, ///< Position 1
-		       const psSphereCoord *restrict position2, ///< Position 2
-		       const char *type		///< Type of offset: Linear, Spherical/Arcsec,
-						///< Spherical/Degreees etc
+                       const psSphereCoord *restrict position2, ///< Position 2
+                       const char *type         ///< Type of offset: Linear, Spherical/Arcsec,
+                                                ///< Spherical/Degreees etc
     );
 
@@ -3318,7 +3217,7 @@
 psSphereCoord *
 psSphereCoordApplyOffset(const psSphereCoord *restrict position, ///< Position
-			 const psSphereCoord *restrict offset, ///< Offset
-			 const char *type		///< Type of offset: Linear, Spherical/Arcsec,
-							///< Spherical/Degreees etc
+                         const psSphereCoord *restrict offset, ///< Offset
+                         const char *type               ///< Type of offset: Linear, Spherical/Arcsec,
+                                                        ///< Spherical/Degreees etc
     );
 \end{verbatim}
@@ -3453,14 +3352,14 @@
  */
 typedef struct {
-    int nReadouts;			///< number of readouts in this cell realization; each may have its
-					///< own image, objects and overscan.
-    struct psReadout *readouts;		///< Readouts from the cell
-    psMetadata *md;			///< Cell-level metadata
-
-    psPlaneCoordXform *cellToChip;	///< Transformations from cell coordinates to chip coordinates
-    psPlaneCoordXform *cellToFPA;	///< Transformations from cell coordinates to FPA coordinates
-    psPlaneCoordXform *cellToSky;	///< Quick and Dirty transformations from cell coordinates to sky
-
-    struct psChip  *parentChip;		///< chip which contains this cell
+    int nReadouts;                      ///< number of readouts in this cell realization; each may have its
+                                        ///< own image, objects and overscan.
+    struct psReadout *readouts;         ///< Readouts from the cell
+    psMetadata *md;                     ///< Cell-level metadata
+
+    psPlaneCoordXform *cellToChip;      ///< Transformations from cell coordinates to chip coordinates
+    psPlaneCoordXform *cellToFPA;       ///< Transformations from cell coordinates to FPA coordinates
+    psPlaneCoordXform *cellToSky;       ///< Quick and Dirty transformations from cell coordinates to sky
+
+    struct psChip  *parentChip;         ///< chip which contains this cell
 } psCell;
 \end{verbatim}
@@ -3484,11 +3383,11 @@
 typedef struct {
     int nCells;                         ///< Number of Cells assigned
-    struct psCell *cells;		///< Cells in the Chip
-
-    psMetadata *md;			///< Chip-level metadata
-    psPlaneCoordXform *chipToFPA;	///< Transformations from chip coordinates to FPA coordinates
-    psPlaneCoordXform *FPAtoChip;	///< Transformations from FPA coordinates to chip
-
-    struct psFPA *parentFPA;		///< FPA which contains this chip
+    struct psCell *cells;               ///< Cells in the Chip
+
+    psMetadata *md;                     ///< Chip-level metadata
+    psPlaneCoordXform *chipToFPA;       ///< Transformations from chip coordinates to FPA coordinates
+    psPlaneCoordXform *FPAtoChip;       ///< Transformations from FPA coordinates to chip
+
+    struct psFPA *parentFPA;            ///< FPA which contains this chip
 } psChip;
 \end{verbatim}
@@ -3520,11 +3419,11 @@
     int nChips;                         ///< Number of Cells assigned
     int nAlloc;                         ///< Number of Cells available
-    struct psChip *chips;		///< Chips in the Focal Plane Array
-
-    psMetadata *md;			///< FPA-level metadata 
-    psPlaneDistortion *TPtoFP;		///< Transformation term from 
-    psPlaneDistortion *FPtoTP;		///< Transformation term from 
-    psFixedPattern *pattern;		///< Fixed pattern residual offsets
-    const psExposure *exp;		///< information about this exposure
+    struct psChip *chips;               ///< Chips in the Focal Plane Array
+
+    psMetadata *md;                     ///< FPA-level metadata 
+    psPlaneDistortion *TPtoFP;          ///< Transformation term from 
+    psPlaneDistortion *FPtoTP;          ///< Transformation term from 
+    psFixedPattern *pattern;            ///< Fixed pattern residual offsets
+    const psExposure *exp;              ///< information about this exposure
     psPhotSystem colorPlus, colorMinus; ///< Colour reference
     float rmsX, rmsY;                   ///< Dispersion in astrometric solution
@@ -3543,22 +3442,22 @@
 typedef struct {
     // Telescope longitude, latitude and height are stored separately, since they don't change with pointing
-    const double ra, dec;		///< Telescope boresight
-    const double ha;			///< Hour angle
-    const double zd;			///< Zenith distance
-    const double az;			///< Azimuth
-    const double lst;			///< Local Sidereal Time
-    const float mjd;			///< MJD of observation
-    const float rotAngle;		///< Rotator position angle
-    const float temp;			///< Air temperature, for estimating refraction
-    const float pressure;		///< Air pressure, for calculating refraction
-    const float humidity;		///< Relative humidity, for calculating refraction
-    const float exptime;		///< Exposure time
+    const double ra, dec;               ///< Telescope boresight
+    const double ha;                    ///< Hour angle
+    const double zd;                    ///< Zenith distance
+    const double az;                    ///< Azimuth
+    const double lst;                   ///< Local Sidereal Time
+    const float mjd;                    ///< MJD of observation
+    const float rotAngle;               ///< Rotator position angle
+    const float temp;                   ///< Air temperature, for estimating refraction
+    const float pressure;               ///< Air pressure, for calculating refraction
+    const float humidity;               ///< Relative humidity, for calculating refraction
+    const float exptime;                ///< Exposure time
     /* Derived quantities */
-    const float posAngle;		///< Position angle
-    const float parallactic;		///< Parallactic angle
-    const float airmass;		///< Airmass, calculated from zenith distance
-    const float pf;			///< Parallactic factor
-    const char *cameraName;		///< name of camera which provided exposure
-    const char *telescopeName;		///< name of telescope which provided exposure
+    const float posAngle;               ///< Position angle
+    const float parallactic;            ///< Parallactic angle
+    const float airmass;                ///< Airmass, calculated from zenith distance
+    const float pf;                     ///< Parallactic factor
+    const char *cameraName;             ///< name of camera which provided exposure
+    const char *telescopeName;          ///< name of telescope which provided exposure
 } psExposure;
 \end{verbatim}
@@ -3646,16 +3545,16 @@
 /** Information needed (by SLALIB) to convert Apparent to Observed Position */
 typedef struct {
-    const double latitude;		///< geodetic latitude (radians)
-    const double sinLat, cosLat;	///< sine and cosine of geodetic latitude
-    const double abberationMag;		///< magnitude of diurnal aberration vector
-    const double height;		///< height (HM)
-    const double temperature;		///< ambient temperature (TDK)
-    const double pressure;		///< pressure (PMB)
-    const double humidity;		///< relative humidity (RH)
-    const double wavelength;		///< wavelength (WL)
-    const double lapseRate;		///< lapse rate (TLR)
-    const double refractA, refractB;	///< refraction constants A and B (radians)
-    const double longitudeOffset;	///< longitude + eqn of equinoxes + ``sidereal UT'' (radians)
-    const double siderealTime;		///< local apparent sidereal time (radians)
+    const double latitude;              ///< geodetic latitude (radians)
+    const double sinLat, cosLat;        ///< sine and cosine of geodetic latitude
+    const double abberationMag;         ///< magnitude of diurnal aberration vector
+    const double height;                ///< height (HM)
+    const double temperature;           ///< ambient temperature (TDK)
+    const double pressure;              ///< pressure (PMB)
+    const double humidity;              ///< relative humidity (RH)
+    const double wavelength;            ///< wavelength (WL)
+    const double lapseRate;             ///< lapse rate (TLR)
+    const double refractA, refractB;    ///< refraction constants A and B (radians)
+    const double longitudeOffset;       ///< longitude + eqn of equinoxes + ``sidereal UT'' (radians)
+    const double siderealTime;          ///< local apparent sidereal time (radians)
 } psGrommit;
 \end{verbatim}
@@ -3667,10 +3566,10 @@
 /** Constructor */
 psGrommit *
-psGrommitAlloc(const psExposure *exp	///< Relevant exposure
+psGrommitAlloc(const psExposure *exp    ///< Relevant exposure
     );
 
 /** Destructor */
 void
-psGrommitFree(psGrommit *grommit	///< Grommit to destroy
+psGrommitFree(psGrommit *grommit        ///< Grommit to destroy
     );
 \end{verbatim}
@@ -3710,22 +3609,22 @@
 /** returns Chip in FPA which contains the given FPA coordinate */
 psChip *
-psChipInFPA (psChip *out,		///< Chip to return, or NULL
-	     const psPlaneCoord *coord	///< coordinate in FPA
-	     const psFPA *fpa, 		///< FPA description
-	     );
+psChipInFPA (psChip *out,               ///< Chip to return, or NULL
+             const psPlaneCoord *coord  ///< coordinate in FPA
+             const psFPA *fpa,          ///< FPA description
+             );
 
 /** returns Cell in Chip which contains the given chip coordinate */
 psCell *
-psCellInChip(psCell *out,		///< Cell to return, or NULL
-	     const psPlaneCoord *coord	///< coordinate in chip
-	     const psChip *chip,	///< chip description
-	     );
+psCellInChip(psCell *out,               ///< Cell to return, or NULL
+             const psPlaneCoord *coord  ///< coordinate in chip
+             const psChip *chip,        ///< chip description
+             );
 
 /** Return the cell in FPA which contains the given FPA coordinates */
 psCell *
-psCellInFPA(psCell *out,		///< Cell to return, or NULL
-	    const psPlaneCoord *coord	///< Coordinate in FPA
-	    const psFPA *fpa,		///< FPA description
-	    );
+psCellInFPA(psCell *out,                ///< Cell to return, or NULL
+            const psPlaneCoord *coord   ///< Coordinate in FPA
+            const psFPA *fpa,           ///< FPA description
+            );
 \end{verbatim}
 
@@ -3763,86 +3662,86 @@
 /** Convert (RA,Dec) to cell and cell coordinates */
 psPlaneCoord *
-psCoordSkyToCell(psPlaneCoord *out,	///< Coordinates to return, or NULL
-		 psCell *cell,		///< Cell to return
-		 const psSphereCoord *in, ///< Input coordinates
-		 const psFPA *fpa	///< FPA description
-		 );
+psCoordSkyToCell(psPlaneCoord *out,     ///< Coordinates to return, or NULL
+                 psCell *cell,          ///< Cell to return
+                 const psSphereCoord *in, ///< Input coordinates
+                 const psFPA *fpa       ///< FPA description
+                 );
 
 /** Convert cell and cell coordinate to (RA,Dec) */
 psSphereCoord *
-psCoordCellToSky(psSphereCoord *out,	///< Coordinates to return, or NULL
-		 const psPlaneCoord *coord ///< cell coordinates to transform
-		 const psCell *cell,	///< Cell to get coordinates for
-		 );
+psCoordCellToSky(psSphereCoord *out,    ///< Coordinates to return, or NULL
+                 const psPlaneCoord *coord ///< cell coordinates to transform
+                 const psCell *cell,    ///< Cell to get coordinates for
+                 );
 
 /** Quick and dirty cell to (RA,Dec) --- employs cellToSky transformation */
 psSphereCoord *
 psCoordCellToSkyQuick(psSphereCoord *out, ///< Coordinates to return, or NULL
-		      const psPlaneCoord *coord	///< cell coordinates to transform
-		      const psCell *cell, ///< Cell description
-		      );
+                      const psPlaneCoord *coord ///< cell coordinates to transform
+                      const psCell *cell, ///< Cell description
+                      );
 
 /** Convert (RA,Dec) to tangent plane coords */
 psPlaneCoord *
-psCoordSkyToTP(psPlaneCoord *out,	///< Coordinates to return, or NULL
-	       const psSphereCoord *coord ///< input Sky coordinate
-	       const psGrommit *grommit, ///< Grommit for fast conversion
-	       );
+psCoordSkyToTP(psPlaneCoord *out,       ///< Coordinates to return, or NULL
+               const psSphereCoord *coord ///< input Sky coordinate
+               const psGrommit *grommit, ///< Grommit for fast conversion
+               );
 
 /** Convert tangent plane coords to focal plane coordinates */
 psPlaneCoord *
-psCoordTPtoFPA(psPlaneCoord *out,	///< Coordinates to return, or NULL
-	       const psPlaneCoord *coord ///< input TP coordinate
-	       const psFPA *fpa,	///< FPA description
-	       );
+psCoordTPtoFPA(psPlaneCoord *out,       ///< Coordinates to return, or NULL
+               const psPlaneCoord *coord ///< input TP coordinate
+               const psFPA *fpa,        ///< FPA description
+               );
 
 /** converts the specified FPA coord to the coord on the given Chip */
 psPlaneCoord *
-psCoordFPAtoChip (psPlaneCoord *out,	///< Coordinates to return, or NULL
-		  const psPlaneCoord *coord ///< input FPA coordinate
-		  const psChip *chip,	///< Chip of interest
-		  ); 
+psCoordFPAtoChip (psPlaneCoord *out,    ///< Coordinates to return, or NULL
+                  const psPlaneCoord *coord ///< input FPA coordinate
+                  const psChip *chip,   ///< Chip of interest
+                  ); 
 
 /** converts the specified Chip coord to the coord on the given Cell */
 psPlaneCoord *
-psCoordChiptoCell (psPlaneCoord *out,	///< Coordinates to return, or NULL
-		   const psPlaneCoord *coord ///< input Chip coordinate
-		   const psCell *cell, 	///< Cell of interest
-		   );
+psCoordChiptoCell (psPlaneCoord *out,   ///< Coordinates to return, or NULL
+                   const psPlaneCoord *coord ///< input Chip coordinate
+                   const psCell *cell,  ///< Cell of interest
+                   );
 
 /** converts the specified Cell coord to the coord on the parent Chip */
 psPlaneCoord *
-psCoordCelltoChip (psPlaneCoord *out,	///< Coordinates to return, or NULL
-		   const psPlaneCoord *coord ///< input Cell coordinate
-		   const psCell *cell, 	///< Cell description
-		   );
+psCoordCelltoChip (psPlaneCoord *out,   ///< Coordinates to return, or NULL
+                   const psPlaneCoord *coord ///< input Cell coordinate
+                   const psCell *cell,  ///< Cell description
+                   );
 
 /** converts the specified Chip coord to the coord on the parent FPA */
 psPlaneCoord *
-psCoordChiptoFPA (psPlaneCoord *out,		///< Coordinates to return, or NULL
-		  const psPlaneCoord *coord	///< input Chip coordinate
-		  const psChip *chip, 	///< Chip description
-		  );
+psCoordChiptoFPA (psPlaneCoord *out,            ///< Coordinates to return, or NULL
+                  const psPlaneCoord *coord     ///< input Chip coordinate
+                  const psChip *chip,   ///< Chip description
+                  );
 
 /** Convert focal plane coords to tangent plane coordinates */
 psPlaneCoord *
-psCoordFPAToTP(psPlaneCoord *out,		///< Coordinates to return, or NULL
-	       const psPlaneCoord *coord ///< input FPA coordinate
-	       const psFPA *fpa,	///< FPA description
-	       );
+psCoordFPAToTP(psPlaneCoord *out,               ///< Coordinates to return, or NULL
+               const psPlaneCoord *coord ///< input FPA coordinate
+               const psFPA *fpa,        ///< FPA description
+               );
 
 /** Convert tangent plane coords to (RA,Dec) */
 psSphereCoord *
-psCoordTPtoSky(psSphereCoord *out,	///< Coordinates to return, or NULL
-	       const psPlaneCoord *coord ///< input TP coordinate
-	       const psGrommit *grommit, ///< Grommit for fast conversion
-	       );
+psCoordTPtoSky(psSphereCoord *out,      ///< Coordinates to return, or NULL
+               const psPlaneCoord *coord ///< input TP coordinate
+               const psGrommit *grommit, ///< Grommit for fast conversion
+               );
 
 /** Convert Cell coords to FPA coordinates */
 psPlaneCoord *
-psCoordCellToFPA(psPlaneCoord *out,	///< Coordinates to return, or NULL
-		 const psPlaneCoord *coord ///< Input cell coordinates
-		 const psCell *cell,	///< Cell description
-		 );
+psCoordCellToFPA(psPlaneCoord *out,     ///< Coordinates to return, or NULL
+                 const psPlaneCoord *coord ///< Input cell coordinates
+                 const psCell *cell,    ///< Cell description
+                 );
 \end{verbatim}
 
@@ -3858,6 +3757,6 @@
 float
 psGetAirmass(const psSphereCoord *coord, ///< Position on the sky
-             double siderealTime,	///< Sidereal time
-	     float height		///< Height above sea level
+             double siderealTime,       ///< Sidereal time
+             float height               ///< Height above sea level
              );
 \end{verbatim}
@@ -3973,12 +3872,12 @@
 /** Get Sun Position */
 psSphereCoord *
-psGetSunPos(float mjd			///< MJD to get position for
+psGetSunPos(float mjd                   ///< MJD to get position for
     );
 
 /** Get Moon position */
 psSphereCoord *
-psGetMoonPos(float mjd,			///< MJD to get position for
-	     double latitude,		///< Latitude for apparent position
-	     double longitude		///< Longitude for apparent position
+psGetMoonPos(float mjd,                 ///< MJD to get position for
+             double latitude,           ///< Latitude for apparent position
+             double longitude           ///< Longitude for apparent position
     );
 
