LMMC
Lamina Mathematic core
载入中...
搜索中...
未找到
dense_elementwise.c
浏览该文件的文档.
1
5
6#include <math.h>
7#include "internal.h"
8#include "lmmc/config.h"
9#include "lmmc/dense.h"
10#include "lmmc/linear_algebra.h"
11
13 size_t i;
14 lmmc_real_t tmp_mul;
15
16 if (!lmmc_vec_descriptor_is_valid(a) ||
17 !lmmc_vec_descriptor_is_valid(b) ||
18 !lmmc_vec_descriptor_is_valid(c)) {
20 }
21 if (a->size != b->size || a->size != c->size) {
23 }
24
25 LMMC_REAL_INIT(&tmp_mul);
26
27 for (i = 0; i < a->size; ++i) {
28 LMMC_REAL_MUL(&tmp_mul, &a->data[i], &b->data[i]);
29 LMMC_REAL_SET(&c->data[i], &tmp_mul);
30 }
31
32 LMMC_REAL_CLEAR(&tmp_mul);
33 return LMMC_STATUS_OK;
34}
35
37 size_t i;
38 lmmc_real_t zero;
39 lmmc_real_t tmp_div;
40
41 if (!lmmc_vec_descriptor_is_valid(a) ||
42 !lmmc_vec_descriptor_is_valid(b) ||
43 !lmmc_vec_descriptor_is_valid(c)) {
45 }
46 if (a->size != b->size || a->size != c->size) {
48 }
49
50 /* Pre-scan b for zeros before writing any output */
51 LMMC_REAL_INIT(&zero);
52 LMMC_REAL_SET_D(&zero, 0.0);
53 for (i = 0; i < b->size; ++i) {
54 if (LMMC_REAL_CMP(&b->data[i], &zero) == 0) {
55 LMMC_REAL_CLEAR(&zero);
57 }
58 }
59 LMMC_REAL_CLEAR(&zero);
60
61 LMMC_REAL_INIT(&tmp_div);
62
63 for (i = 0; i < a->size; ++i) {
64 LMMC_REAL_DIV(&tmp_div, &a->data[i], &b->data[i]);
65 LMMC_REAL_SET(&c->data[i], &tmp_div);
66 }
67
68 LMMC_REAL_CLEAR(&tmp_div);
69 return LMMC_STATUS_OK;
70}
71
73 size_t i;
74
75 if (!lmmc_vec_descriptor_is_valid(a) ||
76 !lmmc_vec_descriptor_is_valid(b) ||
77 !lmmc_vec_descriptor_is_valid(c)) {
79 }
80 if (a->size != b->size || a->size != c->size) {
82 }
83
84 for (i = 0; i < a->size; ++i) {
85 c->data[i] = pow(a->data[i], b->data[i]);
86 }
87
88 return LMMC_STATUS_OK;
89}
90
92 size_t i, j;
93 lmmc_real_t tmp_mul;
94
95 if (!lmmc_mat_descriptor_is_valid(a) ||
96 !lmmc_mat_descriptor_is_valid(b) ||
97 !lmmc_mat_descriptor_is_valid(c)) {
99 }
100 if (a->rows != b->rows || a->cols != b->cols ||
101 a->rows != c->rows || a->cols != c->cols) {
103 }
104
105 LMMC_REAL_INIT(&tmp_mul);
106
107 for (i = 0; i < a->rows; ++i) {
108 for (j = 0; j < a->cols; ++j) {
109 LMMC_REAL_MUL(&tmp_mul,
110 &a->data[i * a->stride + j],
111 &b->data[i * b->stride + j]);
112 LMMC_REAL_SET(&c->data[i * c->stride + j], &tmp_mul);
113 }
114 }
115
116 LMMC_REAL_CLEAR(&tmp_mul);
117 return LMMC_STATUS_OK;
118}
119
121 size_t i, j;
122 lmmc_real_t zero;
123 lmmc_real_t tmp_div;
124
125 if (!lmmc_mat_descriptor_is_valid(a) ||
126 !lmmc_mat_descriptor_is_valid(b) ||
127 !lmmc_mat_descriptor_is_valid(c)) {
129 }
130 if (a->rows != b->rows || a->cols != b->cols ||
131 a->rows != c->rows || a->cols != c->cols) {
133 }
134
135 /* Pre-scan all elements of b for zeros before writing any output */
136 LMMC_REAL_INIT(&zero);
137 LMMC_REAL_SET_D(&zero, 0.0);
138 for (i = 0; i < b->rows; ++i) {
139 for (j = 0; j < b->cols; ++j) {
140 if (LMMC_REAL_CMP(&b->data[i * b->stride + j], &zero) == 0) {
141 LMMC_REAL_CLEAR(&zero);
143 }
144 }
145 }
146 LMMC_REAL_CLEAR(&zero);
147
148 LMMC_REAL_INIT(&tmp_div);
149
150 for (i = 0; i < a->rows; ++i) {
151 for (j = 0; j < a->cols; ++j) {
152 LMMC_REAL_DIV(&tmp_div,
153 &a->data[i * a->stride + j],
154 &b->data[i * b->stride + j]);
155 LMMC_REAL_SET(&c->data[i * c->stride + j], &tmp_div);
156 }
157 }
158
159 LMMC_REAL_CLEAR(&tmp_div);
160 return LMMC_STATUS_OK;
161}
162
164 size_t i, j;
165
166 if (!lmmc_mat_descriptor_is_valid(a) ||
167 !lmmc_mat_descriptor_is_valid(b) ||
168 !lmmc_mat_descriptor_is_valid(c)) {
170 }
171 if (a->rows != b->rows || a->cols != b->cols ||
172 a->rows != c->rows || a->cols != c->cols) {
174 }
175
176 for (i = 0; i < a->rows; ++i) {
177 for (j = 0; j < a->cols; ++j) {
178 c->data[i * c->stride + j] = pow(
179 a->data[i * a->stride + j],
180 b->data[i * b->stride + j]);
181 }
182 }
183
184 return LMMC_STATUS_OK;
185}
186
187lmmc_status_t lmmc_vec_cmp_gt(const lmmc_vec_t* a, const lmmc_vec_t* b, int* out) {
188 size_t i;
189
190 if (!lmmc_vec_descriptor_is_valid(a) ||
191 !lmmc_vec_descriptor_is_valid(b) || out == NULL) {
193 }
194 if (a->size != b->size) {
196 }
197
198 for (i = 0; i < a->size; ++i) {
199 out[i] = (LMMC_REAL_CMP(&a->data[i], &b->data[i]) > 0) ? 1 : 0;
200 }
201
202 return LMMC_STATUS_OK;
203}
204
205lmmc_status_t lmmc_vec_cmp_lt(const lmmc_vec_t* a, const lmmc_vec_t* b, int* out) {
206 size_t i;
207
208 if (!lmmc_vec_descriptor_is_valid(a) ||
209 !lmmc_vec_descriptor_is_valid(b) || out == NULL) {
211 }
212 if (a->size != b->size) {
214 }
215
216 for (i = 0; i < a->size; ++i) {
217 out[i] = (LMMC_REAL_CMP(&a->data[i], &b->data[i]) < 0) ? 1 : 0;
218 }
219
220 return LMMC_STATUS_OK;
221}
222
223lmmc_status_t lmmc_vec_cmp_ge(const lmmc_vec_t* a, const lmmc_vec_t* b, int* out) {
224 size_t i;
225
226 if (!lmmc_vec_descriptor_is_valid(a) ||
227 !lmmc_vec_descriptor_is_valid(b) || out == NULL) {
229 }
230 if (a->size != b->size) {
232 }
233
234 for (i = 0; i < a->size; ++i) {
235 out[i] = (LMMC_REAL_CMP(&a->data[i], &b->data[i]) >= 0) ? 1 : 0;
236 }
237
238 return LMMC_STATUS_OK;
239}
240
241lmmc_status_t lmmc_vec_cmp_le(const lmmc_vec_t* a, const lmmc_vec_t* b, int* out) {
242 size_t i;
243
244 if (!lmmc_vec_descriptor_is_valid(a) ||
245 !lmmc_vec_descriptor_is_valid(b) || out == NULL) {
247 }
248 if (a->size != b->size) {
250 }
251
252 for (i = 0; i < a->size; ++i) {
253 out[i] = (LMMC_REAL_CMP(&a->data[i], &b->data[i]) <= 0) ? 1 : 0;
254 }
255
256 return LMMC_STATUS_OK;
257}
258
260 size_t i;
261 lmmc_real_t diff;
262 lmmc_real_t abs_diff;
263
264 if (!lmmc_vec_descriptor_is_valid(a) ||
265 !lmmc_vec_descriptor_is_valid(b) || out == NULL) {
267 }
268 if (a->size != b->size) {
270 }
271
272 LMMC_REAL_INIT(&diff);
273 LMMC_REAL_INIT(&abs_diff);
274
275 for (i = 0; i < a->size; ++i) {
276 LMMC_REAL_SUB(&diff, &a->data[i], &b->data[i]);
277 LMMC_REAL_ABS(&abs_diff, &diff);
278 out[i] = (LMMC_REAL_CMP(&abs_diff, &tol) <= 0) ? 1 : 0;
279 }
280
281 LMMC_REAL_CLEAR(&diff);
282 LMMC_REAL_CLEAR(&abs_diff);
283 return LMMC_STATUS_OK;
284}
285
287{
288 lmmc_real_t t0, t1, t2;
289 lmmc_real_t mul1, mul2;
290
291 if (!lmmc_vec_descriptor_is_valid(a) ||
292 !lmmc_vec_descriptor_is_valid(b) ||
293 !lmmc_vec_descriptor_is_valid(c)) {
295 }
296 if (a->size != 3 || b->size != 3 || c->size != 3) {
298 }
299
300 LMMC_REAL_INIT(&t0);
301 LMMC_REAL_INIT(&t1);
302 LMMC_REAL_INIT(&t2);
303 LMMC_REAL_INIT(&mul1);
304 LMMC_REAL_INIT(&mul2);
305
306 /* c[0] = a[1]*b[2] - a[2]*b[1] */
307 LMMC_REAL_MUL(&mul1, &a->data[1], &b->data[2]);
308 LMMC_REAL_MUL(&mul2, &a->data[2], &b->data[1]);
309 LMMC_REAL_SUB(&t0, &mul1, &mul2);
310
311 /* c[1] = a[2]*b[0] - a[0]*b[2] */
312 LMMC_REAL_MUL(&mul1, &a->data[2], &b->data[0]);
313 LMMC_REAL_MUL(&mul2, &a->data[0], &b->data[2]);
314 LMMC_REAL_SUB(&t1, &mul1, &mul2);
315
316 /* c[2] = a[0]*b[1] - a[1]*b[0] */
317 LMMC_REAL_MUL(&mul1, &a->data[0], &b->data[1]);
318 LMMC_REAL_MUL(&mul2, &a->data[1], &b->data[0]);
319 LMMC_REAL_SUB(&t2, &mul1, &mul2);
320
321 /* Write results (safe for aliasing since we used temporaries) */
322 LMMC_REAL_SET(&c->data[0], &t0);
323 LMMC_REAL_SET(&c->data[1], &t1);
324 LMMC_REAL_SET(&c->data[2], &t2);
325
326 LMMC_REAL_CLEAR(&t0);
327 LMMC_REAL_CLEAR(&t1);
328 LMMC_REAL_CLEAR(&t2);
329 LMMC_REAL_CLEAR(&mul1);
330 LMMC_REAL_CLEAR(&mul2);
331 return LMMC_STATUS_OK;
332}
333
335{
336 size_t i;
337
338 if (!lmmc_vec_descriptor_is_valid(in) ||
339 !lmmc_vec_descriptor_is_valid(out) || func == NULL) {
341 }
342 if (in->size != out->size) {
344 }
345
346 for (i = 0; i < in->size; ++i) {
347 out->data[i] = func(in->data[i]);
348 }
349
350 return LMMC_STATUS_OK;
351}
352
354{
355 size_t i;
356 size_t j;
357
358 if (!lmmc_mat_descriptor_is_valid(in) ||
359 !lmmc_mat_descriptor_is_valid(out) || func == NULL) {
361 }
362 if (in->rows != out->rows || in->cols != out->cols) {
364 }
365
366 for (i = 0; i < in->rows; ++i) {
367 for (j = 0; j < in->cols; ++j) {
368 out->data[i * out->stride + j] = func(in->data[i * in->stride + j]);
369 }
370 }
371
372 return LMMC_STATUS_OK;
373}
374
376{
377 return lmmc_vec_apply(in, sin, out);
378}
379
381{
382 return lmmc_vec_apply(in, cos, out);
383}
384
386{
387 return lmmc_vec_apply(in, exp, out);
388}
389
391{
392 return lmmc_vec_apply(in, log, out);
393}
394
396{
397 return lmmc_vec_apply(in, sqrt, out);
398}
399
401{
402 return lmmc_vec_apply(in, fabs, out);
403}
404
406{
407 return lmmc_mat_apply(in, sin, out);
408}
409
411{
412 return lmmc_mat_apply(in, cos, out);
413}
414
416{
417 return lmmc_mat_apply(in, exp, out);
418}
419
421{
422 return lmmc_mat_apply(in, log, out);
423}
424
426{
427 return lmmc_mat_apply(in, sqrt, out);
428}
429
431{
432 return lmmc_mat_apply(in, fabs, out);
433}
434
LMMC binary real type and arithmetic spelling.
#define LMMC_REAL_CLEAR(x)
释放一个 lmmc_real_t 变量(POD 类型为空操作)。
#define LMMC_REAL_INIT(x)
初始化一个 lmmc_real_t 变量(POD 类型为空操作)。
#define LMMC_REAL_DIV(res, a, b)
计算 *res = *a / *b 。
#define LMMC_REAL_SUB(res, a, b)
计算 *res = *a - *b 。
double lmmc_real_t
Public and internal LMMC real type.
#define LMMC_REAL_SET(dst, src)
将一个 lmmc_real_t 赋值到另一个:*dst = *src 。
#define LMMC_REAL_MUL(res, a, b)
计算 *res = *a * *b 。
#define LMMC_REAL_ABS(res, a)
计算绝对值,*res = |*a| 。
#define LMMC_REAL_CMP(a, b)
比较 *a 与 *b ,返回 -1/0/1 。
#define LMMC_REAL_SET_D(dst, dbl)
将一个 double 字面量赋值到 lmmc_real_t 。
lmmc_status_t lmmc_vec_cross(const lmmc_vec_t *a, const lmmc_vec_t *b, lmmc_vec_t *c)
计算三维向量叉积: 。
lmmc_status_t lmmc_vec_apply_sqrt(const lmmc_vec_t *in, lmmc_vec_t *out)
对向量逐元素求平方根: 。
lmmc_status_t lmmc_vec_elementwise_div(const lmmc_vec_t *a, const lmmc_vec_t *b, lmmc_vec_t *c)
逐元素向量除法: 。
lmmc_status_t lmmc_vec_cmp_le(const lmmc_vec_t *a, const lmmc_vec_t *b, int *out)
逐元素向量小于等于比较: 。
lmmc_status_t lmmc_mat_apply(const lmmc_mat_t *in, lmmc_real_t(*func)(lmmc_real_t), lmmc_mat_t *out)
对矩阵逐元素应用标量函数: 。
lmmc_status_t lmmc_mat_apply_log(const lmmc_mat_t *in, lmmc_mat_t *out)
对矩阵逐元素求自然对数: 。
lmmc_status_t lmmc_mat_hadamard(const lmmc_mat_t *a, const lmmc_mat_t *b, lmmc_mat_t *c)
逐元素矩阵 Hadamard 乘积: 。
lmmc_status_t lmmc_vec_cmp_eq(const lmmc_vec_t *a, const lmmc_vec_t *b, lmmc_real_t tol, int *out)
逐元素向量近似相等比较: 。
lmmc_status_t lmmc_vec_cmp_ge(const lmmc_vec_t *a, const lmmc_vec_t *b, int *out)
逐元素向量大于等于比较: 。
lmmc_status_t lmmc_vec_hadamard(const lmmc_vec_t *a, const lmmc_vec_t *b, lmmc_vec_t *c)
逐元素向量 Hadamard 乘积: 。
lmmc_status_t lmmc_vec_cmp_gt(const lmmc_vec_t *a, const lmmc_vec_t *b, int *out)
逐元素向量大于比较: 。
lmmc_status_t lmmc_mat_elementwise_pow(const lmmc_mat_t *a, const lmmc_mat_t *b, lmmc_mat_t *c)
逐元素矩阵幂运算: 。
lmmc_status_t lmmc_vec_apply(const lmmc_vec_t *in, lmmc_real_t(*func)(lmmc_real_t), lmmc_vec_t *out)
对向量逐元素应用标量函数: 。
lmmc_status_t lmmc_mat_apply_sin(const lmmc_mat_t *in, lmmc_mat_t *out)
对矩阵逐元素求正弦: 。
lmmc_status_t lmmc_mat_apply_sqrt(const lmmc_mat_t *in, lmmc_mat_t *out)
对矩阵逐元素求平方根: 。
lmmc_status_t lmmc_vec_apply_cos(const lmmc_vec_t *in, lmmc_vec_t *out)
对向量逐元素求余弦: 。
lmmc_status_t lmmc_vec_elementwise_pow(const lmmc_vec_t *a, const lmmc_vec_t *b, lmmc_vec_t *c)
逐元素向量幂运算: 。
lmmc_status_t lmmc_vec_apply_exp(const lmmc_vec_t *in, lmmc_vec_t *out)
对向量逐元素求自然指数: 。
lmmc_status_t lmmc_mat_apply_exp(const lmmc_mat_t *in, lmmc_mat_t *out)
对矩阵逐元素求自然指数: 。
lmmc_status_t lmmc_mat_apply_cos(const lmmc_mat_t *in, lmmc_mat_t *out)
对矩阵逐元素求余弦: 。
lmmc_status_t lmmc_mat_apply_abs(const lmmc_mat_t *in, lmmc_mat_t *out)
对矩阵逐元素求绝对值: 。
lmmc_status_t lmmc_vec_cmp_lt(const lmmc_vec_t *a, const lmmc_vec_t *b, int *out)
逐元素向量小于比较: 。
lmmc_status_t lmmc_vec_apply_abs(const lmmc_vec_t *in, lmmc_vec_t *out)
对向量逐元素求绝对值: 。
lmmc_status_t lmmc_mat_elementwise_div(const lmmc_mat_t *a, const lmmc_mat_t *b, lmmc_mat_t *c)
逐元素矩阵除法: 。
lmmc_status_t lmmc_vec_apply_sin(const lmmc_vec_t *in, lmmc_vec_t *out)
对向量逐元素求正弦: 。
lmmc_status_t lmmc_vec_apply_log(const lmmc_vec_t *in, lmmc_vec_t *out)
对向量逐元素求自然对数: 。
lmmc_real_t * data
lmmc_real_t * data
行优先存储的稠密矩阵。
一维稠密向量。
LMMC 内部使用的公共工具(仅源文件可见).
稠密矩阵直接分解接口(LU、Cholesky、QR)。
lmmc_status_t
LMMC 库统一返回的状态码.
@ LMMC_STATUS_OK
@ LMMC_STATUS_NUMERICAL_FAILURE
@ LMMC_STATUS_DIMENSION_MISMATCH
@ LMMC_STATUS_INVALID_ARGUMENT