/***************************************************************
 * PrVector3.h
 *
 * This class provides a 3x1 vector.
 *
 ****************************************************************/

/*
 * modification history
 *----------------------
 *
 * 11/20/97: K.C. Chang: added inline methods.
 * 11/05/97: K.C. Chang: created.
 */

#ifndef _PrVector3_h
#define _PrVector3_h

#include "PrGlobalDefn.h"
#include <assert.h>

class PrMatrix3;

class PrVector3
{
  public:
    PrVector3();   // initialized to [0,0,0]
    PrVector3(const PrVector3 &v);
    PrVector3(Float x,Float y,Float z);
    ~PrVector3() {}

    PrVector3 &operator=(const PrVector3 &v);

    Float &operator[](int i);
    const Float &operator[](int i) const;

    Float &elementAt(int i);
    const Float &elementAt(int i) const;

    PrVector3 operator-() const;
    void negate(PrVector3 &res) const;

    PrVector3 operator+(const PrVector3 &v) const;
    void add(const PrVector3 &v,PrVector3 &res) const;

    PrVector3 operator-(const PrVector3 &v) const;
    void subtract(const PrVector3 &v,PrVector3 &res) const;

    PrVector3 operator*(Float s) const;
    void multiply(Float s,PrVector3 &res) const;

    PrVector3 operator*(const PrVector3 &v) const;
    void multiply(const PrVector3 &v,PrVector3 &dest) const;

    PrVector3 &operator+=(const PrVector3 &v);
    PrVector3 &operator-=(const PrVector3 &v);
    PrVector3 &operator*=(Float s);

    PrMatrix3 multiplyTransposed(const PrVector3 &v) const;
    void multiplyTransposed(const PrVector3 &v,PrMatrix3 &res) const;

    Float dot(const PrVector3 &v) const;

    PrVector3 cross(const PrVector3 &v) const;
    void cross(const PrVector3 &v,PrVector3 &res) const;

    PrMatrix3 cross() const;
    void cross(PrMatrix3 &res) const;

    Float magnitude() const;

    void normalize();

    inline void values(Float x,Float y,Float z);

    void display(char *name=NULL);

  private:
    Float data_[3];
};

// inline methods

inline PrVector3::PrVector3()
{
    values(0.0,0.0,0.0);
}

inline PrVector3::PrVector3(Float x,Float y,Float z)
{
    values(x,y,z);
}

inline PrVector3::PrVector3(const PrVector3 &v)
{
    values(v.data_[0],v.data_[1],v.data_[2]);
}

inline PrVector3 &PrVector3::operator=(const PrVector3 &v)
{
    if (this != &v)
      {
	  data_[0] = v.data_[0];
	  data_[1] = v.data_[1];
	  data_[2] = v.data_[2];
      }
    return (*this);
}

inline Float &PrVector3::operator[](int i)
{
    assert(i>=0 && i<3);
    return data_[i];
}

inline const Float &PrVector3::operator[](int i) const
{
    assert(i>=0 && i<3);
    return data_[i];
}

inline void PrVector3::values(Float x,Float y,Float z)
{
    data_[0] = x;
    data_[1] = y;
    data_[2] = z;
}

inline Float &PrVector3::elementAt(int i)
{
    assert(i>=0 && i<3);
    return data_[i];
}

inline const Float &PrVector3::elementAt(int i) const
{
    assert(i>=0 && i<3);
    return data_[i];
}

#endif // _PrVector3_h
