/* Vector manipulation code V1.71 16/06/07
   See vec.h for docs
   Copyright 2008 Jeffrey Lee
   This file is part of WOUM.
   WOUM is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
   WOUM is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   You should have received a copy of the GNU General Public License
   along with WOUM.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef _VEC_C
#define _VEC_C

#include <math.h>
#include "vec.h"
#include "fixconv.h"

/* Name of vector structure */
#define NAME vec
/* Type of numbers it contains */
#define TYPE float
#include "vecmain.c"
#undef NAME
#undef TYPE

#define NAME vec16
#define TYPE f1616
#include "vecmain.c"
#undef NAME
#undef TYPE

#define NAME vec24
#define TYPE f248
#include "vecmain.c"
#undef NAME
#undef TYPE

#define NAME vec20
#define TYPE f2012
#include "vecmain.c"
#undef NAME
#undef TYPE

#define NAME vec48
#define TYPE f4816
#include "vecmain.c"
#undef NAME
#undef TYPE

/* Floating point versions of fast moveto* routines
   Actually just wrap onto the slow ones */
void vec_fmovetox(const vec *a,const vec *b,float dest,vec *c)
{
	vec d;
	*c = *a;
	d.x = a->x - b->x;
	d.y = a->y - b->y;
	d.z = a->z - b->z;
	vec_movetox(c,&d,dest,1/d.x);
}

void vec_fmovetoy(const vec *a,const vec *b,float dest,vec *c)
{
	vec d;
	*c = *a;
	d.x = a->x - b->x;
	d.y = a->y - b->y;
	d.z = a->z - b->z;
	vec_movetoy(c,&d,dest,1/d.x);
}

void vec_fmovetoz(const vec *a,const vec *b,float dest,vec *c)
{
	vec d;
	*c = *a;
	d.x = a->x - b->x;
	d.y = a->y - b->y;
	d.z = a->z - b->z;
	vec_movetoz(c,&d,dest,1/d.x);
}

/* Floating point versions of pmoveto* routines */
void vec_pmovetox(const vec *a,const vec *b,int neg,vec *c)
{
	vec d;
	int steps;
	steps = 156; /* 7 bit exponent in floating point numbers+24 bit precision */
	*c = *a; /* C is the new A */
	/* Calc D */
	d.x = b->x-c->x; d.y = b->y-c->y; d.z = b->z-c->z;
	/* Flip if sign says so */
	if (neg)
	{
		c->x = -c->x;
		d.x = (-b->x)-c->x;
	}
	/* Add 0.5 D */
	d.x /= 2; d.y /= 2; d.z /= 2;
	c->x += d.x; c->y += d.y; c->z += d.z;
	/* Flip D if dz-dx<0 */
	if (d.z-d.x < 0)
	{
		d.x = -d.x; d.y = -d.y; d.z = -d.z;
	}
	while (steps--)
	{
		d.x /= 2; d.y /= 2; d.z /= 2;
		if (c->x < c->z)
		{
			c->x -= d.x; c->y -= d.y; c->z -= d.z;
		}
		else if (c->x > c->z)
		{
			c->x += d.x; c->y += d.y; c->z += d.z;
		}
		else
			break; /* Reached targ */
	}
	if (neg)
		c->x = -c->z; /* Clamp to negative value */
	else
		c->x = c->z; /* Clamp to positive value */
}

void vec_pmovetoy(const vec *a,const vec *b,int neg,vec *c)
{
	vec d;
	int steps;
	steps = 156; /* 7 bit exponent in floating point numbers+24 bit precision */
	*c = *a; /* C is the new A */
	/* Calc D */
	d.x = b->x-c->x; d.y = b->y-c->y; d.z = b->z-c->z;
	/* Flip if sign says so */
	if (neg)
	{
		c->y = -c->y;
		d.y = (-b->y)-c->y;
	}
	/* Add 0.5 D */
	d.x /= 2; d.y /= 2; d.z /= 2;
	c->x += d.x; c->y += d.y; c->z += d.z;
	/* Flip D if dz-dy<0 */
	if (d.z-d.y < 0)
	{
		d.x = -d.x; d.y = -d.y; d.z = -d.z;
	}
	while (steps--)
	{
		d.x /= 2; d.y /= 2; d.z /= 2;
		if (c->y < c->z)
		{
			c->x -= d.x; c->y -= d.y; c->z -= d.z;
		}
		else if (c->y > c->z)
		{
			c->x += d.x; c->y += d.y; c->z += d.z;
		}
		else
			break; /* Reached targ */
	}
	if (neg)
		c->y = -c->z; /* Clamp to negative value */
	else
		c->y = c->z; /* Clamp to positive value */
}

#endif
