use super::properties::FunctionProperties;
use crate::core::Expression;
use crate::educational::step_by_step::Step;
use once_cell::sync::Lazy;
use std::collections::HashMap;
pub struct UniversalFunctionRegistry {
properties: HashMap<String, FunctionProperties>,
step_generators: HashMap<String, Box<dyn StepGenerator>>,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum FunctionFamily {
Elementary, Special, Polynomial, UserDefined, }
pub trait StepGenerator: Send + Sync {
fn generate_steps(&self, name: &str, args: &[Expression]) -> Vec<Step>;
fn generate_latex_explanation(&self, name: &str, args: &[Expression]) -> String;
}
pub static UNIVERSAL_REGISTRY: Lazy<UniversalFunctionRegistry> =
Lazy::new(UniversalFunctionRegistry::new);
impl Default for UniversalFunctionRegistry {
fn default() -> Self {
Self::new()
}
}
impl UniversalFunctionRegistry {
pub fn new() -> Self {
let mut registry = Self {
properties: HashMap::with_capacity(64), step_generators: HashMap::with_capacity(64), };
registry.initialize_elementary_functions();
registry.initialize_special_functions();
registry.initialize_polynomial_functions();
registry.initialize_number_theory_functions();
registry
}
#[inline(always)]
pub fn get_properties(&self, name: &str) -> Option<&FunctionProperties> {
self.properties.get(name)
}
#[inline(always)]
pub fn has_intelligence(&self, name: &str) -> bool {
self.properties.contains_key(name)
}
pub fn list_all_functions(&self) -> Vec<String> {
self.properties.keys().cloned().collect()
}
pub fn registry_size(&self) -> usize {
self.properties.len()
}
pub fn explain_function(&self, name: &str, args: &[Expression]) -> Vec<Step> {
if let Some(generator) = self.step_generators.get(name) {
generator.generate_steps(name, args)
} else {
vec![
Step::new("Function Call", format!("Evaluating {}(...)", name)),
Step::new("Arguments", format!("With {} arguments", args.len())),
]
}
}
fn initialize_elementary_functions(&mut self) {
let elementary_intelligence = super::elementary::ElementaryIntelligence::new();
let elementary_properties = elementary_intelligence.get_all_properties();
self.properties.extend(elementary_properties);
}
fn initialize_special_functions(&mut self) {
let special_intelligence = super::special::SpecialIntelligence::new();
let special_properties = special_intelligence.get_all_properties();
self.properties.extend(special_properties);
}
fn initialize_polynomial_functions(&mut self) {
let polynomial_intelligence = super::polynomials::PolynomialIntelligence::new();
let polynomial_properties = polynomial_intelligence.get_all_properties();
self.properties.extend(polynomial_properties);
}
fn initialize_number_theory_functions(&mut self) {
let number_theory_intelligence = super::number_theory::NumberTheoryIntelligence::new();
let number_theory_properties = number_theory_intelligence.get_all_properties();
self.properties.extend(number_theory_properties);
}
}
#[inline(always)]
pub fn get_universal_registry() -> &'static UniversalFunctionRegistry {
&UNIVERSAL_REGISTRY
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_registry_initialization() {
let registry = UniversalFunctionRegistry::new();
assert!(registry.properties.capacity() >= 64);
assert!(registry.step_generators.capacity() >= 64);
assert!(
registry.registry_size() > 0,
"Registry should have functions registered"
);
}
#[test]
fn test_has_intelligence_performance() {
let registry = UniversalFunctionRegistry::new();
let start = std::time::Instant::now();
for _ in 0..100_000 {
registry.has_intelligence("sin");
}
let duration = start.elapsed();
assert!(
duration.as_millis() < 100,
"Intelligence check too slow: {:?}",
duration
);
}
#[test]
fn test_elementary_function_intelligence() {
let registry = UniversalFunctionRegistry::new();
assert!(registry.has_intelligence("sin"));
assert!(registry.has_intelligence("cos"));
assert!(registry.has_intelligence("exp"));
assert!(registry.has_intelligence("ln"));
if let Some(props) = registry.get_properties("sin") {
assert!(props.has_derivative());
assert_eq!(props.family(), FunctionFamily::Elementary);
}
}
#[test]
fn test_polynomial_function_intelligence() {
let registry = UniversalFunctionRegistry::new();
assert!(registry.has_intelligence("legendre_p"));
if let Some(props) = registry.get_properties("legendre_p") {
assert!(props.has_derivative());
assert_eq!(props.family(), FunctionFamily::Polynomial);
}
}
#[test]
fn test_special_function_intelligence() {
let registry = UniversalFunctionRegistry::new();
assert!(
registry.has_intelligence("gamma"),
"Gamma function must be registered in universal registry"
);
assert!(
registry.has_intelligence("bessel_j"),
"Bessel J function must be registered in universal registry"
);
assert!(
registry.has_intelligence("bessel_y"),
"Bessel Y function must be registered in universal registry"
);
assert!(
registry.has_intelligence("zeta"),
"Zeta function must be registered in universal registry"
);
if let Some(props) = registry.get_properties("gamma") {
assert!(props.has_derivative());
assert_eq!(props.family(), FunctionFamily::Special);
}
if let Some(props) = registry.get_properties("zeta") {
assert!(props.has_derivative());
assert_eq!(props.family(), FunctionFamily::Special);
}
}
#[test]
fn test_all_special_functions_registered() {
let registry = UniversalFunctionRegistry::new();
let all_functions = registry.list_all_functions();
let required_special_functions = ["gamma", "beta", "bessel_j", "bessel_y", "zeta"];
for func in required_special_functions.iter() {
assert!(
all_functions.contains(&func.to_string()),
"Special function '{}' must be in registry",
func
);
}
}
#[test]
fn test_special_function_properties_quality() {
let registry = UniversalFunctionRegistry::new();
if let Some(props) = registry.get_properties("gamma") {
match props {
FunctionProperties::Special(sp) => {
assert!(
sp.special_values.len() >= 5,
"Gamma should have at least 5 special values including half-integers"
);
}
_ => panic!("Gamma should have Special properties"),
}
}
if let Some(props) = registry.get_properties("zeta") {
match props {
FunctionProperties::Special(sp) => {
assert!(
sp.special_values.len() >= 9,
"Zeta should have at least 9 special values"
);
}
_ => panic!("Zeta should have Special properties"),
}
}
}
}