##################################################################
# Modul fuer csv-Tabellen einlesen und in Latex umwandeln
#
# VERSION 1
# Letzte Aenderung: 26.02.2009
##################################################################
use POSIX qw /floor ceil/;
use Math::Trig;
use strict;
use warnings;

# Variablen

my (
	$tabelle,         $tabellenkopf,        $tabellenfuss,
	$spaltenzahl,     $zeilenzahl,          $spaltendefinition,
	$i,               $tabellenausrichtung, $spaltenausrichtung,
	$nachkommastelle, $matrix1zeilen,       $matrix2zeilen,
	$matrix1spalten,  $matrix2spalten,      $matrixzaehler
);

$zeilenzahl = $spaltenzahl = $tabelle = 0;
$spaltendefinition = "";
my @zeile        = ();
my @spalte       = ();
my @matrixzeile  = ();
my @matrixspalte = ();
my @matrixstart  = ();

my @zeileinhalt  = ();
my @spalteinhalt = ();
$tabellenausrichtung = 0;
my $tabellenart = "tabular";
my @lange       = ();
my $linien      = 0;

for ( $i = 0 ; $i <= 150 ; $i++ ) {
	$matrixzeile[$i] = $matrixspalte[$i] = $matrixstart[$i] = 0;
}

$matrixzaehler = 1;

# Funktionen fuer die Tabellendefinition in Latex

$tabellenkopf = $tabellenfuss = "{ " . $tabellenart . "}";

sub settabellenart {
	my ($art) = @_;
	$tabellenart = $art;
}

sub gettabellenart { return $tabellenart; }

sub settabelle {
	my ( $tabellenart, $weite ) = @_;
	my ( $kopf,        $fuss );

	settabellenart($tabellenart);

	if ( $tabellenart eq "tabularx" ) {
		$kopf = "{" . $tabellenart . "}{" . $weite . "\\linewidth}";
		$fuss = "{" . $tabellenart . "}";
	}
	else {
		$kopf = "{" . $tabellenart . "}";
		$fuss = $kopf;

	}
	settabellenkopf($kopf);
	settabellenfuss($fuss);
}

# Die Anzahl der Nachkommastellen wird gesetzt

my $kommagesetzt = 0;
$nachkommastelle = -1;

sub setnachkommastellen {
	my ($komma) = @_;
	$nachkommastelle = $komma;
	$kommagesetzt    = 1;
}

sub setspaltendef {
	my ($spalten) = @_;
	$spaltendefinition = $spalten;
}

sub getspaltendef { return $spaltendefinition; }

# Sollen Linien gezeichnet werden?

sub setlinien { $linien = 1; }

sub getlinien { return $linien; }

my $amsmath = 0;

# Der Tabellenkopf wird geschrieben
sub tabellenkopf {
	my ( $layer, $spalteninhalt ) = @_;

	if ( $tabellenart eq "pmatrix" ) {
		if ( $amsmath == 0 ) {
			usepackage( "", "amsmath" );
			$amsmath = 1;
		}
		schreibeinarray( $layer, sprintf( "\\begin%s", gettabellenkopf() ) );
	}
	else {
		schreibeinarray( $layer,
			sprintf( "\\begin%s{%s}", gettabellenkopf(), $spalteninhalt ) );
		if ( getlinien() == 1 ) {
			latex( $layer, "\\hline" );
		}
	}
}

sub gettabellenkopf { return $tabellenkopf; }

sub settabellenkopf {
	my ($kopf) = @_;
	$tabellenkopf = $kopf;
}

sub settabellenfuss {
	my ($fuss) = @_;
	$tabellenfuss = $fuss;
}

sub tabellenfuss {
	my ( $layer, $fuss ) = @_;
	schreibeinarray( $layer, sprintf( "\\end%s", $fuss ) );
}

sub gettabellenfuss { return $tabellenfuss; }

# Funktion um eine Tabelle fuer die lokale Aenderungsrate zu berechnen

