LMMC
Lamina Mathematic core
载入中...
搜索中...
未找到
eigen_svd_factorization.c
浏览该文件的文档.
1
5#include "eigen_internal.h"
6#include "memory_bridge.h"
7
13
14static void destroy_workspace(svd_workspace_t *work)
15{
16 lmmc_mat_destroy(&work->v);
17 lmmc_memory_free(work->d);
18 lmmc_memory_free(work->e);
19}
20
21static lmmc_status_t create_factors(size_t m, size_t n,
22 lmmc_svd_result_t *result)
23{
24 lmmc_status_t status = lmmc_mat_create(m, m, &result->U);
25 if (status != LMMC_STATUS_OK) return status;
26 status = lmmc_vec_create(n, &result->sigma);
27 if (status != LMMC_STATUS_OK) return status;
28 return lmmc_mat_create(n, n, &result->Vt);
29}
30
31static lmmc_status_t create_workspace(size_t n, svd_workspace_t *work)
32{
33 lmmc_status_t status = lmmc_mat_create(n, n, &work->v);
34 if (status != LMMC_STATUS_OK) return status;
35 work->d = lmmc_memory_alloc_array(n, sizeof(*work->d));
36 work->e = lmmc_memory_alloc_array(n, sizeof(*work->e));
37 if (!work->d || !work->e) return LMMC_STATUS_ALLOCATION_FAILED;
38 return LMMC_STATUS_OK;
39}
40
41static void normalize_signs(lmmc_real_t *d, lmmc_mat_t *v)
42{
43 for (size_t i = 0; i < v->cols; ++i) {
44 if (d[i] < 0.0) {
45 d[i] = -d[i];
46 for (size_t k = 0; k < v->rows; ++k) {
47 MAT_ELEM(v, k, i) = -MAT_ELEM(v, k, i);
48 }
49 }
50 }
51}
52
53static void descending_order(const lmmc_real_t *d, size_t n, size_t *order)
54{
55 for (size_t i = 0; i < n; ++i) order[i] = i;
56 for (size_t i = 0; i + 1 < n; ++i) {
57 size_t maximum = i;
58 for (size_t j = i + 1; j < n; ++j) {
59 if (d[order[j]] > d[order[maximum]]) maximum = j;
60 }
61 if (maximum != i) {
62 size_t tmp = order[i];
63 order[i] = order[maximum];
64 order[maximum] = tmp;
65 }
66 }
67}
68
69static lmmc_status_t reorder_left_vectors(lmmc_mat_t *u, size_t n,
70 const size_t *order)
71{
72 const size_t m = u->rows;
73 lmmc_real_t *columns = lmmc_memory_alloc_array_2d(m, n, sizeof(*columns));
74 if (!columns) return LMMC_STATUS_ALLOCATION_FAILED;
75 for (size_t j = 0; j < n; ++j) {
76 for (size_t i = 0; i < m; ++i) {
77 columns[j * m + i] = MAT_ELEM(u, i, j);
78 }
79 }
80 for (size_t j = 0; j < n; ++j) {
81 for (size_t i = 0; i < m; ++i) {
82 MAT_ELEM(u, i, j) = columns[order[j] * m + i];
83 }
84 }
85 lmmc_memory_free(columns);
86 return LMMC_STATUS_OK;
87}
88
89static lmmc_status_t assemble_factors(svd_workspace_t *work,
90 lmmc_svd_result_t *result)
91{
92 const size_t n = result->sigma.size;
93 normalize_signs(work->d, &work->v);
94 size_t *order = lmmc_memory_alloc_array(n, sizeof(*order));
95 if (!order) return LMMC_STATUS_ALLOCATION_FAILED;
96 descending_order(work->d, n, order);
97 for (size_t i = 0; i < n; ++i) {
98 result->sigma.data[i] = work->d[order[i]];
99 for (size_t k = 0; k < n; ++k) {
100 MAT_ELEM(&result->Vt, i, k) = MAT_ELEM(&work->v, k, order[i]);
101 }
102 }
103 lmmc_status_t status = reorder_left_vectors(&result->U, n, order);
104 lmmc_memory_free(order);
105 return status;
106}
107
109 lmmc_svd_result_t *result)
110{
111 svd_workspace_t work = {0};
112 lmmc_svd_result_t factors = {0};
113 lmmc_status_t status = create_factors(a->rows, a->cols, &factors);
114 if (status != LMMC_STATUS_OK) goto cleanup;
115 status = create_workspace(a->cols, &work);
116 if (status != LMMC_STATUS_OK) goto cleanup;
117 status = lmmc_svd_bidiagonalize(a, input_scale, work.d, work.e,
118 &factors.U, &work.v);
119 if (status != LMMC_STATUS_OK) goto cleanup;
120 status = lmmc_svd_diagonalize(work.d, work.e, a->cols, &factors.U, &work.v);
121 if (status != LMMC_STATUS_OK) goto cleanup;
122 status = assemble_factors(&work, &factors);
123cleanup:
124 destroy_workspace(&work);
125 if (status == LMMC_STATUS_OK) {
126 *result = factors;
127 } else {
128 lmmc_svd_result_destroy(&factors);
129 }
130 return status;
131}
double lmmc_real_t
Public and internal LMMC real type.
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)
销毁矩阵,释放其拥有的缓冲区并清零结构体字段。
lmmc_real_t * data
行优先存储的稠密矩阵。
lmmc_vec_t sigma
定义 eigen.h:54
void lmmc_svd_result_destroy(lmmc_svd_result_t *result)
释放 lmmc_svd 输出结果.
奇异值分解结果: .
定义 eigen.h:52
特征值 / SVD 模块内部共享的缩放、Householder 与 Givens 辅助接口(仅源文件可见)。
#define MAT_ELEM(mat, i, j)
lmmc_status_t lmmc_svd_bidiagonalize(const lmmc_mat_t *a, lmmc_real_t input_scale, lmmc_real_t *d, lmmc_real_t *e, lmmc_mat_t *u, lmmc_mat_t *v)
lmmc_status_t lmmc_svd_tall(const lmmc_mat_t *a, lmmc_real_t input_scale, lmmc_svd_result_t *result)
lmmc_status_t lmmc_svd_diagonalize(lmmc_real_t *d, lmmc_real_t *e, size_t n, lmmc_mat_t *u, lmmc_mat_t *v)
void * lmmc_memory_alloc_array(size_t count, size_t element_size)
void * lmmc_memory_alloc_array_2d(size_t rows, size_t cols, size_t element_size)
void lmmc_memory_free(void *pointer)
Private recoverable allocator for persistent LMMC ownership.
lmmc_status_t
LMMC 库统一返回的状态码.
@ LMMC_STATUS_OK
@ LMMC_STATUS_ALLOCATION_FAILED