LMMC
Lamina Mathematic core
载入中...
搜索中...
未找到
stdlib_constants_units.c
浏览该文件的文档.
1#include "lmmc/stdlib.h"
2
3#include <ctype.h>
4#include <math.h>
5#include <string.h>
6
7#include "stdlib_internal.h"
8
9typedef struct {
10 const char* name;
12 const char* unit;
14
15static const lmmc_std_constant_entry_t lmmc_std_constants[] = {
16 {"EARTH_GRAVITY", (lmmc_real_t)9.80665, "m*s^-2"},
17 {"MOON_GRAVITY", (lmmc_real_t)1.625, "m*s^-2"},
18 {"MARS_GRAVITY", (lmmc_real_t)3.72076, "m*s^-2"},
19 {"WATER_DENSITY", (lmmc_real_t)1000.0, "kg*m^-3"},
20 {"STANDARD_PRESSURE", (lmmc_real_t)101325.0, "Pa"},
21 {"STANDARD_TEMPERATURE", (lmmc_real_t)273.15, "K"},
22 {"AIR_DENSITY", (lmmc_real_t)1.225, "kg*m^-3"},
23 {"C", (lmmc_real_t)2.99792458e8, "m*s^-1"},
24 {"G", (lmmc_real_t)6.67430e-11, "m^3*kg^-1*s^-2"},
25 {"H", (lmmc_real_t)6.62607015e-34, "J*s"},
26 {"KB", (lmmc_real_t)1.380649e-23, "J*K^-1"},
27 {"EPSILON_0", (lmmc_real_t)8.8541878128e-12, "F*m^-1"},
28 {"MU_0", (lmmc_real_t)1.25663706212e-6, "H*m^-1"},
29 {"AVOGADRO", (lmmc_real_t)6.02214076e23, "mol^-1"},
30 {"R", (lmmc_real_t)8.314462618, "J*mol^-1*K^-1"},
31 {"FARADAY", (lmmc_real_t)9.648533212e4, "C*mol^-1"},
32 {"AMU", (lmmc_real_t)1.66053906660e-27, "kg"},
33 {"MOLAR_VOLUME_IDEAL", (lmmc_real_t)0.024465, "m^3*mol^-1"},
34 {"ROOM_PRESSURE", (lmmc_real_t)1.0e5, "Pa"},
35 {"ROOM_TEMPERATURE", (lmmc_real_t)297.15, "K"},
36};
37
38static size_t lmmc_std_constants_length(void)
39{
40 return sizeof(lmmc_std_constants) / sizeof(lmmc_std_constants[0]);
41}
42
43static const lmmc_std_constant_entry_t*
44lmmc_std_find_constant(const char* name)
45{
46 if (!name) { return NULL; }
47 for (size_t i = 0; i < lmmc_std_constants_length(); ++i) {
48 if (strcmp(lmmc_std_constants[i].name, name) == 0) {
49 return &lmmc_std_constants[i];
50 }
51 }
52 return NULL;
53}
54
55typedef struct {
56 double scale;
57 int dims[9];
59
60enum {
63};
64
65typedef struct {
66 const char* name;
67 double scale;
68 int dims[9];
70
71static const lmmc_std_unit_entry_t lmmc_std_units[] = {
72 {"1", 1.0, {0, 0, 0, 0, 0, 0, 0}},
73 {"m", 1.0, {1, 0, 0, 0, 0, 0, 0}},
74 {"km", 1000.0, {1, 0, 0, 0, 0, 0, 0}},
75 {"s", 1.0, {0, 0, 1, 0, 0, 0, 0}},
76 {"h", 3600.0, {0, 0, 1, 0, 0, 0, 0}},
77 {"kg", 1.0, {0, 1, 0, 0, 0, 0, 0}},
78 {"g", 0.001, {0, 1, 0, 0, 0, 0, 0}},
79 {"A", 1.0, {0, 0, 0, 1, 0, 0, 0}},
80 {"K", 1.0, {0, 0, 0, 0, 1, 0, 0}},
81 {"mol", 1.0, {0, 0, 0, 0, 0, 1, 0}},
82 {"cd", 1.0, {0, 0, 0, 0, 0, 0, 1}},
83 {"N", 1.0, {1, 1, -2, 0, 0, 0, 0}},
84 {"Pa", 1.0, {-1, 1, -2, 0, 0, 0, 0}},
85 {"J", 1.0, {2, 1, -2, 0, 0, 0, 0}},
86 {"C", 1.0, {0, 0, 1, 1, 0, 0, 0}},
87 {"F", 1.0, {-2, -1, 4, 2, 0, 0, 0}},
88 {"H", 1.0, {2, 1, -2, -2, 0, 0, 0}},
89 {"score", 1.0, {0, 0, 0, 0, 0, 0, 0, 1, 0}},
90 {"token", 1.0, {0, 0, 0, 0, 0, 0, 0, 0, 1}},
91};
92
93static const lmmc_std_unit_entry_t* lmmc_std_find_unit(const char* name,
94 size_t length)
95{
96 for (size_t i = 0; i < sizeof(lmmc_std_units) / sizeof(lmmc_std_units[0]);
97 ++i) {
98 if (strlen(lmmc_std_units[i].name) == length &&
99 strncmp(lmmc_std_units[i].name, name, length) == 0) {
100 return &lmmc_std_units[i];
101 }
102 }
103 return NULL;
104}
105
106static void lmmc_std_unit_identity(lmmc_std_unit_sig_t* sig)
107{
108 sig->scale = 1.0;
109 for (size_t i = 0; i < LMMC_STD_UNIT_DIM_COUNT; ++i) sig->dims[i] = 0;
110}
111
112static int lmmc_std_parse_int(const char** cursor, int* out)
113{
114 int sign = 1;
115 int value = 0;
116 int have_digit = 0;
117 if (**cursor == '+') {
118 ++(*cursor);
119 } else if (**cursor == '-') {
120 sign = -1;
121 ++(*cursor);
122 }
123 while (isdigit((unsigned char)**cursor)) {
124 int digit = **cursor - '0';
125 have_digit = 1;
126 if (value > (LMMC_STD_MAX_UNIT_EXPONENT - digit) / 10) {
127 return 0;
128 }
129 value = value * 10 + digit;
130 ++(*cursor);
131 }
132 if (!have_digit) { return 0; }
133 *out = sign * value;
134 if (*out < -LMMC_STD_MAX_UNIT_EXPONENT ||
136 return 0;
137 }
138 return 1;
139}
140
141static int lmmc_std_accumulate_unit(
142 const lmmc_std_unit_entry_t* unit, int exponent, lmmc_std_unit_sig_t* out)
143{
144 out->scale *= pow(unit->scale, (double)exponent);
145 if (!isfinite(out->scale)) { return 0; }
146 for (size_t i = 0; i < LMMC_STD_UNIT_DIM_COUNT; ++i) {
147 out->dims[i] += unit->dims[i] * exponent;
148 if (out->dims[i] < -LMMC_STD_MAX_UNIT_EXPONENT ||
150 return 0;
151 }
152 }
153 return 1;
154}
155
156static int lmmc_std_parse_unit_factor(
157 const char** position, int op_sign, lmmc_std_unit_sig_t* out)
158{
159 const char* cursor = *position;
160 const char* name_begin = cursor;
161 int exponent = 1;
162 while (isalpha((unsigned char)*cursor) || *cursor == '_') ++cursor;
163 if (cursor == name_begin) { return 0; }
164 const lmmc_std_unit_entry_t* unit =
165 lmmc_std_find_unit(name_begin, (size_t)(cursor - name_begin));
166 if (!unit) { return 0; }
167 if (*cursor == '^') {
168 ++cursor;
169 if (!lmmc_std_parse_int(&cursor, &exponent)) { return 0; }
170 }
171 exponent *= op_sign;
172 if (!lmmc_std_accumulate_unit(unit, exponent, out)) {
173 return 0;
174 }
175 *position = cursor;
176 return 1;
177}
178
179static int lmmc_std_parse_unit_expr(const char* text,
181{
182 const char* cursor = text;
183 int op_sign = 1;
184 lmmc_std_unit_identity(out);
185 if (!text || !*text) { return 0; }
186 if (strcmp(text, "1") == 0) { return 1; }
187 while (*cursor) {
188 if (!lmmc_std_parse_unit_factor(&cursor, op_sign, out)) {
189 return 0;
190 }
191 if (*cursor == '\0') { break; }
192 if (*cursor == '*') {
193 op_sign = 1;
194 } else if (*cursor == '/') {
195 op_sign = -1;
196 } else {
197 return 0;
198 }
199 ++cursor;
200 if (*cursor == '\0') { return 0; }
201 }
202 return 1;
203}
204
205static int lmmc_std_same_dimension(const lmmc_std_unit_sig_t* lhs,
206 const lmmc_std_unit_sig_t* rhs)
207{
208 for (size_t i = 0; i < LMMC_STD_UNIT_DIM_COUNT; ++i) {
209 if (lhs->dims[i] != rhs->dims[i]) { return 0; }
210 }
211 return 1;
212}
213
214static int lmmc_std_dimensionless_sig(const lmmc_std_unit_sig_t* sig)
215{
216 for (size_t i = 0; i < LMMC_STD_UNIT_DIM_COUNT; ++i) {
217 if (sig->dims[i] != 0) { return 0; }
218 }
219 return 1;
220}
222{
223 return lmmc_std_store_real(LMMC_CONST_PI, out);
224}
225
227{
228 return lmmc_std_store_real((lmmc_real_t)2.71828182845904523536, out);
229}
230
232{
233 return lmmc_std_store_real((lmmc_real_t)1.61803398874989484820, out);
234}
235
237{
238 return lmmc_std_constants_length();
239}
240
241const char* lmmc_std_constants_name(size_t index)
242{
243 if (index >= lmmc_std_constants_length()) { return NULL; }
244 return lmmc_std_constants[index].name;
245}
246
248{
249 const lmmc_std_constant_entry_t* entry = lmmc_std_find_constant(name);
250 if (!entry || !out) { return LMMC_STATUS_INVALID_ARGUMENT; }
251 *out = entry->value;
252 return LMMC_STATUS_OK;
253}
254
255const char* lmmc_std_constants_unit(const char* name)
256{
257 const lmmc_std_constant_entry_t* entry = lmmc_std_find_constant(name);
258 return entry ? entry->unit : NULL;
259}
260
262 const char** out_name,
263 lmmc_real_t* out_value,
264 const char** out_unit)
265{
266 if (!out_name || !out_value || !out_unit) {
268 }
269 if (index >= lmmc_std_constants_length()) {
271 }
272 *out_name = lmmc_std_constants[index].name;
273 *out_value = lmmc_std_constants[index].value;
274 *out_unit = lmmc_std_constants[index].unit;
275 return LMMC_STATUS_OK;
276}
277
283 const char* from_unit,
284 const char* to_unit,
285 lmmc_real_t* out)
286{
287 lmmc_std_unit_sig_t from_sig;
288 lmmc_std_unit_sig_t to_sig;
289 double converted;
290 if (!out || !from_unit || !to_unit) { return LMMC_STATUS_INVALID_ARGUMENT; }
291 if (!lmmc_std_real_is_finite(x)) { return LMMC_STATUS_NUMERICAL_FAILURE; }
292 if (!lmmc_std_parse_unit_expr(from_unit, &from_sig) ||
293 !lmmc_std_parse_unit_expr(to_unit, &to_sig)) {
295 }
296 if (!lmmc_std_same_dimension(&from_sig, &to_sig)) {
298 }
299 converted = (double)x * from_sig.scale / to_sig.scale;
300 return lmmc_std_store_finite_real((lmmc_real_t)converted, out);
301}
302
304 const char* to_unit,
305 lmmc_real_t* out)
306{
307 lmmc_std_unit_sig_t to_sig;
308 double converted;
309 if (!out || !to_unit) { return LMMC_STATUS_INVALID_ARGUMENT; }
310 if (!lmmc_std_real_is_finite(x)) { return LMMC_STATUS_NUMERICAL_FAILURE; }
311 if (!lmmc_std_parse_unit_expr(to_unit, &to_sig)) {
313 }
314 converted = (double)x / to_sig.scale;
315 return lmmc_std_store_finite_real((lmmc_real_t)converted, out);
316}
317
319 const char* to_unit,
320 lmmc_real_t* out)
321{
322 return lmmc_std_units_convert_from_si(x, to_unit, out);
323}
324
326{
327 lmmc_status_t status = lmmc_std_store_finite_real(x, out);
328 return status == LMMC_STATUS_NUMERICAL_FAILURE
330 : status;
331}
332
334 const char* unit,
335 lmmc_real_t* out)
336{
338 double value;
339 if (!unit || !out) { return LMMC_STATUS_INVALID_ARGUMENT; }
340 if (strstr(unit, "num<") != NULL || strstr(unit, "scalar<") != NULL) {
342 }
343 if (!lmmc_std_real_is_finite(x)) { return LMMC_STATUS_UNIT_STRIP_OVERFLOW; }
344 if (!lmmc_std_parse_unit_expr(unit, &sig)) {
346 }
347 value = (double)x * sig.scale;
348 {
349 lmmc_status_t status =
350 lmmc_std_store_finite_real((lmmc_real_t)value, out);
351 return status == LMMC_STATUS_NUMERICAL_FAILURE
353 : status;
354 }
355}
356
358{
359 lmmc_status_t status = lmmc_std_store_finite_real(x, out);
360 return status == LMMC_STATUS_NUMERICAL_FAILURE
362 : status;
363}
364
366{
367 if (!out) { return LMMC_STATUS_INVALID_ARGUMENT; }
368 if (!lmmc_std_real_is_finite(x)) { return LMMC_STATUS_NUMERICAL_FAILURE; }
369 *out = 1;
370 return LMMC_STATUS_OK;
371}
372
374{
376 if (!unit || !out) { return LMMC_STATUS_INVALID_ARGUMENT; }
377 if (!lmmc_std_parse_unit_expr(unit, &sig)) {
379 }
380 *out = lmmc_std_dimensionless_sig(&sig);
381 return LMMC_STATUS_OK;
382}
lmmc_status_t lmmc_complex_create(lmmc_real_t real, lmmc_real_t imag, lmmc_complex_t *out)
从笛卡尔坐标构造复数.
复数类型,包含实部与虚部.
double lmmc_real_t
Public and internal LMMC real type.
#define LMMC_CONST_PI
圆周率常数 。
lmmc_status_t
LMMC 库统一返回的状态码.
@ LMMC_STATUS_UNIT_STRIP_LEGACY_SYNTAX
@ LMMC_STATUS_OK
@ LMMC_STATUS_NUMERICAL_FAILURE
@ LMMC_STATUS_DIMENSION_MISMATCH
@ LMMC_STATUS_UNIT_STRIP_INVALID
@ LMMC_STATUS_INVALID_ARGUMENT
@ LMMC_STATUS_UNIT_STRIP_OVERFLOW
const char * lmmc_std_constants_name(size_t index)
按索引返回 LSR 规范的 std.constants 条目名;索引越界时返回 NULL。
lmmc_status_t lmmc_std_constants_get(const char *name, lmmc_real_t *out)
按名称返回 LSR 规范的 std.constants 数值。
lmmc_status_t lmmc_std_math_e(lmmc_real_t *out)
返回 LSR 规范的 std.math 常量 e。
lmmc_status_t lmmc_std_constants_entry(size_t index, const char **out_name, lmmc_real_t *out_value, const char **out_unit)
按索引返回完整的 LSR 规范 std.constants 条目。
lmmc_status_t lmmc_std_units_strip(lmmc_real_t x, lmmc_real_t *out)
lmmc_status_t lmmc_std_units_convert(lmmc_real_t x, const char *from_unit, const char *to_unit, lmmc_real_t *out)
lmmc_status_t lmmc_std_units_strip_scalar(lmmc_real_t x, lmmc_real_t *out)
lmmc_status_t lmmc_std_math_i(lmmc_complex_t *out)
返回虚数单位 std.math.I。
lmmc_status_t lmmc_std_math_phi(lmmc_real_t *out)
返回 LSR 规范的 std.math 常量 phi。
lmmc_status_t lmmc_std_units_convert_num(lmmc_real_t x, const char *to_unit, lmmc_real_t *out)
lmmc_status_t lmmc_std_units_is_dimensionless(const char *unit, int *out)
lmmc_status_t lmmc_std_units_is_dimensionless_num(lmmc_real_t x, int *out)
lmmc_status_t lmmc_std_units_strip_num(lmmc_real_t x, const char *unit, lmmc_real_t *out)
lmmc_status_t lmmc_std_units_convert_from_si(lmmc_real_t x, const char *to_unit, lmmc_real_t *out)
lmmc_status_t lmmc_std_math_pi(lmmc_real_t *out)
返回 LSR 规范的 std.math 常量 pi。
size_t lmmc_std_constants_count(void)
返回 LSR 规范的 std.constants 条目数。
const char * lmmc_std_constants_unit(const char *name)
按名称返回 LSR 规范的 std.constants 单位字符串;条目无单位时返回 NULL。