Skip to content

Commit 20068eb

Browse files
committed
Add RSolve, fix Expand/Together/Simplify/Apart, improve parser and pattern matching
- Add RSolve for linear recurrence relations with constant coefficients - Fix Expand for fraction^n and product^n distribution - Rewrite Together to use LCM-based common denominator computation - Fix Simplify to thread over Lists - Extend Apart for partial fraction decomposition improvements - Fix ReplaceAll to handle list-of-rule-lists (expr /. {{r1}, {r2}}) - Fix denominator parenthesization in display formatting - Add tilde infix notation (~f~) and parser improvements - Add ExpIntegralEi series expansion and numerical evaluation - Add cyclotomic polynomial detection in Solve - Extend arithmetic with Mod, PowerMod, and integer operations
1 parent 15500c9 commit 20068eb

File tree

19 files changed

+3465
-266
lines changed

19 files changed

+3465
-266
lines changed

src/evaluator/dispatch/calculus_functions.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,12 @@ pub fn dispatch_calculus_functions(
6565
"Limit" if (2..=3).contains(&args.len()) => {
6666
return Some(crate::functions::calculus_ast::limit_ast(args));
6767
}
68-
"Series" if args.len() == 2 => {
68+
"Series" if args.len() >= 2 => {
6969
return Some(crate::functions::calculus_ast::series_ast(args));
7070
}
71+
"RSolve" if args.len() == 3 => {
72+
return Some(crate::functions::rsolve_ast::rsolve_ast(args));
73+
}
7174
"DSolve" if args.len() == 3 => {
7275
return Some(crate::functions::ode_ast::dsolve_ast(args));
7376
}

src/evaluator/pattern_matching.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -990,6 +990,21 @@ pub fn apply_replace_all_ast(
990990
replacement,
991991
} => (expr_to_string(pattern), expr_to_string(replacement)),
992992
Expr::List(items) if !items.is_empty() => {
993+
// Check if this is a list of rule-lists: {{x->1}, {x->2}}
994+
// In Wolfram, expr /. {{r1}, {r2}} applies each sub-list independently
995+
// and returns a list of results: {expr/.{r1}, expr/.{r2}}
996+
let is_list_of_rule_lists = items.iter().all(|item| {
997+
matches!(item, Expr::List(sub) if sub.iter().all(|r|
998+
matches!(r, Expr::Rule { .. } | Expr::RuleDelayed { .. })
999+
))
1000+
});
1001+
if is_list_of_rule_lists {
1002+
let results: Result<Vec<Expr>, _> = items
1003+
.iter()
1004+
.map(|sub_rules| apply_replace_all_ast(expr, sub_rules))
1005+
.collect();
1006+
return results.map(Expr::List);
1007+
}
9931008
// Multiple rules - apply at AST level for correctness and performance.
9941009
// Collect (pattern_expr, replacement_expr) pairs.
9951010
let rule_exprs: Vec<(&Expr, &Expr)> = items

0 commit comments

Comments
 (0)