#ifndef MATHLIB_H
#define MATHLIB_H
/* mathlib.h */
#ifdef	HAVE_MATH_H
# include <math.h>
#endif

/*
#ifndef	HAVE_SCALW
#ifdef	HAVE_SCALB
#define	scalw(x, y)	scalb((x), (y))
#else
#define	scalw(x, y)	(((y) >= 0) ? ((x) * (1 << (y))) : ((x) / (1 << (-(y)))))
#endif
#endif
 */

typedef float vec_t;
typedef vec_t vec3_t[3];

#define	SIDE_FRONT		0
#define	SIDE_ON			2
#define	SIDE_BACK		1
#define	SIDE_CROSS		-2

#define	Q_PI	3.14159265358979323846

#define	EQUAL_EPSILON	0.001

#define VectorCompare(v1, v2) (((v1[0] != v2[0]) || (v1[1] != v2[1]) || (v1[2] != v2[2])) ? 0 : 1)
#define VectorZero(v1) ((v1[0] == 0) && (v1[1] == 0) && (v1[2] == 0))

#define DotProduct(x,y) (x[0]*y[0]+x[1]*y[1]+x[2]*y[2])
#define VectorSubtract(a,b,c) {c[0]=a[0]-b[0];c[1]=a[1]-b[1];c[2]=a[2]-b[2];}
#define VectorAdd(a,b,c) {c[0]=a[0]+b[0];c[1]=a[1]+b[1];c[2]=a[2]+b[2];}
#define VectorCopy(a,b) {b[0]=a[0];b[1]=a[1];b[2]=a[2];}
#define VectorClear(x) {x[0] = x[1] = x[2] = 0;}
#define	VectorNegate(x) {x[0]=-x[0];x[1]=-x[1];x[2]=-x[2];}
#define	VectorNegateTo(x, y) {y[0]=-x[0];y[1]=-x[1];y[2]=-x[2];}
#define	VectorAbs(x) {fabs(x[0]);fabs(x[1]);fabs(x[2]);}

#define _DotProduct DotProduct
#define _VectorSubtract VectorSubtract
#define _VectorAdd VectorAdd
#define _VectorCopy VectorCopy

#define VectorLength(v) (sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]))
#define VectorDist(v) (v[0]*v[0] + v[1]*v[1] + v[2]*v[2])

void VectorMA(vec3_t veca, double scale, vec3_t vecb, vec3_t vecc);
void CrossProduct(vec3_t v1, vec3_t v2, vec3_t cross);
vec_t VectorNormalize(vec3_t v);

extern inline void VectorMA(vec3_t veca, double scale, vec3_t vecb, vec3_t vecc)
{
  vecc[0] = veca[0] + scale * vecb[0];
  vecc[1] = veca[1] + scale * vecb[1];
  vecc[2] = veca[2] + scale * vecb[2];
}

extern inline void CrossProduct(vec3_t v1, vec3_t v2, vec3_t cross)
{
  cross[0] = v1[1] * v2[2] - v1[2] * v2[1];
  cross[1] = v1[2] * v2[0] - v1[0] * v2[2];
  cross[2] = v1[0] * v2[1] - v1[1] * v2[0];
}

extern inline vec_t VectorNormalize(vec3_t v)
{
  vec_t len = VectorLength(v);

  if (len) {
    v[0] /= len;
    v[1] /= len;
    v[2] /= len;
  }
  return len;
}

#define VectorInverse(v) {v[0] = -v[0]; v[1] = -v[1]; v[2] = -v[2];}
#define VectorScale(in, scale, out) {out[0] = in[0] * scale; out[1] = in[1] * scale; out[2] = in[2] * scale;}
#endif
