LMMC
Lamina Mathematic core
载入中...
搜索中...
未找到
internal.h
浏览该文件的文档.
1
9#ifndef LMMC_INTERNAL_H
10#define LMMC_INTERNAL_H
11
12#include "lmmc/config.h"
13#include <stddef.h>
14#include <stdint.h>
15#include "lmmc/dense.h"
16#include <math.h>
17
23static inline double lmmc_two_sum(double a, double b, double* residual)
24{
25 const double sum = a + b;
26 const double virtual_b = sum - a;
27 *residual = (a - (sum - virtual_b)) + (b - virtual_b);
28 return sum;
29}
30
32static inline void lmmc_compensated_add(double value, double* sum, double* correction)
33{
34 double residual;
35 *sum = lmmc_two_sum(*sum, value, &residual);
36 *correction += residual;
37}
38
39typedef struct lmmc_rng_t lmmc_rng_t;
40
43
45void lmmc_rng_default_reset(void);
46
47static inline void lmmc_fill_identity_unchecked(lmmc_mat_t* matrix)
48{
49 lmmc_real_t zero = 0.0;
50 lmmc_real_t one = 1.0;
51 for (size_t row = 0; row < matrix->rows; ++row) {
52 for (size_t column = 0; column < matrix->cols; ++column) {
53 LMMC_REAL_SET(&matrix->data[row * matrix->stride + column],
54 row == column ? &one : &zero);
55 }
56 }
57}
58
59static inline int lmmc_is_power_of_four(
60 size_t value, unsigned* out_digits)
61{
62 size_t remaining = value;
63 unsigned digits = 0;
64 if (value == 0) {
65 return 0;
66 }
67 while ((remaining & (size_t)3) == 0) {
68 remaining >>= 2;
69 ++digits;
70 }
71 if (remaining != (size_t)1) {
72 return 0;
73 }
74 if (out_digits != NULL) {
75 *out_digits = digits;
76 }
77 return 1;
78}
86static inline int lmmc_safe_mul_size(size_t a, size_t b, size_t *result)
87{
88 if (a == 0 || b == 0) {
89 *result = 0;
90 return 1;
91 }
92 if (a > SIZE_MAX / b) {
93 return 0;
94 }
95 *result = a * b;
96 return 1;
97}
98
104static inline int lmmc_safe_add_size(size_t a, size_t b, size_t *result)
105{
106 if (a > SIZE_MAX - b) {
107 return 0;
108 }
109 *result = a + b;
110 return 1;
111}
112
113
114typedef struct lmmc_storage_envelope {
115 uintptr_t begin;
116 uintptr_t end;
118
125static inline int lmmc_storage_envelope_checked(
126 const void *data,
127 size_t rows,
128 size_t cols,
129 size_t stride,
130 size_t element_size,
132{
133 size_t last_row;
134 size_t elements;
135 size_t bytes;
136 uintptr_t begin;
137
138 if (data == NULL || out == NULL) {
139 return 0;
140 }
141 begin = (uintptr_t)data;
142 out->begin = begin;
143 out->end = begin;
144 if (rows == 0 || cols == 0) {
145 return 1;
146 }
147 if (!lmmc_safe_mul_size(rows - 1, stride, &last_row)) {
148 return 0;
149 }
150 if (!lmmc_safe_add_size(last_row, cols, &elements)) {
151 return 0;
152 }
153 if (!lmmc_safe_mul_size(elements, element_size, &bytes)) {
154 return 0;
155 }
156 if ((uintptr_t)bytes > UINTPTR_MAX - begin) {
157 return 0;
158 }
159 out->end = begin + (uintptr_t)bytes;
160 return 1;
161}
162
171static inline int lmmc_mat_descriptor_is_valid(const lmmc_mat_t *matrix)
172{
174 return matrix != NULL && matrix->data != NULL &&
175 matrix->rows != 0 && matrix->cols != 0 &&
176 matrix->stride >= matrix->cols &&
177 lmmc_storage_envelope_checked(
178 matrix->data, matrix->rows, matrix->cols, matrix->stride,
179 sizeof(lmmc_real_t), &envelope);
180}
181
183static inline int lmmc_vec_descriptor_is_valid(const lmmc_vec_t *vector)
184{
186 return vector != NULL && vector->data != NULL && vector->size != 0 &&
187 lmmc_storage_envelope_checked(
188 vector->data, 1, vector->size, vector->size,
189 sizeof(lmmc_real_t), &envelope);
190}
191
193static inline int lmmc_storage_envelopes_overlap(
194 const lmmc_storage_envelope_t *left,
195 const lmmc_storage_envelope_t *right)
196{
197 return left->begin < right->end && right->begin < left->end;
198}
199
201static inline int lmmc_is_finite(const lmmc_real_t *x)
202{
203 return LMMC_REAL_IS_FINITE(x) ? 1 : 0;
204}
205
206static inline int lmmc_real_range_is_finite(
207 const lmmc_real_t* values, size_t count)
208{
209 if (values == NULL) {
210 return 0;
211 }
212 for (size_t index = 0; index < count; ++index) {
213 if (!lmmc_is_finite(&values[index])) {
214 return 0;
215 }
216 }
217 return 1;
218}
219
220static inline void lmmc_interval_center_half_width(
221 lmmc_real_t left, lmmc_real_t right,
222 lmmc_real_t* center, lmmc_real_t* half_width)
223{
224 if ((left < 0.0 && right > 0.0) ||
225 (left > 0.0 && right < 0.0)) {
226 *center = left * 0.5 + right * 0.5;
227 *half_width = right * 0.5 - left * 0.5;
228 return;
229 }
230 *half_width = (right - left) * 0.5;
231 *center = left + *half_width;
232}
233
234static inline lmmc_real_t lmmc_interval_midpoint(
235 lmmc_real_t left, lmmc_real_t right)
236{
237 lmmc_real_t center;
238 lmmc_real_t half_width;
239 lmmc_interval_center_half_width(
240 left, right, &center, &half_width);
241 return center;
242}
243
251typedef struct lmmc_scaled_sumsq {
255
256static inline void lmmc_scaled_sumsq_init(lmmc_scaled_sumsq_t *acc)
257{
258 acc->scale = 0.0;
259 acc->sumsq = 1.0;
260}
261
262static inline void lmmc_scaled_sumsq_add(
264{
265 lmmc_real_t magnitude = fabs(value);
266 if (isnan(acc->scale)) {
267 return;
268 }
269 if (isnan(magnitude)) {
270 acc->scale = magnitude;
271 acc->sumsq = 1.0;
272 return;
273 }
274 if (magnitude == 0.0 || isinf(acc->scale)) {
275 return;
276 }
277 if (isinf(magnitude)) {
278 acc->scale = magnitude;
279 acc->sumsq = 1.0;
280 return;
281 }
282 if (acc->scale < magnitude) {
283 lmmc_real_t ratio = acc->scale / magnitude;
284 acc->sumsq = 1.0 + acc->sumsq * ratio * ratio;
285 acc->scale = magnitude;
286 } else {
287 lmmc_real_t ratio = magnitude / acc->scale;
288 acc->sumsq += ratio * ratio;
289 }
290}
291
292static inline lmmc_real_t lmmc_scaled_sumsq_norm(
293 const lmmc_scaled_sumsq_t *acc)
294{
295 return acc->scale == 0.0 ? 0.0 : acc->scale * sqrt(acc->sumsq);
296}
297
299static inline lmmc_real_t lmmc_abs(lmmc_real_t x)
300{
301 return fabs(x);
302}
303
305static inline lmmc_real_t lmmc_max(lmmc_real_t a, lmmc_real_t b)
306{
307 return (a >= b) ? a : b;
308}
309
311static inline lmmc_real_t lmmc_clamp(lmmc_real_t x, lmmc_real_t lo, lmmc_real_t hi)
312{
313 if (x < lo) {
314 return lo;
315 }
316 if (x > hi) {
317 return hi;
318 }
319 return x;
320}
321
323static inline void lmmc_swap(lmmc_real_t *a, lmmc_real_t *b)
324{
325 lmmc_real_t tmp = *a;
326 *a = *b;
327 *b = tmp;
328}
329
330#endif
LMMC binary real type and arithmetic spelling.
double lmmc_real_t
Public and internal LMMC real type.
#define LMMC_REAL_SET(dst, src)
将一个 lmmc_real_t 赋值到另一个:*dst = *src 。
#define LMMC_REAL_IS_FINITE(x)
判断 *x 是否为有限数。
lmmc_real_t * data
lmmc_real_t * data
行优先存储的稠密矩阵。
一维稠密向量。
void lmmc_rng_default_reset(void)
lmmc_rng_t * lmmc_rng_default_get(void)
随机数发生器(不透明类型)。