sub lokaltabelle {
	my ( $layer, $func, $xlokal, $schritt, $spalten, $bezeichnung, $variable,
		$ausrichtung )
		= @_;

	my (
		@xpunkte, @ypunkte, $i,      $x,      $y,       $teiler, $xzeile,
		$yzeile,  $j,       $punkte, $zahler, $zeichen, $n
	);
	$punkte = 0;
	$zahler = 0;
	if ( $schritt >= 1 ) {
		$x = $xlokal + 1;
		$y = calcfunk( $func, "x", $x );
		$xpunkte[$punkte] = nachkommastellen( $x, $nachkommastelle );
		$ypunkte[$punkte] = nachkommastellen( $y, $nachkommastelle );
		$punkte++;
	}

	if ( $schritt >= 2 ) {
		$x = $x - 0.5;
		$y = calcfunk( $func, "x", $x );
		$xpunkte[$punkte] = nachkommastellen( $x, $nachkommastelle );
		$ypunkte[$punkte] = nachkommastellen( $y, $nachkommastelle );
		$punkte++;
	}

	if ( $schritt >= 3 ) {
		for ( $i = 3 ; $i <= $schritt ; $i++ ) {
			$x = $xlokal + 0.1 / ( 10**( $i - 3 ) );
			$y = calcfunk( $func, "x", $x );
			$xpunkte[$punkte] = nachkommastellen( $x, $nachkommastelle );
			$ypunkte[$punkte] = nachkommastellen( $y, $nachkommastelle );
			$punkte++;
		}
	}

	if ( $punkte <= $spalten ) { $spalten = $punkte; }

	if ( $ausrichtung eq "v" ) {
		if ( ( $punkte % $spalten ) == 0 ) {
			$teiler = abrunden( $punkte / $spalten, 1 ) - 1;
		}
		else { $teiler = abrunden( $punkte / $spalten, 1 ); }

		$xzeile = "";
		for ( $j = 0 ; $j <= $teiler ; $j++ ) {
			if ( $j == $teiler ) { $zeichen = " "; }
			else { $zeichen = " ; "; }
			$xzeile =
				  $xzeile . "\$"
				. $variable . "\$ ; "
				. "\$\\frac{"
				. $bezeichnung . "("
				. $variable . ")-"
				. $bezeichnung . "("
				. $xlokal . ")}{"
				. $variable . "-"
				. $xlokal . "} \$"
				. $zeichen;

		}
		tabelle( $layer, $xzeile );

		for ( $i = 0 ; $i < $spalten ; $i++ ) {
			$xzeile = "";
			for ( $j = 0 ; $j <= $teiler ; $j++ ) {
				if ( $j == $teiler ) { $zeichen = ""; }
				else { $zeichen = " ; "; }
				if ( ( $i + $j * $spalten ) > $punkte ) {
					$xzeile = $xzeile . " ;" . $zeichen;
				}
				else {
					$xzeile = $xzeile
						. $xpunkte[ $i + $j * $spalten ] . "" . " ; "
						. $ypunkte[ $i + $j * $spalten ] . ""
						. $zeichen;
				}
			}
			tabelle( $layer, $xzeile );
		}

	}
	else {
		$teiler = aufrunden( $punkte / $spalten, 1 );

		for ( $i = 1 ; $i <= $teiler ; $i++ ) {
			$xzeile = "\$" . $variable . "\$; ";
			$yzeile = "\$\\frac{"
				. $bezeichnung . "("
				. $variable . ")-"
				. $bezeichnung . "("
				. $xlokal . ")}{"
				. $variable . "-"
				. $xlokal . "} \$;";

			for ( $j = 1 ; $j <= $spalten ; $j++ ) {
				if ( $j == $spalten ) { $zeichen = " "; }
				else { $zeichen = " ; "; }
				if ( $zahler > $punkte ) {
					$xzeile = $xzeile . $zeichen;
					$yzeile = $yzeile . $zeichen;

				}
				else {
					$xzeile = $xzeile . "" . $xpunkte[$zahler] . "" . $zeichen;
					$yzeile = $yzeile . "" . $ypunkte[$zahler] . "" . $zeichen;
				}
				$zahler++;
			}
			tabelle( $layer, $xzeile );
			tabelle( $layer, $yzeile );
		}
	}
}

# Funktion um eine Wertetabelle fuer eine Funktion anzulegen

