#ifndef GL_MATRIX_H
#define GL_MATRIX_H

#include <stdlib.h>
#include <math.h>
#include <vector.h>
#include <iostream.h>


// class of matrices .... to replace by stl....

class GL_Matrix
{
private:

  int Row, Col;
  int pivot (int row);

public:

  vector< vector < double > > Val;
  // Constructors
  GL_Matrix(const GL_Matrix& m);
  GL_Matrix(int row = 4, int col = 4);
  GL_Matrix( double a1, double a2,  double a3,  double a4,
	     double a5, double a6,  double a7,  double a8,
	     double a9, double a10, double a11, double a12 );

  // Destructor
  ~GL_Matrix();

  // Value extraction method
  int RowNo () { return Row; }
  int ColNO () { return Col; }

  // Subscript operator
  double& operator () (int row, int col = 0) ;

  // Unary operators
  GL_Matrix operator + ()  { return *this; };
  GL_Matrix operator - () ;

  // Assignment operators
  GL_Matrix& operator = (const GL_Matrix& m); 

  // Combined assignment - calculation operators
  GL_Matrix& operator += (const GL_Matrix& m); 
  GL_Matrix& operator -= (const GL_Matrix& m);
  GL_Matrix& operator *= (const GL_Matrix& m); 
  GL_Matrix& operator *= (const double& d);
  GL_Matrix& operator /= (const GL_Matrix& c); 
  GL_Matrix& operator /= (const double& c); 
  GL_Matrix& operator ^= (const int& pow); 

  // Logical operators
  friend bool operator == (const GL_Matrix& m1, const GL_Matrix& m2);
  friend bool operator != (const GL_Matrix& m1, const GL_Matrix& m2);

  // Calculation operators
  friend GL_Matrix operator+ (const GL_Matrix& m1,const GL_Matrix& m2);
  friend GL_Matrix operator- (const GL_Matrix& m1, const GL_Matrix& m2);
  friend GL_Matrix operator* (const GL_Matrix& m1, const GL_Matrix& m2);
  friend GL_Matrix operator* (const GL_Matrix& m, const double& no);
  friend GL_Matrix operator* (const double& no, const GL_Matrix& m) { return (m*no); }
  friend GL_Matrix operator/ (const GL_Matrix& m1, const GL_Matrix& m2){ return (m1 * !m2); }
  friend GL_Matrix operator/ (const GL_Matrix& m, const double& no) { return (m*(1/no)); }
  friend GL_Matrix operator/ (const double& no, const GL_Matrix& m) { return (!m * no); }
  friend GL_Matrix operator~ (const GL_Matrix& m);
  friend GL_Matrix operator! (GL_Matrix m);
  friend GL_Matrix operator^ (const GL_Matrix& m, const size_t& pow);

  // Miscellaneous -methods
  void Null ();
  void Unit (const int& row);
  void Unit ();
  void SetSize (int row, int col);

  // Utility methods
  GL_Matrix Solve (const GL_Matrix& v) const;
  GL_Matrix Adj ();
  double Det ();
  double Norm ();
  double Cofact (int row, int col);
  double Cond ();

  // Type of matrices
  bool IsSquare () { return (Row == Col); } 
  bool IsSingular ();
  bool IsDiagonal ();
  bool Isscalar ();
  bool IsUnit ();
  bool IsNull ();
  bool IsSymmetric ();
  bool IsSkewSymmetric ();
  bool IsUpperTiangular ();
  bool IsLowerTiangular ();

  // Io-stream operators
  friend istream& operator >> (istream& i, GL_Matrix& m);
  friend ostream& operator << (ostream& o, GL_Matrix& m);
};


#endif //__STD_MATRIX_H
