// -*- Mode: c++ -*-
// $Id: float2.H,v 1.2 1998/02/11 03:46:41 neel Exp $
// $Source: /u2/graphics/projects/6.838/gvis/gprims/float2.H,v $

#ifndef	__FLOAT2_H__
#define	__FLOAT2_H__

static char
__rcs_ref_float2_h( void )
{
  static char rcs_id_h[] = "$Header: /u2/graphics/projects/6.838/gvis/gprims/float2.H,v 1.2 1998/02/11 03:46:41 neel Exp $";
  return rcs_id_h[0];
}
// Do not change anything above this line
static char avoid_stupid_compiler_warnings24 = __rcs_ref_float2_h();

#include <assert.h>
#include <math.h>
#include "utils.H"

class ostream;
class istream;

class Float2;

typedef Float2   Point2;
typedef Float2   Vector2;

// A general 2vector class.
class Float2{

  // constructors
public:
  Float2          ( void ) {}
  Float2          ( const Float2& c ) { v[X] = c.v[X], v[Y] = c.v[Y]; }
  Float2          ( const float a, const float b ) { v[X] = a, v[Y] = b; }
  Float2          ( const float* a )  { v[X] = a[X], v[Y] = a[Y]; }
  Float2          ( const double* a ) { v[X] = a[X], v[Y] = a[Y]; }

  // operators
public:
  operator float*( void ) { return &v[X]; }
  operator const float*( void ) const  { return &v[X]; }
  ~Float2( void ) {}
  
  friend istream& operator>>( istream&, Float2& );
  friend ostream& operator<<( ostream&, const Float2& );
  void print( ostream& os ) const;
  
  Float2& operator=( const Float2& c )
    { v[X] = c.v[X], v[Y] = c.v[Y]; return *this; }

  Float2 operator+( const Float2& c ) const
    { return Float2( v[X] + c.v[X], v[Y] + c.v[Y] ); }

  Float2 operator-( const Float2& c ) const
    { return Float2( v[X] - c.v[X], v[Y] - c.v[Y] ); }

  Float2 operator*( const float s ) const
    { return Float2( s * v[X], s * v[Y] ); }

  friend Float2 operator*( const float s, const Float2& c )
    { return Float2( s * c.v[X], s * c.v[Y] ); }

  Float2 operator/( const float s ) const
    { return Float2( v[X] / s, v[Y] / s ); }
  
  Float2& operator+=( const Float2& c )
    { v[X] += c.v[X], v[Y] += c.v[Y]; return *this; }

  Float2& operator-=( const Float2& c ) 
    { v[X] -= c.v[X], v[Y] -= c.v[Y]; return *this; }

  Float2& operator*=( const float s ) { v[X] *= s, v[Y] *= s; return *this; }

  Float2& operator/=( const float s ) { v[X] /= s, v[Y] /= s; return *this; }

  Float2 operator-( void ) const { return Float2( -v[X], -v[Y] ); }

  int operator==( const Float2& o ) const
    { return ZERO( v[X] - o.v[X] ) && ZERO( v[Y] - o.v[Y] ); }
  

  // accessors
public:
  float&          x          ( void )         { return v[X]; }
  float           x          ( void )         const { return v[X]; }
  float&          y          ( void )         { return v[Y]; }
  float           y          ( void )         const { return v[Y]; }
  
  // numerical / geometric utilities
public:
  float      dot           ( const Float2& c ) const 
  { return v[X] * c.v[X] + v[Y] * c.v[Y]; }
  
  float      dot           ( void ) const 
  { return v[X] * v[X] + v[Y] * v[Y]; }
  
  float      length        ( void ) const 
  { return sqrtf( dot() ); }

  // normalize, return 1 iff successful
  int        normalize     ( void )
  { float mag = length(); return ZERO( mag ) ? 0 : ( *this *= 1 / mag, 1 ); }
  
  Float2     dir           ( void ) const
  { float a = length(); return *this * ( ZERO( a ) ? 1 : 1 / a ); }
  
  float      dist          ( const Float2& c ) const 
  { return ( *this - c ).length(); }
  
private:
  float	v[2];
};

#endif	/* __FLOAT2_H__ */