sub funktabelle {
	my (
		$layer,       $func,    $xmin,        $xmax,
		$schritt,     $spalten, $bezeichnung, $variable,
		$ausrichtung, $schrittanzahl
		)
		= @_;

	my (
		@xpunkte, @ypunkte, $i,      $x,      $y,       $teiler, $xzeile,
		$yzeile,  $j,       $punkte, $zahler, $zeichen, $n
	);
	$schrittanzahl = ( $xmax - $xmin ) / $schritt;

	$zahler = 1;
	$xzeile = $yzeile = "";

	for ( $n = 0 ; $n <= $schrittanzahl ; $n++ ) {
		$punkte++;
		$x = $xmin + ( $xmax - $xmin ) * ( $n / ($schrittanzahl) );
		$y = calcfunk( $func, "x", $x );
		$xpunkte[$punkte] = nachkommastellen( $x, $nachkommastelle );
		$ypunkte[$punkte] = nachkommastellen( $y, $nachkommastelle );
	}

	if ( $punkte < $spalten ) { $spalten = $punkte; }

	if ( $ausrichtung eq "v" ) {
		if ( ( $punkte % $spalten ) == 0 ) {
			$teiler = abrunden( $punkte / $spalten, 1 ) - 1;
		}
		else { $teiler = abrunden( $punkte / $spalten, 1 ); }

		$xzeile = "";
		for ( $j = 0 ; $j <= $teiler ; $j++ ) {
			if ( $j == $teiler ) { $zeichen = " "; }
			else { $zeichen = " ; "; }
			$xzeile =
				  $xzeile . "\$"
				. $variable . "\$ ; " . "\$"
				. $bezeichnung . "("
				. $variable . ")\$"
				. $zeichen;

		}
		tabelle( $layer, $xzeile );

		for ( $i = 1 ; $i <= $spalten ; $i++ ) {
			$xzeile = "";
			for ( $j = 0 ; $j <= $teiler ; $j++ ) {
				if ( $j == $teiler ) { $zeichen = " "; }
				else { $zeichen = " ; "; }
				if ( ( $i + $j * $spalten ) > $punkte ) {
					$xzeile = $xzeile . " ;" . $zeichen;
				}
				else {
					$xzeile = $xzeile
						. $xpunkte[ $i + $j * $spalten ] . "" . " ; "
						. $ypunkte[ $i + $j * $spalten ] . ""
						. $zeichen;
				}
			}
			tabelle( $layer, $xzeile );
		}
	}
	else {
		$teiler = aufrunden( $punkte / $spalten, 1 );

		for ( $i = 1 ; $i <= $teiler ; $i++ ) {
			$xzeile = "\$" . $variable . "\$ ;";
			$yzeile = "\$" . $bezeichnung . "(" . $variable . ")\$ ;";

			for ( $j = 1 ; $j <= $spalten ; $j++ ) {
				if ( $j == $spalten ) { $zeichen = " "; }
				else { $zeichen = " ; "; }
				if ( $zahler > $punkte ) {
					$xzeile = $xzeile . $zeichen;
					$yzeile = $yzeile . $zeichen;

				}
				else {
					$xzeile = $xzeile . "" . $xpunkte[$zahler] . "" . $zeichen;
					$yzeile = $yzeile . "" . $ypunkte[$zahler] . "" . $zeichen;
				}
				$zahler++;
			}
			tabelle( $layer, $xzeile );
			tabelle( $layer, $yzeile );

		}
	}

}

# Die Spalten- und Zeilenzahl wird bestimmt
sub setspalten {
	my ($spalte) = @_;
	if ( $spalte > $spaltenzahl ) { $spaltenzahl = $spalte; }
	else { $spaltenzahl = $spaltenzahl; }
	if ( $spalte == 0 ) { $spaltenzahl = $spalte; }
}

sub setzeilen {
	my ($zeile) = @_;
	if ( $zeile > $zeilenzahl ) { $zeilenzahl = $zeile; }
	else { $zeilenzahl = $zeilenzahl; }
}

sub getspalten { return $spaltenzahl; }
sub getzeilen  { return $zeilenzahl; }

# Die maximale Spaltenbreite wird festgestellt
sub spaltenbreite {
	my ( $spalte, $breite ) = @_;

	if ( $lange[$spalte] < length($breite) ) {
		$lange[$spalte] = length($breite);
	}
	else { $lange[$spalte] = $lange[$spalte]; }
}

# Die Spaltenbreite wird wieder zurueckgesetzt fuer die naechsten Tabellen

sub spaltenbreiterueck {
	my $j;
	for ( $j = 0 ; $j < getspalten() ; $j++ ) { $lange[$j] = 0; }
}

for ( $i = 0 ; $i <= 1000 ; $i++ ) {
	$spalte[$i] = $spalteinhalt[$i] = $lange[$i] = 0;
}

# Eintraege in die Tabelle werden vorgenommen
sub schreibeintabelle {
	my ( $zeilennummer, $zelle ) = @_;
	$zeile[$zeilennummer][ $spalte[$zeilennummer] ] = $zelle;
	spaltenbreite( $spalte[$zeilennummer], $zelle );
	$spalte[$zeilennummer]++;
}

my $leer = 0;

sub zahlodertext {
	my ( $layer, $zeile ) = @_;
	$zeileinhalt[$layer][ $spalteinhalt[$layer] ] = suchezahl($zeile);
	$spalteinhalt[$layer]++;
}

