
#ifndef SPECTRE_MATH_MATRIX3_H
#define SPECTRE_MATH_MATRIX3_H

// 3x3 matrix implementation.

#include <iostream>
#include <Spectre/Math/Vector2.h>

template<typename T>
struct Matrix3
{
	// Column-major order are used for the matrices here to be compatible with OpenGL.
	union {
		T m[3][3]; // format: [col][row]

		/* Indicies to use for accessing elements.
		  _     _
	     |       |
	     | 0 3 6 |
	     | 1 4 7 |
	     | 2 5 8 |
	     |_     _|
		*/
		T v[9];
	};

	static Matrix3<T> Identity;


	inline Matrix3();

	inline Matrix3( T a, T b, T c, 
			T d, T e, T f, 
			T g, T h, T i);

	inline Matrix3(T *a);

	// -----------------
	// Copy & Assignment.
	// -----------------

	inline Matrix3<T>& operator=(const Matrix3<T>& mat);

	// -----------------
	// Compare
	// -----------------

	inline bool operator==(const Matrix3<T>& mat) const;
	inline bool operator!=(const Matrix3<T>& mat) const;

	// -----------------
	// Arithmetic: Matrix-Matrix
	// -----------------

	inline Matrix3<T> operator*(const Matrix3<T>& mat) const;
	inline Matrix3<T> operator*=(const Matrix3<T>& mat);

	// Need scalar, vector arithmetic?

	// -----------------
	// Named operations.
	// -----------------

	// Determinant.
	float det() const;

	// Transpose matrix.
	Matrix3<T> transpose() const;
};

template <typename T>
inline std::ostream& operator<<(std::ostream &s, const Matrix3<T>& v);

typedef Matrix3<float>		Matrix3f;
typedef Matrix3<double>		Matrix3d;
typedef Matrix3<int>		Matrix3i;
typedef Matrix3<unsigned>	Matrix3u;

#include "Matrix3.inl"

#endif /* SPECTRE_MATH_MATRIX3_H */