#!/usr/bin/ruby

# Tests for the Matrix class

var A = %m(
    2 -3  1;        # comment test #1
    1 -2 -2;
    3 -4, 1;        # comment test #2
)

var B = %m(
    9, -3, -2;
    3, -1,  7;
    2, -4, -8       # comment test
)

var C = Matrix(
    [2, -1,  5,  1],
    [3,  2,  2, -6],
    [1,  3,  3, -1],
    [5, -2, -3,  3],
)

assert_eq(A+B, [[11, -6, -1], [4, -3, 5], [5, -8, -7]])
assert_eq(A-B, [[-7, 0, 3], [-2, -1, -9], [1, 0, 9]])
assert_eq(A*B, [[11, -7, -33], [-1, 7, 0], [17, -9, -42]])
assert_eq(A/B, [[-26/115, 101/115, 7/10], [-2/23, 6/23, 1/2], [-27/115, 127/115, 9/10]])

assert_eq(B+A, [[11, -6, -1], [4, -3, 5], [5, -8, -7]])
assert_eq(B-A, [[7, 0, -3], [2, 1, 9], [-1, 0, -9]])
assert_eq(B*A, [[9, -13, 13], [26, -35, 12], [-24, 34, 2]])
assert_eq(B/A, [[-73/3, -4/3, 59/3], [-3, -3, 4], [-8/3, 10/3, 4/3]])

assert_eq(A+42, [[44, 39, 43], [43, 40, 40], [45, 38, 43]])
assert_eq(A-42, [[-40, -45, -41], [-41, -44, -44], [-39, -46, -41]])
assert_eq(A*42, [[84, -126, 42], [42, -84, -84], [126, -168, 42]])
assert_eq(A/42, [[1/21, -1/14, 1/42], [1/42, -1/21, -1/21], [1/14, -2/21, 1/42]])

assert_eq(B+42, [[51, 39, 40], [45, 41, 49], [44, 38, 34]])
assert_eq(B-42, [[-33, -45, -44], [-39, -43, -35], [-40, -46, -50]])
assert_eq(B*42, [[378, -126, -84], [126, -42, 294], [84, -168, -336]])
assert_eq(B/42, [[3/14, -1/14, -1/21], [1/14, -1/42, 1/6], [1/21, -2/21, -4/21]])

assert_eq(A**3, A * A * A)
assert_eq(A**4, A * A * A *A)

assert_eq(B**3, [[518, -96, -64], [96, 198, 224], [64, -128, -26]])
assert_eq(B**4, [[4246, -1202, -1196], [1906, -1382, -598], [140, 40, -816]])

assert_eq(A**-2, (A**2).inv)
assert_eq(B**-3, (B**3).inv)

assert_eq(A**-1, A.inv)
assert_eq(B**-1, B.inv)

assert_eq(A.inv, [[-10/3, -1/3, 8/3], [-7/3, -1/3, 5/3], [2/3, -1/3, -1/3]])
assert_eq(B.inv, [[18/115, -8/115, -1/10], [19/115, -34/115, -3/10], [-1/23, 3/23, 0]])

assert_eq(A.gauss_jordan_invert, A.inv)
assert_eq(B.gauss_jordan_invert, B.inv)
assert_eq(C.gauss_jordan_invert, C.inv)

assert_eq(A.det, 3)
assert_eq(B.det, 230)
assert_eq(C.det, 684)

assert_eq(A.det_bareiss, 3)
assert_eq(B.det_bareiss, 230)
assert_eq(C.det_bareiss, 684)

assert_eq(C.solve([-3, -32, -47, 49]), [2, -12, -4, 1])
assert_eq(C.gauss_jordan_solve([-3, -32, -47, 49]), [2, -12, -4, 1])

assert_eq(A.solve([-3, 43, 9]), [59/3, 23/3, -58/3])
assert_eq(B.solve([-3, 43, 9]), [-1003/230, -3659/230, 132/23])

assert_eq(A.transpose, [[2, 1, 3], [-3, -2, -4], [1, -2, 1]])
assert_eq(C.transpose, [[2, 3, 1, 5], [-1, 2, 3, -2], [5, 2, 3, -3], [1, -6, -1, 3]])

do {
    var a = Matrix(
        [1.5,3.9],
        [5.8, 3.2],
    )

    assert_eq(
        a.ceil,
        Matrix(
            [2, 4],
            [6, 4],
        )
    )

    assert_eq(
        a.floor,
        Matrix(
            [1,3],
            [5,3],
        )
    )

    assert_eq(a.sum, 14.4)
    assert_eq(a.prod, 108.576)

    assert_eq(a.sum { _**2 }, 61.34)
    assert_eq(a.prod { _**2 }, 108.576**2)
}

say "** Test passed!"