/* Tuplex.h
 *
 * Interface definition for the Tuplex class, which is a 3x3 matrix with
 * standard matrix operations.
 */

#ifndef TUPLEX_H_INCLUDED
#define TUPLEX_H_INCLUDED 1

#include <iostream>
#include "Tuple.h"

class Tuplex
{
private:
	// Member variables
	Tuple r1_;
	Tuple r2_;
	Tuple r3_;

public:
	// Constructors/Destructor
	Tuplex();
	Tuplex(const Tuple x, const Tuple y, const Tuple z);
	Tuplex(const Tuplex& toCopy);
	virtual ~Tuplex();

 	// Operators
	Tuplex&			operator =	(const Tuplex& toCopy);
	const bool		operator ==	(const Tuplex& toCompare) const;
	const bool		operator !=	(const Tuplex& toCompare) const;
	const Tuplex	operator +	(const Tuplex& toAdd) const;
	Tuplex&			operator +=	(const Tuplex& toAdd);
	const Tuplex	operator -	() const;
	const Tuplex	operator -	(const Tuplex& toSub) const;
	Tuplex&			operator -=	(const Tuplex& toSub);
	const Tuplex	operator *	(const Tuplex& toMultiply) const;
	Tuplex&			operator *=	(double scaleFactor);	// unary scalar mult
	Tuplex&			operator /=	(double scaleFactor);	// unary scalar div

	// Accessors
	const Tuple&	r1() const				{return r1_;}
	const Tuple&	r2() const				{return r2_;}
	const Tuple&	r3() const				{return r3_;}
	const Tuple		c1() const
		{return Tuple(r1_.x(), r2_.x(), r3_.x());}
	const Tuple		c2() const
		{return Tuple(r1_.y(), r2_.y(), r3_.y());}
	const Tuple		c3() const
		{return Tuple(r1_.z(), r2_.z(), r3_.z());}
	void			setR1(const Tuple& r1)	{r1_ = r1;}
	void			setR2(const Tuple& r2)	{r2_ = r2;}
	void			setR3(const Tuple& r3)	{r3_ = r3;}
	void			setC1(const Tuple& c1)
		{r1_.setX(c1.x()); r2_.setX(c1.y()); r3_.setX(c1.z());}
	void			setC2(const Tuple& c2)
		{r1_.setY(c2.x()); r2_.setY(c2.y()); r3_.setY(c2.z());}
	void			setC3(const Tuple& c3)
		{r1_.setZ(c3.x()); r2_.setZ(c3.y()); r3_.setZ(c3.z());}
};

// More Operators
const Tuple		operator *	(const Tuplex& transform, const Tuple& toMultiply);
const Tuple		operator *	(const Tuple& toMultiply, const Tuplex& transform);
const Tuplex	operator *	(const Tuplex& toMultiply, const double& scaleFactor);
const Tuplex	operator *	(const double& scaleFactor, const Tuplex& toMultiply);
const Tuplex	operator /	(const Tuplex& toDivide, const double& scaleFactor);
std::ostream&	operator <<	(std::ostream &out_file, const Tuplex& theTuple);

#endif // TUPLEX_H_INCLUDED
