#ifndef V_TYPES_H
#define V_TYPES_H

/*
 * Limits.
 */
#if     !defined(MAXCHAR)
#define	MAXCHAR							(0x7F)
#define	MINCHAR							(0x80)
#endif  /* !MAXCHAR */
#if     !defined(MAXSHORT)
#define	MAXSHORT						0x7FFF
#define	MINSHORT						0x8000
#endif  /* !MAXSHORT */
#if     !defined(MAXLONG)
#define MAXLONG							(0x7FFFFFFF)
#define MINLONG							(0x80000000)
#endif  /* !MAXLONG */
#if     !defined(MAXLONGLONG) && !defined(INT64BROKEN)
#define MAXLONGLONG						0x7FFFFFFFFFFFFFFF
#define MINLONGLONG						0x8000000000000000
#endif  /* MAXLONGLONG */
#if     !defined(MAXFLOAT)
#define MAXFLOAT						3.4e+38
#endif  /* MAXFLOAT */
#if     !defined(MAXDOUBLE)
#define MAXDOUBLE						1.7e+308
#endif  /* MAXDOUBLE */

#ifndef	DOUBLEVEC
#define	MAXVEC							((vec_t)MAXFLOAT)
#else
#define	MAXVEC							((vec_t)MAXDOUBLE)
#endif	/* DOUBLEVEC */

/*
 * Upper limit for estimated fp round-off error (and for square of error)
 */
#ifndef	FLOAT_ZERO_EPSILON
#define	FLOAT_ZERO_EPSILON				1e-6
#endif	/* FLOAT_ZERO_EPSILON */
#ifndef	FLOAT_ZERO_EPSILON_SQUARE
#define	FLOAT_ZERO_EPSILON_SQUARE		1e-12
#endif	/* FLOAT_ZERO_EPSILON_SQUARE */

/*
 * Base LibV types.
 */
typedef unsigned char			u8_t,	*u8_p;
typedef signed char				s8_t,	*i8_p;
typedef unsigned short			u16_t,	*u16_p;
typedef signed short			s16_t,	*i16_p;
typedef unsigned long			u32_t,	*u32_p;
typedef signed long				s32_t,	*i32_p;
#ifndef	INT64BROKEN
#if		!defined(__UNIX__) && !defined(__CYGWIN32__)
typedef unsigned __int64		u64_t,	*u64_p;
typedef signed __int64			s64_t,	*i64_p;
#else
typedef unsigned long long int	u64_t,	*u64_p;
typedef long long int			s64_t,	*i64_p;
#endif	/* __UNIX__ */
#endif	/* INT64BROKEN */

/*
 * Pointers: void and string.
 * Note: char_t may be either signed (most platforms) or unsigned.
 */
typedef		void				void_t,	*void_p, **void_pp;
typedef		char				char_t, *char_p, **char_pp;

/*
 * Handle of LibV object. Returned by numerous factory functions.
 */
typedef		void				*vhandle_t;
#define		LIBV_INVALID_HANDLE	NULL

/*
 * Another one boolean type
 */
#if			!defined(__cplusplus) && defined(__WATCOMC__)
typedef		enum				{ false, true }	vboolean;
#else		/* !defined(__cplusplus) && defined(__WATCOMC__) */
typedef 	int					vboolean;
#define 	false				0
#define 	true				1
#endif		/* !defined(__cplusplus) && defined(__WATCOMC__) */

/*
 * Base floating-point scalar type.
 * Names of type and macro stolen from Quake.
 */
#ifdef		DOUBLEVEC
typedef		double				vec_t, *vec_p;
#else		/* !DOUBLEVEC */
typedef		float				vec_t, *vec_p;
#endif		/* DOUBLEVEC  */

/*
 *	NOTE: config macro MATRIX_DOUBLE controls precision of floatin-point
 *		any-order vector and matrix calculations. It is undependent
 * 		from DOUBLEVEC setting because such matrices are often used in
 *		scientific calculations, which requires extra precision.
 *
 *  05.05.2002: FIXME: remove mvec_t !
 */

#ifdef	MATRIX_DOUBLE
typedef	double					mvec_t;
#else
typedef	float					mvec_t;
#endif

typedef	mvec_t					*mvec_p;

/*
 * Vector and matrix types (low-order).
 * Values in matrices stored in row-major order (unlike in OpenGL)
 */
typedef vec_t					vec2_t[2];
typedef vec_t					vec3_t[3];
typedef vec_t					vec4_t[4];
typedef vec_t					matrix2_t[2][2];
typedef vec_t					matrix3_t[3][3];
typedef vec_t					matrix4_t[4][4];
typedef vec_t					matrix3x4_t[3][4];

/*
 * 24- & 32-bit RGBA colors.
 */
typedef u8_t					color3b_t[3];
typedef u8_t					color4b_t[4];

/*
 * Handy macros for making powers of 2.
 * TODO: move them to other file.
 */

/* Returns 1 if value is power of 2; otherwise returns 0 */
#define IS_POWER_TWO(x)			(((x) & ((x)-1)) ? 0 : 1)

/*
 * Aligns u32_t 'src', so:
 *	a) dst>=src;
 *	b) least 'zero_bits' in 'dst' set to zero.
 * For expample, if 'zero_bits' is 2: 0->0; {1,2,3,4}->4; etc.
 * 'dst' and 'src' can be the same.
 */

#define	ALIGN_UP(dst,src,zero_bits) { \
		u32_t set_bits=(1<<(zero_bits))-1; \
		(dst)=((src)+set_bits)&(0xFFFFFFFF-set_bits); }

/* Based on Quake's net_loop.c::IntAlign */
#define	INT_ALIGN(value) \
		(((value) + (sizeof(int) - 1)) & (~(sizeof(int) - 1)))

/* Sets retval to power of 2 which is not less than value */
/* TODO: There are better ways to do it ... */
#define	NOT_LESS_POWER_TWO(retval,value,type)\
		{\
			type mask;\
			if((value)==(type)0) {\
				retval=0;\
			} else {\
				mask=(type)1 << ((sizeof(type)<<3)-1);\
				while(!(mask & (value)))\
					mask>>=1;\
				retval = (mask < (value)) ? mask << 1 : mask;\
			}\
		}

/* Sets retval to power of 2 which is greater than value */
/* TODO: There are better ways to do it ... */
#define	GREATER_POWER_TWO(retval,value,type)\
		{\
			type mask;\
			if((value)==(type)0) {\
				retval=1;\
			} else {\
				mask=(type)1 << ((sizeof(type)<<3)-1);\
				while(!(mask & (value)))\
					mask>>=1;\
				retval = (mask <= (value)) ? mask << 1 : mask;\
			}\
		}

/*
 * Is this really needed - ?
 */
#define		SWAP_FOUR_BYTES(n)\
			((((u32_t)(n)<<24)&0xFF000000)|(((u32_t)(n)<<8)&0xFF0000)|\
			(((u32_t)(n)>>8)&0xFF00)|(((u32_t)(n)>>24)&0xFF))
#define 	SWAP_TWO_BYTES(n)\
			((((u16_t)(n)<<8)&0xFF00)|(((u16_t)(n)>>8)&0xFF))


#endif	/* V_TYPES_H */
