RosettaCodeData/Task/LU-decomposition/Sidef/lu-decomposition.sidef

73 lines
1.5 KiB
Text
Raw Permalink Normal View History

2023-07-01 11:58:00 -04:00
func is_square(m) { m.all { .len == m.len } }
func matrix_zero(n, m=n) { m.of { n.of(0) } }
2023-12-16 21:33:55 -08:00
func matrix_ident(n) { n.of {|i| [i.of(0)..., 1, (n - i - 1).of(0)...] } }
2023-07-01 11:58:00 -04:00
func pivotize(m) {
var size = m.len
var id = matrix_ident(size)
2023-12-16 21:33:55 -08:00
for i in (^size) {
2023-07-01 11:58:00 -04:00
var max = m[i][i]
var row = i
2023-12-16 21:33:55 -08:00
for j in (i ..^ size) {
2023-07-01 11:58:00 -04:00
if (m[j][i] > max) {
max = m[j][i]
row = j
}
}
2023-12-16 21:33:55 -08:00
if (row != i) {
2023-07-01 11:58:00 -04:00
id.swap(row, i)
}
}
return id
}
2023-12-16 21:33:55 -08:00
2023-07-01 11:58:00 -04:00
func mmult(a, b) {
var p = []
2023-12-16 21:33:55 -08:00
for r in ^a, c in ^b[0], i in ^b {
p[r][c] := 0 += (a[r][i] * b[i][c])
2023-07-01 11:58:00 -04:00
}
return p
}
2023-12-16 21:33:55 -08:00
2023-07-01 11:58:00 -04:00
func lu(a) {
is_square(a) || die "Defined only for square matrices!";
var n = a.len
var P = pivotize(a)
var Aʼ = mmult(P, a)
var L = matrix_ident(n)
var U = matrix_zero(n)
2023-12-16 21:33:55 -08:00
for i in ^n, j in ^n {
2023-07-01 11:58:00 -04:00
if (j >= i) {
2023-12-16 21:33:55 -08:00
U[i][j] = (Aʼ[i][j] - sum(^i, { U[_][j] * L[i][_] }))
2023-07-01 11:58:00 -04:00
} else {
2023-12-16 21:33:55 -08:00
L[i][j] = ((Aʼ[i][j] - sum(^j, { U[_][j] * L[i][_] })) / U[j][j])
2023-07-01 11:58:00 -04:00
}
}
return [P, Aʼ, L, U]
}
2023-12-16 21:33:55 -08:00
2023-07-01 11:58:00 -04:00
func say_it(message, array) {
say "\n#{message}"
array.each { |row|
say row.map{"%7s" % .as_rat}.join(' ')
}
}
2023-12-16 21:33:55 -08:00
2023-07-01 11:58:00 -04:00
var t = [[
%n(1 3 5),
%n(2 4 7),
%n(1 1 0),
],[
%n(11 9 24 2),
%n( 1 5 2 6),
%n( 3 17 18 1),
%n( 2 5 7 1),
]]
2023-12-16 21:33:55 -08:00
t.each { |test|
say_it('A Matrix', test)
for a,b in (['P Matrix', 'Aʼ Matrix', 'L Matrix', 'U Matrix'] ~Z lu(test)) {
2023-07-01 11:58:00 -04:00
say_it(a, b)
}
}