sub suchezahl {
	my ($zeile) = @_;

	if ( $zeile =~ /([0-9\.]+)/ ) { return 1; }
	else { return 0; }
}

sub tabellenausrichtung {
	my ($string) = @_;

	my ( $vor, $nach, $zahler, $hilfsstring, $neuerstring, $i );
	$vor         = "";
	$hilfsstring = $string;
	$zahler      = 1;
	$neuerstring = "";
	while ( $hilfsstring ne "" ) {
		if ( $hilfsstring =~ /^([^,]*),(.*)$/i ) {
			if ( $zahler <= getspalten() - 1 ) {
				$vor         = $1;
				$nach        = $2;
				$hilfsstring = $2;
				$zahler++;
			}
			else {
				$vor         = $1;
				$nach        = "";
				$hilfsstring = "";
			}
		}
		else {
			$vor         = $nach;
			$hilfsstring = "";
		}

		$neuerstring = $neuerstring . $vor;

	}
	$spaltenausrichtung = $zahler + 1;

	$neuerstring =~ tr/,//d;
	setspaltendef($neuerstring);
	$tabellenausrichtung = 1;

}

## Eine Tabelle wird eingelesen

sub tabelle {
	my ( $layer, $string ) = @_;

	# Die Zeilenzahl fuer eine Tabelle wird bestimmt
	setzeilen( $zeilenzahl + 1 );

	my ( $vor, $nach, $zahler );
	$zahler = 0;

	while ( $string ne "" ) {
		if ( $string =~ /^([^;]*);(.*)$/i ) {
			$vor    = $1;
			$string = $2;
			$nach   = $2;
		}
		else {
			$vor    = $nach;
			$string = "";
		}

		$vor =~ s/\s+$//g;
		$vor =~ s/^\s+//g;
		$vor =~ tr/,/./d; # Fuer Rechnungen wird das Komma in einen Punkt verwandelt

		if ( istzahl($vor) == 1 ) {
			if    ( $vor =~ /^([+][+])([0-9]+)$/i ) { $vor = $2; }
			elsif ( $vor =~ /^([+])([0-9]+)$/i )    { $vor = $2; }
			elsif ( $vor =~ /^([-][-])([0-9]+)$/i ) { $vor = $2; }
			elsif ( $vor =~ /^([+][-])([0-9]+)$/i ) { $vor = -$2; }
			elsif ( $vor =~ /^([-][+])([0-9]+)$/i ) { $vor = -$2; }
		}
		else { $vor = $vor; }

		zahlodertext( getzeilen(), $vor );

		# Die Nachkommastellen der Tabelle werden gesetzt
		if ( $kommagesetzt == 0 ) { $vor = $vor; }
		else {
			if ( istzahl($vor) == 1 ) {
				$vor = nachkommastellen( $vor, $nachkommastelle );
			}
			else { $vor = $vor; }
		}

		schreibeintabelle( getzeilen(), $vor );
		$zahler++;
	}

	setspalten($zahler);
}

my $zeiletabelle = 0;

