/** @file  psComments.h
 *
 *  This file will hold definitions of various constants as well as common
 *  macros used throughout psLib.
 *
 *  @author GLG, MHPCC
 *
 *  @version $Revision: 1.12 $ $Name: not supported by cvs2svn $
 *  @date $Date: 2004-10-14 23:43:12 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
 */

#define DETERMINE_BRACKET_STEP_SIZE 0.10
#define MAX_LMM_ITERATIONS 100
#define MAX_MINIMIZE_ITERATIONS 100
#define LEFT_SPLINE_DERIV 0.0
#define RIGHT_SPLINE_DERIV 0.0

#define CONVERT_VECTOR_F64_TO_F32(OLD, NEW_PTR32, NEW_STATIC32) \
if (OLD->type.type == PS_TYPE_F32) { \
    NEW_PTR32 = (psVector *) OLD; \
} else if (OLD->type.type == PS_TYPE_F64) { \
    NEW_STATIC32 = psVectorRecycle(NEW_STATIC32, OLD->n, PS_TYPE_F32); \
    p_psMemSetPersistent(NEW_STATIC32, true); \
    p_psMemSetPersistent(NEW_STATIC32->data.V, true); \
    for (i=0; i < OLD->n ; i++) { \
        NEW_STATIC32->data.F32[i] = (float) OLD->data.F64[i]; \
    } \
    NEW_PTR32 = NEW_STATIC32; \
} \

#define CONVERT_VECTOR_F32_TO_F64(OLD, NEW_PTR64, NEW_STATIC64) \
if (OLD->type.type == PS_TYPE_F64) { \
    NEW_PTR64 = (psVector *) OLD; \
} else if (OLD->type.type == PS_TYPE_F32) { \
    NEW_STATIC64 = psVectorRecycle(NEW_STATIC64, OLD->n, PS_TYPE_F64); \
    p_psMemSetPersistent(NEW_STATIC64, true); \
    p_psMemSetPersistent(NEW_STATIC64->data.V, true); \
    for (i=0; i < OLD->n ; i++) { \
        NEW_STATIC64->data.F64[i] = (double) OLD->data.F32[i]; \
    } \
    NEW_PTR64 = NEW_STATIC64; \
} \

#define VECTOR_CHECK_TYPE_F32_OR_F64_RETURN_NULL(VEC) \
if ((VEC->type.type != PS_TYPE_F32) && (VEC->type.type != PS_TYPE_F64)) { \
    psAbort(__func__, "Bad type for VEC (%d)", VEC->type.type); \
    return(NULL); \
} \

#define GEN_PERSIST_YERR_VEC_F32(VEC, N) \
VEC = psVectorRecycle(VEC, N, PS_TYPE_F32); \
p_psMemSetPersistent(VEC, true); \
p_psMemSetPersistent(VEC->data.V, true); \
for (int i=0;i<N;i++) { \
    VEC->data.F32[i] = 1.0; \
} \

#define GEN_PERSIST_YERR_VEC_F64(VEC, N) \
VEC = psVectorRecycle(VEC, N, PS_TYPE_F64); \
p_psMemSetPersistent(VEC, true); \
p_psMemSetPersistent(VEC->data.V, true); \
for (int i=0;i<N;i++) { \
    VEC->data.F64[i] = 1.0; \
} \

#define GEN_PERSIST_X_INDEX_VEC_F32(VEC, N) \
VEC = psVectorRecycle(VEC, N, PS_TYPE_F32); \
p_psMemSetPersistent(VEC, true); \
p_psMemSetPersistent(VEC->data.V, true); \
for (int i=0;i<N;i++) { \
    VEC->data.F32[i] = (float) i; \
} \

#define GEN_PERSIST_X_INDEX_VEC_F64(VEC, N) \
VEC = psVectorRecycle(VEC, N, PS_TYPE_F64); \
p_psMemSetPersistent(VEC, true); \
p_psMemSetPersistent(VEC->data.V, true); \
for (int i=0;i<N;i++) { \
    VEC->data.F64[i] = (float) i; \
} \

#define GEN_STATIC_RECYCLED_VECTOR(NAME, SIZE, TYPE) \
static psVector *NAME = NULL; \
NAME = psVectorRecycle(NAME, SIZE, TYPE); \
p_psMemSetPersistent(NAME, true); \
p_psMemSetPersistent(NAME->data.V, true); \






