/*
  vector2.c: C equivalent of:

  implementation class Vector2;

  double method magnitude() {                 // find the magnitude
      return sqrt(x*x+y*y);                   // (distance to origin)
  }
  double method distance_to(Vector2 p) {      // distance to a point
      double a = x - p.x;
      double b = y - p.y;
      return sqrt(a*a+b*b);
  }
  void method add( Vector2 v ) {              // this += v
      x += v.x;
      y += v.y;
  }
  void method scale( double n ) {             // this *= n
      x *= n;
      y *= n;
  }
  void method normalize() {                   // make a unit vector
      double m = magnitude();
      scale( 1/m ) unless m == 0 || m == 1;
  }
  void method print() {                       // display this vector
      printf( "[%.3f,%.3f]", x, y );
  }
*/

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>

#include "vector2.h"


static double magnitude( Vector2 this )
{
	double x = this->x;
	double y = this->y;
	return sqrt(x*x+y*y);
}

static double distance_to( Vector2 this, Vector2 v )
{
	double a = this->x - v->x;
	double b = this->y - v->y;
	return sqrt(a*a+b*b);
}

static void add( Vector2 this, Vector2 v ) {
	this->x += v->x;
	this->y += v->y;
}

static void scale( Vector2 this, double n ) {
	this->x *= n;
	this->y *= n;
}

static void normalize( Vector2 this ) {
	double m = OM0(this,magnitude);		// m = magnitude()
	if( m != 0.0 && m != 1.0 )
	{
		OM1(this, scale, 1.0/m);	// scale(1.0/m)
	}
}

static void print( Vector2 this )
{
	printf( "[%.3f,%.3f]", this->x, this->y );
}

static void dispose( Vector2 this ) {
	free( this );
}

Vector2 alloc_Vector2( void ) {
	Vector2 v = (Vector2) malloc( sizeof(struct Vector2) );
	assert( v != NULL );
	return v;
}

void init_Vector2( Vector2 v, double x, double y ) {
	v->isa          = "Vector2";
	v->x            = x==-1 ? 0 : x;        // implement default
	v->y            = y==-1 ? 0 : y;        // implement default
	v->magnitude    = &magnitude;
	v->distance_to  = &distance_to;
	v->add          = &add;
	v->scale        = &scale;
	v->normalize    = &normalize;
	v->print        = &print;
	v->dispose      = &dispose;
}

Vector2 new_Vector2( double x, double y ) {
	Vector2 v = alloc_Vector2();
	init_Vector2( v, x, y );
	return v;
}
