Matrix arithmetic

Uses the permutations generator from the Permutations by swapping task. This implementation is naive and brute-force (slow) but exact.

sub insert ($x, @xs) { ([flat @xs[0 ..^ $_], $x, @xs[$_ .. *]] for 0 .. @xs) }
sub order ($sg, @xs) { $sg > 0 ?? @xs !! @xs.reverse }

multi σ_permutations ([]) { [] => 1 }

multi σ_permutations ([$x, *@xs]) {
    σ_permutations(@xs).map({ |order($_.value, insert($x, $_.key)) }) Z=> |(1,-1) xx *
}

sub m_arith ( @a, $op ) {
    note "Not a square matrix" and return
      if [||] map { @a.elems cmp @a[$_].elems }, ^@a;
    [+] map {
        my $permutation = .key;
        my $term = $op eq 'perm' ?? 1 !! .value;
        for $permutation.kv -> $i, $j { $term *= @a[$i][$j] };
        $term
    }, σ_permutations [^@a];
}

########### Testing ###########

my @tests = (
    [
        [ 1, 2 ],
        [ 3, 4 ]
    ],
    [
        [  1,  2,  3,  4 ],
        [  4,  5,  6,  7 ],
        [  7,  8,  9, 10 ],
        [ 10, 11, 12, 13 ]
    ],
    [
        [  0,  1,  2,  3,  4 ],
        [  5,  6,  7,  8,  9 ],
        [ 10, 11, 12, 13, 14 ],
        [ 15, 16, 17, 18, 19 ],
        [ 20, 21, 22, 23, 24 ]
    ]
);

sub dump (@matrix) {
    say $_».fmt: "%3s" for @matrix;
    say '';
}

for @tests -> @matrix {
    say 'Matrix:';
    @matrix.&dump;
    say "Determinant:\t", @matrix.&m_arith: <det>;
    say "Permanent:  \t", @matrix.&m_arith: <perm>;
    say '-' x 25;
}

Output

Output:

Matrix:
[  1   2]
[  3   4]

Determinant:    -2
Permanent:      10
-------------------------
Matrix:
[  1   2   3   4]
[  4   5   6   7]
[  7   8   9  10]
[ 10  11  12  13]

Determinant:    0
Permanent:      29556
-------------------------
Matrix:
[  0   1   2   3   4]
[  5   6   7   8   9]
[ 10  11  12  13  14]
[ 15  16  17  18  19]
[ 20  21  22  23  24]

Determinant:    0
Permanent:      6778800
-------------------------