 //  Copyright © 2016 pauljohanneskraft. All rights reserved.
 //
 
-import Foundation
-
-infix operator * { associativity left precedence 140 }
-
-func * <T: NumericType>(left: [[T]], right: [[T]]) -> [[T]]? {
-    if left[0].count != right.count { return nil }
+//import Foundation
+
+postfix func ++<T: NumericType>(inout left: [[T]]) -> [[T]] {
+    let before = left
+    ++left
+    return before
+}
+
+prefix func ++<T: NumericType>(inout left: [[T]]) -> [[T]] {
+    for row in 0..<left.count {
+        for column in 0..<left[row].count {
+            left[row][column]++
+        }
+    }
+    return left
+}
+
+func * <T: NumericType>(left: [[T]], right: [[T]]) throws -> [[T]] {
+    var left = left
+    try left *= right
+    return left
+}
+
+func *= <T: NumericType>(inout left: [[T]], right: [[T]]) throws -> [[T]] {
+    if left[0].count != right.count { throw MatrixError.NotMultipliable }
     var matrix : [[T]] = []
     
     for i in 0..<left.count {

        }
        matrix.append(array)
    }
    return matrix
}

func * <T: NumericType>(left: [[T]], right: T) -> [[T]] {
    var left = left
    for row in 0..<left.count {
        for column in 0..<left[row].count {
            left[row][column] = left[row][column]*right
        }
    }
    return left
}

func * <T: NumericType>(left: T, right: [[T]]) -> [[T]] {
    var right = right
    for row in 0..<right.count {
        for column in 0..<right[row].count {
            right[row][column] = right[row][column]*left
        }
    }
    return right
}

func print<T>(matrix: [[T]]) {
    print(toLaTeX(matrix))
}

func toLaTeX<T>(matrix: [[T]]) -> String {

    return out + "\\end{pmatrix}"
}

func print<T>(matrix: [[T]]) {
    print(toLaTeX(matrix))
}


// source: https://wiki.freitagsrunde.org/Javakurs/Übungsaufgaben/Gauß-Algorithmus/Musterloesung
// originally written in Java, rewritten by me in Swift

func solve<T : NumericType>(matrix: [[T]], _ vector: [T]) throws -> [T] {
    if matrix.count < matrix[0].count { throw MatrixError.Unsolvable }
    var matrix = matrix
    var vector = vector
    var tmpColumn : Int
    for line in 0..<matrix.count {
        tmpColumn = -1
        for column in 0..<matrix[line].count {
            for row in line..<matrix.count {
                if matrix[row][column] != T(0) {
                    tmpColumn = column
                }
            }
            if tmpColumn != -1 { break }
        }
        
        if tmpColumn == -1 {
            for _ in line..<matrix.count {
                if vector[line] != T(0) {
                    //print(matrix)
                    //print(vector)
                    throw MatrixError.Unsolvable
                }
            }
            
            if matrix[0].count - 1 >= line {
                //print(matrix)
                //print(vector)
                throw MatrixError.Unsolvable
            }
            break
        }
        // Umformungsschritt 2: Die Zahl matrix[line][tmpColumn] soll
        // UNgleich null sein
        if matrix[line][tmpColumn] == T(0) {
            for row in line+1..<matrix.count {
                if matrix[row][tmpColumn] != T(0) {
                    //print(matrix, vector)
                    //print("\nRow \(line + 1) will be swapped with row \(row + 1)")
                    matrix.swap(line, row)
                    vector.swap(line, row)
                    break
                }
            }
        }
        
        // Umformungsschritt 3: matrix[line][tmpColumn] soll gleich 1 sein.
        if matrix[line][tmpColumn] != T(0) {
            //print(matrix, vector)
            //print("\nRow \(line + 1) will be divided by \(matrix[line][tmpColumn])")
            divideLine(line, matrix[line][tmpColumn], &matrix, &vector)
        }
        
        //print(matrix, vector)
        
        for row in line+1..<matrix.count {
            //print(matrix, vector)
            //print("\nRow \(row + 1) will be subtracted by: \(matrix[row][tmpColumn]) * row \(line + 1)")
            removeRowLeadingNumber(matrix[row][tmpColumn], line, row, &matrix, &vector)
        }

    }
    
    for column in 1..<matrix[0].count {
        for row in 1...column {
            //print(matrix, vector)
            //print("\nRow \(row) will be subtracted by \(matrix[row - 1][column]) * row \(column + 1)")
            removeRowLeadingNumber(matrix[row - 1][column], column, row - 1, &matrix, &vector);
        }
    }
    
    //print(matrix, vector)
    return vector
}

private func removeRowLeadingNumber<T : NumericType>(factor: T, _ rowRoot: Int, _ row: Int, inout _ matrix: [[T]], inout _ vector: [T]) {
    for column in 0..<matrix[row].count {
        matrix[row][column] = matrix[row][column] - factor * matrix[rowRoot][column];
    }
    vector[row] = vector[row] - factor * vector[rowRoot];
}

private func divideLine< T: NumericType>(row : Int, _ div : T, inout _ matrix : [[T]], inout _ vector: [T]){
    for column in 0..<matrix[row].count {
        matrix[row][column] = matrix[row][column] / div;
    }
    vector[row] = vector[row] / div;
}