LMMC
Lamina Mathematic core
载入中...
搜索中...
未找到
tensor3_ops.c
浏览该文件的文档.
1
6
8 size_t i = 0;
9 size_t j = 0;
10 size_t k = 0;
11 if (lmmc_tensor3_validate(tensor) != LMMC_STATUS_OK) {
13 }
14 for (i = 0; i < tensor->dim0; ++i) {
15 for (j = 0; j < tensor->dim1; ++j) {
16 for (k = 0; k < tensor->dim2; ++k) {
17 LMMC_REAL_SET(&tensor->data[i * tensor->stride0 + j * tensor->stride1 + k * tensor->stride2], &value);
18 }
19 }
20 }
21 return LMMC_STATUS_OK;
22}
23
26 if (lmmc_tensor3_validate(tensor) != LMMC_STATUS_OK || out_norm == NULL) {
28 }
29
30 lmmc_scaled_sumsq_init(&acc);
31 for (size_t i = 0; i < tensor->dim0; ++i) {
32 for (size_t j = 0; j < tensor->dim1; ++j) {
33 for (size_t k = 0; k < tensor->dim2; ++k) {
34 lmmc_scaled_sumsq_add(
35 &acc,
36 tensor->data[
37 i * tensor->stride0 +
38 j * tensor->stride1 +
39 k * tensor->stride2]);
40 }
41 }
42 }
43 *out_norm = lmmc_scaled_sumsq_norm(&acc);
44 return LMMC_STATUS_OK;
45}
46
48 size_t i = 0, j = 0, k = 0;
49 lmmc_status_t st = lmmc_tensor3_validate_binary(a, b, out_tensor);
50 lmmc_real_t vr;
51 LMMC_REAL_INIT(&vr);
52
53 if (st != LMMC_STATUS_OK) {
54 LMMC_REAL_CLEAR(&vr);
55 return st;
56 }
57
58 for (i = 0; i < a->dim0; ++i) {
59 for (j = 0; j < a->dim1; ++j) {
60 for (k = 0; k < a->dim2; ++k) {
61 lmmc_real_t* va = &a->data[i * a->stride0 + j * a->stride1 + k * a->stride2];
62 lmmc_real_t* vb = &b->data[i * b->stride0 + j * b->stride1 + k * b->stride2];
63 if (!lmmc_is_finite(va) || !lmmc_is_finite(vb)) {
64 LMMC_REAL_CLEAR(&vr);
66 }
67 LMMC_REAL_ADD(&vr, va, vb);
68 if (!lmmc_is_finite(&vr)) {
69 LMMC_REAL_CLEAR(&vr);
71 }
72 LMMC_REAL_SET(&out_tensor->data[i * out_tensor->stride0 + j * out_tensor->stride1 + k * out_tensor->stride2], &vr);
73 }
74 }
75 }
76 LMMC_REAL_CLEAR(&vr);
77 return LMMC_STATUS_OK;
78}
79
81 size_t i = 0, j = 0, k = 0;
82 lmmc_status_t st = lmmc_tensor3_validate_binary(a, b, out_tensor);
83 lmmc_real_t vr;
84 LMMC_REAL_INIT(&vr);
85
86 if (st != LMMC_STATUS_OK) {
87 LMMC_REAL_CLEAR(&vr);
88 return st;
89 }
90
91 for (i = 0; i < a->dim0; ++i) {
92 for (j = 0; j < a->dim1; ++j) {
93 for (k = 0; k < a->dim2; ++k) {
94 lmmc_real_t* va = &a->data[i * a->stride0 + j * a->stride1 + k * a->stride2];
95 lmmc_real_t* vb = &b->data[i * b->stride0 + j * b->stride1 + k * b->stride2];
96 if (!lmmc_is_finite(va) || !lmmc_is_finite(vb)) {
97 LMMC_REAL_CLEAR(&vr);
99 }
100 LMMC_REAL_SUB(&vr, va, vb);
101 if (!lmmc_is_finite(&vr)) {
102 LMMC_REAL_CLEAR(&vr);
104 }
105 LMMC_REAL_SET(&out_tensor->data[i * out_tensor->stride0 + j * out_tensor->stride1 + k * out_tensor->stride2], &vr);
106 }
107 }
108 }
109 LMMC_REAL_CLEAR(&vr);
110 return LMMC_STATUS_OK;
111}
112
114 size_t i = 0, j = 0, k = 0;
115 lmmc_status_t st = lmmc_tensor3_validate_binary(a, b, out_tensor);
116 lmmc_real_t vr;
117 LMMC_REAL_INIT(&vr);
118
119 if (st != LMMC_STATUS_OK) {
120 LMMC_REAL_CLEAR(&vr);
121 return st;
122 }
123
124 for (i = 0; i < a->dim0; ++i) {
125 for (j = 0; j < a->dim1; ++j) {
126 for (k = 0; k < a->dim2; ++k) {
127 lmmc_real_t* va = &a->data[i * a->stride0 + j * a->stride1 + k * a->stride2];
128 lmmc_real_t* vb = &b->data[i * b->stride0 + j * b->stride1 + k * b->stride2];
129 if (!lmmc_is_finite(va) || !lmmc_is_finite(vb)) {
130 LMMC_REAL_CLEAR(&vr);
132 }
133 LMMC_REAL_MUL(&vr, va, vb);
134 if (!lmmc_is_finite(&vr)) {
135 LMMC_REAL_CLEAR(&vr);
137 }
138 LMMC_REAL_SET(&out_tensor->data[i * out_tensor->stride0 + j * out_tensor->stride1 + k * out_tensor->stride2], &vr);
139 }
140 }
141 }
142 LMMC_REAL_CLEAR(&vr);
143 return LMMC_STATUS_OK;
144}
145
147 size_t i = 0, j = 0, k = 0;
148 lmmc_status_t st = lmmc_tensor3_validate_binary(a, b, out_tensor);
149 lmmc_real_t vr, zero;
150 LMMC_REAL_INIT(&vr);
151 LMMC_REAL_INIT(&zero);
152
153 if (st != LMMC_STATUS_OK) {
154 LMMC_REAL_CLEAR(&vr);
155 LMMC_REAL_CLEAR(&zero);
156 return st;
157 }
158 LMMC_REAL_SET_D(&zero, 0.0);
159
160 for (i = 0; i < a->dim0; ++i) {
161 for (j = 0; j < a->dim1; ++j) {
162 for (k = 0; k < a->dim2; ++k) {
163 lmmc_real_t* va = &a->data[i * a->stride0 + j * a->stride1 + k * a->stride2];
164 lmmc_real_t* vb = &b->data[i * b->stride0 + j * b->stride1 + k * b->stride2];
165 if (!lmmc_is_finite(va) || !lmmc_is_finite(vb) || LMMC_REAL_CMP(vb, &zero) == 0) {
166 LMMC_REAL_CLEAR(&vr);
167 LMMC_REAL_CLEAR(&zero);
169 }
170 LMMC_REAL_DIV(&vr, va, vb);
171 if (!lmmc_is_finite(&vr)) {
172 LMMC_REAL_CLEAR(&vr);
173 LMMC_REAL_CLEAR(&zero);
175 }
176 LMMC_REAL_SET(&out_tensor->data[i * out_tensor->stride0 + j * out_tensor->stride1 + k * out_tensor->stride2], &vr);
177 }
178 }
179 }
180 LMMC_REAL_CLEAR(&vr);
181 LMMC_REAL_CLEAR(&zero);
182 return LMMC_STATUS_OK;
183}
184
186 size_t i = 0, j = 0, k = 0;
187 lmmc_real_t vr;
188 LMMC_REAL_INIT(&vr);
189 if (lmmc_tensor3_validate(tensor) != LMMC_STATUS_OK || lmmc_tensor3_validate(out_tensor) != LMMC_STATUS_OK) {
190 LMMC_REAL_CLEAR(&vr);
192 }
193 if (!lmmc_tensor3_same_shape(tensor, out_tensor)) {
194 LMMC_REAL_CLEAR(&vr);
196 }
197 if (!lmmc_is_finite(&alpha)) {
198 LMMC_REAL_CLEAR(&vr);
200 }
201
202 for (i = 0; i < tensor->dim0; ++i) {
203 for (j = 0; j < tensor->dim1; ++j) {
204 for (k = 0; k < tensor->dim2; ++k) {
205 lmmc_real_t* v = &tensor->data[i * tensor->stride0 + j * tensor->stride1 + k * tensor->stride2];
206 if (!lmmc_is_finite(v)) {
207 LMMC_REAL_CLEAR(&vr);
209 }
210 LMMC_REAL_MUL(&vr, v, &alpha);
211 if (!lmmc_is_finite(&vr)) {
212 LMMC_REAL_CLEAR(&vr);
214 }
215 LMMC_REAL_SET(&out_tensor->data[i * out_tensor->stride0 + j * out_tensor->stride1 + k * out_tensor->stride2], &vr);
216 }
217 }
218 }
219 LMMC_REAL_CLEAR(&vr);
220 return LMMC_STATUS_OK;
221}
222
224 size_t i = 0, j = 0, k = 0;
225 lmmc_real_t sum, tmp_sum;
226 LMMC_REAL_INIT(&sum);
227 LMMC_REAL_INIT(&tmp_sum);
228 if (lmmc_tensor3_validate(tensor) != LMMC_STATUS_OK || out_sum == NULL) {
229 LMMC_REAL_CLEAR(&sum);
230 LMMC_REAL_CLEAR(&tmp_sum);
232 }
233 LMMC_REAL_SET_D(&sum, 0.0);
234
235 for (i = 0; i < tensor->dim0; ++i) {
236 for (j = 0; j < tensor->dim1; ++j) {
237 for (k = 0; k < tensor->dim2; ++k) {
238 lmmc_real_t* v = &tensor->data[i * tensor->stride0 + j * tensor->stride1 + k * tensor->stride2];
239 if (!lmmc_is_finite(v)) {
240 LMMC_REAL_CLEAR(&sum);
241 LMMC_REAL_CLEAR(&tmp_sum);
243 }
244 LMMC_REAL_ADD(&tmp_sum, &sum, v);
245 LMMC_REAL_SET(&sum, &tmp_sum);
246 if (!lmmc_is_finite(&sum)) {
247 LMMC_REAL_CLEAR(&sum);
248 LMMC_REAL_CLEAR(&tmp_sum);
250 }
251 }
252 }
253 }
254 LMMC_REAL_SET(out_sum, &sum);
255 LMMC_REAL_CLEAR(&sum);
256 LMMC_REAL_CLEAR(&tmp_sum);
257 return LMMC_STATUS_OK;
258}
259
261 size_t i = 0, j = 0, k = 0;
262 lmmc_real_t max_v;
263 LMMC_REAL_INIT(&max_v);
264 if (lmmc_tensor3_validate(tensor) != LMMC_STATUS_OK || out_max == NULL) {
265 LMMC_REAL_CLEAR(&max_v);
267 }
268 LMMC_REAL_SET(&max_v, &tensor->data[0]);
269 if (!lmmc_is_finite(&max_v)) {
270 LMMC_REAL_CLEAR(&max_v);
272 }
273
274 for (i = 0; i < tensor->dim0; ++i) {
275 for (j = 0; j < tensor->dim1; ++j) {
276 for (k = 0; k < tensor->dim2; ++k) {
277 lmmc_real_t* v = &tensor->data[i * tensor->stride0 + j * tensor->stride1 + k * tensor->stride2];
278 if (!lmmc_is_finite(v)) {
279 LMMC_REAL_CLEAR(&max_v);
281 }
282 if (LMMC_REAL_CMP(v, &max_v) > 0) {
283 LMMC_REAL_SET(&max_v, v);
284 }
285 }
286 }
287 }
288 LMMC_REAL_SET(out_max, &max_v);
289 LMMC_REAL_CLEAR(&max_v);
290 return LMMC_STATUS_OK;
291}
292
294 size_t i = 0, j = 0, k = 0;
295 lmmc_real_t min_v;
296 LMMC_REAL_INIT(&min_v);
297 if (lmmc_tensor3_validate(tensor) != LMMC_STATUS_OK || out_min == NULL) {
298 LMMC_REAL_CLEAR(&min_v);
300 }
301 LMMC_REAL_SET(&min_v, &tensor->data[0]);
302 if (!lmmc_is_finite(&min_v)) {
303 LMMC_REAL_CLEAR(&min_v);
305 }
306
307 for (i = 0; i < tensor->dim0; ++i) {
308 for (j = 0; j < tensor->dim1; ++j) {
309 for (k = 0; k < tensor->dim2; ++k) {
310 lmmc_real_t* v = &tensor->data[i * tensor->stride0 + j * tensor->stride1 + k * tensor->stride2];
311 if (!lmmc_is_finite(v)) {
312 LMMC_REAL_CLEAR(&min_v);
314 }
315 if (LMMC_REAL_CMP(v, &min_v) < 0) {
316 LMMC_REAL_SET(&min_v, v);
317 }
318 }
319 }
320 }
321 LMMC_REAL_SET(out_min, &min_v);
322 LMMC_REAL_CLEAR(&min_v);
323 return LMMC_STATUS_OK;
324}
325
326static lmmc_status_t lmmc_tensor3_validate_axis_sum(
327 const lmmc_tensor3_t* tensor, size_t axis, const lmmc_mat_t* out_matrix) {
328 if (lmmc_tensor3_validate(tensor) != LMMC_STATUS_OK ||
329 !lmmc_mat_descriptor_is_valid(out_matrix)) {
331 }
332 if (axis > 2) {
334 }
335 const size_t rows = axis == 0 ? tensor->dim1 : tensor->dim0;
336 const size_t cols = axis == 2 ? tensor->dim1 : tensor->dim2;
337 if (out_matrix->rows != rows || out_matrix->cols != cols) {
339 }
340 return LMMC_STATUS_OK;
341}
342
343static lmmc_status_t lmmc_tensor3_sum_line(
344 const lmmc_real_t* data, size_t count, size_t stride,
345 lmmc_real_t* sum, lmmc_real_t* tmp_sum) {
346 LMMC_REAL_SET_D(sum, 0.0);
347 for (size_t i = 0; i < count; ++i) {
348 const lmmc_real_t* v = &data[i * stride];
349 if (!lmmc_is_finite(v)) {
351 }
352 LMMC_REAL_ADD(tmp_sum, sum, v);
353 LMMC_REAL_SET(sum, tmp_sum);
354 if (!lmmc_is_finite(sum)) {
356 }
357 }
358 return LMMC_STATUS_OK;
359}
360
362 const lmmc_tensor3_t* tensor, size_t axis, lmmc_mat_t* out_matrix) {
363 lmmc_real_t sum, tmp_sum;
364 LMMC_REAL_INIT(&sum);
365 LMMC_REAL_INIT(&tmp_sum);
366 lmmc_status_t st = lmmc_tensor3_validate_axis_sum(tensor, axis, out_matrix);
367 if (st == LMMC_STATUS_OK) {
368 const size_t dims[3] = {tensor->dim0, tensor->dim1, tensor->dim2};
369 const size_t strides[3] = {tensor->stride0, tensor->stride1, tensor->stride2};
370 const size_t row_stride = axis == 0 ? tensor->stride1 : tensor->stride0;
371 const size_t col_stride = axis == 2 ? tensor->stride1 : tensor->stride2;
372 for (size_t row = 0; row < out_matrix->rows; ++row) {
373 for (size_t col = 0; col < out_matrix->cols; ++col) {
374 const size_t offset = row * row_stride + col * col_stride;
375 st = lmmc_tensor3_sum_line(
376 &tensor->data[offset], dims[axis], strides[axis], &sum, &tmp_sum);
377 if (st != LMMC_STATUS_OK) {
378 goto done;
379 }
380 LMMC_REAL_SET(&out_matrix->data[row * out_matrix->stride + col], &sum);
381 }
382 }
383 }
384done:
385 LMMC_REAL_CLEAR(&sum);
386 LMMC_REAL_CLEAR(&tmp_sum);
387 return st;
388}
#define LMMC_REAL_CLEAR(x)
释放一个 lmmc_real_t 变量(POD 类型为空操作)。
#define LMMC_REAL_INIT(x)
初始化一个 lmmc_real_t 变量(POD 类型为空操作)。
#define LMMC_REAL_ADD(res, a, b)
计算 *res = *a + *b 。
#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_CMP(a, b)
比较 *a 与 *b ,返回 -1/0/1 。
#define LMMC_REAL_SET_D(dst, dbl)
将一个 double 字面量赋值到 lmmc_real_t 。
lmmc_real_t * data
行优先存储的稠密矩阵。
lmmc_status_t
LMMC 库统一返回的状态码.
@ LMMC_STATUS_OK
@ LMMC_STATUS_NUMERICAL_FAILURE
@ LMMC_STATUS_DIMENSION_MISMATCH
@ LMMC_STATUS_INVALID_ARGUMENT
lmmc_status_t lmmc_tensor3_sum(const lmmc_tensor3_t *tensor, lmmc_real_t *out_sum)
累加全部元素。
lmmc_status_t lmmc_tensor3_add(const lmmc_tensor3_t *a, const lmmc_tensor3_t *b, lmmc_tensor3_t *out_tensor)
同形状张量逐元素加法。
lmmc_status_t lmmc_tensor3_sum_axis(const lmmc_tensor3_t *tensor, size_t axis, lmmc_mat_t *out_matrix)
沿指定轴求和,结果为二维矩阵。
lmmc_status_t lmmc_tensor3_min(const lmmc_tensor3_t *tensor, lmmc_real_t *out_min)
求最小元素。
lmmc_status_t lmmc_tensor3_div(const lmmc_tensor3_t *a, const lmmc_tensor3_t *b, lmmc_tensor3_t *out_tensor)
同形状张量逐元素除法,b 中元素须非零。
lmmc_status_t lmmc_tensor3_fill(lmmc_tensor3_t *tensor, lmmc_real_t value)
用 value 填充张量所有元素。
lmmc_status_t lmmc_tensor3_scale(const lmmc_tensor3_t *tensor, lmmc_real_t alpha, lmmc_tensor3_t *out_tensor)
标量乘:out = alpha * tensor。
lmmc_status_t lmmc_tensor3_sub(const lmmc_tensor3_t *a, const lmmc_tensor3_t *b, lmmc_tensor3_t *out_tensor)
同形状张量逐元素减法。
lmmc_status_t lmmc_tensor3_max(const lmmc_tensor3_t *tensor, lmmc_real_t *out_max)
求最大元素。
lmmc_status_t lmmc_tensor3_mul(const lmmc_tensor3_t *a, const lmmc_tensor3_t *b, lmmc_tensor3_t *out_tensor)
同形状张量逐元素乘法(Hadamard)。
lmmc_real_t * data
lmmc_status_t lmmc_tensor3_norm_fro(const lmmc_tensor3_t *tensor, lmmc_real_t *out_norm)
用缩放平方和计算张量 Frobenius 范数。
三阶张量结构。
三阶张量描述符的公共检查。