/*
author:
	seth from http://www.bierdatenbank.de
tab size:
	2 (otherwise hardly readable!)
*/
#ifndef __seth_matrix_h
#define __seth_matrix_h

#include <iostream>
#include <vector>
using std::vector;
#include "seth_std.h"

// damit die friend-linker-errors verschwinden
// klappt noch nedd
//template<typename T> class matrix;
//template<typename T> std::ostream& operator<< (std::ostream&, const matrix<T>&);// ausgabe

template<typename T>
class matrix{
public:
	matrix(unsigned, unsigned);										// ctor
	class BadSize{ };															// throws a badsize object if either size is zero
	matrix(const matrix<T>&);											// copy-ctor
	matrix(T**, unsigned, unsigned);							// copy-ctor: import aus array
	~matrix();																		// dtor
	matrix<T>& operator=(const matrix<T>&);				// operator=
	T&         operator() (unsigned, unsigned);		// zugriff per (i,j)
	const T&   operator() (unsigned, unsigned) const;// lese-zugriff per (i,j)
	class BoundsViolation{ };											// these throw a boundsviolation object if i or j is too big

	matrix<T>  operator-();												// unitaerer matrix operator -m
	matrix<T>  operator*(const matrix<T>&) const;	// m*m = m
	vector<T>  operator*(const vector<T>&) const;	// m*v = v
	matrix<T>  operator*(T) const;								// m*s = m (komponentenweise)
//friend matrix operator*(T, const matrix<T>&);	// s*m = m (komponentenweise)
	matrix<T>& operator*=(const matrix<T>&);			// m*=m = m
	matrix<T>& operator*=(T);											// m*=s = m
	matrix<T>  operator+(const matrix<T>&) const;	// m+m = m
	matrix<T>& operator+=(const matrix<T>&);			// m+=m = m
	matrix<T>  operator-(const matrix<T>&) const;	// m-m = m
	matrix<T>& operator-=(const matrix<T>&);			// m-=m = m
	bool operator==(const matrix<T>&) const;			// ==
	bool operator!=(const matrix<T>&) const;			// !=

//	friend std::ostream& operator<< <> (std::ostream&, const matrix<T>&);	// ausgabe
	friend std::ostream& operator<< (std::ostream&, const matrix<int>&);		// ausgabe
	friend std::ostream& operator<< (std::ostream&, const matrix<double>&);	// ausgabe

	bool isIndex(unsigned, unsigned) const;				// ueberpruefe, ob dimensionen eingehalten
	unsigned size(bool) const;										// anzahl zeilen(0) oder spalten(1
	unsigned size_rows() const;										// anzahl zeilen
	unsigned size_cols() const;										// anzahl spalten
	void identity();															// aendert matrix zu identitaet
	matrix<T> inverse() const;										// liefert inverse
	void solve(const vector<T>&, vector<T>&) const;// loest Ax=b (A.solve(b, x);)
	void zeros();																	// aendert matrix zu nullmatrix
	matrix transpose();														// transponiert matrix
private:
	unsigned nrows_, ncols_;											// anzahl zeilen, spalten
	T* data_;																			// zeiger auf die komponenten
};

#endif


