LMMC
Lamina Mathematic core
载入中...
搜索中...
未找到
numeric.c
浏览该文件的文档.
1
5#include <math.h>
6#include <float.h>
8
9static void lmmc_max_inplace(lmmc_real_t* res, const lmmc_real_t* a, const lmmc_real_t* b) {
10 if (LMMC_REAL_CMP(a, b) > 0) {
11 LMMC_REAL_SET(res, a);
12 } else {
13 LMMC_REAL_SET(res, b);
14 }
15}
16
18 if (out_inf == NULL) return LMMC_STATUS_INVALID_ARGUMENT;
19#ifdef INFINITY
20 LMMC_REAL_SET_D(out_inf, INFINITY);
21#else
22 LMMC_REAL_SET_D(out_inf, HUGE_VAL);
23#endif
24 return LMMC_STATUS_OK;
25}
26
28 if (out_nan == NULL) return LMMC_STATUS_INVALID_ARGUMENT;
29#ifdef NAN
30 LMMC_REAL_SET_D(out_nan, NAN);
31#else
32 lmmc_real_t zero;
33 LMMC_REAL_INIT(&zero);
34 LMMC_REAL_SET_D(&zero, 0.0);
35 LMMC_REAL_DIV(out_nan, &zero, &zero);
36 LMMC_REAL_CLEAR(&zero);
37#endif
38 return LMMC_STATUS_OK;
39}
40
42 if (out_eps == NULL) return LMMC_STATUS_INVALID_ARGUMENT;
43 LMMC_REAL_SET_D(out_eps, DBL_EPSILON);
44 return LMMC_STATUS_OK;
45}
46
48 if (out_isnan == NULL) return LMMC_STATUS_INVALID_ARGUMENT;
49 *out_isnan = isnan(x) ? 1 : 0;
50 return LMMC_STATUS_OK;
51}
52
54 if (out_isinf == NULL) return LMMC_STATUS_INVALID_ARGUMENT;
55 *out_isinf = isinf(x) ? 1 : 0;
56 return LMMC_STATUS_OK;
57}
58
60 if (out_isfinite == NULL) return LMMC_STATUS_INVALID_ARGUMENT;
61 *out_isfinite = isfinite(x) ? 1 : 0;
62 return LMMC_STATUS_OK;
63}
64
66 if (out_signbit == NULL) return LMMC_STATUS_INVALID_ARGUMENT;
67 *out_signbit = signbit(x) ? 1 : 0;
68 return LMMC_STATUS_OK;
69}
70
72 lmmc_real_t diff, zero;
73 if (out_equal == NULL) return LMMC_STATUS_INVALID_ARGUMENT;
74 if (!isfinite(epsilon) || epsilon < 0.0) {
76 }
77 if (isnan(a) || isnan(b)) {
78 *out_equal = 0;
79 return LMMC_STATUS_OK;
80 }
81 if (isinf(a) || isinf(b)) {
82 *out_equal = (LMMC_REAL_CMP(&a, &b) == 0) ? 1 : 0;
83 return LMMC_STATUS_OK;
84 }
85
86 LMMC_REAL_INIT(&diff);
87 LMMC_REAL_INIT(&zero);
88
89 LMMC_REAL_SET_D(&zero, 0.0);
90 LMMC_REAL_SUB(&diff, &a, &b);
91
92 if (LMMC_REAL_CMP(&diff, &zero) < 0) {
93 lmmc_real_t tmp;
94 LMMC_REAL_INIT(&tmp);
95 LMMC_REAL_SET(&tmp, &diff);
96 LMMC_REAL_SUB(&diff, &zero, &tmp);
97 LMMC_REAL_CLEAR(&tmp);
98 }
99 *out_equal = (LMMC_REAL_CMP(&diff, &epsilon) <= 0) ? 1 : 0;
100
101 LMMC_REAL_CLEAR(&diff);
102 LMMC_REAL_CLEAR(&zero);
103 return LMMC_STATUS_OK;
104}
105
107 lmmc_real_t a,
108 lmmc_real_t b,
109 lmmc_real_t abs_tol,
110 lmmc_real_t rel_tol,
111 int* out_equal
112) {
113 lmmc_real_t diff, scale, threshold, zero, tmp1, tmp2;
114
115 if (out_equal == NULL) {
117 }
118
119 LMMC_REAL_INIT(&diff);
120 LMMC_REAL_INIT(&scale);
121 LMMC_REAL_INIT(&threshold);
122 LMMC_REAL_INIT(&zero);
123 LMMC_REAL_INIT(&tmp1);
124 LMMC_REAL_INIT(&tmp2);
125
126 LMMC_REAL_SET_D(&zero, 0.0);
127
128 if (LMMC_REAL_CMP(&abs_tol, &zero) < 0 || LMMC_REAL_CMP(&rel_tol, &zero) < 0 || !LMMC_REAL_IS_FINITE(&abs_tol) || !LMMC_REAL_IS_FINITE(&rel_tol)) {
129 LMMC_REAL_CLEAR(&diff); LMMC_REAL_CLEAR(&scale); LMMC_REAL_CLEAR(&threshold);
130 LMMC_REAL_CLEAR(&zero); LMMC_REAL_CLEAR(&tmp1); LMMC_REAL_CLEAR(&tmp2);
132 }
133
134 if (isnan(a) || isnan(b)) {
135 LMMC_REAL_CLEAR(&diff); LMMC_REAL_CLEAR(&scale); LMMC_REAL_CLEAR(&threshold);
136 LMMC_REAL_CLEAR(&zero); LMMC_REAL_CLEAR(&tmp1); LMMC_REAL_CLEAR(&tmp2);
138 }
139
140 if (isinf(a) || isinf(b)) {
141 *out_equal = (LMMC_REAL_CMP(&a, &b) == 0) ? 1 : 0;
142 LMMC_REAL_CLEAR(&diff); LMMC_REAL_CLEAR(&scale); LMMC_REAL_CLEAR(&threshold);
143 LMMC_REAL_CLEAR(&zero); LMMC_REAL_CLEAR(&tmp1); LMMC_REAL_CLEAR(&tmp2);
144 return LMMC_STATUS_OK;
145 }
146
147 LMMC_REAL_SUB(&tmp1, &a, &b);
148 LMMC_REAL_ABS(&diff, &tmp1);
149
150 LMMC_REAL_ABS(&tmp1, &a);
151 LMMC_REAL_ABS(&tmp2, &b);
152 lmmc_max_inplace(&scale, &tmp1, &tmp2);
153
154 LMMC_REAL_MUL(&tmp1, &rel_tol, &scale);
155 lmmc_max_inplace(&threshold, &abs_tol, &tmp1);
156
157 if (isnan(diff) || isnan(threshold)) {
158 LMMC_REAL_CLEAR(&diff); LMMC_REAL_CLEAR(&scale); LMMC_REAL_CLEAR(&threshold);
159 LMMC_REAL_CLEAR(&zero); LMMC_REAL_CLEAR(&tmp1); LMMC_REAL_CLEAR(&tmp2);
161 }
162
163 if (isinf(threshold)) {
164 *out_equal = 1;
165 LMMC_REAL_CLEAR(&diff); LMMC_REAL_CLEAR(&scale); LMMC_REAL_CLEAR(&threshold);
166 LMMC_REAL_CLEAR(&zero); LMMC_REAL_CLEAR(&tmp1); LMMC_REAL_CLEAR(&tmp2);
167 return LMMC_STATUS_OK;
168 }
169
170 *out_equal = (LMMC_REAL_CMP(&diff, &threshold) <= 0) ? 1 : 0;
171
172 LMMC_REAL_CLEAR(&diff);
173 LMMC_REAL_CLEAR(&scale);
174 LMMC_REAL_CLEAR(&threshold);
175 LMMC_REAL_CLEAR(&zero);
176 LMMC_REAL_CLEAR(&tmp1);
177 LMMC_REAL_CLEAR(&tmp2);
178 return LMMC_STATUS_OK;
179}
180
182 lmmc_real_t abs_tol, rel_tol;
183 lmmc_status_t st;
184 LMMC_REAL_INIT(&abs_tol);
185 LMMC_REAL_INIT(&rel_tol);
188 st = lmmc_double_nearly_equal_tol(a, b, abs_tol, rel_tol, out_equal);
189 LMMC_REAL_CLEAR(&abs_tol);
190 LMMC_REAL_CLEAR(&rel_tol);
191 return st;
192}
#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 。
#define LMMC_REAL_IS_FINITE(x)
判断 *x 是否为有限数。
lmmc_status_t lmmc_double_nearly_equal(lmmc_real_t a, lmmc_real_t b, int *out_equal)
使用默认容差的近似相等比较,等价于以 LMMC_DEFAULT_ABS_TOL / LMMC_DEFAULT_REL_TOL 调用 lmmc_double_nearly_equal_tol .
lmmc_status_t lmmc_isfinite(lmmc_real_t x, int *out_isfinite)
检测是否为有限数(非 NaN 且非 +/-infinity).
lmmc_status_t lmmc_isnan(lmmc_real_t x, int *out_isnan)
检测是否为 NaN ,结果写入 *out_isnan (0/1).
lmmc_status_t lmmc_signbit(lmmc_real_t x, int *out_signbit)
检测符号位(含 -0 ).
lmmc_status_t lmmc_inf(lmmc_real_t *out_inf)
写入 IEEE-754 正无穷.
lmmc_status_t lmmc_eps(lmmc_real_t *out_eps)
写入机器精度(1 与下一个可表示数的差).
#define LMMC_DEFAULT_REL_TOL
库默认的相对容差.
lmmc_status_t lmmc_isinf(lmmc_real_t x, int *out_isinf)
检测是否为 +/-infinity .
lmmc_status_t lmmc_approx_eq(lmmc_real_t a, lmmc_real_t b, lmmc_real_t epsilon, int *out_equal)
按绝对容差比较: 。
#define LMMC_DEFAULT_ABS_TOL
库默认的绝对容差.
lmmc_status_t lmmc_nan(lmmc_real_t *out_nan)
写入 IEEE-754 NaN.
lmmc_status_t lmmc_double_nearly_equal_tol(lmmc_real_t a, lmmc_real_t b, lmmc_real_t abs_tol, lmmc_real_t rel_tol, int *out_equal)
同时考虑绝对与相对容差的近似相等判定.
lmmc_status_t
LMMC 库统一返回的状态码.
@ LMMC_STATUS_OK
@ LMMC_STATUS_NUMERICAL_FAILURE
@ LMMC_STATUS_INVALID_ARGUMENT