1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
//! Named results of matrix decompositions and normal forms.
//!
//! Every factorisation here used to come back as a tuple of two or three
//! matrices — `(Q, R)`, `(P, D)`, `(H, U)`, `(S, U, V)` — where nothing but
//! memory said which position was which, and a transposition compiled
//! silently. These structs name each factor and document the identity it
//! satisfies, at zero runtime cost. See CONTRIBUTING.md, "Tuples versus
//! structs".
//!
//! The structs are generic over the matrix type so that the symbolic
//! [`Matrix`](crate::matrix::Matrix) and the exact
//! [`ZMatrix`](crate::matrix::ZMatrix) / [`QMatrix`](crate::matrix::QMatrix)
//! share one vocabulary: `Qr<Matrix>`, `HermiteNormalForm<ZMatrix>`, ….
//!
//! # Examples
//!
//! ```
//! use symplex::prelude::*;
//!
//! let ctx = Context::new();
//! let a = matrix![ctx, [4, 2], [2, 3]];
//! let ldl = a.ldl().unwrap();
//! assert_eq!((&(&ldl.l * &ldl.d) * &ldl.l.transpose()).eval(), a);
//!
//! let Qr { q, r } = matrix![ctx, [1, 1], [0, 1]].qr().unwrap();
//! assert_eq!((&q * &r).simplify(), matrix![ctx, [1, 1], [0, 1]]);
//! ```
/// QR decomposition `A = Q·R`: `Q` has orthonormal columns, `R` is upper
/// triangular.
/// LDLᵀ decomposition `A = L·D·Lᵀ` of a symmetric matrix: `L` unit lower
/// triangular, `D` diagonal.
/// LU decomposition with partial pivoting `P·A = L·U`: `L` unit lower
/// triangular, `U` upper triangular, and `perm` the row permutation —
/// row `i` of `P·A` is row `perm[i]` of `A`.
/// Eigendecomposition `A = P·D·P⁻¹`: the columns of `P` are eigenvectors,
/// `D` is diagonal with the eigenvalues in the same order.
/// Jordan normal form `A = P·J·P⁻¹`: `J` is block diagonal with Jordan
/// blocks `J_k(λ)` (eigenvalue on the diagonal, ones on the superdiagonal),
/// `P` holds the (generalized) eigenvectors.
/// Upper Hessenberg form by similarity: `H = P⁻¹·A·P` (equivalently
/// `A·P = P·H`) with `h_ij = 0` for `i > j + 1`.
/// Full-rank factorisation `A = C·F` with `r = rank A`: `C` (`m × r`) is
/// made of the pivot columns of `A`, `F` (`r × n`) of the nonzero rows of
/// `rref(A)`.
/// Row-style Hermite normal form `H = U·A` with `U` unimodular
/// (`det U = ±1`).
/// Smith normal form `S = U·A·V` with `U`, `V` unimodular
/// (`det U = det V = ±1`) and `S = diag(d₁, …, dᵣ, 0, …)`, `dᵢ | dᵢ₊₁`.
/// LLL reduction of the lattice basis formed by the rows of `A`:
/// `reduced = transform·A` with `transform` unimodular (`det = ±1`), so
/// both span the same lattice.