gardesk/garcalc / 645536e

Browse files

wire up solve_system, factor dispatch, and Factorer export

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
645536e7672d4d21436a3137547b755f527b8337
Parents
7f372ce
Tree
c6b35bc

2 changed files

StatusFile+-
M garcalc-cas/src/eval.rs 50 5
M garcalc-cas/src/lib.rs 1 1
garcalc-cas/src/eval.rsmodified
@@ -8,7 +8,7 @@ use std::f64::consts::{E, PI};
88
 
99
 use crate::error::{CasError, Result};
1010
 use crate::expr::{Expr, Rational, Sign, Symbol};
11
-use crate::symbolic::{Differentiator, Integrator, Limits, Simplifier, Solver};
11
+use crate::symbolic::{Differentiator, Factorer, Integrator, Limits, Simplifier, Solver};
1212
 
1313
 /// Variable bindings for evaluation
1414
 pub type Environment = HashMap<String, Expr>;
@@ -571,8 +571,31 @@ impl Evaluator {
571571
             }
572572
 
573573
             ("solve", 2, _) => {
574
+                // solve([eq1, eq2], [x, y]) — system of equations
575
+                if let (Expr::Vector(equations), Expr::Vector(vars)) = (&args[0], &args[1]) {
576
+                    let var_symbols: std::result::Result<Vec<Symbol>, _> = vars
577
+                        .iter()
578
+                        .map(|v| match v {
579
+                            Expr::Symbol(s) => Ok(s.clone()),
580
+                            _ => Err(CasError::Type(
581
+                                "solve system requires variables as second argument".to_string(),
582
+                            )),
583
+                        })
584
+                        .collect();
585
+                    let var_symbols = var_symbols?;
586
+                    let solutions = Solver::solve_system(equations, &var_symbols)?;
587
+                    // Return as vector of equations: [x = val1, y = val2]
588
+                    let result: Vec<Expr> = solutions
589
+                        .into_iter()
590
+                        .map(|(var, val)| Expr::Equation(
591
+                            Box::new(Expr::Symbol(var)),
592
+                            Box::new(val),
593
+                        ))
594
+                        .collect();
595
+                    Ok(Expr::Vector(result))
596
+                }
574597
                 // solve(expr, var) or solve(equation, var)
575
-                if let Expr::Symbol(var) = &args[1] {
598
+                else if let Expr::Symbol(var) = &args[1] {
576599
                     let solutions = Solver::solve(&args[0], var)?;
577600
                     if solutions.len() == 1 {
578601
                         Ok(solutions.into_iter().next().unwrap())
@@ -611,9 +634,19 @@ impl Evaluator {
611634
             ("expand", 1, _) => Ok(Simplifier::simplify(&Simplifier::expand(&args[0]))),
612635
 
613636
             ("factor", 1, _) => {
614
-                // Basic factoring - just return simplified for now
615
-                // Full factoring is complex, can add later
616
-                Ok(Simplifier::simplify(&args[0]))
637
+                let var = Self::infer_primary_var(&args[0])
638
+                    .unwrap_or_else(|| Symbol::new("x"));
639
+                Ok(Factorer::factor(&args[0], &var))
640
+            }
641
+
642
+            ("factor", 2, _) => {
643
+                if let Expr::Symbol(var) = &args[1] {
644
+                    Ok(Factorer::factor(&args[0], var))
645
+                } else {
646
+                    Err(CasError::Type(
647
+                        "factor requires variable as second argument".to_string(),
648
+                    ))
649
+                }
617650
             }
618651
 
619652
             ("substitute", 3, _) | ("subs", 3, _) => {
@@ -1195,6 +1228,18 @@ impl Evaluator {
11951228
         }
11961229
     }
11971230
 
1231
+    fn infer_primary_var(expr: &Expr) -> Option<crate::expr::Symbol> {
1232
+        let mut vars = BTreeSet::new();
1233
+        Self::collect_symbols(expr, &mut vars);
1234
+        vars.remove("pi");
1235
+        vars.remove("e");
1236
+        if vars.len() == 1 {
1237
+            vars.into_iter().next().map(crate::expr::Symbol::new)
1238
+        } else {
1239
+            None
1240
+        }
1241
+    }
1242
+
11981243
     fn collect_symbols(expr: &Expr, out: &mut BTreeSet<String>) {
11991244
         match expr {
12001245
             Expr::Symbol(s) => {
garcalc-cas/src/lib.rsmodified
@@ -17,4 +17,4 @@ pub use error::{CasError, Result};
1717
 pub use eval::Evaluator;
1818
 pub use expr::{Expr, LimitDirection, Rational, Sign, Symbol};
1919
 pub use parser::Parser;
20
-pub use symbolic::{Differentiator, Integrator, Limits, Simplifier, Solver};
20
+pub use symbolic::{Differentiator, Factorer, Integrator, Limits, Simplifier, Solver};