1use crate::core::Expression;
7use once_cell::sync::Lazy;
8use std::collections::HashMap;
9
10pub mod function_names {
12 pub const SIN: &str = "sin";
14 pub const COS: &str = "cos";
15 pub const TAN: &str = "tan";
16
17 pub const SINH: &str = "sinh";
19 pub const COSH: &str = "cosh";
20 pub const TANH: &str = "tanh";
21 pub const SECH: &str = "sech";
22 pub const CSCH: &str = "csch";
23 pub const COTH: &str = "coth";
24
25 pub const ARCSIN: &str = "arcsin";
27 pub const ARCCOS: &str = "arccos";
28 pub const ARCTAN: &str = "arctan";
29 pub const ARCSEC: &str = "arcsec";
30 pub const ARCCSC: &str = "arccsc";
31 pub const ARCCOT: &str = "arccot";
32
33 pub const SEC: &str = "sec";
35 pub const CSC: &str = "csc";
36 pub const COT: &str = "cot";
37
38 pub const LN: &str = "ln";
40 pub const LOG: &str = "log";
41 pub const LOG10: &str = "log10";
42 pub const LOG2: &str = "log2";
43
44 pub const SQRT: &str = "sqrt";
46 pub const ABS: &str = "abs";
47 pub const EXP: &str = "exp";
48
49 pub const FACTORIAL: &str = "factorial";
51 pub const DOUBLE_FACTORIAL: &str = "double_factorial";
52
53 pub const GAMMA: &str = "gamma";
55 pub const BESSEL_J: &str = "bessel_j";
56 pub const BESSEL_Y: &str = "bessel_y";
57 pub const BESSEL_I: &str = "bessel_i";
58 pub const BESSEL_K: &str = "bessel_k";
59 pub const LEGENDRE_P: &str = "legendre_p";
60 pub const LEGENDRE_Q: &str = "legendre_q";
61 pub const HERMITE: &str = "hermite";
62 pub const HERMITE_PHYSICIST: &str = "hermite_physicist";
63 pub const LAGUERRE: &str = "laguerre";
64 pub const LAGUERRE_ASSOCIATED: &str = "laguerre_associated";
65 pub const CHEBYSHEV_FIRST: &str = "chebyshev_first";
66 pub const CHEBYSHEV_SECOND: &str = "chebyshev_second";
67
68 pub const DERIVATIVE: &str = "derivative";
70 pub const INTEGRAL: &str = "integral";
71 pub const LIMIT: &str = "limit";
72 pub const SUM: &str = "sum";
73 pub const PRODUCT: &str = "product";
74
75 pub const TEXT_RE: &str = "text_re";
77 pub const TEXT_IM: &str = "text_im";
78 pub const TEXT_QR: &str = "text_qr";
79 pub const TEXT_PRIM_ROOT: &str = "text_primroot";
80
81 pub const CONJUGATE: &str = "conjugate";
83 pub const REAL: &str = "real";
84 pub const IMAG: &str = "imag";
85 pub const ARG: &str = "arg";
86
87 pub const SIGN: &str = "sign";
89 pub const FLOOR: &str = "floor";
90 pub const CEILING: &str = "ceiling";
91 pub const ROUND: &str = "round";
92 pub const MAX: &str = "max";
93 pub const MIN: &str = "min";
94
95 pub const MEAN: &str = "mean";
100 pub const MEDIAN: &str = "median";
101 pub const VARIANCE: &str = "variance";
102 pub const STD: &str = "std";
103
104 pub const GCD_CAPS: &str = "gcd";
106 pub const LCM_CAPS: &str = "lcm";
107 pub const BINOMIAL: &str = "binomial";
108
109 pub const CYCLOTOMIC_POLYNOMIAL: &str = "cyclotomic_polynomial";
111 pub const MINIMAL_POLYNOMIAL: &str = "minimal_polynomial";
112 pub const GROEBNER_BASIS: &str = "groebner_basis";
113 pub const RESULTANT: &str = "resultant";
114 pub const DISCRIMINANT: &str = "discriminant";
115 pub const POLYNOMIAL_GCD: &str = "polynomial_gcd";
116 pub const RIEMANN_ZETA: &str = "riemann_zeta";
117 pub const RIEMANN_SIEGEL_THETA: &str = "riemann_siegel_theta";
118 pub const MOEBIUS_MU: &str = "moebius_mu";
119 pub const EULER_PHI: &str = "euler_phi";
120 pub const PRIME_PI: &str = "prime_pi";
121}
122
123pub mod math_constants {
125 use super::*;
126
127 pub static ZERO: Lazy<Expression> = Lazy::new(|| Expression::integer(0));
128 pub static ONE: Lazy<Expression> = Lazy::new(|| Expression::integer(1));
129 pub static MINUS_ONE: Lazy<Expression> = Lazy::new(|| Expression::integer(-1));
130 pub static TWO: Lazy<Expression> = Lazy::new(|| Expression::integer(2));
131 pub static HALF: Lazy<Expression> = Lazy::new(|| Expression::rational(1, 2));
132 pub static PI: Lazy<Expression> = Lazy::new(Expression::pi);
133 pub static E: Lazy<Expression> = Lazy::new(Expression::e);
134 pub static I: Lazy<Expression> = Lazy::new(Expression::i);
135}
136
137pub static SPECIAL_FUNCTION_MAP: Lazy<HashMap<&'static str, &'static str>> = Lazy::new(|| {
142 let mut map = HashMap::new();
143
144 map.insert("J", function_names::BESSEL_J);
146 map.insert("Y", function_names::BESSEL_Y);
147 map.insert("I", function_names::BESSEL_I);
148 map.insert("K", function_names::BESSEL_K);
149
150 map.insert("P", function_names::LEGENDRE_P);
152 map.insert("Q", function_names::LEGENDRE_Q);
153
154 map.insert("H", function_names::HERMITE);
156 map.insert("He", function_names::HERMITE_PHYSICIST);
157
158 map.insert("L", function_names::LAGUERRE);
160 map.insert("La", function_names::LAGUERRE_ASSOCIATED);
161
162 map.insert("T", function_names::CHEBYSHEV_FIRST);
164 map.insert("U", function_names::CHEBYSHEV_SECOND);
165
166 map
167});
168
169pub static WOLFRAM_FUNCTION_MAP: Lazy<HashMap<&'static str, &'static str>> = Lazy::new(|| {
175 let mut map = HashMap::new();
176
177 map.insert("Sin", function_names::SIN);
179 map.insert("Cos", function_names::COS);
180 map.insert("Tan", function_names::TAN);
181 map.insert("Log", function_names::LN);
182 map.insert("Sqrt", function_names::SQRT);
183 map.insert("Exp", function_names::EXP);
184
185 map.insert("Sinh", function_names::SINH);
187 map.insert("Cosh", function_names::COSH);
188 map.insert("Tanh", function_names::TANH);
189
190 map.insert("ArcSin", function_names::ARCSIN);
192 map.insert("ArcCos", function_names::ARCCOS);
193 map.insert("ArcTan", function_names::ARCTAN);
194
195 map.insert("BesselJ", function_names::BESSEL_J);
197 map.insert("BesselY", function_names::BESSEL_Y);
198 map.insert("BesselI", function_names::BESSEL_I);
199 map.insert("BesselK", function_names::BESSEL_K);
200 map.insert("LegendreP", function_names::LEGENDRE_P);
201 map.insert("LegendreQ", function_names::LEGENDRE_Q);
202 map.insert("HermiteH", function_names::HERMITE);
203 map.insert("LaguerreL", function_names::LAGUERRE);
204 map.insert("ChebyshevT", function_names::CHEBYSHEV_FIRST);
205 map.insert("ChebyshevU", function_names::CHEBYSHEV_SECOND);
206
207 map.insert(
209 "CyclotomicPolynomial",
210 function_names::CYCLOTOMIC_POLYNOMIAL,
211 );
212 map.insert("MinimalPolynomial", function_names::MINIMAL_POLYNOMIAL);
213 map.insert("GroebnerBasis", function_names::GROEBNER_BASIS);
214 map.insert("Resultant", function_names::RESULTANT);
215 map.insert("Discriminant", function_names::DISCRIMINANT);
216 map.insert("PolynomialGCD", function_names::POLYNOMIAL_GCD);
217 map.insert("RiemannSiegelTheta", function_names::RIEMANN_ZETA);
218 map.insert("MoebiusMu", function_names::MOEBIUS_MU);
219 map.insert("EulerPhi", function_names::EULER_PHI);
220 map.insert("PrimePi", function_names::PRIME_PI);
221
222 map.insert("Sec", function_names::SEC);
224 map.insert("Csc", function_names::CSC);
225 map.insert("Cot", function_names::COT);
226
227 map.insert("Sech", function_names::SECH);
229 map.insert("Csch", function_names::CSCH);
230 map.insert("Coth", function_names::COTH);
231
232 map.insert("ArcSec", function_names::ARCSEC);
234 map.insert("ArcCsc", function_names::ARCCSC);
235 map.insert("ArcCot", function_names::ARCCOT);
236
237 map.insert("Abs", function_names::ABS);
239 map.insert("Sign", function_names::SIGN);
240 map.insert("Max", function_names::MAX);
241 map.insert("Min", function_names::MIN);
242 map.insert("Floor", function_names::FLOOR);
243 map.insert("Ceiling", function_names::CEILING);
244 map.insert("Round", function_names::ROUND);
245
246 map.insert("Re", function_names::REAL);
248 map.insert("Im", function_names::IMAG);
249 map.insert("Conjugate", function_names::CONJUGATE);
250 map.insert("Arg", function_names::ARG);
251
252 map.insert("GCD", function_names::GCD_CAPS);
257 map.insert("LCM", function_names::LCM_CAPS);
258 map.insert("Factorial", function_names::FACTORIAL);
259 map.insert("Binomial", function_names::BINOMIAL);
260
261 map.insert("Mean", function_names::MEAN);
263 map.insert("Median", function_names::MEDIAN);
264 map.insert("Variance", function_names::VARIANCE);
265 map.insert("StandardDeviation", function_names::STD);
266
267 map
268});
269
270pub static STANDARD_FUNCTION_MAP: Lazy<HashMap<&'static str, &'static str>> = Lazy::new(|| {
275 let mut map = HashMap::new();
276
277 map.insert("sin", function_names::SIN);
279 map.insert("cos", function_names::COS);
280 map.insert("tan", function_names::TAN);
281 map.insert("sec", function_names::SEC);
282 map.insert("csc", function_names::CSC);
283 map.insert("cot", function_names::COT);
284
285 map.insert("sinh", function_names::SINH);
287 map.insert("cosh", function_names::COSH);
288 map.insert("tanh", function_names::TANH);
289 map.insert("sech", function_names::SECH);
290 map.insert("csch", function_names::CSCH);
291 map.insert("coth", function_names::COTH);
292
293 map.insert("arcsin", function_names::ARCSIN);
295 map.insert("arccos", function_names::ARCCOS);
296 map.insert("arctan", function_names::ARCTAN);
297 map.insert("arcsec", function_names::ARCSEC);
298 map.insert("arccsc", function_names::ARCCSC);
299 map.insert("arccot", function_names::ARCCOT);
300 map.insert("asin", function_names::ARCSIN); map.insert("acos", function_names::ARCCOS);
302 map.insert("atan", function_names::ARCTAN);
303
304 map.insert("ln", function_names::LN);
306 map.insert("log", function_names::LOG);
307 map.insert("log10", function_names::LOG10);
308 map.insert("log2", function_names::LOG2);
309
310 map.insert("sqrt", function_names::SQRT);
312 map.insert("abs", function_names::ABS);
313 map.insert("exp", function_names::EXP);
314 map.insert("sign", function_names::SIGN);
315 map.insert("floor", function_names::FLOOR);
316 map.insert("ceiling", function_names::CEILING);
317 map.insert("round", function_names::ROUND);
318 map.insert("max", function_names::MAX);
319 map.insert("min", function_names::MIN);
320
321 map.insert("gamma", function_names::GAMMA);
323 map.insert("factorial", function_names::FACTORIAL);
324
325 map.insert("real", function_names::REAL);
327 map.insert("imag", function_names::IMAG);
328 map.insert("conj", function_names::CONJUGATE);
329 map.insert("arg", function_names::ARG);
330
331 map.insert("mean", function_names::MEAN);
335 map.insert("median", function_names::MEDIAN);
336 map.insert("var", function_names::VARIANCE);
337 map.insert("std", function_names::STD);
338
339 map.insert("gcd", function_names::GCD_CAPS);
341 map.insert("lcm", function_names::LCM_CAPS);
342
343 map
344});
345
346pub fn resolve_wolfram_function(name: &str) -> Option<&'static str> {
357 WOLFRAM_FUNCTION_MAP.get(name).copied()
358}
359
360pub fn pascal_to_snake_case(name: &str) -> String {
376 let mut result = String::with_capacity(name.len() + 4); let chars = name.chars().peekable();
378
379 for ch in chars {
380 if ch.is_uppercase() {
381 if !result.is_empty() {
383 result.push('_');
384 }
385 for lowercase_ch in ch.to_lowercase() {
387 result.push(lowercase_ch);
388 }
389 } else {
390 result.push(ch);
391 }
392 }
393
394 result
395}
396
397pub fn resolve_special_function(name: &str) -> Option<&'static str> {
409 SPECIAL_FUNCTION_MAP.get(name).copied()
410}
411
412pub fn resolve_standard_function(name: &str) -> Option<&'static str> {
424 STANDARD_FUNCTION_MAP.get(name).copied()
425}
426
427#[cfg(test)]
428mod tests {
429 use super::*;
430
431 #[test]
432 fn test_wolfram_function_resolution() {
433 assert_eq!(resolve_wolfram_function("Sin"), Some(function_names::SIN));
434 assert_eq!(resolve_wolfram_function("Cos"), Some(function_names::COS));
435 assert_eq!(
436 resolve_wolfram_function("BesselJ"),
437 Some(function_names::BESSEL_J)
438 );
439 assert_eq!(resolve_wolfram_function("UnknownFunction"), None);
440 }
441
442 #[test]
443 fn test_pascal_to_snake_case() {
444 assert_eq!(pascal_to_snake_case("Sin"), "sin");
446 assert_eq!(pascal_to_snake_case("Cos"), "cos");
447
448 assert_eq!(pascal_to_snake_case("BesselJ"), "bessel_j");
450 assert_eq!(pascal_to_snake_case("ArcSin"), "arc_sin");
451 assert_eq!(pascal_to_snake_case("DiracDelta"), "dirac_delta");
452 assert_eq!(pascal_to_snake_case("HeavisideTheta"), "heaviside_theta");
453
454 assert_eq!(
456 pascal_to_snake_case("Hypergeometric2F1"),
457 "hypergeometric2_f1"
458 );
459 assert_eq!(pascal_to_snake_case("LegendreP"), "legendre_p");
460
461 assert_eq!(pascal_to_snake_case("A"), "a");
463 assert_eq!(pascal_to_snake_case("AB"), "a_b");
464 assert_eq!(pascal_to_snake_case("ABC"), "a_b_c");
465 }
466
467 #[test]
468 fn test_special_function_resolution() {
469 assert_eq!(
470 resolve_special_function("J"),
471 Some(function_names::BESSEL_J)
472 );
473 assert_eq!(
474 resolve_special_function("P"),
475 Some(function_names::LEGENDRE_P)
476 );
477 assert_eq!(resolve_special_function("H"), Some(function_names::HERMITE));
478 assert_eq!(resolve_special_function("Unknown"), None);
479 }
480
481 #[test]
482 fn test_math_constants_initialization() {
483 let _zero = &*math_constants::ZERO;
485 let _one = &*math_constants::ONE;
486 let _pi = &*math_constants::PI;
487 }
488}