/*
 * Created on 08.04.2005
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */

/**
 * @author GerberDom
 *
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Style - Code Templates
 */

public class Gauss_Algorithmus
{

	/* Konstanten */
	private static final int n=4;					// (n-x-n)-Gleichungssystem
	private static final int vorKomma = 2;
	private static final int nachKomma= 5;
	

	public static void main(String [] a){
		
		/* Gleichungs-Matrix der Form ( A | b ) */
		double[][] matrix =  { 	{ 1, -1, 2, -1, -8},
 								{ 2, -2, 3, -3, -20},
  								{ 1, 1, 1, 0, -2},
       							{1, -1, 4, 3, 4}	};
	           							
		gauss(matrix);
	}

	private static void gauss(double [][]matrix){
		System.out.println("\n*********************************************************\n");
		System.out.println("\t   Loesen von LinearSystemen mit dem  \n");
		System.out.println("\t  G A U S S  -  A L G O R I T H M U S  \n");
		System.out.println("*********************************************************\n");

		int[] xOrder = new int[n];
		for(int i = 0; i < n; i++){
			xOrder[i] = i;
		}
		double[] xVals = new double[n];
		
		System.out.println("\n\nMatrix: [ A | b] \n");
		print(matrix);
		
		/* Gauss-Algorithmus */
		for(int x = 0; x < n-1; x++){
			/* finde groesstes Elt in Restmatrix */
			int zIndex = 0, sIndex = 0;
			double maxElt = - Double.MIN_VALUE;		
			for(int z = x; z < n; z++){
				for(int s = x; s < n; s++){
					if(Math.abs(matrix[z][s]) > maxElt){
						maxElt = Math.abs(matrix[z][s]);
						zIndex = z;
						sIndex = s;
					}
	    		}								
			}
			/* swap Zeile */
			if(zIndex != 0){
				for(int s = 0; s < n+1; s++){
					double tmp = matrix[x][s];
					matrix[x][s] = matrix[zIndex][s];
					matrix[zIndex][s] = tmp;
	  			}
			}
	  		/* swap Spalte */
			if(sIndex != 0){
	  			for(int z = 0; z < n; z++){
			  		double tmp = matrix[z][x];
			  		matrix[z][x] = matrix[z][sIndex];
			  		matrix[z][sIndex] = tmp;
		  		}
	  			int tmp = xOrder[x];
	  			xOrder[x] = xOrder[sIndex];
	  			xOrder[sIndex] = tmp;
	  		}
	 		/* eliminiere Elts */
			for(int z = x+1; z < n; z++){
				double pivotMultiplikator = matrix[z][x] / matrix[x][x];
				for(int s = x; s <= n; s++){
					matrix[z][s] -= pivotMultiplikator * matrix[x][s];
				}
			}
		}
		
		/* Berechnung der Variablen */
		for(int z = n-1; z >= 0; z--){
			double x = (matrix[z][n] - summe(matrix, z, z+1, n-1)) / matrix[z][z];
			for(int z2 = z-1; z2 >= 0; z2--){
				matrix[z2][z] *= x;
			}
			xVals[z] = x;
		}
		xSort(xOrder, xVals);

		System.out.println("\n\nLoesung: [ x-Vektor ]\n");
		print(xVals);
	}

	private static double summe(double matrix[][], int zeile, int von, int bis){
		double s = 0.0;
		for(int i = von; i <= bis; i++){
			s += matrix[zeile][i];
		}
		return s;
	}

	private static void printMatrix(double matrix[][]){
		for(int z = 0; z < n; z++){
			for(int s = 0; s <= n; s++)
			System.out.println( matrix[z][s]);
			System.out.println("\n");
		}
	}
	
	private static void print(double[][] A)
	{
		for (int i = 0; i<n; i++)
		{
			System.out.print(" | ");
			for(int j = 0; j<n; j++)
			{
				InOut.print(A[i][j], vorKomma, nachKomma);
				System.out.print("  ");
			}
			System.out.print("|  ");
			InOut.print(A[i][n], vorKomma, nachKomma);
			System.out.println("   |");
		}	
	}
	private static void print(double[] A)
	{
		
		for(int j = 0; j<n; j++)
		{
			System.out.print(" | ");
			InOut.print(A[j], vorKomma, nachKomma);
			System.out.println("   |");
		}
		System.out.println("\n");
	}

	private static void xSort(int xOrder[], double xVals[]){
		for(int i = 0; i < n; i++){
			for(int j = n-1; j > i; j--){
				if(xOrder[j] < xOrder[j-1]){
					int tempI = xOrder[j-1];
					double tempD = xVals[j-1];
					
					xOrder[j-1] = xOrder[j];
					xVals[j-1] = xVals[j];
					
					xOrder[j] = tempI;
					xVals[j] = tempD;
				}
			}
		}
	}
}
