/** @file  psVector.h
 *
 *  @brief Contains basic vector definitions and operations
 *
 *  This file defines the basic type for a vector struct and functions useful
 *  in manupulating vectors.
 *
 *  @ingroup Vector
 *
 *  @author Robert DeSonia, MHPCC
 *  @author Ross Harman, MHPCC
 *
 *  @version $Revision: 1.51 $ $Name: not supported by cvs2svn $
 *  @date $Date: 2006-01-28 01:12:14 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
 */

#ifndef PS_VECTOR_H
#define PS_VECTOR_H

#include<stdio.h>

#include "psType.h"

/// @addtogroup Vector
/// @{

/** An vector to support primitive types.
 *
 * Struct for maintaining an vector of frequently used primitive types.
 *
 */
typedef struct
{
    psMathType type;                   ///< Type of data.
    long n;                            ///< Number of elements in use.
    const long nalloc;                 ///< Total number of elements available.
    union {
        psS8* S8;                      ///< Signed 8-bit integer data.
        psS16* S16;                    ///< Signed 16-bit integer data.
        psS32* S32;                    ///< Signed 32-bit integer data.
        psS64* S64;                    ///< Signed 64-bit integer data.
        psU8* U8;                      ///< Unsigned 8-bit integer data.
        psU16* U16;                    ///< Unsigned 16-bit integer data.
        psU32* U32;                    ///< Unsigned 32-bit integer data.
        psU64* U64;                    ///< Unsigned 64-bit integer data.
        psF32* F32;                    ///< Single-precision float data.
        psF64* F64;                    ///< Double-precision float data.
        psC32* C32;                    ///< Single-precision complex data.
        psC64* C64;                    ///< Double-precision complex data.
    } data;
    void *lock;                        ///< Optional lock for thread safety.
}
psVector;

#define P_PSVECTOR_SET_NALLOC(vec,n) *(long*)&(vec->nalloc) = n

        /*****************************************************************************/

        /* FUNCTION PROTOTYPES                                                       */

        /*****************************************************************************/

        /** Checks the type of a particular pointer.
         *
         *  Uses the appropriate deallocation function in psMemBlock to check the ptr datatype.
         *
         *  @return bool:       True if the pointer matches a psVector structure, false otherwise.
         */
        bool psMemCheckVector(
            psPtr ptr                          ///< the pointer whose type to check
        )
        ;

/** Allocate a vector.
 *
 *  Uses psLib memory allocation functions to create a vector collection of
 *  data as defined by the psType type.
 *
 * @return psVector*    Pointer to psVector.
 */
psVector* psVectorAlloc(
    long nalloc,                       ///< Total number of elements to make available.
    psElemType type                    ///< Type of data to be held by vector.
);

/** Reallocate a vector.
 *
 *  Uses psLib memory allocation functions to reallocate a vector collection
 *  of data. The vector is reallocated according to the psType type member
 *  contained within the vector.
 *
 *  @return psVector*      Pointer to psVector.
 *
 */
psVector* psVectorRealloc(
    psVector* vector,                  ///< Vector to reallocate.
    long nalloc                        ///< Total number of elements to make available.
);

/** Extend a vector's length.
 *
 *  Increments a vector's length, n, by the specified number of elements.
 *  If the allocated storage is less than the current vector's length plus
 *  twice the number of elements to be added, it is reallocated larger by
 *  a given amount.
 *
 *  @return psVector*      Pointer to the adjusted psVector
 */
psVector *psVectorExtend(
    psVector *vector,                  ///< Vector to extend
    long delta,                        ///< Amount to expand allocation, if necessary
    long nExtend                       ///< Number of elements to add to vector length
);

/** Recycle a vector.
 *
 *  Uses psLib memory allocation functions to reallocate a vector collection
 *  of data. The vector is reallocated according to the psElemType type
 *  parameter.
 *
 * @return psVector*       Pointer to psVector.
 *
 */
psVector* psVectorRecycle(
    psVector* vector,
    ///< Vector to recycle.  If NULL, a new vector is created.  No effort
    ///< taken to preserve the values.

    long nalloc,                       ///< Total number of elements to make available.
    psElemType type                    ///< the datatype of the returned vector
);