sub schreibetabelle {

	my ( $layer, $j, $i, $inhalt );

	# Zeilen und Spalten fuer eine Matrix werden bestimmt
	matrix();

	if ( ( $matrixzeile[ $matrixzaehler - 1 ] == 1 )
		&& ( $matrixspalte[ $matrixzaehler - 1 ] == 1 ) )
	{
		ausgabe( $zeile[ $matrixstart[ $matrixzaehler - 1 ] ][0] );
	}
	else {

		my $tabart = "l";
		if ( $tabellenart eq "tabularx" ) { $tabart = "X"; }

		# Diese Funktion wird nur aufgerufen, wenn neue Zeilen hinzu gekommen sind
		if ( $zeiletabelle != getzeilen() ) {

# Es wird die Zahl der Spalten bestimmt und wenn die Spaltendefinition nicht gesetzt ist,
# werden alle Spalten linksbuendig gesetzt
			if ( $tabellenausrichtung == 0 ) {
				$inhalt = getspaltendef();
				for ( $i = 0 ; $i < getspalten() ; $i++ ) {
					if ( getlinien() == 1 ) { $inhalt = $inhalt . "|" . $tabart; }
					else { $inhalt = $inhalt . $tabart; }
				}

				if ( getlinien() == 1 ) { $inhalt = $inhalt . "|"; }
				else { $inhalt = $inhalt; }

			}
			else {
				$inhalt = getspaltendef();

				if ( $spaltenausrichtung < getspalten() ) {
					for ( $i = $spaltenausrichtung ; $i <= getspalten() ; $i++ ) {
						if ( getlinien() == 1 ) { $inhalt = $inhalt . "|" . $tabart; }
						else { $inhalt = $inhalt . $tabart; }
					}
				}
			}
			if ( getlinien() == 1 ) { $inhalt = $inhalt . "|"; }
			else { $inhalt = $inhalt . ""; }

			setspaltendef($inhalt);

			$inhalt = "";

			# Der Tabellenkopf wird gesetzt
			tabellenkopf( 10, getspaltendef() );

			# Die Inhalte einer Spalte werden alle so ausgerichtet,
			# dass die & Zeichen alle untereinander stehen
			for ( $layer = $zeiletabelle + 1 ; $layer <= getzeilen() ; $layer++ ) {

				for ( $i = 0 ; $i < getspalten() ; $i++ ) {

					if ( $i < $spalte[$layer] ) {
						if ( $i < 1 ) { $inhalt = $inhalt . $zeile[$layer][$i]; }

						for (
							$j = 0 ;
							$j < $lange[$i] - ( length( $zeile[$layer][$i] ) - 1 ) ;
							$j++
							)
						{
							$inhalt = $inhalt . " ";
						}

						if ( $i >= 1 ) {
							$inhalt = $inhalt . $zeile[$layer][$i];

							# Bei Zahlen wird der Punkt durch ein Komma ersetzt
							$inhalt =~ tr/./,/d;
						}
						if ( $i == getspalten() - 1 ) {
							if ( getlinien() == 1 ) { $inhalt = $inhalt . " \\\\ \\hline"; }
							else { $inhalt = $inhalt . " \\\\"; }
						}

						else { $inhalt = $inhalt . " & "; }

					}
					else {
						ausgabe( "i" . $layer );
						if ( defined $zeile[$layer][$i] ) {
							for (
								$j = 0 ;
								$j < $lange[$i] - ( length( $zeile[$layer][$i] ) - 1 ) ;
								$j++
								)
							{
								$inhalt = $inhalt . " ";
							}
						}

						if ( $i == getspalten() - 1 ) {
							if ( getlinien() == 1 ) { $inhalt = $inhalt . " \\\\ \\hline"; }
							else { $inhalt = $inhalt . " \\\\"; }
						}
						else { $inhalt = $inhalt . " & "; }

					}
				}
				ausgabe($inhalt);
				$inhalt = "";
			}
			tabellenfuss( 10, gettabellenfuss() );
		}

		# Die Werte einer Tabelle werden wieder zurueckgesetzt fuer die naechste
		spaltenbreiterueck();
		setspalten(0);
		setspaltendef("");

		# Der Tabellenfuss wird gesetzt

	}
	$zeiletabelle = getzeilen();

}

sub liste {
	my ( $element1, $element2, $reiheoderzeile ) = @_;

	my ( $i, $inhalt );
	latex( 11,
		"listplot layer=90 farbe=red linie=1,solid parameter=\"plotstyle=curve\"" );

	if ( $reiheoderzeile eq "h" ) {

		if ( $element1 > getzeilen() ) { $element1 = getzeilen() - 1; }
		if ( $element2 > getzeilen() ) { $element2 = getzeilen() - 1; }

		for ( $i = 1 ; $i < getspalten() ; $i++ ) {
			if ( ( suchezahl( $zeile[$element1][$i] ) == 1 )
				|| ( suchezahl( $zeile[$element2][$i] ) == 1 ) )
			{
				$zeile[$element1][$i] =~ tr/,/./d;
				$zeile[$element2][$i] =~ tr/,/./d;
				$inhalt = $zeile[$element1][$i] . "," . $zeile[$element2][$i];
				latex( 11, $inhalt );
			}

		}
	}
	else {
		if ( $element1 > getspalten() ) { $element1 = getspalten() - 1; }
		if ( $element2 > getspalten() ) { $element2 = getspalten() - 1; }

		for ( $i = 1 ; $i <= getzeilen() ; $i++ ) {
			if ( ( suchezahl( $zeile[$i][$element1] ) == 1 )
				|| ( suchezahl( $zeile[$i][$element2] ) == 1 ) )
			{
				if ( defined $zeile[$i][$element1] ) {
					$zeile[$i][$element1] =~ tr/,/./d;
				}

				if ( defined $zeile[$i][$element2] ) {
					$zeile[$i][$element2] =~ tr/,/./d;
				}
				if (
					( defined $zeile[$i][$element2] )
					&& ( defined $zeile[$i][$element2] )){
						$inhalt =
							$zeile[$i][$element1] . "," . $zeile[$i][$element2]; 
							latex( 11, $inhalt );
					};
				}
			}
		}

		latex( 11, "ende" );

	}

