22 for (i = 0; i < n - k - 1; i++) {
24 for (j = 0; j < n - k - 1; j++) {
26 sum +=
MAT_ELEM(a, k + 1 + i, k + 1 + j) * vj;
31 for (i = 0; i < n - k - 1; i++) {
36 for (i = 0; i < n - k - 1; i++) {
40 for (i = 0; i < n - k - 1; i++) {
42 for (j = i; j < n - k - 1; j++) {
45 MAT_ELEM(a, k + 1 + i, k + 1 + j) -= update;
47 MAT_ELEM(a, k + 1 + j, k + 1 + i) -= update;
59 lmmc_scaled_sumsq_init(&acc);
60 for (i = k + 2; i < n; i++) {
61 lmmc_scaled_sumsq_add(&acc,
MAT_ELEM(a, i, k));
63 lmmc_real_t tail_norm = lmmc_scaled_sumsq_norm(&acc);
65 if (tail_norm == 0.0) {
66 offdiag[k] = alpha_val; diag[k] =
MAT_ELEM(a, k, k);
71 for (i = k + 2; i < n; i++) {
80 alpha_val / norm_x - beta / norm_x;
81 for (i = k + 2; i < n; i++) {
83 (
MAT_ELEM(a, i, k) / norm_x) / denominator_scaled;
95 tridiag_rank_update(a, k, tau, *workspace);
104 for (
size_t i = 0; i + 1 < n; i++) taus[i] = 0.0;
113 for (
size_t k = 0; k < n - 1; k++) {
114 status = tridiag_column(a, k, diag, offdiag, taus, &w);
125 for (
size_t i = 0; i < n; i++) diag[i] =
MAT_ELEM(a, i, i);
129static void accumulate_reflector(
const lmmc_mat_t* a,
size_t k,
134 for (j = 0; j < n; j++) {
136 for (i = k + 2; i < n; i++) {
141 for (i = k + 2; i < n; i++) {
148 size_t n = a->
rows;
size_t i, j, k;
149 for (i = 0; i < n; i++) {
150 for (j = 0; j < n; j++) {
151 MAT_ELEM(Q, i, j) = (i == j) ? 1.0 : 0.0;
158 for (k = n - 3; ; k--) {
162 accumulate_reflector(a, k, tau, Q);
176 for (
size_t k = 0; k < Q->
rows; k++) {
188 g = (diag[l + 1] - diag[l]) / (2.0 * offdiag[l]);
191 g = diag[m] - diag[l] + offdiag[l] / (g + r);
193 g = diag[m] - diag[l] + offdiag[l] / (g - r);
195 s = 1.0; c = 1.0; p = 0.0;
196 for (i = m; i > l; i--) {
197 f = s * offdiag[i - 1]; b = c * offdiag[i - 1];
198 if (lmmc_abs(f) >= lmmc_abs(g)) {
199 c = g / f; r = sqrt(c * c + 1.0); offdiag[i] = f * r; s = 1.0 / r; c *= s;
201 s = f / g; r = sqrt(s * s + 1.0); offdiag[i] = g * r; c = 1.0 / r; s *= c;
203 g = diag[i] - p; r = (diag[i - 1] - g) * s + 2.0 * c * b;
204 p = s * r; diag[i] = g + p; g = c * r - b;
205 ql_rotate_vectors(Q, i, s, c);
207 diag[l] -= p; offdiag[l] = g; offdiag[m] = 0.0;
217 for (l = 0; l < n; l++) {
220 for (m = l; m < n - 1; m++) {
221 tst1 = lmmc_abs(diag[m]) + lmmc_abs(diag[m + 1]);
225 if (lmmc_abs(offdiag[m]) <= eps * tst1) {
236 tridiag_ql_step(diag, offdiag, l, m, Q);
243 size_t i, j, min_idx;
244 for (i = 0; i < n - 1; i++) {
246 for (j = i + 1; j < n; j++) {
247 if (eigenvalues[j] < eigenvalues[min_idx]) {
252 lmmc_swap(&eigenvalues[i], &eigenvalues[min_idx]);
254 for (j = 0; j < n; j++) {
264 size_t n = vectors->
rows;
267 for (ii = 0; ii < n - 1; ii++) {
270 offdiag[ii] = (off >= 0.0) ? off : -off;
272 if (sign_next < 0.0) {
274 for (jj = 0; jj < n; jj++) {
285 size_t n = work->
rows;
293 status = accumulate_q(work, taus, &result->
eigenvectors);
313 for (
size_t i = 0; i < n; ++i) {
314 for (
size_t j = 0; j < n; ++j) {
315 MAT_ELEM(&work, i, j) /= matrix_scale;
324 status = symmetric_reduce(&work, offdiag, result);
327 tridiag_positive_offdiagonal(offdiag, &result->
eigenvectors);
338 if (!lmmc_mat_descriptor_is_valid(a) || !out_result) {
360 status = symmetric_large(a, matrix_scale, out_result);
366 for (i = 0; i < n; ++i) {
LMMC binary real type and arithmetic spelling.
double lmmc_real_t
Public and internal LMMC real type.
lmmc_status_t lmmc_mat_copy(const lmmc_mat_t *src, lmmc_mat_t *dst)
逐元素复制矩阵内容:dst = src。
lmmc_status_t lmmc_mat_create(size_t rows, size_t cols, lmmc_mat_t *out_mat)
创建 rows x cols 的零矩阵。
lmmc_status_t lmmc_vec_create(size_t size, lmmc_vec_t *out_vec)
创建长度为 size 的零向量。
void lmmc_mat_destroy(lmmc_mat_t *mat)
销毁矩阵,释放其拥有的缓冲区并清零结构体字段。
void lmmc_vec_destroy(lmmc_vec_t *vec)
销毁向量,释放其拥有的缓冲区并清零字段。
void lmmc_eigen_sym_result_destroy(lmmc_eigen_sym_result_t *result)
释放 lmmc_eigen_symmetric 输出结果.
lmmc_status_t lmmc_eigen_symmetric(const lmmc_mat_t *a, lmmc_eigen_sym_result_t *out_result)
计算实对称矩阵的全部特征值与特征向量.
lmmc_status_t lmmc_eigen_matrix_scale(const lmmc_mat_t *a, lmmc_real_t *scale)
特征值 / SVD 模块内部共享的缩放、Householder 与 Givens 辅助接口(仅源文件可见)。
#define MAT_ELEM(mat, i, j)
稠密矩阵直接分解接口(LU、Cholesky、QR)。
void * lmmc_memory_alloc_array(size_t count, size_t element_size)
void lmmc_memory_free(void *pointer)
Private recoverable allocator for persistent LMMC ownership.
lmmc_status_t
LMMC 库统一返回的状态码.
@ LMMC_STATUS_CONVERGENCE_FAILED
@ LMMC_STATUS_NUMERICAL_FAILURE
@ LMMC_STATUS_ALLOCATION_FAILED
@ LMMC_STATUS_INVALID_ARGUMENT