LMMC
Lamina Mathematic core
载入中...
搜索中...
未找到
eigen_general_small.c
浏览该文件的文档.
1#include <math.h>
2#include <string.h>
3#include "memory_bridge.h"
4#include "internal.h"
5#include "eigen_internal.h"
6#include "lmmc/config.h"
7#include "lmmc/dense.h"
8#include "lmmc/eigen.h"
11
12static void real_null_vector(lmmc_real_t a00, lmmc_real_t a01,
14 lmmc_real_t* v0, lmmc_real_t* v1)
15{
16 lmmc_real_t r0_diag = lmmc_abs(a00 - lam);
17 lmmc_real_t r1_diag = lmmc_abs(a11 - lam);
18 lmmc_real_t r0_off = lmmc_abs(a01);
19 lmmc_real_t r1_off = lmmc_abs(a10);
20 if (r0_off > 1e-15 || r0_diag > 1e-15) {
21 if (r0_off >= r0_diag || r0_off >= 1e-15) {
22 *v0 = -a01;
23 *v1 = a00 - lam;
24 } else {
25 *v0 = (r0_diag > 1e-15) ? 0.0 : 1.0;
26 *v1 = (r0_diag > 1e-15) ? 1.0 : 0.0;
27 }
28 return;
29 }
30 if (r1_off > 1e-15 || r1_diag > 1e-15) {
31 if (r1_diag > 1e-15) {
32 *v0 = 1.0;
33 *v1 = -a10 / (a11 - lam);
34 } else {
35 *v0 = 0.0;
36 *v1 = 1.0;
37 }
38 return;
39 }
40 *v0 = 1.0;
41 *v1 = 0.0;
42}
43
44static void real_vectors_2x2(lmmc_real_t a00, lmmc_real_t a01,
45 lmmc_real_t a10, lmmc_real_t a11, lmmc_real_t matrix_scale,
47{
48 for (size_t i = 0; i < 2; i++) {
49 lmmc_real_t lam = out_result->real_parts.data[i] / matrix_scale;
50 lmmc_real_t v0, v1, nrm;
51 real_null_vector(a00, a01, a10, a11, lam, &v0, &v1);
52 nrm = hypot(v0, v1);
53 if (nrm == 0.0) { v0 = 1.0; v1 = 0.0; nrm = 1.0; }
54 MAT_ELEM(&out_result->vectors_real, 0, i) = v0 / nrm;
55 MAT_ELEM(&out_result->vectors_real, 1, i) = v1 / nrm;
56 MAT_ELEM(&out_result->vectors_imag, 0, i) = 0.0;
57 MAT_ELEM(&out_result->vectors_imag, 1, i) = 0.0;
58 }
59}
60
61static void complex_vectors_2x2(lmmc_real_t a00, lmmc_real_t a01,
62 lmmc_real_t a10, lmmc_real_t a11, lmmc_real_t matrix_scale,
64{
65 lmmc_real_t tr = a00 + a11;
66 lmmc_real_t sq =
67 out_result->imag_parts.data[0] / matrix_scale;
68 out_result->real_parts.data[0] = tr * 0.5 * matrix_scale;
69 out_result->imag_parts.data[0] = sq * matrix_scale;
70 out_result->real_parts.data[1] = tr * 0.5 * matrix_scale;
71 out_result->imag_parts.data[1] = -sq * matrix_scale;
72
78 lmmc_real_t re_part = tr * 0.5 - a00;
79 if (lmmc_abs(a01) > lmmc_abs(a10)) {
81 lmmc_real_t vr0 = a01;
82 lmmc_real_t vr1 = re_part;
83 lmmc_real_t vi0 = 0.0;
84 lmmc_real_t vi1 = sq;
85 lmmc_real_t nrm = hypot(hypot(vr0, vr1), hypot(vi0, vi1));
86 if (nrm == 0.0) {
87 nrm = 1.0;
88 }
89 MAT_ELEM(&out_result->vectors_real, 0, 0) = vr0 / nrm;
90 MAT_ELEM(&out_result->vectors_real, 1, 0) = vr1 / nrm;
91 MAT_ELEM(&out_result->vectors_imag, 0, 0) = vi0 / nrm;
92 MAT_ELEM(&out_result->vectors_imag, 1, 0) = vi1 / nrm;
93 } else {
95 lmmc_real_t vr0 = tr * 0.5 - a11;
96 lmmc_real_t vr1 = a10;
97 lmmc_real_t vi0 = sq;
98 lmmc_real_t vi1 = 0.0;
99 lmmc_real_t nrm = hypot(hypot(vr0, vr1), hypot(vi0, vi1));
100 if (nrm == 0.0) {
101 nrm = 1.0;
102 }
103 MAT_ELEM(&out_result->vectors_real, 0, 0) = vr0 / nrm;
104 MAT_ELEM(&out_result->vectors_real, 1, 0) = vr1 / nrm;
105 MAT_ELEM(&out_result->vectors_imag, 0, 0) = vi0 / nrm;
106 MAT_ELEM(&out_result->vectors_imag, 1, 0) = vi1 / nrm;
107 }
109 MAT_ELEM(&out_result->vectors_real, 0, 1) = MAT_ELEM(&out_result->vectors_real, 0, 0);
110 MAT_ELEM(&out_result->vectors_real, 1, 1) = MAT_ELEM(&out_result->vectors_real, 1, 0);
111 MAT_ELEM(&out_result->vectors_imag, 0, 1) = -MAT_ELEM(&out_result->vectors_imag, 0, 0);
112 MAT_ELEM(&out_result->vectors_imag, 1, 1) = -MAT_ELEM(&out_result->vectors_imag, 1, 0);
113}
114
117{
118 lmmc_real_t a00 = MAT_ELEM(a, 0, 0) / matrix_scale;
119 lmmc_real_t a01 = MAT_ELEM(a, 0, 1) / matrix_scale;
120 lmmc_real_t a10 = MAT_ELEM(a, 1, 0) / matrix_scale;
121 lmmc_real_t a11 = MAT_ELEM(a, 1, 1) / matrix_scale;
123 a00, a01, a10, a11,
124 &out_result->real_parts.data[0],
125 &out_result->imag_parts.data[0],
126 &out_result->real_parts.data[1],
127 &out_result->imag_parts.data[1]);
128 out_result->real_parts.data[0] *= matrix_scale;
129 out_result->imag_parts.data[0] *= matrix_scale;
130 out_result->real_parts.data[1] *= matrix_scale;
131 out_result->imag_parts.data[1] *= matrix_scale;
132if (out_result->imag_parts.data[0] == 0.0) {
133 real_vectors_2x2(a00, a01, a10, a11, matrix_scale, out_result);
134 } else {
135 complex_vectors_2x2(a00, a01, a10, a11, matrix_scale, out_result);
136 }
137}
LMMC binary real type and arithmetic spelling.
double lmmc_real_t
Public and internal LMMC real type.
lmmc_real_t * data
行优先存储的稠密矩阵。
特征值 / 奇异值分解,伪逆与条件数接口.
一般实矩阵完整特征分解结果(特征值 + 特征向量).
定义 eigen.h:42
void lmmc_eigen_values_2x2(lmmc_real_t a00, lmmc_real_t a01, lmmc_real_t a10, lmmc_real_t a11, lmmc_real_t *real0, lmmc_real_t *imag0, lmmc_real_t *real1, lmmc_real_t *imag1)
void lmmc_eigen_vectors_2x2(const lmmc_mat_t *a, lmmc_real_t scale, lmmc_eigen_gen_full_result_t *result)
特征值 / SVD 模块内部共享的缩放、Householder 与 Givens 辅助接口(仅源文件可见)。
#define MAT_ELEM(mat, i, j)
LMMC 内部使用的公共工具(仅源文件可见).
稠密矩阵直接分解接口(LU、Cholesky、QR)。
Private recoverable allocator for persistent LMMC ownership.