/** Copy a vector, converting types.
 *
 *  Performs a deep copy of the elements of one psVector to a new psVector,
 *  converting numeric types to a specified type.
 *
 * @return psVector*       Pointer to resulting psVector.
 *
 */
psVector* psVectorCopy(
    psVector* output,                  ///< if non-NULL, a psVector to recycle
    const psVector* input,             ///< the vector to copy.
    psElemType type                    ///< the data type of the resulting psVector
);

/** Sort an array of floats.
 *
 *  Sorts an array of floats in ascending order.  This function is valid for
 *  all non-complex data types.
 *
 *  @return  psVector*     Pointer to sorted psVector.
 */
psVector* psVectorSort(
    psVector* outVector,               ///< the output vector to recycle, or NULL if new vector desired.
    const psVector* inVector           ///< the vector to sort.
);

/** Creates an array of indices based on sort ordered of array.
 *
 *  Sorts a vector and creates an integer array holding indices of
 *  sorted float values based on pre-sort index positions.
 *
 *  @return  psVector*     vector of the indices of sort.
 */
psVector* psVectorSortIndex(
    psVector* outVector,               ///< vector to recycle
    const psVector* inVector           ///< vector to sort
);

/** Creates a string from a psVector's values in the form "[x0,x1,x2]".
 *
 *  @return psPtr          a newly allocated string
 */
char* psVectorToString(
    psVector* vector,                  ///< vector to create a string from
    int maxLength                      ///< the maximum length of the resulting string
);

/** Returns an element in the vector as a psF64 value
 *
 *  @return psF64          the value at specified position, or NAN if position is invalid.
 */
psF64 p_psVectorGetElementF64(
    psVector* vector,                  ///< vector to retrieve element
    int position                       ///< the vector position to get
);

/** Print a vector to a stream
 *
 *  @return psBool          TRUE is successful, otherwise FALSE.
 */
bool p_psVectorPrint (
    int fd,                            ///< output file descriptor
    psVector *a,                       ///< vector to print
    char *name                         ///< name of vector (for title)
);

/** Initializes the vector with the given value.
 *
 *  The input data is cast to match the vector datatype, allowing for integers to be preserved.
 *
 *  @return bool:       True if successful, otherwise false.
 */
bool psVectorInit(
    psVector *vector,                  ///< the vector to be initialized
    ...                                ///< Variable argument list for initialization
);

/** Creates a new vector, or reallocates the provided vector if input is not NULL.
 *
 *  The created vector consists of the data range starting at lower, running to upper,
 *  in steps of delta.  The upper-end value is exclusive; the sequence is equivalent to
 *  for (x = lower; x <= upper - 1; x += delta).
 *
 *  @return psVector*:       the newly created psVector
 */
psVector *psVectorCreate (
    psVector *input,                   ///< Input vector
    double lower,                      ///< lower bound
    double upper,                      ///< upper bound
    double delta,                      ///< size of increment
    psElemType type                    ///< type of vector to create
);

/** Sets the value of the input vector at the specified position to value.
 *
 *  A negative position means index from the end.
 *
 *  @return bool:       True if successful, otherwise false.
 */
bool psVectorSet(
    const psVector *input,             ///< Input vector to set
    long position,                     ///< vector position
    double complex value               ///< value to set
);

/** Returns the value of the input vector at the specified position.
 *
 *  A negative position means index from the end.
 *
 *  @return complex:        Value of the input vector at the specified position.
 */
double complex psVectorGet(
    const psVector *input,             ///< Input vector from which to get value
    long position                      ///< vector position
);

/** Returns the number of pixels in the vector which satisfy any of the mask bits.
 *
 *  An error (eg, invalid vector) results in a return value of -1.  The vector must be U8.
 *
 *  @return long:       the number of pixels counted
 */
long psVectorCountPixelMask(
    psVector *mask,                    ///< input vector to count
    psMaskType value                   ///< the mask value to satisfy
);

/// @}

#endif // #ifndef PS_VECTOR_H
