#if !defined (PS_MATH_H)
#define PS_MATH_H

/** \file psMath.h
 *  \brief math operators between PSLib data types
 *  \ingroup MathGroup
 */

/** private structure used to pass constant values into the math operators. */
typedef struct {
    psType type;			///< data type information
    union {			       
        psS8   S8;                      ///< bye value entry
        psS16 S16;                      ///< short int value entry
        psU8   U8;                      ///< unsigned byte value entry
        psU16 U16;                      ///< unsigned short int value entry
        psF32 F32;                      ///< float value entry
        psF64 F64;                      ///< double value entry
        psC32 C32;                      ///< complex value entry
        psC64 C64;                      ///< double complex value entry
    } data;
} p_psScalar;

/** Functions **************************************************************/
/** \addtogroup MathGroup Math Utilities
 *  \{
 */

/** Scalar constructor */
psScalar *psScalarAlloc(psC64 value,	///< Value to set
			psElemType dataType ///< Data type
    );

/** Copy a scalar */
psScalar *psScalarCopy(psScalar *value	///< Scalar to copy
    );

/** Perform a binary operation on two data items (psImage, psVector, psScalar). */
psType *
psBinaryOp (void *out,			///< destination (may be NULL) 
	    void *in1,			///< first input
	    char *op,			///< operator 
	    void *in2)			///< second input
;

/** Perform a unary operation on two data items (psImage, psVector, psScalar). */
psType *
psUnaryOp (void *out,			///< destination (may be NULL) 
	   void *in,			///< input
	   char *op)			///< operator 
;

/* \} */ // End of MathGroup Functions

/** the functions defined here can operate on the basic PSLib data types: psImage, psVector, XXX.  These data
 *  types include embedded information about their type in the structure.  Constant values are handled by
 *  wrapping the value in the psScalar function, which returns a private scalar data type, p_ps_Scalar, which
 *  is always freed by the function.  The return value type can be determined by casting the return to psType
 *  and checking the type entry.  
 */

/* examples of usage:

psImage A, B, C;
psVector X, Y;

calculate C = sin(A^2)

B = psBinaryOp (NULL, A, "^", psScalar(2));
C = psUnaryOp (NULL, B, "sin");
psFree (B);

calculate Y = X^2

Y = psBinaryOp (NULL, Y, "^", psScalar(2));

Y = psBinaryOp (NULL, A, "^", X);

Y = psBinaryOp (NULL, A, "^", psVectorTranspose(X));

psFree (B);

*/

#endif

/** allowed operators for the different image functions 

    PS_BINARY_ADD        = "+", 
    PS_BINARY_SUBTRACT   = "-", 
    PS_BINARY_MULTIPLY   = "*", 
    PS_BINARY_DIVIDE     = "/", 
    PS_BINARY_POWER      = "^", 
    PS_BINARY_MIN, 
    PS_BINARY_MAX, 
    PS_BINARY_LESSTHAN   = "<", 
    PS_BINARY_MORETHAN   = ">", 
    PS_BINARY_ISEQUAL    = "==", 
    PS_BINARY_NOTEQUAL   = "!=", 
    PS_BINARY_LESSOREQ   = "<=", 
    PS_BINARY_MOREOREQ   = ">=", 
    PS_BINARY_AND        = "&&", 
    PS_BINARY_OR         = "||", 
    PS_BINARY_BITAND     = "&", 
    PS_BINARY_BITOR      = "|", 
    PS_BINARY_XOR        = "~", 
    PS_BINARY_ATAN2      = "atan2", 
    PS_BINARY_MODULO     = "%"

    -- all valid for complex types


    PS_UNARY_IS     = "=", 
    PS_UNARY_ABS,
    PS_UNARY_INT,
    PS_UNARY_EXP,
    PS_UNARY_TEN,
    PS_UNARY_LOG,
    PS_UNARY_LN,
    PS_UNARY_SQRT,
    PS_UNARY_SIN,
    PS_UNARY_COS,
    PS_UNARY_TAN,
    PS_UNARY_DSIN,
    PS_UNARY_DCOS,
    PS_UNARY_DTAN,
    PS_UNARY_ASIN,
    PS_UNARY_ACOS,
    PS_UNARY_ATAN,
    PS_UNARY_DASIN,
    PS_UNARY_DACOS,
    PS_UNARY_DATAN,
    PS_UNARY_RND,
    PS_UNARY_NOT,
    PS_UNARY_NEGATE = "-",
    PS_UNARY_INCR,
    PS_UNARY_DECR,
    PS_UNARY_ISINF,
    PS_UNARY_ISNAN
    PS_UNARY_MOD,   // specific to complex data types
    PS_UNARY_CONJ,  // specific to complex data types
    PS_UNARY_ARG,   // specific to complex data types
**/
