mathhook_core/functions/
intelligence.rs1use super::properties::FunctionProperties;
7use crate::core::Expression;
8use crate::educational::step_by_step::Step;
9use once_cell::sync::Lazy;
10use std::collections::HashMap;
11
12pub struct UniversalFunctionRegistry {
18 properties: HashMap<String, FunctionProperties>,
21
22 step_generators: HashMap<String, Box<dyn StepGenerator>>,
25}
26
27#[derive(Debug, Clone, Copy, PartialEq)]
29pub enum FunctionFamily {
30 Elementary, Special, Polynomial, UserDefined, }
35
36pub trait StepGenerator: Send + Sync {
41 fn generate_steps(&self, name: &str, args: &[Expression]) -> Vec<Step>;
43
44 fn generate_latex_explanation(&self, name: &str, args: &[Expression]) -> String;
46}
47
48pub static UNIVERSAL_REGISTRY: Lazy<UniversalFunctionRegistry> =
53 Lazy::new(UniversalFunctionRegistry::new);
54
55impl Default for UniversalFunctionRegistry {
56 fn default() -> Self {
57 Self::new()
58 }
59}
60
61impl UniversalFunctionRegistry {
62 pub fn new() -> Self {
66 let mut registry = Self {
70 properties: HashMap::with_capacity(64), step_generators: HashMap::with_capacity(64), };
73
74 registry.initialize_elementary_functions();
76 registry.initialize_special_functions();
77 registry.initialize_polynomial_functions();
78 registry.initialize_number_theory_functions();
79
80 registry
81 }
82
83 #[inline(always)]
85 pub fn get_properties(&self, name: &str) -> Option<&FunctionProperties> {
86 self.properties.get(name)
87 }
88
89 #[inline(always)]
91 pub fn has_intelligence(&self, name: &str) -> bool {
92 self.properties.contains_key(name)
93 }
94
95 pub fn list_all_functions(&self) -> Vec<String> {
97 self.properties.keys().cloned().collect()
98 }
99
100 pub fn registry_size(&self) -> usize {
102 self.properties.len()
103 }
104
105 pub fn explain_function(&self, name: &str, args: &[Expression]) -> Vec<Step> {
109 if let Some(generator) = self.step_generators.get(name) {
110 generator.generate_steps(name, args)
111 } else {
112 vec![
114 Step::new("Function Call", format!("Evaluating {}(...)", name)),
115 Step::new("Arguments", format!("With {} arguments", args.len())),
116 ]
117 }
118 }
119
120 fn initialize_elementary_functions(&mut self) {
121 let elementary_intelligence = super::elementary::ElementaryIntelligence::new();
123
124 let elementary_properties = elementary_intelligence.get_all_properties();
126
127 self.properties.extend(elementary_properties);
129 }
130
131 fn initialize_special_functions(&mut self) {
133 let special_intelligence = super::special::SpecialIntelligence::new();
135 let special_properties = special_intelligence.get_all_properties();
136 self.properties.extend(special_properties);
137 }
138
139 fn initialize_polynomial_functions(&mut self) {
141 let polynomial_intelligence = super::polynomials::PolynomialIntelligence::new();
143
144 let polynomial_properties = polynomial_intelligence.get_all_properties();
146
147 self.properties.extend(polynomial_properties);
149 }
150
151 fn initialize_number_theory_functions(&mut self) {
153 let number_theory_intelligence = super::number_theory::NumberTheoryIntelligence::new();
155 let number_theory_properties = number_theory_intelligence.get_all_properties();
156 self.properties.extend(number_theory_properties);
157 }
158}
159
160#[inline(always)]
164pub fn get_universal_registry() -> &'static UniversalFunctionRegistry {
165 &UNIVERSAL_REGISTRY
166}
167
168#[cfg(test)]
169mod tests {
170 use super::*;
171
172 #[test]
173 fn test_registry_initialization() {
174 let registry = UniversalFunctionRegistry::new();
175
176 assert!(registry.properties.capacity() >= 64);
179 assert!(registry.step_generators.capacity() >= 64);
180
181 assert!(
183 registry.registry_size() > 0,
184 "Registry should have functions registered"
185 );
186 }
187
188 #[test]
189 fn test_has_intelligence_performance() {
190 let registry = UniversalFunctionRegistry::new();
191
192 let start = std::time::Instant::now();
194 for _ in 0..100_000 {
195 registry.has_intelligence("sin");
196 }
197 let duration = start.elapsed();
198
199 assert!(
203 duration.as_millis() < 100,
204 "Intelligence check too slow: {:?}",
205 duration
206 );
207 }
208
209 #[test]
210 fn test_elementary_function_intelligence() {
211 let registry = UniversalFunctionRegistry::new();
212
213 assert!(registry.has_intelligence("sin"));
215 assert!(registry.has_intelligence("cos"));
216 assert!(registry.has_intelligence("exp"));
217 assert!(registry.has_intelligence("ln"));
218
219 if let Some(props) = registry.get_properties("sin") {
221 assert!(props.has_derivative());
222 assert_eq!(props.family(), FunctionFamily::Elementary);
223 }
224 }
225
226 #[test]
227 fn test_polynomial_function_intelligence() {
228 let registry = UniversalFunctionRegistry::new();
229
230 assert!(registry.has_intelligence("legendre_p"));
232
233 if let Some(props) = registry.get_properties("legendre_p") {
235 assert!(props.has_derivative());
236 assert_eq!(props.family(), FunctionFamily::Polynomial);
237 }
238 }
239
240 #[test]
241 fn test_special_function_intelligence() {
242 let registry = UniversalFunctionRegistry::new();
243
244 assert!(
246 registry.has_intelligence("gamma"),
247 "Gamma function must be registered in universal registry"
248 );
249 assert!(
250 registry.has_intelligence("bessel_j"),
251 "Bessel J function must be registered in universal registry"
252 );
253 assert!(
254 registry.has_intelligence("bessel_y"),
255 "Bessel Y function must be registered in universal registry"
256 );
257 assert!(
258 registry.has_intelligence("zeta"),
259 "Zeta function must be registered in universal registry"
260 );
261
262 if let Some(props) = registry.get_properties("gamma") {
264 assert!(props.has_derivative());
265 assert_eq!(props.family(), FunctionFamily::Special);
266 }
267
268 if let Some(props) = registry.get_properties("zeta") {
270 assert!(props.has_derivative());
271 assert_eq!(props.family(), FunctionFamily::Special);
272 }
273 }
274
275 #[test]
276 fn test_all_special_functions_registered() {
277 let registry = UniversalFunctionRegistry::new();
278 let all_functions = registry.list_all_functions();
279
280 let required_special_functions = ["gamma", "beta", "bessel_j", "bessel_y", "zeta"];
282
283 for func in required_special_functions.iter() {
284 assert!(
285 all_functions.contains(&func.to_string()),
286 "Special function '{}' must be in registry",
287 func
288 );
289 }
290 }
291
292 #[test]
293 fn test_special_function_properties_quality() {
294 let registry = UniversalFunctionRegistry::new();
295
296 if let Some(props) = registry.get_properties("gamma") {
298 match props {
299 FunctionProperties::Special(sp) => {
300 assert!(
301 sp.special_values.len() >= 5,
302 "Gamma should have at least 5 special values including half-integers"
303 );
304 }
305 _ => panic!("Gamma should have Special properties"),
306 }
307 }
308
309 if let Some(props) = registry.get_properties("zeta") {
311 match props {
312 FunctionProperties::Special(sp) => {
313 assert!(
314 sp.special_values.len() >= 9,
315 "Zeta should have at least 9 special values"
316 );
317 }
318 _ => panic!("Zeta should have Special properties"),
319 }
320 }
321 }
322}