#define DELTA 0.000000000001	// Everything less than this is ZERO
#define SIGNDIGITS 12		// Maximal number of digits after the period

#include <stdio.h>

#define __MATRIX

// Base class - the matrix
class MATRIX{

	protected:
		unsigned height;
		unsigned length;
		double **elem;

		void AllocObject(unsigned, unsigned);	// Allocating the object
		void FreeObject(void);			// Deallocating the object

	public:
		MATRIX (){elem=NULL; height = length = 0;}
			// Constructor without memory allocation
		MATRIX (unsigned h, unsigned l){ AllocObject(h, l); }
			// Constructor with memory allocation
		MATRIX (const MATRIX &);
			// Constructor for initialization the matrix object with another matrix object
			// and for copying objects when passing or returning by value
		~MATRIX (){ FreeObject(); }     	// Destructor
		MATRIX operator*(MATRIX &); 		// Matrix * matrix
		MATRIX operator*(double);			// Matrix * scalar
		friend MATRIX operator*(double, MATRIX &);	// Scalar * matrix
		MATRIX operator+(MATRIX &); 		// Matrix + matrix
		MATRIX operator-(MATRIX &); 		// Matrix - matrix
		MATRIX operator-(); 			// -matrix
		MATRIX operator^(MATRIX &);
			// Concatenation of two matrices of the same height
		MATRIX operator~(); 			// Inversion
		MATRIX operator!(); 			// Transposition
		MATRIX operator/(double);		// Matrix / scalar 
		MATRIX &operator=(MATRIX &);		// Matrix = matrix
		operator double();			// (double) matrix
		MATRIX MatrAbs();
			// Produce a matrix consisting of absolute values of elements of this matrix
		friend double GetNorm00(MATRIX &);	// Norm by infinity
		friend double GetNorm2(MATRIX &);	// Morm by two (the Euclide's norm)
		void ChangeCols(unsigned,unsigned);	// Exchabge columns
		void ChangeRows(unsigned,unsigned);	// Exchange rows
		void InitObject(FILE*);			// Initialization from file
		void FPrintObject(FILE*);		// Print matrix to file
		// If necessary to print matrix on the screen, it's enough
		// to call FPrintObject(stdout), but there's now special means
		// for formatted screen output, bacause it may need much more
		// space than the screen has.

		// Methods to get/set the internal data:
		unsigned Height( void ){ return height; }
		unsigned Length( void ){ return length; }
		double Element( unsigned, unsigned );
		double Element( unsigned, unsigned, double );
};


// Derived class - vector
class VECTOR : public MATRIX{

	private:
		unsigned dim;  // Same as height

	public:
		VECTOR() :	MATRIX() { dim = 0; }	 // Constructor without memory allocation
		VECTOR(unsigned d) {  AllocObject(d, 1); dim = height; }
			// Constructor with memory allocation
		VECTOR(const VECTOR &Vect) : MATRIX(Vect) { dim = ( height == 1 ? length : height ); }
			// Constructor for initialization by another vector
			// and for copying objects when passing or returning by value
		VECTOR(MATRIX &Matr);
			// Constructor for initilaization by matrix and for implicit
			// casting of matrix, consisting of one column or one row, to a vector
			// because the most methods of the base class return matrix while
			// in vector operation a vector will be expected.
		~VECTOR() { FreeObject(); }    // Destructor
		double operator ,(VECTOR &Vect) { return double(!Vect * (*this)); }
			// Scalar multiplication
		// Vector is a column by default. If necessary to multiplicate
		// matrix by vector, it needs to be transpositioned.

		// Methods to get/set the internal data:
		unsigned Dim( void ){ return dim; }
		double Element( unsigned );
		double Element( unsigned, double );
};
