librarylibs/Matrix/src/Matrix.xtl
Matrix: matrices -- identity, diagonal, trace, product, determinant, inverse, solving linear systems. Import it with an alias of your choice: "mx:" u_se< "Matrix". Put libs/Matrix/src on XETAL_PATH ("just path"); the reference is libs/Matrix/docs. Names with l: are exported; those under h: are private to this file.
A matrix is a rank-2 array, rows first. The numerical functions (d_et, i_nverse, s_olve) work in Floats, by Gaussian elimination with partial pivoting; compare their results with Check's k:n_ear. The transpose is the built-in o_\.
Basics
ˡi̲dentity : Num a => Int -> a
i_dentity n: the n by n identity matrix (1 then n zeros, cycled).
ˡi̲dentity ← { n → (n c̲at n) r̲eshape 1 c̲at n r̲eshape 0 }
ˡd̲iag : a -> a
d_iag m: the items on the main diagonal.
ˡd̲iag ← { m → k ← 'm̲in r̲/ s̲hape m (1 + (o̲ffsets k) × 1 + f̲irst r̲ev s̲hape m) s̲elect r̲avel m }
ˡm̲ul : Num a => a -> a -> a
a m_ul b: the matrix product (a matrix and a vector work too).
ˡm̲ul ← { a b → a '+ '× i̲nner b }
Solving
ʰs̲wapping : Int -> Int -> Int -> Int
The permutation of 1..n that swaps i and j.
ʰs̲wapping ← { n i j → r ← r̲ange n r + ((r = i) × j − i) + (r = j) × i − j }
ʰp̲ivot : Num a => Int -> a -> Int
The row (k..n) whose item in column k is largest in size.
ʰp̲ivot ← { k m → c ← a̲bs (k − 1) d̲rop k s̲elect₂ m k + (f̲irst g̲rade n̲eg c) − 1 }
ʰg̲j : Int -> Int -> Float -> Float
Gauss-Jordan on m (Float) for columns k..n of its first n: each column's pivot row moved up, scaled to 1, and the column cleared from every other row.
ʰg̲j ← { n k m → k > n ? m m ← ((n ʰs̲wapping k)_ k ʰp̲ivot m) s̲elect m r ← r̲ange t̲ally m v ← f̲irst k s̲elect k s̲elect₂ m ⍝ the pivot 0.000000000001 > a̲bs v ? @ p̲anic< "the matrix is singular: it has no inverse, and its system no unique solution" row ← (k s̲elect m) ÷ v c ← (k s̲elect₂ m) − f̲loat r = k ((n ʰg̲j k + 1)_ m − c '× t̲able row) }
ˡs̲olve : Num a => a -> a -> Float
b s_olve a: x with a m_ul x = b, for a square a; b is a vector or a matrix of right-hand sides (one per column). A singular a divides by zero (error[division-by-zero]).
ˡs̲olve ← { b a → n ← t̲ally a x ← n d̲rop₂ ((n ʰg̲j 1)_ f̲loat a c̲at₂ b) (s̲hape b) r̲eshape x }
ˡi̲nverse : Num a => a -> Float
i_nverse a: the inverse of a square matrix.
ˡi̲nverse ← { a → (ˡi̲dentity t̲ally a) ˡs̲olve a }
Determinant
ʰd̲etF : Float -> Float
The determinant of a Float matrix m, by elimination: the first pivot times the determinant of what is left, negated for a row swap.
ʰd̲etF ← { m → n ← t̲ally m n = 1 ? f̲irst r̲avel m p ← 1 ʰp̲ivot m m ← ((n ʰs̲wapping 1)_ p) s̲elect m v ← f̲irst r̲avel m v = 0 ? 0.0 s ← f̲loat (p = 1) − p ≠ 1 r ← (1 d̲rop₂ 1 d̲rop m) − ((1 d̲rop f̲irst₂ m) ÷ v) '× t̲able 1 d̲rop f̲irst m s × v × ʰd̲etF r }