// EXEC: cjc %import-path %L %l %f --test  
// EXEC: ./main

package matrix4cj.tests.LLT.bugfix

import std.unittest.*
import std.unittest.testmacro.*
import std.math.*
import matrix4cj.*

@Test
public class MatrixTester01 {
    @TestCase
    func fix_issue13(): Unit {
        var A_Matrix = Matrix([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
        var A_Matrix_SVD = SingularValueDecomposition(A_Matrix)
        var A_Matrix_SVD_V = A_Matrix_SVD.getV()
        var Expected_A_Matrix_EVD_V = Matrix(
            [
                [-0.428667, 0.805964, 0.408248],
                [-0.570682, -0.239768, -0.125874],
                [-0.706025, -0.748512, 0.736375]
            ]
        )
        var rows = A_Matrix_SVD_V.rowNum
        var cols = A_Matrix_SVD_V.colNum
        for (i in 0..rows) {
            for (j in 0..cols) {
                @Assert(abs(A_Matrix_SVD_V.get(i,j)-Expected_A_Matrix_EVD_V.get(i,j))<1e-6,true)
            }
        }
    }

    @TestCase
    func fix_issue14(): Unit {
        var A_Matrix = Matrix([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
        var A_Matrix_SVD = SingularValueDecomposition(A_Matrix)
        var cond = A_Matrix_SVD.cond()
        @Assert(cond == 12.302245504069207)
    }

    @TestCase
    func fix_issue12(): Unit {
        var A_Matrix = Matrix(
            [
                [2.0, 5.0, 8.0, 7.0],
                [5.0, 2.0, 2.0, 8.0],
                [7.0, 5.0, 6.0, 6.0],
                [5.0, 4.0, 4.0, 8.0]
            ]
        )
        var A_Matrix_CD = CholeskyDecomposition(A_Matrix)
        var B_Tmp: Array<Float64> = [1.0, 1.0, 1.0, 1.0]
        var B_Matrix = Matrix(B_Tmp, rowNum: 4)
        var flag = 0
        try {
            A_Matrix_CD.solve(B_Matrix)
        } catch (e: Matrix4cjException) {
            if (e.toString().contains("Matrix is not symmetric positive definite.")) {
                flag = 1
            }
        }
        @Assert(flag,1)
    }

    @TestCase
    func fix_issue15(): Unit {
        var arr = Array<Array<Float64>>()
        var flag = false
        try {
            Matrix(arr)
        } catch (e: IllegalArgumentException) {
            flag = true
        }
        @Assert(flag)
    }

    @TestCase
    func fix_issue16(): Unit {
        var A_Matrix = Matrix(
            [
                [2.0, 5.0, 8.0, 7.0],
                [5.0, 2.0, 2.0, 8.0],
                [7.0, 5.0, 6.0, 6.0],
                [5.0, 4.0, 4.0, 8.0]
            ]
        )
        var A_Matrix_EVD = EigenvalueDecomposition(A_Matrix)
        var A_Matrix_EVD_V = A_Matrix_EVD.getV()
        var expected_matrix = Matrix(
            [
                [0.5221402566778668, 0.8402454749753158, -0.1453084980671888, -0.49605125729440236],
                [0.40138660797330256, -0.4447338590298808, 0.9802352411509356, 0.7758424353831935],
                [0.5684794484810822, -0.2964453254374863, -0.40515519633448227, -0.9938739984678833],
                [0.4930410327251712, -0.10048025006502033, -0.17494872648396198, 0.5718952095633261]
            ]
        )
        @Assert(A_Matrix_EVD_V.rowNum,expected_matrix.rowNum)
        @Assert(A_Matrix_EVD_V.colNum,expected_matrix.colNum)
        var rows = A_Matrix_EVD_V.rowNum
        var cols = A_Matrix_EVD_V.colNum
        for (i in 0..rows) {
            for (j in 0..cols) {
                @Assert(abs(expected_matrix.get(i,j)-A_Matrix_EVD_V.get(i,j))<1e-6,true)
            }
        }
    }
}