/** @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.35 $ $Name: not supported by cvs2svn $
 *  @date $Date: 2005-06-10 21:46:46 $
 *
 *  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
/// @{

///< Union of psVector data types.
typedef union {
    psU8* U8;               ///< Unsigned 8-bit integer data.
    psU16* U16;             ///< Unsigned 16-bit integer data.
    psU32* U32;             ///< Unsigned 32-bit integer data.
    psU64* U64;             ///< Unsigned 64-bit integer data.
    psS8* S8;               ///< Signed 8-bit integer data.
    psS16* S16;             ///< Signed 16-bit integer data.
    psS32* S32;             ///< Signed 32-bit integer data.
    psS64* S64;             ///< Signed 64-bit integer data.
    psF32* F32;             ///< Single-precision float data.
    psF64* F64;             ///< Double-precision float data.
    psC32* C32;             ///< Single-precision complex data.
    psC64* C64;             ///< Double-precision complex data.
} p_psVectorData;

/** An vector to support primitive types.
 *
 * Struct for maintaining an vector of frequently used primitive types.
 *
 */
typedef struct
{
    psType type;                ///< Type of data.
    int n;                      ///< Number of elements in use.
    const int nalloc;           ///< Total number of elements available.
    p_psVectorData data;        ///< Union for data types.
}
psVector;

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

/* FUNCTION PROTOTYPES                                                       */

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


/** 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(
    psU32 nalloc,               ///< Total number of elements to make available.
    psElemType dataType                ///< 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* psVec,                   ///< Vector to reallocate.
    psU32 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
    int delta,                         ///< Amount to expand allocation, if necessary
    int 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* psVec,
    ///< Vector to recycle.  If NULL, a new vector is created.  No effort
    ///< taken to preserve the values.

    psU32 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* out,                     ///< if non-NULL, a psVector to recycle
    const psVector* in,                ///< 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 (
    FILE *f,                           ///< output stream
    psVector *a,                       ///< vector to print
    char *name                         ///< name of vector (for title)
);

/// @}

#endif // #ifndef PS_VECTOR_H