## Matrixoperationen

	sub matrix {
		$matrixzeile[$matrixzaehler] =
			getzeilen() - $matrixzeile[ $matrixzaehler - 1 ];
		$matrixspalte[$matrixzaehler] = getspalten();
		$matrixstart[$matrixzaehler]  =
			getzeilen() - $matrixzeile[$matrixzaehler] + 1;
		$matrixzaehler++;
	}

	# Matrixaddition

	sub matrixaddition {
		my ( $matrix1, $matrix2, $ausgabe ) = @_;

		my ( $i, $j, $text, $text1, $text2 );
		$text = $text1 = $text2 = "";
		my $layer = 0;
		$j = 0;
		my $ergebnis;

		if ( ( $matrixzeile[$matrix1] == $matrixzeile[$matrix2] )
			&& ( $matrixspalte[$matrix1] == $matrixspalte[$matrix2] ) )
		{

			if ( $ausgabe == 0 ) {
				for (
					$layer = $matrixstart[$matrix1] ;
					$layer <= ( $matrixstart[$matrix1] + $matrixzeile[$matrix1] - 1 ) ;
					$layer++
					)
				{

					for ( $i = 0 ; $i < $matrixspalte[$matrix1] ; $i++ ) {
						$text1 = $zeile[$layer][$i];
						if ( $zeile[ $matrixstart[$matrix2] + $j ][$i] < 0 ) {
							$text2 = $zeile[ $matrixstart[$matrix2] + $j ][$i];
						}
						else {
							$text2 = "+" . $zeile[ $matrixstart[$matrix2] + $j ][$i];
						}
						$text = $text . $text1 . $text2 . ";";

					}
					$j++;

					tabelle( 10, $text );
					$text = "";
				}
				$j = 0;
				schreibetabelle();
			}
			else {
				for (
					$layer = $matrixstart[$matrix1] ;
					$layer <= ( $matrixstart[$matrix1] + $matrixzeile[$matrix1] - 1 ) ;
					$layer++
					)
				{
					$text = "";

					for ( $i = 0 ; $i < $matrixspalte[$matrix1] ; $i++ ) {
						if ( ( istzahl( $zeile[$layer][$i] ) == 1 )
							&& ( istzahl( $zeile[ $matrixstart[$matrix2] + $j ][$i] ) == 1 ) )
						{
							$ergebnis =
								$zeile[$layer][$i] + $zeile[ $matrixstart[$matrix2] + $j ][$i];
							$text = $text . $ergebnis . ";";

						}
						else {
							$text = $text
								. $zeile[$layer][$i] . " + "
								. $zeile[ $matrixstart[$matrix2] + $j ][$i] . ";";
						}
					}
					$j++;

					tabelle( 10, $text );
				}
				schreibetabelle();
			}
		}
	}

	#Subtraktion von Matrizen

	sub matrixsubtraktion {
		my ( $matrix1, $matrix2, $ausgabe ) = @_;

		my ( $i, $j, $text1, $text2, $text );

		my $layer = 0;
		$j = 0;
		my $ergebnis;
		$text = $text1 = $text2 = "";

		if ( ( $matrixzeile[$matrix1] == $matrixzeile[$matrix2] )
			&& ( $matrixspalte[$matrix1] == $matrixspalte[$matrix2] ) )
		{

			if ( $ausgabe == 0 ) {

				for (
					$layer = $matrixstart[$matrix1] ;
					$layer <= ( $matrixstart[$matrix1] + $matrixzeile[$matrix1] - 1 ) ;
					$layer++
					)
				{

					for ( $i = 0 ; $i < $matrixspalte[$matrix1] ; $i++ ) {

						$text1 = $zeile[$layer][$i];
						if ( istzahl( $zeile[ $matrixstart[$matrix2] + $j ][$i] ) == 1 ) {

							if ( $zeile[ $matrixstart[$matrix2] + $j ][$i] < 0 ) {
								$text2 = "+" . abs( $zeile[ $matrixstart[$matrix2] + $j ][$i] );
							}
							else { $text2 = "-" . $zeile[ $matrixstart[$matrix2] + $j ][$i]; }

						}
						else {
							$text2 = "-" . $zeile[ $matrixstart[$matrix2] + $j ][$i];
						}
						$text = $text . $text1 . $text2 . ";";
					}
					$j++;

					tabelle( 10, $text );
					$text = "";
				}
				$j = 0;
				schreibetabelle();
			}
			else {

				for (
					$layer = $matrixstart[$matrix1] ;
					$layer <= ( $matrixstart[$matrix1] + $matrixzeile[$matrix1] - 1 ) ;
					$layer++
					)
				{

					for ( $i = 0 ; $i < $matrixspalte[$matrix1] ; $i++ ) {
						if ( ( istzahl( $zeile[$layer][$i] ) == 1 )
							&& ( istzahl( $zeile[ $matrixstart[$matrix2] + $j ][$i] ) == 1 ) )
						{
							$ergebnis =
								$zeile[$layer][$i] - $zeile[ $matrixstart[$matrix2] + $j ][$i];
							$text = $text . $ergebnis . ";";
						}
						else {
							$text = $text
								. $zeile[$layer][$i] . "-"
								. $zeile[ $matrixstart[$matrix2] + $j ][$i] . ";";
						}
					}
					$j++;

					tabelle( 10, $text );
					$text = "";

				}
				schreibetabelle();
			}
		}
	}

	# Matrizenmultiplikation
	sub matrixmultiplikation {
		my ( $matrix1, $matrix2, $ausgabe ) = @_;
		my ( $i, $ii, $text1, $text2 );
		my $text  = "";
		my $layer = 0;
		my $ergebnis;
		my $semikolon   = 1;
		my $skalar      = 0;
		my $hilfsmatrix = 0;

		# Hat eine Matrix nur eine Zeile und Spalte, so ist dies ein Skalar.

		if ( ( $matrixzeile[$matrix1] == 1 ) && ( $matrixspalte[$matrix1] == 1 ) ) {
			$skalar      = $zeile[ $matrixstart[$matrix1] ][0];
			$hilfsmatrix = $matrix2;
		}

		if ( ( $matrixzeile[$matrix2] == 1 ) && ( $matrixspalte[$matrix2] == 1 ) ) {
			$skalar      = $zeile[ $matrixstart[$matrix2] ][0];
			$hilfsmatrix = $matrix1;
		}

		# Der Rang wird ueberprueft
		if ( $matrixzeile[$matrix2] == $matrixspalte[$matrix1] ) {

			if ( $ausgabe == 0 ) {
				for (
					$layer = $matrixstart[$matrix1] ;
					$layer <= ( $matrixstart[$matrix1] + $matrixzeile[$matrix1] - 1 ) ;
					$layer++
					)
				{
					$text     = "";
					$ergebnis = 0;

					for ( $i = 0 ; $i < $matrixspalte[$matrix2] ; $i++ ) {
						for ( $ii = 0 ; $ii < $matrixspalte[$matrix1] ; $ii++ ) {
							if ( istzahl( $zeile[$layer][$ii] ) == 1 ) {
								if ( $zeile[$layer][$ii] < 0 ) {
									$text1 = "(" . $zeile[$layer][$ii] . ")";
								}
								else { $text1 = $zeile[$layer][$ii]; }
							}
							else { $text1 = $zeile[$layer][$ii]; }
							if ( istzahl( $zeile[ $matrixstart[$matrix2] + $ii ][$i] ) == 1 )
							{
								if ( $zeile[ $matrixstart[$matrix2] + $ii ][$i] < 0 ) {
									$text2 =
										"(" . $zeile[ $matrixstart[$matrix2] + $ii ][$i] . ")";
								}
								else {
									$text2 = $zeile[ $matrixstart[$matrix2] + $ii ][$i];
								}
							}
							else {
								$text2 = $zeile[ $matrixstart[$matrix2] + $ii ][$i];
							}

							if ( $ii == $matrixspalte[$matrix1] - 1 ) {
								$text = $text . $text1 . "\\cdot " . $text2 . ";";
							}
							else { $text = $text . $text1 . "\\cdot " . $text2 . "+"; }
						}

					}

					tabelle( 10, $text );
					$text = "";
				}

				schreibetabelle;
			}

			else {
				for (
					$layer = $matrixstart[$matrix1] ;
					$layer <= ( $matrixstart[$matrix1] + $matrixzeile[$matrix1] - 1 ) ;
					$layer++
					)
				{
					$text     = "";
					$ergebnis = 0;

					for ( $i = 0 ; $i < $matrixspalte[$matrix2] ; $i++ ) {
						for ( $ii = 0 ; $ii < $matrixspalte[$matrix1] ; $ii++ ) {

							if ( istzahl( $zeile[$layer][$ii] ) == 1 ) {
								if ( $zeile[$layer][$ii] < 0 ) {
									$text1 = "(" . $zeile[$layer][$ii] . ")";
								}
								else { $text1 = $zeile[$layer][$ii]; }
							}
							else { $text1 = $zeile[$layer][$ii]; }
							if ( istzahl( $zeile[ $matrixstart[$matrix2] + $ii ][$i] ) == 1 )
							{
								if ( $zeile[ $matrixstart[$matrix2] + $ii ][$i] < 0 ) {
									$text2 =
										"(" . $zeile[ $matrixstart[$matrix2] + $ii ][$i] . ")";
								}
								else { $text2 = $zeile[ $matrixstart[$matrix2] + $ii ][$i]; }
							}
							else { $text2 = $zeile[ $matrixstart[$matrix2] + $ii ][$i]; }

							if ( $ii == $matrixspalte[$matrix1] - 1 ) {

								if (
									( istzahl( $zeile[$layer][$ii] ) == 1 )
									&& (
										istzahl( $zeile[ $matrixstart[$matrix2] + $ii ][$i] ) == 1 )
									)
								{
									$ergebnis = $ergebnis + $zeile[$layer][$ii] *
										$zeile[ $matrixstart[$matrix2] + $ii ][$i];
									$text     = $text . "+" . $ergebnis . ";";
									$ergebnis = 0;
								}
								else {

									$text = $text
										. $zeile[$layer][$ii] . "\\cdot "
										. $zeile[ $matrixstart[$matrix2] + $ii ][$i] . ";";
									$semikolon = 1;
								}
							}

							else {
								if (
									( istzahl( $zeile[$layer][$ii] ) == 1 )
									&& (
										istzahl( $zeile[ $matrixstart[$matrix2] + $ii ][$i] ) == 1 )
									)
								{

									$ergebnis = $ergebnis + $zeile[$layer][$ii] *
										$zeile[ $matrixstart[$matrix2] + $ii ][$i];
								}
								else {
									$text = $text
										. $zeile[$layer][$ii] . "\\cdot " 
										. $zeile[ $matrixstart[$matrix2] + $ii ][$i];
								}
							}
						}

					}
					$semikolon = 1;

					tabelle( 10, $text );
					$text = "";
				}
				schreibetabelle;
			}
		}
		elsif ( $hilfsmatrix != 0 ) {

			if ( $skalar < 0 ) { $text1 = "(" . $skalar . ")"; }
			else { $text1 = $skalar; }

			if ( $ausgabe == 0 ) {
				for (
					$layer = $matrixstart[$hilfsmatrix] ;
					$layer <=
					( $matrixstart[$hilfsmatrix] + $matrixzeile[$hilfsmatrix] - 1 ) ;
					$layer++
					)
				{

					for ( $ii = 0 ; $ii < $matrixspalte[$hilfsmatrix] ; $ii++ ) {
						if ( istzahl( $zeile[$layer][$ii] ) == 1 ) {
							if ( $zeile[$layer][$ii] < 0 ) {
								$text2 = "(" . $zeile[$layer][$ii] . ")";
							}
							else {
								$text2 = $zeile[$layer][$ii];
							}
						}
						else { $text2 = $zeile[$layer][$ii]; }
						$text = $text . $text1 . "\\cdot " . $text2 . ";"

					}
					tabelle( 10, $text );
					$text = "";

				}
				schreibetabelle;

			}

			else {
				for (
					$layer = $matrixstart[$hilfsmatrix] ;
					$layer <=
					( $matrixstart[$hilfsmatrix] + $matrixzeile[$hilfsmatrix] - 1 ) ;
					$layer++
					)
				{
					for ( $ii = 0 ; $ii < $matrixspalte[$hilfsmatrix] ; $ii++ ) {
						if ( istzahl( $zeile[$layer][$ii] ) == 1 ) {
							$text2 = $skalar * $zeile[$layer][$ii];

						}
						else { $text2 = $text1 . "\\cdot " . $zeile[$layer][$ii]; }
						$text = $text . $text2 . ";"

					}
					tabelle( 10, $text );
					$text = "";

				}
				schreibetabelle;
			}
		}
	}

## Transponierte Matrix

	sub transponiert {
		my ($matrix1) = @_;
		my ( $text, $i, $layer );

		$text = "";
		for ( $i = 0 ; $i < $matrixspalte[$matrix1] ; $i++ ) {
			for (
				$layer = $matrixstart[$matrix1] ;
				$layer <= ( $matrixstart[$matrix1] + $matrixzeile[$matrix1] - 1 ) ;
				$layer++
				)
			{
				$text = $text . $zeile[$layer][$i] . ";";
			}

			tabelle( 10, $text );
			$text = "";
		}
		schreibetabelle();
	}

	1;

