///|
// =====================================================================
// matrix.mbt — 矩陣空間 M_{m×n}(R):代數運算、消去法、分解、特徵值
// 定理自證於 matrix_wbtest.mbt(det 乘法性、LU/QR/Cholesky 重構、
// 譜定理、Cayley–Hamilton 等)
// =====================================================================
/// 矩陣(列主序)
pub struct Mat {
rows : Int
cols : Int
data : Array[Double]
} derive(Debug, Eq)
/// M-1 零矩陣
pub fn mat_new(rows : Int, cols : Int) -> Mat {
{ rows, cols, data: Array::make(rows * cols, 0.0) }
}
/// M-2 由列向量陣列構造
pub fn mat_from_rows(rs : Array[Array[Double]]) -> Mat {
let rows = rs.length()
let cols = if rows == 0 { 0 } else { rs[0].length() }
let data : Array[Double] = []
for i = 0; i < rows; i = i + 1 {
for j = 0; j < cols; j = j + 1 {
data.push(rs[i][j])
}
}
{ rows, cols, data }
}
/// M-3 取元素
pub fn mat_get(m : Mat, i : Int, j : Int) -> Double {
m.data[i * m.cols + j]
}
/// M-4 設元素
pub fn mat_set(m : Mat, i : Int, j : Int, v : Double) -> Unit {
m.data[i * m.cols + j] = v
}
/// M-5 第 i 列
pub fn mat_row(m : Mat, i : Int) -> Array[Double] {
let out : Array[Double] = []
for j = 0; j < m.cols; j = j + 1 {
out.push(mat_get(m, i, j))
}
out
}
/// M-6 第 j 行
pub fn mat_col(m : Mat, j : Int) -> Array[Double] {
let out : Array[Double] = []
for i = 0; i < m.rows; i = i + 1 {
out.push(mat_get(m, i, j))
}
out
}
/// M-7 加法
pub fn mat_add(a : Mat, b : Mat) -> Mat {
let out = mat_new(a.rows, a.cols)
for i = 0; i < a.rows * a.cols; i = i + 1 {
out.data[i] = a.data[i] + b.data[i]
}
out
}
/// M-8 減法
pub fn mat_sub(a : Mat, b : Mat) -> Mat {
let out = mat_new(a.rows, a.cols)
for i = 0; i < a.rows * a.cols; i = i + 1 {
out.data[i] = a.data[i] - b.data[i]
}
out
}
/// M-9 純量乘法
pub fn mat_scale(c : Double, a : Mat) -> Mat {
let out = mat_new(a.rows, a.cols)
for i = 0; i < a.rows * a.cols; i = i + 1 {
out.data[i] = c * a.data[i]
}
out
}
/// M-10 矩陣乘法 (AB)ᵢₖ = Σⱼ AᵢⱼBⱼₖ
pub fn mat_mul(a : Mat, b : Mat) -> Mat {
let out = mat_new(a.rows, b.cols)
for i = 0; i < a.rows; i = i + 1 {
for k = 0; k < b.cols; k = k + 1 {
let mut s = 0.0
for j = 0; j < a.cols; j = j + 1 {
s = s + mat_get(a, i, j) * mat_get(b, j, k)
}
mat_set(out, i, k, s)
}
}
out
}
/// M-11 矩陣-向量乘
pub fn mat_vec(a : Mat, x : Array[Double]) -> Array[Double] {
let out = Array::make(a.rows, 0.0)
for i = 0; i < a.rows; i = i + 1 {
let mut s = 0.0
for j = 0; j < a.cols; j = j + 1 {
s = s + mat_get(a, i, j) * x[j]
}
out[i] = s
}
out
}
/// M-12 轉置
pub fn mat_transpose(a : Mat) -> Mat {
let out = mat_new(a.cols, a.rows)
for i = 0; i < a.rows; i = i + 1 {
for j = 0; j < a.cols; j = j + 1 {
mat_set(out, j, i, mat_get(a, i, j))
}
}
out
}
/// M-13 單位矩陣
pub fn mat_eye(n : Int) -> Mat {
let out = mat_new(n, n)
for i = 0; i < n; i = i + 1 {
mat_set(out, i, i, 1.0)
}
out
}
/// M-14 跡 tr(A) = Σ Aᵢᵢ
pub fn mat_trace(a : Mat) -> Double {
let mut s = 0.0
for i = 0; i < a.rows; i = i + 1 {
s = s + mat_get(a, i, i)
}
s
}
/// M-15 Frobenius 內積 ⟨A,B⟩_F = Σ AᵢⱼBᵢⱼ = tr(AᵀB)
pub fn mat_frob_inner(a : Mat, b : Mat) -> Double {
let mut s = 0.0
for i = 0; i < a.rows * a.cols; i = i + 1 {
s = s + a.data[i] * b.data[i]
}
s
}
/// M-16 Frobenius 範數
pub fn mat_frob_norm(a : Mat) -> Double {
mat_frob_inner(a, a).sqrt()
}
/// M-17 近似相等
pub fn mat_eq_eps(a : Mat, b : Mat, eps : Double) -> Bool {
if a.rows != b.rows || a.cols != b.cols {
false
} else {
let mut ok = true
for i = 0; i < a.rows * a.cols; i = i + 1 {
if (a.data[i] - b.data[i]).abs() >= eps {
ok = false
}
}
ok
}
}
/// M-18 扁平方陣行列式(部分主元高斯消去)——供內積空間體積公式使用
pub fn flat_det(data : Array[Double], n : Int) -> Double {
let m : Mat = { rows: n, cols: n, data: data.copy() }
mat_det(m)
}
/// M-19 行列式(部分主元高斯消去,O(n³))
pub fn mat_det(a : Mat) -> Double {
let n = a.rows
if n != a.cols {
0.0
} else if n == 0 {
1.0
} else {
let m = a.data.copy()
let mut sign = 1.0
let mut det = 1.0
for col = 0; col < n; col = col + 1 {
// 部分主元
let mut piv = col
for r = col + 1; r < n; r = r + 1 {
if m[r * n + col].abs() > m[piv * n + col].abs() {
piv = r
}
}
if m[piv * n + col].abs() < 1.0e-14 {
det = 0.0
break
}
if piv != col {
for j = 0; j < n; j = j + 1 {
let t = m[col * n + j]
m[col * n + j] = m[piv * n + j]
m[piv * n + j] = t
}
sign = -sign
}
let d = m[col * n + col]
det = det * d
for r = col + 1; r < n; r = r + 1 {
let f = m[r * n + col] / d
for j = col; j < n; j = j + 1 {
m[r * n + j] = m[r * n + j] - f * m[col * n + j]
}
}
}
sign * det
}
}
/// M-20 約化列梯形(RREF,部分主元,容差 eps)
pub fn mat_rref(a : Mat, eps : Double) -> Mat {
let m = a.data.copy()
let rows = a.rows
let cols = a.cols
let mut r = 0
let mut lead = 0
while r < rows && lead < cols {
// 覓主元
let mut piv = r
for k = r + 1; k < rows; k = k + 1 {
if m[k * cols + lead].abs() > m[piv * cols + lead].abs() {
piv = k
}
}
if m[piv * cols + lead].abs() < eps {
// 此行無主元:往右移
lead = lead + 1
} else {
if piv != r {
for j = 0; j < cols; j = j + 1 {
let t = m[r * cols + j]
m[r * cols + j] = m[piv * cols + j]
m[piv * cols + j] = t
}
}
let d = m[r * cols + lead]
for j = 0; j < cols; j = j + 1 {
m[r * cols + j] = m[r * cols + j] / d
}
for k = 0; k < rows; k = k + 1 {
if k != r {
let f = m[k * cols + lead]
for j = 0; j < cols; j = j + 1 {
m[k * cols + j] = m[k * cols + j] - f * m[r * cols + j]
}
}
}
r = r + 1
lead = lead + 1
}
}
{ rows, cols, data: m }
}