/** Preprocessor macro to generate error on an incorrect type */
#define PS_CHECK_VECTOR_TYPE_RETURN_NULL(NAME, TYPE) \
if (NAME->type.type != TYPE) { \
    psError(__func__,"Unallowable operation: %s has incorrect type.", #NAME); \
    return(NULL); \
}

/** Preprocessor macro to generate error on a NULL vector */
#define PS_CHECK_NULL_VECTOR_RETURN_NULL(NAME) \
if (NAME == NULL || NAME->data.V == NULL) { \
    psError(__func__,"Unallowable operation: %s or its data is NULL.", #NAME); \
    return(NULL); \
} \

/** Preprocessor macro to generate error on a NULL poniter */
#define PS_CHECK_NULL_PTR_RETURN_NULL(NAME) \
if (NAME == NULL) { \
    psError(__func__,"Unallowable operation: %s is NULL.", #NAME); \
    return(NULL); \
}
/** Preprocessor macro to generate error on a NULL poniter */
#define PS_CHECK_NULL_PTR_RETURN_ZERO(NAME) \
if (NAME == NULL) { \
    psError(__func__,"Unallowable operation: %s is NULL.", #NAME); \
    return(0); \
}

/** Preprocessor macro to generate error for zero length vector */
#define PS_CHECK_EMPTY_VECTOR_RETURN_NULL(NAME) \
if (NAME->n < 1) { \
    psError(__func__,"Unallowable operation: %s has zero n value.", #NAME); \
    return(NULL); \
} \

/** Preprocessor macro to generate error on differing size vectors */
#define PS_CHECK_VECTOR_SIZE_EQUAL_RETURN_NULL(VEC1, VEC2) \
if (VEC1->n != VEC2->n) { \
    psError(__func__,"Vector %s has size %d, Vector %s has size %d.", #VEC1, VEC1->n, #VEC2, VEC2->n); \
    return(NULL); \
}

/** Preprocessor macro to generate error on differing size vectors */
#define PS_CHECK_VECTOR_SIZE_EQUAL_RETURN_NULL(VEC1, VEC2) \
if (VEC1->n != VEC2->n) { \
    psError(__func__,"Vector %s has size %d, Vector %s has size %d.", #VEC1, VEC1->n, #VEC2, VEC2->n); \
    return(NULL); \
}

/** Preprocessor macro to generate error on a NULL image */
#define PS_CHECK_NULL_IMAGE_RETURN_NULL(NAME) \
if (NAME == NULL || NAME->data.V == NULL) {                                                         \
    psError(__func__,"Unallowable operation: %s or its data is NULL.", #NAME);                          \
    return(NULL); \
}

/** Preprocessor macro to generate error for zero length rows or columns */
#define PS_CHECK_EMPTY_IMAGE_RETURN_NULL(NAME) \
if (NAME->numCols < 1 || NAME->numRows < 1) {                                                       \
    psError(__func__,"Unallowable operation: %s has zero rows or columns (%dx%d).", #NAME,              \
            NAME->numCols, NAME->numRows);                                                          \
    return(NULL); \
}

#define PS_CHECK_IMAGE_TYPE_RETURN_NULL(NAME, TYPE) \
if (NAME->type.type != TYPE) { \
    psError(__func__,"Unallowable operation: %s has incorrect type.", #NAME); \
    return(NULL); \
}

/** Preprocessor macro to generate error on a NULL image */
#define PS_CHECK_NULL_IMAGE_READOUT_NULL(NAME) \
if (NAME == NULL || NAME->image == NULL) {                                                         \
    psError(__func__,"Unallowable operation: %s or its data is NULL.", #NAME);                          \
    return(NULL); \
}

#define PS_CHECK_NULL_1DPOLY_RETURN_NULL(NAME)                                                          \
if (NAME == NULL || NAME->coeff == NULL) {                                                         \
    psError(__func__,"Unallowable operation: %s or its coeffs is NULL.", #NAME);                          \
    return(NULL); \
} \





#define PS_PRINT_VECTOR(NAME) \
for (int my_i=0;my_i<NAME->n;my_i++) { \
    printf("%s->data.F32[%d] is %f\n", #NAME, my_i, NAME->data.F32[my_i]); \
} \
printf("\n"); \

#define PS_VECTOR_F64_TO_F32(X64, X32) \
psVector *X32 = psVectorAlloc(X64->n, PS_TYPE_F32); \
for (int i=0;i<X64->n;i++) { \
    X32->data.F32[i] = (float) X64->data.F64[i]; \
} \

#define PS_VECTOR_F32_TO_F64(X32, X64) \
psVector *X64 = psVectorAlloc(X32->n, PS_TYPE_F64); \
for (int i=0;i<X32->n;i++) { \
    X64->data.F64[i] = (float) X32->data.F32[i]; \
} \


#define PS_MAX(A, B) \
((A > B) ? A : B) \

#define PS_MIN(A, B) \
((A < B) ? A : B) \

