/*
 * mxn - Matrix
 * 
 * @author Thorsten Raasch, Manuel Werner
 */
import java.text.DecimalFormat;
import java.util.Locale;
import java.lang.Math;

public class Matrix
{
    /*
     * konstruiert Nullmatrix
     */
    public Matrix(int rows, int columns)
    {
	this.rows = rows;
	this.columns = columns;
	entries = new Vector(rows * columns);
    }
	
    /*
     * konstruiert Matrix vorgegebener Groesse,
     * Eintraege als Zeichenkette (zeilenweise, durch Leerzeichen getrennt)
     */
    public Matrix(int rows, int columns, String s)
    {
	this.rows = rows;
	this.columns = columns;
	entries = new Vector(rows * columns, s);
    }
	
    /*
     * Kopier-Konstruktor
     */
    public Matrix(Matrix M)
    {
	rows = M.rows();
	columns = M.columns();
	entries = new Vector(M.entries);
    }
	
    /*
     * Anzahl Zeilen
     */
    public int rows()
    {
	return rows; 
    }
	
    /*
     * Anzahl Spalten
     */
    public int columns()
    {
	return columns;
    }
	
    /*
     * Lesezugriff auf Eintrag a_{i,j} 
     */
    public double get_entry(int row, int column)
    {
	return entries.get_entry(row * columns() + column);
    }
	
    /*
     * Schreibzugriff auf Eintrag a_{i,j}
     */
    public void set_entry(int row, int column, double value)
    {
	entries.set_entry(row * columns() + column, value);
    }
	
    /*
     * Matrix-Vektor-Produkt
     */
    public Vector apply(Vector x)
    {
	Vector r = new Vector(rows());
	for (int i = 0; i < rows(); i++)
	    {
		double ri = 0;
		for (int j = 0; j < columns(); j++)
		    ri += get_entry(i, j) * x.get_entry(j);
		r.set_entry(i, ri);
	    }
	return r;
    }

    /*
     * Matrix-Matrix-Produkt
     */
    public Matrix mult(Matrix B)
    {
	double d = 0.0;
	Matrix AB = new Matrix(rows(),B.columns());
	for (int k= 0; k < B.columns(); k++) {
	    for (int i = 0; i < rows(); i++) {
		for (int j = 0; j < columns(); j++) {
		    d += get_entry(i,j)*B.get_entry(j,k);
		}
		AB.set_entry(i,k,d);
		d = 0.0;
	    }
	}
	return AB;
    }

    /*
     * Differenz zweier Matrizen
     */
    public Matrix diff(Matrix B)
    {
	double d = 0.0;
	Matrix AdiffB = new Matrix(rows(),columns());
	for (int i=0; i < columns(); i++) {
	    for (int j = 0; j < rows(); j++) {
		AdiffB.set_entry(i,j,get_entry(i,j)-B.get_entry(i,j));
	    }
	}
	return AdiffB;
    }



    /*
     * Frobenius-Norm
     */
    public double frobenius_norm()
    {
	double res = 0.0;
	for (int i=0; i<rows(); i++) {
	    for (int j=0; j < rows(); j++) {
		res += get_entry(i,j)*get_entry(i,j);
	    }
	}
	return Math.sqrt(res);
    }

	
    /*
     * Ausgabe als Zeichenkette
     */
    public String toString()
    {
	String s = "[";

	DecimalFormat df = (DecimalFormat)DecimalFormat.getInstance(Locale.US);
	df.applyPattern("0.000000");
		
	for (int i = 0; i< rows(); i++)
	    {
		for (int j = 0; j < columns(); j++)
		    {
			s += df.format(get_entry(i, j));
			if (j < columns()-1)
			    s += " ";
		    }
		if (i < rows()-1)
		    s += "\n ";
	    }
	s += "]";
	return s;
    }
	
    private Vector entries;
    private int rows, columns;
};
