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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
// SPDX-FileCopyrightText: 2026 Daisuke Nagao
// SPDX-License-Identifier: MIT
//! Low-level API compatible with the original LUmod calling conventions.
//!
//! Enable it with the `lumod-c` Cargo feature. This module preserves the
//! original names and mode arguments, but it is a Rust slice API rather than a
//! C ABI. New code should normally use [`crate::LuMod`], which validates
//! dimensions, indices, and workspace before modifying factors.
//! The public compatibility surface consists of [`LUmod`], [`Lprod`], and
//! [`Usolve`].
//!
//! All indices are zero-based. For a positive `maxmod`, `l` uses dense
//! row-major storage of at least `maxmod * maxmod` elements and `u` uses packed
//! upper-triangular storage of at least `maxmod * (maxmod + 1) / 2` elements.
//! These functions return no validation errors: callers must satisfy each
//! function's preconditions.
//!
//! Internal factor-update building blocks are not part of this Rust API:
//!
//! ```compile_fail,E0425
//! let _ = rlumod::lumod_c::LUforw;
//! ```
//!
//! ```compile_fail,E0425
//! let _ = rlumod::lumod_c::LUback;
//! ```
//!
//! ```compile_fail,E0425
//! let _ = rlumod::lumod_c::elm;
//! ```
//!
//! ```compile_fail,E0425
//! let _ = rlumod::lumod_c::elmgen;
//! ```
//!
//! # Example
//!
//! ```
//! use rlumod::lumod_c::{LUmod, Lprod, Usolve};
//!
//! let (mut l, mut u) = ([0.0; 1], [0.0; 1]);
//! let (mut y, mut z, mut w) = ([2.0], [2.0], [0.0]);
//! LUmod(1, 1, 1, 0, 0, &mut l, &mut u, &mut y, &mut z, &mut w);
//!
//! let (mut rhs, mut work) = ([6.0], [0.0]);
//! Lprod(1, 1, 1, &mut l, &mut rhs, &mut work);
//! Usolve(1, 1, 1, &mut u, &mut work);
//! assert_eq!(work, [3.0]);
//! ```
// Mirrors the indexed C storage formulas.
use crate;
const MACHINE_PRECISION: f64 = 2.22e-16;
const TINY_NUMBER: f64 = 1.0e-4;
/// Updates LUmod factor storage in place using an original operation mode.
///
/// | `mode` | Operation | Required input |
/// |---|---|---|
/// | `1` | Append the last row and column; `n` is the new dimension | `y[..n]` is the new row, `z[..n - 1]` is the new column, and `y[n - 1]` is the diagonal |
/// | `2` | Replace column `kcol` | `z[..n]` is the replacement column |
/// | `3` | Replace row `krow` | `y[..n]` is the replacement row |
/// | `4` | Move the last row/column into `krow`/`kcol`, then remove the last positions | `y`, `z`, and `w` are workspace; the resulting logical dimension is `n - 1` |
///
/// An unsupported mode or an out-of-range mode-specific index is a no-op. A
/// non-positive `n` is also a no-op. Singular and non-finite values are not
/// rejected.
///
/// # Preconditions
///
/// For a nonempty valid operation, `0 < n <= maxmod`, the factor buffers must
/// satisfy the module storage contract, and `y`, `z`, and `w` must each contain
/// at least `n` elements. Existing factor entries must represent the matrix at
/// the dimension expected by the selected mode.
///
/// # Panics
///
/// May panic if a required slice is too short or the dimension and capacity
/// relationships are invalid.
/// Multiplies a vector by the stored L factor.
///
/// With `mode == 1`, writes `L * y` to `z`; every other mode writes `Lᵀ * y`.
/// The first `n` output elements are overwritten and `y` is unchanged.
///
/// # Preconditions
///
/// `0 <= n <= maxmod`, `l` must satisfy the module storage contract, and `y`
/// and `z` must each contain at least `n` elements. The active part of `l` must
/// encode a valid L factor.
///
/// # Panics
///
/// May panic, possibly after partially writing `z`, if a required slice is too
/// short or the dimension and capacity relationships are invalid.
/// Solves an upper-triangular system in place.
///
/// With `mode == 1`, replaces `y` with the solution of `U * x = y`; every
/// other mode solves `Uᵀ * x = y`. The diagonal is not validated, so zero or
/// non-finite entries can produce infinite or NaN output.
///
/// # Preconditions
///
/// `0 <= n <= maxmod`, `u` must satisfy the module storage contract, `y` must
/// contain at least `n` elements, and the active entries of `u` must encode the
/// intended U factor.
///
/// # Panics
///
/// May panic if a required slice is too short or the dimension and capacity
/// relationships are invalid.