#include <math.h>
#include <stdlib.h>
#include "gpklib/assert.h"
#include "gpklib/v2.h"
#include "gpklib/ltrans.h"
#include "gpklib/ieee754.h"

ostream& operator<<(ostream& s, C vector2& a)
{
 if(a.ok())	{
 	s << "[" << a(0) << ',' << a(1);
	if(a.space() != 0)
		s << " in " << a.space()->name;
	s << "]";
 	}
 else
 	s << "[ NO GOOD ]";

 return s;
}

double vector2::norm() C	{assert(ok()); return hypot(d[0], d[1]);}
double vector2::max() C
{assert(ok()); return fabs(d[0])>fabs(d[1]) ? fabs(d[0]) : fabs(d[1]);}

vector2 vector2::unitvec(double angle)
{
 return vector2(cos(angle), sin(angle));
}

vector2 normalize(C vector2& a)
{
 C double d = hypot(a(0), a(1));
 return vector2(a(0)/d, a(1)/d, a.space());
}

#include <string.h>

vector_space::vector_space(C char *nm, C ltransform *tob)
 : name(nm ? (char *)malloc(strlen(nm)+1) : 0), tobase(tob)
{
 assert(!tob || vector_space::vseQ(tob->Center().space(), this));
 if(name)
 	strcpy(name, nm);
}

vector_space::vector_space(C ltransform *tob)
 : name(0), tobase(tob)
{
 assert(!tob || vector_space::vseQ(tob->Center().space(), this));
}

C vector_space vector_space::bad("Bad Vector");

vector2& vector2::operator+=(C vector2& a)
{ d[0] += a(0); d[1] += a(1);
		vs = vector_space::vseq(vs, a.vs);
		return *this;}


vector2& vector2::operator-=(C vector2& a)
{ d[0] -= a(0); d[1] -= a(1);
		vs = vector_space::vseq(vs, a.vs);
		return *this;}

BOOL vector_space::vseQ(C vector_space *a, C vector_space *b)
		{ return vsok(vseq(a, b));}

#include <string.h>

vector_space::vector_space(C vector_space& a)
 : name(a.name ? (char *)malloc(strlen(a.name)+1) : 0), tobase(a.tobase)
{
 if(name)	strcpy(name, a.name);
}



vector_space& vector_space::operator=(C vector_space& a)
{
 if(name)	free(name);
 name = a.name ? (char *)malloc(strlen(a.name)+1) : 0;
 if(name)
 	strcpy(name, a.name);
 tobase = a.tobase;
 assert(!tobase || vector_space::vseQ(tobase->Center().space(), this));
 return *this;
}



vector_space& vector_space::set_name(C char *nm)
{
 assert(!name);
 name = (char *)malloc(strlen(nm)+1);
 if(name)
 	strcpy(name, nm);
 return *this;
}


vector_space::~vector_space()
{
 if(name) free(name);
}


double angle(C vector2& a)
{ return atan2(a(0), a(1)); }



vector2::vector2()
: vs(&vector_space::bad)
{d[0] = d[1] = quiet_nan(0);}



int finite(C vector2& a)
{
 return finite(a(0)) && finite(a(1));
}
