Repository: nw-rs/citrus-cas (language: rust)

Issue:
add memoization to rule application
because rules are applied bottom-up and are frequently repeated on the same inputs, doing memoization on modify could create massive speed improvements


Discussion / hints:

Fix patch:
diff --git a/Cargo.lock b/Cargo.lock
index cd014fc..ef90aef 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -108,6 +108,12 @@ dependencies = [
  "byteorder",
 ]
 
+[[package]]
+name = "hashbrown"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
+
 [[package]]
 name = "heapless"
 version = "0.7.14"
@@ -121,6 +127,16 @@ dependencies = [
  "stable_deref_trait",
 ]
 
+[[package]]
+name = "indexmap"
+version = "1.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
+dependencies = [
+ "autocfg",
+ "hashbrown",
+]
+
 [[package]]
 name = "lazy_static"
 version = "1.4.0"
@@ -185,6 +201,7 @@ name = "rcas"
 version = "0.1.0"
 dependencies = [
  "heapless",
+ "indexmap",
  "libm",
  "nom",
 ]
diff --git a/Cargo.toml b/Cargo.toml
index 09928b6..770f67f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,6 +13,7 @@ repository = "https://github.com/willemml/rcas"
 nom = { version = "7.1.1", default-features = false, features = ["alloc"] }
 heapless = "0.7.14"
 libm = "0.2.2"
+indexmap = "1.9.1"
 
 [lib]
 name = "rcas"
diff --git a/src/expression/expression_tree.rs b/src/expression/expression_tree.rs
index 406e6a1..c52e327 100644
--- a/src/expression/expression_tree.rs
+++ b/src/expression/expression_tree.rs
@@ -1,9 +1,19 @@
-use core::{fmt, str::FromStr, cmp::Ordering, ops::{Add, Sub, Mul, Div}};
-use alloc::boxed::Box;
-
-use heapless::{Vec, String, LinearMap,};
-
-use crate::{expression::parser::parse, Error, modifier::Modifier};
+use alloc::{boxed::Box, string::String, vec::Vec};
+use core::{
+    cmp::Ordering,
+    fmt,
+    hash::{Hash, Hasher},
+    ops::{Add, Div, Mul, Sub},
+    str::FromStr,
+};
+
+use heapless::LinearMap;
+
+use crate::{
+    expression::parser::parse,
+    modifier::{ModifierImmutable, ModifierMutable, adaptable_modifier::ModifierFunction},
+    Error,
+};
 
 //Numeric: representation of any numeric value
 #[derive(Debug, Clone, PartialEq, PartialOrd, Copy)]
@@ -15,6 +25,19 @@ pub enum Numeric {
 
 impl Eq for Numeric {}
 
+impl Hash for Numeric {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        match self {
+            Numeric::Integer(i) => i.hash(state),
+            Numeric::Decimal(f) => f.to_bits().hash(state),
+            Numeric::Fraction(n, d) => {
+                n.hash(state);
+                d.hash(state);
+            }
+        }
+    }
+}
+
 impl Add for Numeric {
     type Output = Self;
 
@@ -91,12 +114,8 @@ impl Mul for Numeric {
             (Numeric::Fraction(a, b), Numeric::Fraction(c, d)) => {
                 Numeric::Fraction((a * d) + (b * c), b * d)
             }
-            (Numeric::Integer(a), Numeric::Fraction(b, c)) => {
-                Numeric::Fraction((a * c) + b, c)
-            }
-            (Numeric::Fraction(a, b), Numeric::Integer(c)) => {
-                Numeric::Fraction(a + (b * c), b)
-            }
+            (Numeric::Integer(a), Numeric::Fraction(b, c)) => Numeric::Fraction((a * c) + b, c),
+            (Numeric::Fraction(a, b), Numeric::Integer(c)) => Numeric::Fraction(a + (b * c), b),
             (Numeric::Decimal(a), Numeric::Fraction(b, c)) => {
                 Numeric::Decimal(a * (b as f32 / c as f32))
             }
@@ -119,12 +138,8 @@ impl Div for Numeric {
             (Numeric::Fraction(a, b), Numeric::Fraction(c, d)) => {
                 Numeric::Fraction((a * d) - (b * c), b * d)
             }
-            (Numeric::Integer(a), Numeric::Fraction(b, c)) => {
-                Numeric::Fraction((a * c) - b, c)
-            }
-            (Numeric::Fraction(a, b), Numeric::Integer(c)) => {
-                Numeric::Fraction(a - (b * c), b)
-            }
+            (Numeric::Integer(a), Numeric::Fraction(b, c)) => Numeric::Fraction((a * c) - b, c),
+            (Numeric::Fraction(a, b), Numeric::Integer(c)) => Numeric::Fraction(a - (b * c), b),
             (Numeric::Decimal(a), Numeric::Fraction(b, c)) => {
                 Numeric::Decimal(a / (b as f32 / c as f32))
             }
@@ -135,9 +150,9 @@ impl Div for Numeric {
     }
 }
 
-impl Into<f32> for Numeric {
-    fn into(self) -> f32 {
-        match self {
+impl From<Numeric> for f32 {
+    fn from(n: Numeric) -> f32 {
+        match n {
             Numeric::Integer(i) => i as f32,
             Numeric::Decimal(d) => d,
             Numeric::Fraction(n, d) => n as f32 / d as f32,
@@ -156,17 +171,17 @@ impl fmt::Display for Numeric {
 }
 
 //Atom: the smallest unit of an expression
-#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Copy)]
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Copy, Hash)]
 pub enum Atom {
     Numeric(Numeric),
     Variable(char),
-    //escapes indicate where something in an expression should be replaced: 
+    //escapes indicate where something in an expression should be replaced:
     // - A for atoms
     // - F for functions
     // - V for vectors
     // - M for matrices
     // - * for everything
-    Escape(char, u8), 
+    Escape(char, u8),
 }
 
 impl fmt::Display for Atom {
@@ -179,23 +194,21 @@ impl fmt::Display for Atom {
     }
 }
 
-type AlVec<T> = alloc::vec::Vec<T>;
-
 //Expression: a tree representing a mathematical expression
-#[derive(Debug, Clone, PartialEq)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub enum Expression {
     //atoms
     Atom(Atom),
 
     // Vector
     Vector {
-        backing: AlVec<Box<Expression>>,
+        backing: Vec<Box<Expression>>,
         size: u8,
     },
 
     // Matrix
     Matrix {
-        backing: AlVec<Box<Expression>>,
+        backing: Vec<Box<Expression>>,
         shape: (u8, u8),
     },
 
@@ -213,29 +226,87 @@ pub enum Expression {
     Modulus(Box<Self>, Box<Self>),
 
     //n-ary operators
-    Function { //TODO: make smaller somehow?
-        name: String<8>,
-        args: Vec<Box<Self>, 8>,
+    Function {
+        name: String,
+        args: Vec<Box<Self>>,
     },
 }
 
 impl Expression {
+    //reorganizes the expression tree using the given modifier a max of L times, with a modifier that cannot be mutated
+    pub fn simplify_im<S: ModifierImmutable, const L: usize>(&mut self, simplifier: &S) {
+        for _ in 0..L {
+            if !simplifier.modify_immut(self) {
+                break;
+            }
+        }
+    }
+
+    //simplifies, then uses the evaluation modifier on the tree a max of L times, with a modifier that cannot be mutated
+    pub fn evaluate_im<E: ModifierImmutable, S: ModifierImmutable, const L: usize>(
+        &self,
+        evaluator: &E,
+        simplifier: &S,
+    ) -> Expression {
+        let mut expr = self.clone();
+
+        for _ in 0..L {
+            expr.simplify_im::<S, L>(simplifier);
+            if !evaluator.modify_immut(&mut expr) {
+                break;
+            }
+        }
+
+        expr
+    }
+
+    //evaluates, then uses the approximation modifier on the tree a max of L times, with a modifier that cannot be mutated
+    pub fn approximate_im<
+        A: ModifierImmutable,
+        E: ModifierImmutable,
+        S: ModifierImmutable,
+        const L: usize,
+    >(
+        &self,
+        approximator: &A,
+        evaluator: &E,
+        simplifier: &S,
+    ) -> Result<Numeric, crate::Error> {
+        let mut expr = self.clone();
+
+        for _ in 0..L {
+            expr = expr.evaluate_im::<E, S, L>(evaluator, simplifier);
+            if !approximator.modify_immut(&mut expr) {
+                break;
+            }
+        }
+
+        match expr {
+            Expression::Atom(Atom::Numeric(n)) => Ok(n),
+            _ => Err(Error::UndefinedSymbol),
+        }
+    }
+
     //reorganizes the expression tree using the given modifier a max of L times
-    pub fn simplify<S: Modifier, const L: usize>(&mut self, simplifier: &S) {
+    pub fn simplify<S: ModifierMutable, const L: usize>(&mut self, simplifier: &mut S) {
         for _ in 0..L {
-            if !simplifier.modify(self) {
+            if !simplifier.modify_mut(self) {
                 break;
             }
         }
     }
 
     //simplifies, then uses the evaluation modifier on the tree a max of L times
-    pub fn evaluate<E: Modifier, S: Modifier, const L: usize>(&self, evaluator: &E, simplifier: &S) -> Expression {
+    pub fn evaluate<E: ModifierMutable, S: ModifierMutable, const L: usize>(
+        &self,
+        evaluator: &mut E,
+        simplifier: &mut S,
+    ) -> Expression {
         let mut expr = self.clone();
 
         for _ in 0..L {
             expr.simplify::<S, L>(simplifier);
-            if !evaluator.modify(&mut expr) {
+            if !evaluator.modify_mut(&mut expr) {
                 break;
             }
         }
@@ -244,196 +315,223 @@ impl Expression {
     }
 
     //evaluates, then uses the approximation modifier on the tree a max of L times
-    pub fn approximate<A: Modifier, E: Modifier, S: Modifier, const L: usize>(&self, approximator: &A, evaluator: &E, simplifier: &S) -> Result<Numeric, ()> {
+    pub fn approximate<
+        A: ModifierMutable,
+        E: ModifierMutable,
+        S: ModifierMutable,
+        const L: usize,
+    >(
+        &self,
+        approximator: &mut A,
+        evaluator: &mut E,
+        simplifier: &mut S,
+    ) -> Result<Numeric, crate::Error> {
         let mut expr = self.clone();
 
         for _ in 0..L {
             expr = expr.evaluate::<E, S, L>(evaluator, simplifier);
-            if !approximator.modify(&mut expr) {
+            if !approximator.modify_mut(&mut expr) {
                 break;
             }
         }
 
         match expr {
-            Expression::Atom(a) => match a {
-                Atom::Numeric(n) => Ok(n),
-                _ => Err(()),
-            },
-            _ => Err(()),
+            Expression::Atom(Atom::Numeric(n)) => Ok(n),
+            _ => Err(Error::UndefinedSymbol),
         }
     }
 
     //returns the number of escapes in the other expression, or None if the expressions are not equal
-    pub fn level_eq(&self, other: &Self) -> Option<(u8, LinearMap<Atom, Expression, 8>)> {
+    pub fn level_eq(&self, other: &Self, map: &mut LinearMap<Atom, Expression, 8>) -> Option<u8> {
         match (self, other) {
             (e, Expression::Atom(a)) => match a {
                 Atom::Escape(escape, _) => match escape {
                     'A' => match e {
-                        Expression::Atom(a) => {
-                            let mut map = LinearMap::new();
-                            map.insert(a.clone(), e.clone());
-                            Some((1, map))
+                        Expression::Atom(a) => match map.get(a) {
+                            Some(expr) => {
+                                if expr == e {
+                                    Some(1)
+                                } else {
+                                    None
+                                }
+                            }
+                            None => {
+                                map.insert(*a, e.clone())
+                                    .map_err(|(_, _)| "too many escapes")
+                                    .unwrap();
+                                Some(1)
+                            }
                         },
                         _ => None,
-                    }
+                    },
                     'F' => match e {
-                        Expression::Function { name: _, args: _ } => {
-                            let mut map = LinearMap::new();
-                            map.insert(a.clone(), e.clone());
-                            Some((1, map))
+                        Expression::Function { name: _, args: _ } => match map.get(a) {
+                            Some(expr) => {
+                                if expr == e {
+                                    Some(1)
+                                } else {
+                                    None
+                                }
+                            }
+                            None => {
+                                map.insert(*a, e.clone())
+                                    .map_err(|(_, _)| "too many escapes")
+                                    .unwrap();
+                                Some(1)
+                            }
                         },
                         _ => None,
-                    }
+                    },
                     'V' => match e {
-                        Expression::Vector { backing: _, size: _ } => {
-                            let mut map = LinearMap::new();
-                            map.insert(a.clone(), e.clone());
-                            Some((1, map))
+                        Expression::Vector {
+                            backing: _,
+                            size: _,
+                        } => match map.get(a) {
+                            Some(expr) => {
+                                if expr == e {
+                                    Some(1)
+                                } else {
+                                    None
+                                }
+                            }
+                            None => {
+                                map.insert(*a, e.clone())
+                                    .map_err(|(_, _)| "too many escapes")
+                                    .unwrap();
+                                Some(1)
+                            }
                         },
                         _ => None,
-                    }
+                    },
                     'M' => match e {
-                        Expression::Matrix { backing: _, shape: _ } => {
-                            let mut map = LinearMap::new();
-                            map.insert(a.clone(), e.clone());
-                            Some((1, map))
+                        Expression::Matrix {
+                            backing: _,
+                            shape: _,
+                        } => match map.get(a) {
+                            Some(expr) => {
+                                if expr == e {
+                                    Some(1)
+                                } else {
+                                    None
+                                }
+                            }
+                            None => {
+                                map.insert(*a, e.clone())
+                                    .map_err(|(_, _)| "too many escapes")
+                                    .unwrap();
+                                Some(1)
+                            }
                         },
                         _ => None,
-                    }
-                    '*' => {
-                        let mut map = LinearMap::new();
-                        map.insert(a.clone(), e.clone());
-                        Some((1, map))
+                    },
+                    '*' => match map.get(a) {
+                        Some(expr) => {
+                            if expr == e {
+                                Some(1)
+                            } else {
+                                None
+                            }
+                        }
+                        None => {
+                            map.insert(*a, e.clone())
+                                .map_err(|(_, _)| "too many escapes")
+                                .unwrap();
+                            Some(1)
+                        }
                     },
                     _ => unimplemented!(),
+                },
+                _ => {
+                    if self == other {
+                        Some(0)
+                    } else {
+                        None
+                    }
                 }
-                _ => if self == other { Some((0, LinearMap::new())) } else { None },
             },
-            (Expression::Function { name: n1, args: a1 }, Expression::Function { name: n2, args: a2 }) => {
+            (
+                Expression::Function { name: n1, args: a1 },
+                Expression::Function { name: n2, args: a2 },
+            ) => {
                 if n1 == n2 {
                     let mut level = 0;
-                    let mut map = LinearMap::new();
 
                     for (arg1, arg2) in a1.iter().zip(a2.iter()) {
-                        match arg1.level_eq(arg2) {
-                            Some(l) => {
-                                level += l.0;
-                                l.1.iter().for_each(|(k, v)| {
-                                    if let Some(value) = map.get(k) {
-                                        if value != v {
-                                            level=u8::MAX;
-                                        }
-                                    } else {
-                                        map.insert(k.clone(), v.clone());
-                                    }
-                                });
-                                if level == u8::MAX {
-                                    return None;
-                                }
-                            },
+                        match arg1.level_eq(arg2, map) {
+                            Some(l) => level += l,
                             None => return None,
-                        }
+                        };
                     }
 
-                    Some((level, map))
+                    Some(level)
                 } else {
                     None
                 }
             }
-            (Expression::Vector { backing: b1, size: s1 }, Expression::Vector { backing: b2, size: s2 }) => {
+            (
+                Expression::Vector {
+                    backing: b1,
+                    size: s1,
+                },
+                Expression::Vector {
+                    backing: b2,
+                    size: s2,
+                },
+            ) => {
                 if s1 == s2 {
                     let mut level = 0;
-                    let mut map = LinearMap::new();
 
                     for (expr1, expr2) in b1.iter().zip(b2.iter()) {
-                        match expr1.level_eq(expr2) {
-                            Some(l) => {
-                                level += l.0;
-                                l.1.iter().for_each(|(k, v)| {
-                                    if let Some(value) = map.get(k) {
-                                        if value != v {
-                                            level=u8::MAX;
-                                        }
-                                    } else {
-                                        map.insert(k.clone(), v.clone());
-                                    }
-                                });
-                                if level == u8::MAX {
-                                    return None;
-                                }
-                            },
+                        match expr1.level_eq(expr2, map) {
+                            Some(l) => level += l,
                             None => return None,
-                        }
+                        };
                     }
 
-                    Some((level, map))
+                    Some(level)
                 } else {
                     None
                 }
             }
-            (Expression::Matrix { backing: b1, shape: s1 }, Expression::Matrix { backing: b2, shape: s2 }) => {
+            (
+                Expression::Matrix {
+                    backing: b1,
+                    shape: s1,
+                },
+                Expression::Matrix {
+                    backing: b2,
+                    shape: s2,
+                },
+            ) => {
                 if s1 == s2 {
                     let mut level = 0;
-                    let mut map = LinearMap::new();
 
                     for (expr1, expr2) in b1.iter().zip(b2.iter()) {
-                        match expr1.level_eq(expr2) {
-                            Some(l) => {
-                                level += l.0;
-                                l.1.iter().for_each(|(k, v)| {
-                                    if let Some(value) = map.get(k) {
-                                        if value != v {
-                                            level=u8::MAX;
-                                        }
-                                    } else {
-                                        map.insert(k.clone(), v.clone());
-                                    }
-                                });
-                                if level == u8::MAX {
-                                    return None;
-                                }
-                            },
+                        match expr1.level_eq(expr2, map) {
+                            Some(l) => level += l,
                             None => return None,
-                        }
+                        };
                     }
 
-                    Some((level, map))
+                    Some(level)
                 } else {
                     None
                 }
             }
-            (Expression::Negate(e1), Expression::Negate(e2)) |
-            (Expression::Factorial(e1), Expression::Factorial(e2)) |
-            (Expression::Percent(e1), Expression::Percent(e2)) => {
-                e1.level_eq(e2)
-            },
-            (Expression::Add(e11, e12), Expression::Add(e21, e22)) |
-            (Expression::Subtract(e11, e12), Expression::Subtract(e21, e22)) |
-            (Expression::Multiply(e11, e12), Expression::Multiply(e21, e22)) |
-            (Expression::Divide(e11, e12), Expression::Divide(e21, e22)) |
-            (Expression::Power(e11, e12), Expression::Power(e21, e22)) |
-            (Expression::Modulus(e11, e12), Expression::Modulus(e21, e22)) => {
-                let level1 = e11.level_eq(e21);
-                let level2 = e12.level_eq(e22);
+            (Expression::Negate(e1), Expression::Negate(e2))
+            | (Expression::Factorial(e1), Expression::Factorial(e2))
+            | (Expression::Percent(e1), Expression::Percent(e2)) => e1.level_eq(e2, map),
+            (Expression::Add(e11, e12), Expression::Add(e21, e22))
+            | (Expression::Subtract(e11, e12), Expression::Subtract(e21, e22))
+            | (Expression::Multiply(e11, e12), Expression::Multiply(e21, e22))
+            | (Expression::Divide(e11, e12), Expression::Divide(e21, e22))
+            | (Expression::Power(e11, e12), Expression::Power(e21, e22))
+            | (Expression::Modulus(e11, e12), Expression::Modulus(e21, e22)) => {
+                let level1 = e11.level_eq(e21, map);
+                let level2 = e12.level_eq(e22, map);
+
                 match (level1, level2) {
-                    (Some(l1), Some(l2)) => {
-                        let mut level = l1.0 + l2.0;
-                        let mut map = l1.1;
-                        l2.1.iter().for_each(|(k, v)| {
-                            if let Some(value) = map.get(k) {
-                                if value != v {
-                                    level=u8::MAX;
-                                }
-                            } else {
-                                map.insert(k.clone(), v.clone());
-                            }
-                        });
-                        if level == u8::MAX {
-                            None
-                        } else {
-                            Some((level, map))
-                        }
-                    },
+                    (Some(l1), Some(l2)) => Some(l1 + l2),
                     _ => None,
                 }
             }
@@ -442,89 +540,117 @@ impl Expression {
     }
 
     //extracts a modification function from the given expression
-    pub fn conversion(self) -> Box<dyn Fn (&LinearMap<Atom, Expression, 8>) -> (Expression, bool)> {
+    pub fn conversion(self) -> ModifierFunction {
         Box::new(move |map: &LinearMap<Atom, Expression, 8>| {
-            (match &self {
-                Expression::Atom(a) => match a {
-                    Atom::Escape(_, _) => {
-                         map.get(&a).unwrap().clone()
-                    }
-                    _ => {
-                        self.clone()
-                    }
-                }
-                Expression::Function { name: n, args: a } => {
-                    let mut args = Vec::new();
+            (
+                match &self {
+                    Expression::Atom(a) => match a {
+                        Atom::Escape(_, _) => map.get(a).unwrap().clone(),
+                        _ => self.clone(),
+                    },
+                    Expression::Function { name: n, args: a } => {
+                        let mut args = Vec::new();
 
-                    for arg in a.clone() {
-                        args.push(Box::new(arg.conversion()(&map).0)).unwrap(); //vec overflow is impossible here
+                        for arg in a.clone() {
+                            args.push(Box::new(arg.conversion()(map).0)); //vec overflow is impossible here
+                        }
+
+                        Expression::Function {
+                            name: n.clone(),
+                            args,
+                        }
                     }
-                    
-                    Expression::Function { name: n.clone(), args }
-                }
-                Expression::Vector { backing: b, size: s } => {
-                    let mut backing = alloc::vec::Vec::new();
+                    Expression::Vector {
+                        backing: b,
+                        size: s,
+                    } => {
+                        let mut backing = alloc::vec::Vec::new();
+
+                        for arg in b.clone() {
+                            backing.push(Box::new(arg.conversion()(map).0));
+                        }
 
-                    for arg in b.clone() {
-                        backing.push(Box::new(arg.conversion()(&map).0));
+                        Expression::Vector {
+                            backing,
+                            size: *s,
+                        }
                     }
-                    
-                    Expression::Vector { backing, size: s.clone() }
-                }
-                Expression::Matrix { backing: b, shape: s } => {
-                    let mut backing = alloc::vec::Vec::new();
+                    Expression::Matrix {
+                        backing: b,
+                        shape: s,
+                    } => {
+                        let mut backing = alloc::vec::Vec::new();
+
+                        for arg in b.clone() {
+                            backing.push(Box::new(arg.conversion()(map).0));
+                        }
 
-                    for arg in b.clone() {
-                        backing.push(Box::new(arg.conversion()(&map).0));
+                        Expression::Matrix {
+                            backing,
+                            shape: *s,
+                        }
                     }
-                    
-                    Expression::Matrix { backing, shape: s.clone() }
-                }
-                Expression::Negate(e) => {
-                    Expression::Negate(Box::new(e.clone().conversion()(&map).0))
-                }
-                Expression::Factorial(e) => {
-                    Expression::Factorial(Box::new(e.clone().conversion()(&map).0))
-                }
-                Expression::Percent(e) => {
-                    Expression::Percent(Box::new(e.clone().conversion()(&map).0))
-                }
-                Expression::Add(e1, e2) => {
-                    Expression::Add(Box::new(e1.clone().conversion()(&map).0), Box::new(e2.clone().conversion()(&map).0))
-                }
-                Expression::Subtract(e1, e2) => {
-                    Expression::Subtract(Box::new(e1.clone().conversion()(&map).0), Box::new(e2.clone().conversion()(&map).0))
-                }
-                Expression::Multiply(e1, e2) => {
-                    Expression::Multiply(Box::new(e1.clone().conversion()(&map).0), Box::new(e2.clone().conversion()(&map).0))
-                }
-                Expression::Divide(e1, e2) => {
-                    Expression::Divide(Box::new(e1.clone().conversion()(&map).0), Box::new(e2.clone().conversion()(&map).0))
-                }
-                Expression::Power(e1, e2) => {
-                    Expression::Power(Box::new(e1.clone().conversion()(&map).0), Box::new(e2.clone().conversion()(&map).0))
-                }
-                Expression::Modulus(e1, e2) => {
-                    Expression::Modulus(Box::new(e1.clone().conversion()(&map).0), Box::new(e2.clone().conversion()(&map).0))
-                }
-            }, true)},
-        )
+                    Expression::Negate(e) => {
+                        Expression::Negate(Box::new(e.clone().conversion()(map).0))
+                    }
+                    Expression::Factorial(e) => {
+                        Expression::Factorial(Box::new(e.clone().conversion()(map).0))
+                    }
+                    Expression::Percent(e) => {
+                        Expression::Percent(Box::new(e.clone().conversion()(map).0))
+                    }
+                    Expression::Add(e1, e2) => Expression::Add(
+                        Box::new(e1.clone().conversion()(map).0),
+                        Box::new(e2.clone().conversion()(map).0),
+                    ),
+                    Expression::Subtract(e1, e2) => Expression::Subtract(
+                        Box::new(e1.clone().conversion()(map).0),
+                        Box::new(e2.clone().conversion()(map).0),
+                    ),
+                    Expression::Multiply(e1, e2) => Expression::Multiply(
+                        Box::new(e1.clone().conversion()(map).0),
+                        Box::new(e2.clone().conversion()(map).0),
+                    ),
+                    Expression::Divide(e1, e2) => Expression::Divide(
+                        Box::new(e1.clone().conversion()(map).0),
+                        Box::new(e2.clone().conversion()(map).0),
+                    ),
+                    Expression::Power(e1, e2) => Expression::Power(
+                        Box::new(e1.clone().conversion()(map).0),
+                        Box::new(e2.clone().conversion()(map).0),
+                    ),
+                    Expression::Modulus(e1, e2) => Expression::Modulus(
+                        Box::new(e1.clone().conversion()(map).0),
+                        Box::new(e2.clone().conversion()(map).0),
+                    ),
+                },
+                true,
+            )
+        })
     }
 
     //uses a template expression to extract the sub-expressions from the given expression
-    pub fn extract_arguments(&self, template: &Expression, map: LinearMap<Atom, Expression, 8>) -> LinearMap<Atom, Expression, 8> {
+    pub fn extract_arguments(
+        &self,
+        template: &Expression,
+        map: LinearMap<Atom, Expression, 8>,
+    ) -> LinearMap<Atom, Expression, 8> {
         match (self, template) {
-            (_, Expression::Atom(a)) => {
-                match a {
-                    Atom::Escape(_, _) => {
-                        let mut map_n = map;
-                        map_n.insert(a.clone(), self.clone()).map_err(|_| "too many arguments").unwrap();
-                        map_n
-                    }
-                    _ => map
+            (_, Expression::Atom(a)) => match a {
+                Atom::Escape(_, _) => {
+                    let mut map_n = map;
+                    map_n
+                        .insert(*a, self.clone())
+                        .map_err(|_| "too many arguments")
+                        .unwrap();
+                    map_n
                 }
-            }
-            (Expression::Function { name: n1, args: a1 }, Expression::Function { name: n2, args: a2 }) => {
+                _ => map,
+            },
+            (
+                Expression::Function { name: n1, args: a1 },
+                Expression::Function { name: n2, args: a2 },
+            ) => {
                 if n1 == n2 {
                     let mut map_n = map;
                     for (arg1, arg2) in a1.iter().zip(a2.iter()) {
@@ -535,7 +661,16 @@ impl Expression {
                     map
                 }
             }
-            (Expression::Vector { backing: b1, size: s1 }, Expression::Vector { backing: b2, size: s2 }) => {
+            (
+                Expression::Vector {
+                    backing: b1,
+                    size: s1,
+                },
+                Expression::Vector {
+                    backing: b2,
+                    size: s2,
+                },
+            ) => {
                 if s1 == s2 {
                     let mut map_n = map;
                     for (arg1, arg2) in b1.iter().zip(b2.iter()) {
@@ -546,7 +681,16 @@ impl Expression {
                     map
                 }
             }
-            (Expression::Matrix { backing: b1, shape: s1 }, Expression::Matrix { backing: b2, shape: s2 }) => {
+            (
+                Expression::Matrix {
+                    backing: b1,
+                    shape: s1,
+                },
+                Expression::Matrix {
+                    backing: b2,
+                    shape: s2,
+                },
+            ) => {
                 if s1 == s2 {
                     let mut map_n = map;
                     for (arg1, arg2) in b1.iter().zip(b2.iter()) {
@@ -557,17 +701,15 @@ impl Expression {
                     map
                 }
             }
-            (Expression::Negate(e1), Expression::Negate(e2)) |
-            (Expression::Factorial(e1), Expression::Factorial(e2)) |
-            (Expression::Percent(e1), Expression::Percent(e2)) => {
-                e1.extract_arguments(e2, map)
-            },
-            (Expression::Add(e11, e12), Expression::Add(e21, e22)) |
-            (Expression::Subtract(e11, e12), Expression::Subtract(e21, e22)) |
-            (Expression::Multiply(e11, e12), Expression::Multiply(e21, e22)) |
-            (Expression::Divide(e11, e12), Expression::Divide(e21, e22)) |
-            (Expression::Power(e11, e12), Expression::Power(e21, e22)) |
-            (Expression::Modulus(e11, e12), Expression::Modulus(e21, e22)) => {
+            (Expression::Negate(e1), Expression::Negate(e2))
+            | (Expression::Factorial(e1), Expression::Factorial(e2))
+            | (Expression::Percent(e1), Expression::Percent(e2)) => e1.extract_arguments(e2, map),
+            (Expression::Add(e11, e12), Expression::Add(e21, e22))
+            | (Expression::Subtract(e11, e12), Expression::Subtract(e21, e22))
+            | (Expression::Multiply(e11, e12), Expression::Multiply(e21, e22))
+            | (Expression::Divide(e11, e12), Expression::Divide(e21, e22))
+            | (Expression::Power(e11, e12), Expression::Power(e21, e22))
+            | (Expression::Modulus(e11, e12), Expression::Modulus(e21, e22)) => {
                 let map_n = e11.extract_arguments(e21, map);
                 e12.extract_arguments(e22, map_n)
             }
@@ -613,20 +755,39 @@ impl PartialOrd for Expression {
     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
         match (self, other) {
             (Expression::Atom(_), _) | (_, Expression::Atom(_)) => Some(Ordering::Equal),
-            (Expression::Function { name: n1, args: a1 }, Expression::Function { name: n2, args: a2 }) => a1.partial_cmp(a2).and(n1.partial_cmp(n2)),
-            (Expression::Vector { backing: b1, size: s1 }, Expression::Vector { backing: b2, size: s2 }) => b1.partial_cmp(b2).and(s1.partial_cmp(s2)),
-            (Expression::Matrix { backing: b1, shape: s1 }, Expression::Matrix { backing: b2, shape: s2 }) => b1.partial_cmp(b2).and(s1.partial_cmp(s2)),
-            (Expression::Negate(e1), Expression::Negate(e2)) |
-            (Expression::Factorial(e1), Expression::Factorial(e2)) |
-            (Expression::Percent(e1), Expression::Percent(e2)) => {
-                e1.partial_cmp(e2)
-            }
-            (Expression::Add(a1, a2), Expression::Add(b1, b2)) |
-            (Expression::Subtract(a1, a2), Expression::Subtract(b1, b2)) |
-            (Expression::Multiply(a1, a2), Expression::Multiply(b1, b2)) |
-            (Expression::Divide(a1, a2), Expression::Divide(b1, b2)) |
-            (Expression::Power(a1, a2), Expression::Power(b1, b2)) |
-            (Expression::Modulus(a1, a2), Expression::Modulus(b1, b2)) => {
+            (
+                Expression::Function { name: n1, args: a1 },
+                Expression::Function { name: n2, args: a2 },
+            ) => a1.partial_cmp(a2).and(n1.partial_cmp(n2)),
+            (
+                Expression::Vector {
+                    backing: b1,
+                    size: s1,
+                },
+                Expression::Vector {
+                    backing: b2,
+                    size: s2,
+                },
+            ) => b1.partial_cmp(b2).and(s1.partial_cmp(s2)),
+            (
+                Expression::Matrix {
+                    backing: b1,
+                    shape: s1,
+                },
+                Expression::Matrix {
+                    backing: b2,
+                    shape: s2,
+                },
+            ) => b1.partial_cmp(b2).and(s1.partial_cmp(s2)),
+            (Expression::Negate(e1), Expression::Negate(e2))
+            | (Expression::Factorial(e1), Expression::Factorial(e2))
+            | (Expression::Percent(e1), Expression::Percent(e2)) => e1.partial_cmp(e2),
+            (Expression::Add(a1, a2), Expression::Add(b1, b2))
+            | (Expression::Subtract(a1, a2), Expression::Subtract(b1, b2))
+            | (Expression::Multiply(a1, a2), Expression::Multiply(b1, b2))
+            | (Expression::Divide(a1, a2), Expression::Divide(b1, b2))
+            | (Expression::Power(a1, a2), Expression::Power(b1, b2))
+            | (Expression::Modulus(a1, a2), Expression::Modulus(b1, b2)) => {
                 match a1.partial_cmp(b1) {
                     Some(Ordering::Equal) => a2.partial_cmp(b2),
                     o => o,
@@ -634,10 +795,34 @@ impl PartialOrd for Expression {
             }
             (Expression::Function { name: _, args: _ }, _) => Some(Ordering::Greater),
             (_, Expression::Function { name: _, args: _ }) => Some(Ordering::Less),
-            (Expression::Vector { backing: _, size: _ }, _) => Some(Ordering::Greater),
-            (_, Expression::Vector { backing: _, size: _ }) => Some(Ordering::Less),
-            (Expression::Matrix { backing: _, shape: _ }, _) => Some(Ordering::Greater),
-            (_, Expression::Matrix { backing: _, shape: _ }) => Some(Ordering::Less),
+            (
+                Expression::Vector {
+                    backing: _,
+                    size: _,
+                },
+                _,
+            ) => Some(Ordering::Greater),
+            (
+                _,
+                Expression::Vector {
+                    backing: _,
+                    size: _,
+                },
+            ) => Some(Ordering::Less),
+            (
+                Expression::Matrix {
+                    backing: _,
+                    shape: _,
+                },
+                _,
+            ) => Some(Ordering::Greater),
+            (
+                _,
+                Expression::Matrix {
+                    backing: _,
+                    shape: _,
+                },
+            ) => Some(Ordering::Less),
             (Expression::Negate(_), _) => Some(Ordering::Greater),
             (_, Expression::Negate(_)) => Some(Ordering::Less),
             (Expression::Factorial(_), _) => Some(Ordering::Greater),
@@ -664,7 +849,10 @@ impl fmt::Display for Expression {
         match self {
             Expression::Atom(a) => write!(f, "{}", a),
 
-            Expression::Vector { backing: vec, size: _ } => {
+            Expression::Vector {
+                backing: vec,
+                size: _,
+            } => {
                 write!(f, "<")?;
                 for (i, e) in vec.iter().enumerate() {
                     if i > 0 {
@@ -675,7 +863,10 @@ impl fmt::Display for Expression {
                 write!(f, ">")
             }
 
-            Expression::Matrix { backing: vec, shape: (rs, cs) } => {
+            Expression::Matrix {
+                backing: vec,
+                shape: (rs, cs),
+            } => {
                 write!(f, "[")?;
                 for r in 0..*rs {
                     if r > 0 {
@@ -690,18 +881,18 @@ impl fmt::Display for Expression {
                 }
                 write!(f, "]")
             }
-            
+
             Expression::Negate(e) => write!(f, "-({})", e),
             Expression::Factorial(e) => write!(f, "({})!", e),
             Expression::Percent(e) => write!(f, "({})%", e),
-            
+
             Expression::Add(l, r) => write!(f, "({} + {})", l, r),
             Expression::Subtract(l, r) => write!(f, "({} - {})", l, r),
             Expression::Multiply(l, r) => write!(f, "({} * {})", l, r),
             Expression::Divide(l, r) => write!(f, "({} / {})", l, r),
             Expression::Power(l, r) => write!(f, "({} ^ {})", l, r),
             Expression::Modulus(l, r) => write!(f, "({} % {})", l, r),
-            
+
             Expression::Function { name, args } => {
                 write!(f, "{}(", name)?;
                 for (i, arg) in args.iter().enumerate() {
@@ -736,14 +927,24 @@ mod tests {
 
     #[test]
     fn test_numeric_eq() {
-        assert_ne!(Expression::Atom(Atom::Numeric(Numeric::Integer(1))), Expression::Atom(Atom::Numeric(Numeric::Decimal(1.2))));
+        assert_ne!(
+            Expression::Atom(Atom::Numeric(Numeric::Integer(1))),
+            Expression::Atom(Atom::Numeric(Numeric::Decimal(1.2)))
+        );
     }
 
     #[test]
     fn test_fmt_parse() {
         //TODO: fix Expression to_string()
-        assert_eq!(Expression::from_str("1 * 3 + 5 / 6 + sin(x) + -6").unwrap(),
-            Expression::from_str(Expression::from_str("1 * 3 + 5 / 6 + sin(x) + -6").unwrap().to_string().as_str()).unwrap()
+        assert_eq!(
+            Expression::from_str("1 * 3 + 5 / 6 + sin(x) + -6").unwrap(),
+            Expression::from_str(
+                Expression::from_str("1 * 3 + 5 / 6 + sin(x) + -6")
+                    .unwrap()
+                    .to_string()
+                    .as_str()
+            )
+            .unwrap()
         )
     }
-}
\ No newline at end of file
+}
diff --git a/src/expression/mod.rs b/src/expression/mod.rs
index f0ebff7..895376f 100644
--- a/src/expression/mod.rs
+++ b/src/expression/mod.rs
@@ -1,2 +1,2 @@
 pub mod expression_tree;
-mod parser;
\ No newline at end of file
+mod parser;
diff --git a/src/expression/parser.rs b/src/expression/parser.rs
index 98ecb11..dd7f0c2 100644
--- a/src/expression/parser.rs
+++ b/src/expression/parser.rs
@@ -1,66 +1,63 @@
-use core::str::FromStr;
-
-use alloc::{boxed::Box, vec::Vec, vec};
+use alloc::{boxed::Box, string::ToString, vec::Vec};
 
+use nom::multi::separated_list0;
 use nom::{
-    IResult,
-    sequence::{delimited, tuple, preceded, terminated,},
-    character::complete::{space0, char, digit1,},
-    combinator::map,
     branch::alt,
-    bytes::complete::{take_while1, take},
+    bytes::complete::{take, take_while1},
+    character::complete::{char, digit1, space0},
+    combinator::map,
     multi::many0,
+    sequence::{delimited, preceded, terminated, tuple},
+    IResult,
 };
-use nom::multi::separated_list0;
 
-use crate::expression::expression_tree::{Expression, Numeric, Atom};
+use crate::expression::expression_tree::{Atom, Expression, Numeric};
 
 //TODO: explain parser
 
 pub fn parse(input: &str) -> Expression {
-    parse_add_sub(input).map_err(|_| "failed to parse").unwrap().1
+    parse_add_sub(input)
+        .map_err(|_| "failed to parse")
+        .unwrap()
+        .1
 }
 
 fn parse_recursive(input: &str) -> IResult<&str, Expression> {
-    alt((parse_parentheses, parse_vector, parse_matrix, parse_numeric, parse_function, parse_escape, parse_variable,))(input)
+    alt((
+        parse_parentheses,
+        parse_vector,
+        parse_matrix,
+        parse_numeric,
+        parse_function,
+        parse_escape,
+        parse_variable,
+    ))(input)
 }
 
 fn parse_parentheses(input: &str) -> IResult<&str, Expression> {
     delimited(
         space0,
-        delimited(
-            char('('),
-            parse_add_sub,
-            char(')'),
-        ),
+        delimited(char('('), parse_add_sub, char(')')),
         space0,
     )(input)
 }
 
 fn parse_numeric(input: &str) -> IResult<&str, Expression> {
     map(
-        delimited(
-            space0,
-            take_while1(is_numeric_value),
-            space0,
-        ),
-        parse_number
+        delimited(space0, take_while1(is_numeric_value), space0),
+        parse_number,
     )(input)
 }
 
 fn is_numeric_value(c: char) -> bool {
-    c.is_digit(10) || c == '.'
+    c.is_ascii_digit() || c == '.'
 }
 
 fn parse_number(input: &str) -> Expression {
-    Expression::Atom(
-        Atom::Numeric(
-            match input.contains('.') {
-                true => Numeric::Decimal(input.parse::<f32>().unwrap()),
-                false => Numeric::Integer(input.parse::<i32>().unwrap()),
-            }
-        )
-    )
+    Expression::Atom(Atom::Numeric(match input.contains('.') {
+        true => Numeric::Decimal(input.parse::<f32>().unwrap()),
+        false => Numeric::Integer(input.parse::<i32>().unwrap()),
+    }))
 }
 
 fn parse_function(input: &str) -> IResult<&str, Expression> {
@@ -68,21 +65,18 @@ fn parse_function(input: &str) -> IResult<&str, Expression> {
         delimited(
             space0,
             tuple((
-                preceded(
-                    space0,
-                    take_while1(|c: char| {c.is_alphabetic()}),
-                ),
+                preceded(space0, take_while1(|c: char| c.is_alphabetic())),
                 preceded(
                     char('('),
                     many0(terminated(parse_add_sub, alt((char(','), char(')'))))),
-                )
+                ),
             )),
             space0,
         ),
         |(name, arg_list)| Expression::Function {
-            name: heapless::String::from_str(name).unwrap(),
-            args: arg_list.into_iter().map(|arg| Box::new(arg)).collect(),
-        }
+            name: name.to_string(),
+            args: arg_list.into_iter().map(Box::new).collect(),
+        },
     )(input)
 }
 
@@ -92,20 +86,14 @@ fn parse_vector(input: &str) -> IResult<&str, Expression> {
             space0,
             preceded(
                 char('<'),
-                many0(
-                    terminated(
-                        parse_add_sub,
-                        alt(
-                            (char(','), char('>'))
-                        )
-                    )
-                )
+                many0(terminated(parse_add_sub, alt((char(','), char('>'))))),
             ),
-            space0
-        ), |vector| Expression::Vector {
+            space0,
+        ),
+        |vector| Expression::Vector {
             size: vector.len() as u8,
-            backing: vector.into_iter().map(|arg| Box::new(arg)).collect(),
-        }
+            backing: vector.into_iter().map(Box::new).collect(),
+        },
     )(input)
 }
 
@@ -115,27 +103,25 @@ fn parse_matrix(input: &str) -> IResult<&str, Expression> {
             space0,
             delimited(
                 char('['),
-                separated_list0(
-                    char(';'),
-                    separated_list0(
-                        char(','),
-                        parse_add_sub,
-                    ),
-                ),
+                separated_list0(char(';'), separated_list0(char(','), parse_add_sub)),
                 char(']'),
             ),
             space0,
         ),
-        | flatten_matrix | {
-            let mut row_count = flatten_matrix.len() as u8;
-            let mut col_count = flatten_matrix[0].len() as u8; // assuming every row has the same number of columns
-
-            let backing = flatten_matrix.into_iter().flatten().map(|a| Box::new(a)).collect();
+        |flatten_matrix| {
+            let row_count = flatten_matrix.len() as u8;
+            let col_count = flatten_matrix[0].len() as u8; // assuming every row has the same number of columns
+
+            let backing = flatten_matrix
+                .into_iter()
+                .flatten()
+                .map(Box::new)
+                .collect();
             Expression::Matrix {
                 backing,
                 shape: (row_count, col_count),
             }
-        }
+        },
     )(input)
 }
 
@@ -143,32 +129,22 @@ fn parse_escape(input: &str) -> IResult<&str, Expression> {
     map(
         delimited(
             space0,
-            tuple((
-                preceded(
-                    char('_'),
-                    take(1usize),
-                ),
-                digit1,
-            )),
+            tuple((preceded(char('_'), take(1usize)), digit1)),
             space0,
         ),
-        |(value, num): (&str, &str)| Expression::Atom(
-            Atom::Escape(value.chars().next().unwrap(), num.parse::<u8>().unwrap())
-        )
+        |(value, num): (&str, &str)| {
+            Expression::Atom(Atom::Escape(
+                value.chars().next().unwrap(),
+                num.parse::<u8>().unwrap(),
+            ))
+        },
     )(input)
 }
 
 fn parse_variable(input: &str) -> IResult<&str, Expression> {
-    map(
-        delimited(
-            space0,
-            take(1usize),
-            space0,
-        ),
-        |value: &str| Expression::Atom(
-            Atom::Variable(value.chars().next().unwrap())
-        )
-    )(input)
+    map(delimited(space0, take(1usize), space0), |value: &str| {
+        Expression::Atom(Atom::Variable(value.chars().next().unwrap()))
+    })(input)
 }
 
 fn parse_unary(input: &str) -> IResult<&str, Expression> {
@@ -183,15 +159,15 @@ fn parse_exponents(input: &str) -> IResult<&str, Expression> {
 
 fn parse_unary_prefix(input: &str) -> IResult<&str, Expression> {
     map(
-        delimited(space0, tuple((char('-'), parse_unary)), space0,),
-        parse_unary_prefix_op
+        delimited(space0, tuple((char('-'), parse_unary)), space0),
+        parse_unary_prefix_op,
     )(input)
 }
 
 fn parse_unary_postfix(input: &str) -> IResult<&str, Expression> {
     map(
-        delimited(space0, tuple((parse_exponents, char('!'))), space0,),
-        parse_unary_postfix_op
+        delimited(space0, tuple((parse_exponents, char('!'))), space0),
+        parse_unary_postfix_op,
     )(input)
 }
 
@@ -224,7 +200,8 @@ fn parse_unary_postfix_op(operator_pair: (Expression, char)) -> Expression {
 }
 
 fn fold_binary_operators(expr: Expression, ops: Vec<(char, Expression)>) -> Expression {
-    ops.into_iter().fold(expr, |acc, val| parse_binary_op(val, acc))
+    ops.into_iter()
+        .fold(expr, |acc, val| parse_binary_op(val, acc))
 }
 
 fn parse_binary_op(operator_pair: (char, Expression), expr1: Expression) -> Expression {
@@ -242,158 +219,106 @@ fn parse_binary_op(operator_pair: (char, Expression), expr1: Expression) -> Expr
 
 #[cfg(test)]
 mod tests {
-    use core::str::FromStr;
-
-    use alloc::{boxed::Box, vec};
+    use alloc::{boxed::Box, string::ToString, vec};
 
     use super::parse;
     use crate::expression::expression_tree::*;
 
     #[test]
     fn test_integer() {
-        assert_eq!(parse("1"),
-            Expression::Atom(
-                Atom::Numeric(
-                    Numeric::Integer(1)
-                )
-            )
+        assert_eq!(
+            parse("1"),
+            Expression::Atom(Atom::Numeric(Numeric::Integer(1)))
         );
-        assert_eq!(parse("55"),
-            Expression::Atom(
-                Atom::Numeric(
-                    Numeric::Integer(55)
-                )
-            )
+        assert_eq!(
+            parse("55"),
+            Expression::Atom(Atom::Numeric(Numeric::Integer(55)))
         );
     }
 
     #[test]
     fn test_decimal() {
-        assert_eq!(parse("1.0"),
-            Expression::Atom(
-                Atom::Numeric(
-                    Numeric::Decimal(1.0)
-                )
-            )
+        assert_eq!(
+            parse("1.0"),
+            Expression::Atom(Atom::Numeric(Numeric::Decimal(1.0)))
         );
     }
 
     #[test]
     fn test_escape() {
-        assert_eq!(parse("_A2"),
-            Expression::Atom(
-                Atom::Escape('A', 2)
-            )
-        );
+        assert_eq!(parse("_A2"), Expression::Atom(Atom::Escape('A', 2)));
     }
 
     #[test]
     fn test_wildcard_escape() {
-        assert_eq!(parse("_*0"),
-            Expression::Atom(
-                Atom::Escape('*', 0)
-            )
-        );
+        assert_eq!(parse("_*0"), Expression::Atom(Atom::Escape('*', 0)));
     }
 
     #[test]
     fn test_variable() {
-        assert_eq!(parse("x"),
-            Expression::Atom(
-                Atom::Variable('x')
-            )
-        );
+        assert_eq!(parse("x"), Expression::Atom(Atom::Variable('x')));
     }
 
     #[test]
     fn test_unicode_variable() {
-        assert_eq!(parse("π"),
-            Expression::Atom(
-                Atom::Variable('π')
-            )
-        );
+        assert_eq!(parse("π"), Expression::Atom(Atom::Variable('π')));
     }
 
     #[test]
     fn test_function() {
-        assert_eq!(parse("sin(1 + -2)"),
+        assert_eq!(
+            parse("sin(1 + -2)"),
             Expression::Function {
-                name: heapless::String::from_str("sin").unwrap(),
-                args: vec![
-                    Box::new(Expression::Add(
-                        Box::new(Expression::Atom(
-                            Atom::Numeric(
-                                Numeric::Integer(1)
-                            )
-                        )),
-                        Box::new(Expression::Negate(
-                            Box::new(Expression::Atom(
-                                Atom::Numeric(
-                                    Numeric::Integer(2)
-                                )
-                            ))
-                        ))
-                    )),
-                ].into_iter().collect(),
+                name: "sin".to_string(),
+                args: vec![Box::new(Expression::Add(
+                    Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(1)))),
+                    Box::new(Expression::Negate(Box::new(Expression::Atom(
+                        Atom::Numeric(Numeric::Integer(2))
+                    ))))
+                )),]
+                .into_iter()
+                .collect(),
             }
         );
     }
 
     #[test]
     fn test_multiple_arguments() {
-        assert_eq!(parse("normcdf(0, 1, 2.5, x)"),
+        assert_eq!(
+            parse("normcdf(0, 1, 2.5, x)"),
             Expression::Function {
-                name: heapless::String::from_str("normcdf").unwrap(),
+                name: "normcdf".to_string(),
                 args: vec![
-                    Box::new(Expression::Atom(
-                        Atom::Numeric(
-                            Numeric::Integer(0)
-                        )
-                    )),
-                    Box::new(Expression::Atom(
-                        Atom::Numeric(
-                            Numeric::Integer(1)
-                        )
-                    )),
-                    Box::new(Expression::Atom(
-                        Atom::Numeric(
-                            Numeric::Decimal(2.5)
-                        )
-                    )),
-                    Box::new(Expression::Atom(
-                        Atom::Variable('x')
-                    )),
-                ].into_iter().collect(),
+                    Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(0)))),
+                    Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(1)))),
+                    Box::new(Expression::Atom(Atom::Numeric(Numeric::Decimal(2.5)))),
+                    Box::new(Expression::Atom(Atom::Variable('x'))),
+                ]
+                .into_iter()
+                .collect(),
             }
         );
     }
 
     #[test]
     fn test_advanced_function() {
-        assert_eq!(parse("5 * log(10, sin(x))"),
+        assert_eq!(
+            parse("5 * log(10, sin(x))"),
             Expression::Multiply(
-                Box::new(Expression::Atom(
-                    Atom::Numeric(
-                        Numeric::Integer(5)
-                    )
-                )),
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(5)))),
                 Box::new(Expression::Function {
-                    name: heapless::String::from_str("log").unwrap(),
+                    name: "log".to_string(),
                     args: vec![
-                        Box::new(Expression::Atom(
-                            Atom::Numeric(
-                                Numeric::Integer(10)
-                            )
-                        )),
+                        Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(10)))),
                         Box::new(Expression::Function {
-                            name: heapless::String::from_str("sin").unwrap(),
-                            args: vec![
-                                Box::new(Expression::Atom(
-                                    Atom::Variable('x')
-                                )),
-                            ].into_iter().collect(),
+                            name: "sin".to_string(),
+                            args: vec![Box::new(Expression::Atom(Atom::Variable('x'))),]
+                                .into_iter()
+                                .collect(),
                         }),
-                    ].into_iter().collect(),
+                    ]
+                    .into_iter()
+                    .collect(),
                 })
             )
         );
@@ -401,216 +326,131 @@ mod tests {
 
     #[test]
     fn test_add() {
-        assert_eq!(parse("1 + 2"),
+        assert_eq!(
+            parse("1 + 2"),
             Expression::Add(
-                Box::new(Expression::Atom(
-                    Atom::Numeric(
-                        Numeric::Integer(1)
-                    )
-                )),
-                Box::new(Expression::Atom(
-                    Atom::Numeric(
-                        Numeric::Integer(2)
-                    )
-                ))
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(1)))),
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(2))))
             )
         );
     }
 
     #[test]
     fn test_subtract() {
-        assert_eq!(parse("1 - 2"),
+        assert_eq!(
+            parse("1 - 2"),
             Expression::Subtract(
-                Box::new(Expression::Atom(
-                    Atom::Numeric(
-                        Numeric::Integer(1)
-                    )
-                )),
-                Box::new(Expression::Atom(
-                    Atom::Numeric(
-                        Numeric::Integer(2)
-                    )
-                ))
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(1)))),
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(2))))
             )
         );
     }
 
     #[test]
     fn test_add_negative() {
-        assert_eq!(parse("1 + -2"),
+        assert_eq!(
+            parse("1 + -2"),
             Expression::Add(
-                Box::new(Expression::Atom(
-                    Atom::Numeric(
-                        Numeric::Integer(1)
-                    )
-                )),
-                Box::new(Expression::Negate(
-                    Box::new(Expression::Atom(
-                        Atom::Numeric(
-                            Numeric::Integer(2)
-                        )
-                    ))
-                ))
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(1)))),
+                Box::new(Expression::Negate(Box::new(Expression::Atom(
+                    Atom::Numeric(Numeric::Integer(2))
+                ))))
             )
         );
     }
 
     #[test]
     fn test_modulus() {
-        assert_eq!(parse("1 % 2"),
+        assert_eq!(
+            parse("1 % 2"),
             Expression::Modulus(
-                Box::new(Expression::Atom(
-                    Atom::Numeric(
-                        Numeric::Integer(1)
-                    )
-                )),
-                Box::new(Expression::Atom(
-                    Atom::Numeric(
-                        Numeric::Integer(2)
-                    )
-                ))
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(1)))),
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(2))))
             )
         );
     }
 
     #[test]
     fn test_multiply() {
-        assert_eq!(parse("1 * 2"),
+        assert_eq!(
+            parse("1 * 2"),
             Expression::Multiply(
-                Box::new(Expression::Atom(
-                    Atom::Numeric(
-                        Numeric::Integer(1)
-                    )
-                )),
-                Box::new(Expression::Atom(
-                    Atom::Numeric(
-                        Numeric::Integer(2)
-                    )
-                ))
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(1)))),
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(2))))
             )
         );
     }
 
     #[test]
     fn test_divide() {
-        assert_eq!(parse("1 / 2"),
+        assert_eq!(
+            parse("1 / 2"),
             Expression::Divide(
-                Box::new(Expression::Atom(
-                    Atom::Numeric(
-                        Numeric::Integer(1)
-                    )
-                )),
-                Box::new(Expression::Atom(
-                    Atom::Numeric(
-                        Numeric::Integer(2)
-                    )
-                ))
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(1)))),
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(2))))
             )
         );
     }
 
     #[test]
     fn test_multiply_negative() {
-        assert_eq!(parse("1 * -2"),
+        assert_eq!(
+            parse("1 * -2"),
             Expression::Multiply(
-                Box::new(Expression::Atom(
-                    Atom::Numeric(
-                        Numeric::Integer(1)
-                    )
-                )),
-                Box::new(Expression::Negate(
-                    Box::new(Expression::Atom(
-                        Atom::Numeric(
-                            Numeric::Integer(2)
-                        )
-                    ))
-                ))
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(1)))),
+                Box::new(Expression::Negate(Box::new(Expression::Atom(
+                    Atom::Numeric(Numeric::Integer(2))
+                ))))
             )
         );
     }
 
     #[test]
     fn test_exponent() {
-        assert_eq!(parse("1 ^ 2"),
+        assert_eq!(
+            parse("1 ^ 2"),
             Expression::Power(
-                Box::new(Expression::Atom(
-                    Atom::Numeric(
-                        Numeric::Integer(1)
-                    )
-                )),
-                Box::new(Expression::Atom(
-                    Atom::Numeric(
-                        Numeric::Integer(2)
-                    )
-                ))
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(1)))),
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(2))))
             )
         );
     }
 
     #[test]
     fn test_factorial() {
-        assert_eq!(parse("5!"),
-            Expression::Factorial(
-                Box::new(Expression::Atom(
-                    Atom::Numeric(
-                        Numeric::Integer(5)
-                    )
-                ))
-            )
+        assert_eq!(
+            parse("5!"),
+            Expression::Factorial(Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(
+                5
+            )))))
         );
     }
 
     #[test]
     fn test_parentheses() {
-        assert_eq!(parse("(1 + 2) * 5"),
+        assert_eq!(
+            parse("(1 + 2) * 5"),
             Expression::Multiply(
                 Box::new(Expression::Add(
-                    Box::new(Expression::Atom(
-                        Atom::Numeric(
-                            Numeric::Integer(1)
-                        )
-                    )),
-                    Box::new(Expression::Atom(
-                        Atom::Numeric(
-                            Numeric::Integer(2)
-                        )
-                    ))
+                    Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(1)))),
+                    Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(2))))
                 )),
-                Box::new(Expression::Atom(
-                    Atom::Numeric(
-                        Numeric::Integer(5)
-                    )
-                ))
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(5))))
             )
         );
     }
 
     #[test]
     fn test_nested_parentheses() {
-        assert_eq!(parse("(5 * (4 + (6 / 3)))"),
+        assert_eq!(
+            parse("(5 * (4 + (6 / 3)))"),
             Expression::Multiply(
-                Box::new(Expression::Atom(
-                    Atom::Numeric(
-                        Numeric::Integer(5)
-                    )
-                )),
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(5)))),
                 Box::new(Expression::Add(
-                    Box::new(Expression::Atom(
-                        Atom::Numeric(
-                            Numeric::Integer(4)
-                        )
-                    )),
+                    Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(4)))),
                     Box::new(Expression::Divide(
-                        Box::new(Expression::Atom(
-                            Atom::Numeric(
-                                Numeric::Integer(6)
-                            )
-                        )),
-                        Box::new(Expression::Atom(
-                            Atom::Numeric(
-                                Numeric::Integer(3)
-                            )
-                        ))
+                        Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(6)))),
+                        Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(3))))
                     ))
                 ))
             )
@@ -619,24 +459,13 @@ mod tests {
 
     #[test]
     fn test_spaceless() {
-        assert_eq!(parse("1+2*5"),
+        assert_eq!(
+            parse("1+2*5"),
             Expression::Add(
-                Box::new(Expression::Atom(
-                    Atom::Numeric(
-                        Numeric::Integer(1)
-                    )
-                )),
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(1)))),
                 Box::new(Expression::Multiply(
-                    Box::new(Expression::Atom(
-                        Atom::Numeric(
-                            Numeric::Integer(2)
-                        )
-                    )),
-                    Box::new(Expression::Atom(
-                        Atom::Numeric(
-                            Numeric::Integer(5)
-                        )
-                    ))
+                    Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(2)))),
+                    Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(5))))
                 ))
             )
         );
@@ -644,24 +473,13 @@ mod tests {
 
     #[test]
     fn test_whitespace() {
-        assert_eq!(parse(" 1    +  2 *   5  "),
+        assert_eq!(
+            parse(" 1    +  2 *   5  "),
             Expression::Add(
-                Box::new(Expression::Atom(
-                    Atom::Numeric(
-                        Numeric::Integer(1)
-                    )
-                )),
+                Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(1)))),
                 Box::new(Expression::Multiply(
-                    Box::new(Expression::Atom(
-                        Atom::Numeric(
-                            Numeric::Integer(2)
-                        )
-                    )),
-                    Box::new(Expression::Atom(
-                        Atom::Numeric(
-                            Numeric::Integer(5)
-                        )
-                    ))
+                    Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(2)))),
+                    Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(5))))
                 ))
             )
         );
@@ -669,45 +487,22 @@ mod tests {
 
     #[test]
     fn test_multi_level_expression() {
-        assert_eq!(parse("1 * 2 + 3 / 4 ^ 6 % 7"),
+        assert_eq!(
+            parse("1 * 2 + 3 / 4 ^ 6 % 7"),
             Expression::Add(
                 Box::new(Expression::Multiply(
-                    Box::new(Expression::Atom(
-                        Atom::Numeric(
-                            Numeric::Integer(1)
-                        )
-                    )),
-                    Box::new(Expression::Atom(
-                        Atom::Numeric(
-                            Numeric::Integer(2)
-                        )
-                    ))
+                    Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(1)))),
+                    Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(2))))
                 )),
                 Box::new(Expression::Modulus(
                     Box::new(Expression::Divide(
-                        Box::new(Expression::Atom(
-                            Atom::Numeric(
-                                Numeric::Integer(3)
-                            )
-                        )),
+                        Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(3)))),
                         Box::new(Expression::Power(
-                            Box::new(Expression::Atom(
-                                Atom::Numeric(
-                                    Numeric::Integer(4)
-                                )
-                            )),
-                            Box::new(Expression::Atom(
-                                Atom::Numeric(
-                                    Numeric::Integer(6)
-                                )
-                            ))
+                            Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(4)))),
+                            Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(6))))
                         ))
                     )),
-                    Box::new(Expression::Atom(
-                        Atom::Numeric(
-                            Numeric::Integer(7)
-                        )
-                    ))
+                    Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(7))))
                 ))
             )
         );
@@ -716,7 +511,7 @@ mod tests {
     macro_rules! integer_atom {
         ( $i:literal ) => {
             Expression::Atom(Atom::Numeric(Numeric::Integer($i)))
-        }
+        };
     }
 
     #[test]
@@ -739,19 +534,15 @@ mod tests {
         assert_eq!(
             parse("1 + <2, 3, 4>"),
             Expression::Add(
-                Box::new(
-                    integer_atom!(1)
-                ),
-                Box::new(
-                    Expression::Vector {
-                        backing: vec![
-                            Box::new(integer_atom!(2)),
-                            Box::new(integer_atom!(3)),
-                            Box::new(integer_atom!(4)),
-                        ],
-                        size: 3 as u8,
-                    }
-                )
+                Box::new(integer_atom!(1)),
+                Box::new(Expression::Vector {
+                    backing: vec![
+                        Box::new(integer_atom!(2)),
+                        Box::new(integer_atom!(3)),
+                        Box::new(integer_atom!(4)),
+                    ],
+                    size: 3 as u8,
+                })
             )
         )
     }
@@ -763,44 +554,24 @@ mod tests {
             Expression::Vector {
                 backing: vec![
                     Box::new(Expression::Add(
-                        Box::new(
-                            integer_atom!(1)
-                        ),
-                        Box::new(
-                            integer_atom!(2)
-                        )
+                        Box::new(integer_atom!(1)),
+                        Box::new(integer_atom!(2))
                     )),
                     Box::new(Expression::Subtract(
-                        Box::new(
-                            integer_atom!(3)
-                        ),
-                        Box::new(
-                            integer_atom!(4)
-                        )
+                        Box::new(integer_atom!(3)),
+                        Box::new(integer_atom!(4))
                     )),
                     Box::new(Expression::Multiply(
-                        Box::new(
-                            integer_atom!(5)
-                        ),
-                        Box::new(
-                            integer_atom!(6)
-                        )
+                        Box::new(integer_atom!(5)),
+                        Box::new(integer_atom!(6))
                     )),
                     Box::new(Expression::Divide(
-                        Box::new(
-                            integer_atom!(7)
-                        ),
-                        Box::new(
-                            integer_atom!(8)
-                        )
+                        Box::new(integer_atom!(7)),
+                        Box::new(integer_atom!(8))
                     )),
                     Box::new(Expression::Modulus(
-                        Box::new(
-                            integer_atom!(9)
-                        ),
-                        Box::new(
-                            integer_atom!(10)
-                        )
+                        Box::new(integer_atom!(9)),
+                        Box::new(integer_atom!(10))
                     )),
                 ],
                 size: 5 as u8,
@@ -811,7 +582,7 @@ mod tests {
     macro_rules! variable_atom {
         ( $i:expr ) => {
             Expression::Atom(Atom::Variable($i))
-        }
+        };
     }
 
     #[test]
@@ -821,42 +592,22 @@ mod tests {
             Expression::Vector {
                 backing: vec![
                     Box::new(Expression::Multiply(
-                        Box::new(
-                            variable_atom!('r')
-                        ),
-                        Box::new(
-                            Expression::Function {
-                                name: heapless::String::from_str("cos").unwrap(),
-                                args: vec![
-                                    Box::new(
-                                        variable_atom!('t')
-                                    )
-                                ].into_iter().collect()
-                            }
-                        )
+                        Box::new(variable_atom!('r')),
+                        Box::new(Expression::Function {
+                            name: "cos".to_string(),
+                            args: vec![Box::new(variable_atom!('t'))].into_iter().collect()
+                        })
                     )),
                     Box::new(Expression::Multiply(
-                        Box::new(
-                            variable_atom!('r')
-                        ),
-                        Box::new(
-                            Expression::Function {
-                                name: heapless::String::from_str("sin").unwrap(),
-                                args: vec![
-                                    Box::new(
-                                        variable_atom!('t')
-                                    )
-                                ].into_iter().collect()
-                            }
-                        )
+                        Box::new(variable_atom!('r')),
+                        Box::new(Expression::Function {
+                            name: "sin".to_string(),
+                            args: vec![Box::new(variable_atom!('t'))].into_iter().collect()
+                        })
                     )),
                     Box::new(Expression::Multiply(
-                        Box::new(
-                            variable_atom!('z')
-                        ),
-                        Box::new(
-                            variable_atom!('t')
-                        )
+                        Box::new(variable_atom!('z')),
+                        Box::new(variable_atom!('t'))
                     ))
                 ],
                 size: 3 as u8,
@@ -869,29 +620,27 @@ mod tests {
         assert_eq!(
             parse("dot(<1, 2, 3>, <4, 5, 6>)"),
             Expression::Function {
-                name: heapless::String::from_str("dot").unwrap(),
+                name: "dot".to_string(),
                 args: vec![
-                    Box::new(
-                        Expression::Vector {
-                            backing: vec![
-                                Box::new(integer_atom!(1)),
-                                Box::new(integer_atom!(2)),
-                                Box::new(integer_atom!(3)),
-                            ],
-                            size: 3 as u8,
-                        }
-                    ),
-                    Box::new(
-                        Expression::Vector {
-                            backing: vec![
-                                Box::new(integer_atom!(4)),
-                                Box::new(integer_atom!(5)),
-                                Box::new(integer_atom!(6)),
-                            ],
-                            size: 3 as u8,
-                        }
-                    ),
-                ].into_iter().collect()
+                    Box::new(Expression::Vector {
+                        backing: vec![
+                            Box::new(integer_atom!(1)),
+                            Box::new(integer_atom!(2)),
+                            Box::new(integer_atom!(3)),
+                        ],
+                        size: 3 as u8,
+                    }),
+                    Box::new(Expression::Vector {
+                        backing: vec![
+                            Box::new(integer_atom!(4)),
+                            Box::new(integer_atom!(5)),
+                            Box::new(integer_atom!(6)),
+                        ],
+                        size: 3 as u8,
+                    }),
+                ]
+                .into_iter()
+                .collect()
             }
         )
     }
@@ -974,36 +723,26 @@ mod tests {
             Expression::Matrix {
                 backing: vec![
                     Box::new(Expression::Subtract(
-                        Box::new(
-                            Expression::Add(
-                                Box::new(integer_atom!(1)),
-                                Box::new(integer_atom!(2)),
-                            )
-                        ),
-                        Box::new(
-                            integer_atom!(3),
-                        ),
+                        Box::new(Expression::Add(
+                            Box::new(integer_atom!(1)),
+                            Box::new(integer_atom!(2)),
+                        )),
+                        Box::new(integer_atom!(3),),
                     )),
                     Box::new(Expression::Divide(
-                        Box::new(
-                            Expression::Multiply(
-                                Box::new(integer_atom!(4)),
-                                Box::new(integer_atom!(5)),
-                            ),
-                        ),
-                        Box::new(
-                            integer_atom!(6),
-                        ),
+                        Box::new(Expression::Multiply(
+                            Box::new(integer_atom!(4)),
+                            Box::new(integer_atom!(5)),
+                        ),),
+                        Box::new(integer_atom!(6),),
                     )),
                     Box::new(Expression::Modulus(
                         Box::new(integer_atom!(7)),
                         Box::new(integer_atom!(8)),
                     )),
                     Box::new(Expression::Function {
-                        name: heapless::String::from_str("cos").unwrap(),
-                        args: vec![
-                            Box::new(variable_atom!('x'))
-                        ].into_iter().collect(),
+                        name: "cos".to_string(),
+                        args: vec![Box::new(variable_atom!('x'))].into_iter().collect(),
                     })
                 ],
                 shape: (2, 2),
@@ -1016,20 +755,18 @@ mod tests {
         assert_eq!(
             parse("T([1, 2; 3, 4])"),
             Expression::Function {
-                name: heapless::String::from_str("T").unwrap(),
-                args: vec![
-                    Box::new(
-                        Expression::Matrix {
-                            backing: vec![
-                                Box::new(integer_atom!(1)),
-                                Box::new(integer_atom!(2)),
-                                Box::new(integer_atom!(3)),
-                                Box::new(integer_atom!(4)),
-                            ],
-                            shape: (2, 2),
-                        }
-                    ),
-                ].into_iter().collect(),
+                name: "T".to_string(),
+                args: vec![Box::new(Expression::Matrix {
+                    backing: vec![
+                        Box::new(integer_atom!(1)),
+                        Box::new(integer_atom!(2)),
+                        Box::new(integer_atom!(3)),
+                        Box::new(integer_atom!(4)),
+                    ],
+                    shape: (2, 2),
+                }),]
+                .into_iter()
+                .collect(),
             }
         )
     }
@@ -1064,4 +801,4 @@ mod tests {
             }
         )
     }
-}
\ No newline at end of file
+}
diff --git a/src/lib.rs b/src/lib.rs
index 68b6272..b93e771 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -5,7 +5,7 @@ extern crate alloc;
 pub mod expression;
 pub mod modifier;
 
-#[derive(Debug)]
+#[derive(Debug, PartialEq, Eq)]
 pub enum Error {
     NotEnoughMemory,
     InvalidSyntax,
diff --git a/src/modifier/adaptable_modifier.rs b/src/modifier/adaptable_modifier.rs
index dbfc5ee..cc6855f 100644
--- a/src/modifier/adaptable_modifier.rs
+++ b/src/modifier/adaptable_modifier.rs
@@ -1,21 +1,31 @@
-use core::{ops::{Add, AddAssign}, fmt};
+use core::{
+    fmt,
+    ops::{Add, AddAssign},
+};
 
-use alloc::{boxed::Box, vec::Vec, vec};
+use alloc::{boxed::Box, vec, vec::Vec};
 use heapless::LinearMap;
+use indexmap::IndexMap;
 
-use crate::expression::expression_tree::{Expression, Atom};
+use crate::expression::expression_tree::{Atom, Expression};
 
-use super::Modifier;
+use super::{ModifierImmutable, ModifierMutable};
 
 //TODO: create more efficient AdaptableModifier backend
 //MultiKeyBinarySearchTree: generic BST struct that has multiple keys per node
-struct MultiKeyBinarySearchTree<T, K> where T: PartialOrd + fmt::Display {
+struct MultiKeyBinarySearchTree<T, K>
+where
+    T: PartialOrd + fmt::Display,
+{
     pub value_pairs: Vec<(T, K)>,
     pub left: Option<Box<MultiKeyBinarySearchTree<T, K>>>,
     pub right: Option<Box<MultiKeyBinarySearchTree<T, K>>>,
 }
 
-impl<T, K> MultiKeyBinarySearchTree<T, K> where T: PartialOrd + fmt::Display {
+impl<T, K> MultiKeyBinarySearchTree<T, K>
+where
+    T: PartialOrd + fmt::Display,
+{
     pub fn new(value_pairs: Vec<(T, K)>) -> Self {
         Self {
             value_pairs,
@@ -65,130 +75,248 @@ impl<T, K> MultiKeyBinarySearchTree<T, K> where T: PartialOrd + fmt::Display {
     }
 }
 
+pub type ModifierFunction = Box<dyn Fn(&LinearMap<Atom, Expression, 8>) -> (Expression, bool)>;
+
 //AdaptableModifier: a modifier whose rules can be added to at runtime
 pub struct AdaptableModifier {
     //8 here is a magic number: it's the max number of arguments that can be passed to a function
-    search_tree: MultiKeyBinarySearchTree<Expression, Box<dyn Fn (&LinearMap<Atom, Expression, 8>) -> (Expression, bool)>>,
+    search_tree: MultiKeyBinarySearchTree<
+        Expression,
+        ModifierFunction,
+    >,
+    memoizing_map: IndexMap<Expression, bool>,
 }
 
 impl AdaptableModifier {
     //automatically derives an AdaptableModifier from a list of rules in string form
     pub fn from_str_list(rules: Vec<(&str, &str)>) -> Self {
         let mut search_tree = MultiKeyBinarySearchTree::new(Vec::new());
-        
+
         for (key, value) in rules {
-            search_tree.insert((key.parse::<Expression>().unwrap(), value.parse::<Expression>().unwrap().conversion()));
+            search_tree.insert((
+                key.parse::<Expression>().unwrap(),
+                value.parse::<Expression>().unwrap().conversion(),
+            ));
         }
 
         Self {
             search_tree,
+            memoizing_map: IndexMap::new(),
         }
     }
 
     //derives an AdaptableModifier from a list of rules in Expression and Function form
-    pub fn from_fn_list(list: Vec<(Expression, Box<dyn Fn (&LinearMap<Atom, Expression, 8>) -> (Expression, bool)>)>) -> Self {
+    pub fn from_fn_list(
+        list: Vec<(
+            Expression,
+            ModifierFunction,
+        )>,
+    ) -> Self {
         let mut search_tree = MultiKeyBinarySearchTree::new(Vec::new());
-        
+
         for (expression, function) in list {
             search_tree.insert((expression, function));
         }
 
         Self {
             search_tree,
+            memoizing_map: IndexMap::new(),
         }
     }
 
-    pub fn insert_rule(&mut self, expr: Expression, func: Box<dyn Fn (&LinearMap<Atom, Expression, 8>) -> (Expression, bool)>) {
+    pub fn insert_rule(
+        &mut self,
+        expr: Expression,
+        func: ModifierFunction,
+    ) {
         self.search_tree.insert((expr, func));
+        self.memoizing_map.clear();
     }
 
     //retrieves the rule which is the closest match with the given expression
-    pub fn get_rule(&self, expr: &Expression) -> Vec<&(Expression, Box<dyn Fn (&LinearMap<Atom, Expression, 8>) -> (Expression, bool)>)> {
+    pub fn get_rule(
+        &self,
+        expr: &Expression,
+    ) -> Vec<&(
+        Expression,
+        ModifierFunction,
+    )> {
         match self.search_tree.get(expr) {
             Some(list) => {
                 let (mut level, mut new_list) = (8, Vec::new()); //8 is mod magic here
                 list.iter().for_each(|pair| {
-                    if let Some(l) = expr.level_eq(&pair.0) {
-                        if l.0 == level {
-                            new_list.push(pair);
-                        } else if l.0 < level {
-                            new_list.clear();
-                            new_list.push(pair);
-                            level = l.0;
+                    if let Some(l) = expr.level_eq(&pair.0, &mut LinearMap::new()) {
+                        match l.cmp(&level) {
+                            core::cmp::Ordering::Less => {
+                                level = l;
+                                new_list = vec![pair];
+                            }
+                            core::cmp::Ordering::Equal => new_list.push(pair),
+                            _ => (),
                         }
                     }
                 });
                 new_list
-            },
+            }
             None => Vec::new(),
         }
     }
 }
 
-impl Modifier for AdaptableModifier {
-    fn modify(&self, expression: &mut Expression) -> bool {
+impl ModifierImmutable for AdaptableModifier {
+    fn modify_immut(&self, expression: &mut Expression) -> bool {
+        if let Some(result) = self.memoizing_map.get(expression) {
+            if *result {
+                return true;
+            }
+        }
+
         let mut modified = false;
 
         match expression {
             Expression::Atom(_) => {}
 
-            Expression::Vector { backing: vec, size: _ } => {
+            Expression::Vector {
+                backing: vec,
+                size: _,
+            } => {
                 for e in vec {
-                    modified = self.modify(e) || modified;
+                    modified = self.modify_immut(e) || modified;
                 }
             }
-            Expression::Matrix { backing: vec, shape: (_, _) } => {
+            Expression::Matrix {
+                backing: vec,
+                shape: (_, _),
+            } => {
                 for e in vec {
-                    modified = self.modify(e) || modified;
+                    modified = self.modify_immut(e) || modified;
                 }
             }
 
             Expression::Function { name: _, args: a } => {
                 for expr in a {
-                    modified = self.modify(expr) || modified;
+                    modified = self.modify_immut(expr) || modified;
                 }
             }
-            
-            Expression::Negate(e1) |
-            Expression::Factorial(e1) |
-            Expression::Percent(e1) => modified = self.modify(e1),
-            
-            Expression::Add(e1, e2) |
-            Expression::Subtract(e1, e2) |
-            Expression::Multiply(e1, e2) |
-            Expression::Divide(e1, e2) |
-            Expression::Power(e1, e2) |
-            Expression::Modulus(e1, e2) => {
-                let m1 = self.modify(e1); 
-                let m2 = self.modify(e2);
+
+            Expression::Negate(e1) | Expression::Factorial(e1) | Expression::Percent(e1) => {
+                modified = self.modify_immut(e1)
+            }
+
+            Expression::Add(e1, e2)
+            | Expression::Subtract(e1, e2)
+            | Expression::Multiply(e1, e2)
+            | Expression::Divide(e1, e2)
+            | Expression::Power(e1, e2)
+            | Expression::Modulus(e1, e2) => {
+                let m1 = self.modify_immut(e1);
+                let m2 = self.modify_immut(e2);
                 modified = m1 || m2;
-            } 
+            }
         }
 
         let mut rule_mod = false;
         for rule in self.get_rule(expression) {
-            (*expression, rule_mod) = rule.1(&expression.extract_arguments(&rule.0, LinearMap::new()));
+            (*expression, rule_mod) =
+                rule.1(&expression.extract_arguments(&rule.0, LinearMap::new()));
             if rule_mod {
                 modified = true;
                 break;
             }
         }
-        
+
         modified
     }
 }
 
-fn get_value_pairs(mkbst: MultiKeyBinarySearchTree<Expression, Box<dyn Fn (&LinearMap<Atom, Expression, 8>) -> (Expression, bool)>>) -> Vec<(Expression, Box<dyn Fn (&LinearMap<Atom, Expression, 8>) -> (Expression, bool)>)> {
+impl ModifierMutable for AdaptableModifier {
+    fn modify_mut(&mut self, expression: &mut Expression) -> bool {
+        if let Some(result) = self.memoizing_map.get(expression) {
+            if *result {
+                return true;
+            }
+        }
+
+        let mem_save = expression.clone();
+        let mut modified = false;
+
+        match expression {
+            Expression::Atom(_) => {}
+
+            Expression::Vector {
+                backing: vec,
+                size: _,
+            } => {
+                for e in vec {
+                    modified = self.modify_mut(e) || modified;
+                }
+            }
+            Expression::Matrix {
+                backing: vec,
+                shape: (_, _),
+            } => {
+                for e in vec {
+                    modified = self.modify_mut(e) || modified;
+                }
+            }
+
+            Expression::Function { name: _, args: a } => {
+                for expr in a {
+                    modified = self.modify_mut(expr) || modified;
+                }
+            }
+
+            Expression::Negate(e1) | Expression::Factorial(e1) | Expression::Percent(e1) => {
+                modified = self.modify_mut(e1)
+            }
+
+            Expression::Add(e1, e2)
+            | Expression::Subtract(e1, e2)
+            | Expression::Multiply(e1, e2)
+            | Expression::Divide(e1, e2)
+            | Expression::Power(e1, e2)
+            | Expression::Modulus(e1, e2) => {
+                let m1 = self.modify_mut(e1);
+                let m2 = self.modify_mut(e2);
+                modified = m1 || m2;
+            }
+        }
+
+        let mut rule_mod = false;
+        for rule in self.get_rule(expression) {
+            (*expression, rule_mod) =
+                rule.1(&expression.extract_arguments(&rule.0, LinearMap::new()));
+            if rule_mod {
+                modified = true;
+                break;
+            }
+        }
+
+        self.memoizing_map.insert(mem_save, modified);
+
+        modified
+    }
+}
+
+fn get_value_pairs(
+    mkbst: MultiKeyBinarySearchTree<
+        Expression,
+        ModifierFunction,
+    >,
+) -> Vec<(
+    Expression,
+    ModifierFunction,
+)> {
     let mut value_pairs = mkbst.value_pairs;
-    
+
     if let Some(left) = mkbst.left {
         value_pairs.extend(get_value_pairs(*left));
     }
-    
+
     if let Some(right) = mkbst.right {
         value_pairs.extend(get_value_pairs(*right));
     }
-    
+
     value_pairs
 }
 
@@ -199,7 +327,7 @@ impl Add for AdaptableModifier {
         for (expr, func) in get_value_pairs(other.search_tree) {
             self.insert_rule(expr, func);
         }
-        
+
         self
     }
 }
@@ -212,7 +340,12 @@ impl AddAssign for AdaptableModifier {
     }
 }
 
-impl fmt::Display for MultiKeyBinarySearchTree<Expression, Box<dyn Fn (&LinearMap<Atom, Expression, 8>) -> (Expression, bool)>> {
+impl fmt::Display
+    for MultiKeyBinarySearchTree<
+        Expression,
+        ModifierFunction,
+    >
+{
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         for (expr, _) in self.value_pairs.iter() {
             write!(f, "{}", expr)?;
@@ -238,29 +371,30 @@ impl fmt::Display for AdaptableModifier {
 
 #[cfg(test)]
 mod tests {
-    use core::str::FromStr;
     use alloc::{boxed::Box, vec};
+    use core::str::FromStr;
     use heapless::LinearMap;
 
-    use crate::expression::expression_tree::{Expression, Atom};
-    use super::{Modifier, AdaptableModifier};
+    use super::{AdaptableModifier, ModifierImmutable};
+    use crate::{
+        expression::expression_tree::{Atom, Expression},
+        modifier::ModifierMutable,
+    };
 
     #[test]
     fn test_adaptable_simple() {
-        let modifier = AdaptableModifier::from_str_list(vec![
-            ("_*1 - _*2", "_*1 + -_*2")
-        ]);
+        let modifier = AdaptableModifier::from_str_list(vec![("_*1 - _*2", "_*1 + -_*2")]);
 
         let mut expr = Expression::from_str("1*2 - 3*4").unwrap();
         let expected_expr = Expression::from_str("1*2 + -(3*4)").unwrap();
-        modifier.modify(&mut expr);
-        
+        modifier.modify_immut(&mut expr);
+
         assert_eq!(expr, expected_expr);
     }
 
     #[test]
-    fn test_adaptable_order() {       
-        let modifier2 = AdaptableModifier::from_str_list(vec![
+    fn test_adaptable_order() {
+        let mut modifier2 = AdaptableModifier::from_str_list(vec![
             ("_A1 + _A2", "3"),
             ("_A1 * _A2", "4"),
             ("_F1 + _A1", "1"),
@@ -268,11 +402,11 @@ mod tests {
         ]);
 
         let mut expr3 = "sin(x) * 5".parse::<Expression>().unwrap();
-        expr3.simplify::<AdaptableModifier, 100>(&modifier2);
+        expr3.simplify_im::<AdaptableModifier, 100>(&mut modifier2);
 
         assert_eq!(expr3, "2".parse::<Expression>().unwrap());
 
-        let modifier1 = AdaptableModifier::from_str_list(vec![
+        let mut modifier1 = AdaptableModifier::from_str_list(vec![
             ("_F1 + _A1", "1"),
             ("_F1 * _A1", "2"),
             ("_A1 + _A2", "3"),
@@ -280,71 +414,67 @@ mod tests {
         ]);
 
         let mut expr1 = "x + 5".parse::<Expression>().unwrap();
-        expr1.simplify::<AdaptableModifier, 100>(&modifier1);
+        expr1.simplify_im::<AdaptableModifier, 100>(&mut modifier1);
 
         assert_eq!(expr1, "3".parse::<Expression>().unwrap());
 
         let mut expr4 = "sin(x) * 5".parse::<Expression>().unwrap();
-        expr4.simplify::<AdaptableModifier, 100>(&modifier1);
+        expr4.simplify_im::<AdaptableModifier, 100>(&mut modifier1);
 
         assert_eq!(expr4, "2".parse::<Expression>().unwrap());
     }
 
     #[test]
     fn test_adaptable_truth() {
-        let modifier = AdaptableModifier::from_str_list(vec![
-            ("_*1 - _*2", "_*1 + -_*2")
-        ]);
+        let modifier = AdaptableModifier::from_str_list(vec![("_*1 - _*2", "_*1 + -_*2")]);
 
         let mut expr = Expression::from_str("1 - 2").unwrap();
 
-        assert_eq!(modifier.modify(&mut expr), true);
+        assert_eq!(modifier.modify_immut(&mut expr), true);
 
         let mut expr = Expression::from_str("1 + 2").unwrap();
 
-        assert_eq!(modifier.modify(&mut expr), false);
+        assert_eq!(modifier.modify_immut(&mut expr), false);
     }
 
     #[test]
     fn test_adaptable_insert() {
-        let mut modifier = AdaptableModifier::from_str_list(vec![
-            ("_*1 - _*2", "_*1 + -_*2")
-        ]);
+        let mut modifier = AdaptableModifier::from_str_list(vec![("_*1 - _*2", "_*1 + -_*2")]);
 
-        modifier.insert_rule(Expression::from_str("1 + 2").unwrap(), Box::new(|_| (Expression::from_str("3").unwrap(), true)));
+        modifier.insert_rule(
+            Expression::from_str("1 + 2").unwrap(),
+            Box::new(|_| (Expression::from_str("3").unwrap(), true)),
+        );
 
         let mut expr = Expression::from_str("1 + 2").unwrap();
         let expected_expr = Expression::from_str("3").unwrap();
-        modifier.modify(&mut expr);
-        
+        modifier.modify_immut(&mut expr);
+
         assert_eq!(expr, expected_expr);
     }
 
     #[test]
     fn test_adaptable_overlap() {
-        let modifier = AdaptableModifier::from_str_list(vec![
-            ("_*1 - _*2", "_*1 + -_*2"),
-            ("_*1 - 5", "50")
-        ]);
+        let modifier =
+            AdaptableModifier::from_str_list(vec![("_*1 - _*2", "_*1 + -_*2"), ("_*1 - 5", "50")]);
 
         let mut expr1 = Expression::from_str("1 - 5").unwrap();
         let expected_expr1 = Expression::from_str("50").unwrap();
-        modifier.modify(&mut expr1);
+        modifier.modify_immut(&mut expr1);
 
         assert_eq!(expr1, expected_expr1);
 
         let mut expr2 = Expression::from_str("1 - 2").unwrap();
         let expected_expr2 = Expression::from_str("1 + -2").unwrap();
-        assert_eq!(expr2.level_eq(&"_*1 - 5".parse::<Expression>().unwrap()), None);
 
-        modifier.modify(&mut expr2);
+        modifier.modify_immut(&mut expr2);
 
         assert_eq!(expr2, expected_expr2);
     }
 
     #[test]
     fn test_adaptable_recursive() {
-        let modifier = AdaptableModifier::from_str_list(vec![
+        let mut modifier = AdaptableModifier::from_str_list(vec![
             ("_*1 * _*2 + _*3", "_*1 / _*3"),
             ("5 * 6", "30"),
             ("_*1 / _*2", "5"),
@@ -353,32 +483,30 @@ mod tests {
 
         let mut expr = Expression::from_str("(8 * 9 + 5) * (2 ^ 10)").unwrap();
         let expected_expr = Expression::from_str("30").unwrap();
-        expr.simplify::<AdaptableModifier, 50>(&modifier);
+        expr.simplify_im::<AdaptableModifier, 50>(&mut modifier);
 
         assert_eq!(expr, expected_expr);
     }
 
     #[test]
     fn test_adaptable_atom() {
-        let modifier = AdaptableModifier::from_str_list(vec![
-            ("_*1 ^ _A1", "log(_A1)"),
-        ]);
+        let mut modifier = AdaptableModifier::from_str_list(vec![("_*1 ^ _A1", "log(_A1)")]);
 
         let mut expr1 = Expression::from_str("2 ^ 10").unwrap();
         let expected_expr1 = Expression::from_str("log(10)").unwrap();
-        expr1.simplify::<AdaptableModifier, 50>(&modifier);
+        expr1.simplify_im::<AdaptableModifier, 50>(&mut modifier);
 
         assert_eq!(expr1, expected_expr1);
 
         let mut expr2 = Expression::from_str("2 ^ (10 + 5)").unwrap();
         let expected_expr2 = Expression::from_str("2 ^ (10 + 5)").unwrap();
-        expr2.simplify::<AdaptableModifier, 50>(&modifier);
+        expr2.simplify_im::<AdaptableModifier, 50>(&mut modifier);
 
         assert_eq!(expr2, expected_expr2);
 
         let mut expr3 = Expression::from_str("2 ^ x").unwrap();
         let expected_expr3 = Expression::from_str("log(x)").unwrap();
-        expr3.simplify::<AdaptableModifier, 50>(&modifier);
+        expr3.simplify_im::<AdaptableModifier, 50>(&mut modifier);
 
         assert_eq!(expr3, expected_expr3);
     }
@@ -387,54 +515,53 @@ mod tests {
     fn test_adaptable_function() {
         let modifier = AdaptableModifier::from_str_list(vec![
             ("_F1 * 15", "cos(25)"),
-            ("_F1 + _F2", "_F2 * 15")
+            ("_F1 + _F2", "_F2 * 15"),
         ]);
 
         let mut expr1 = Expression::from_str("sin(10) + cos(10)").unwrap();
         let expected_expr1 = Expression::from_str("cos(25)").unwrap();
-        expr1.simplify::<AdaptableModifier, 50>(&modifier);
+        expr1.simplify_im::<AdaptableModifier, 50>(&modifier);
 
         assert_eq!(expr1, expected_expr1);
     }
 
     #[test]
     fn test_adaptable_addition() {
-        let modifier1 = AdaptableModifier::from_str_list(vec![
-            ("_*1 - _*2", "_*1 + -_*2"),
-        ]);
+        let modifier1 = AdaptableModifier::from_str_list(vec![("_*1 - _*2", "_*1 + -_*2")]);
 
-        let modifier2 = AdaptableModifier::from_str_list(vec![
-            ("_*1 / _*2", "_*1 * (_*2 ^ -1)"),
-        ]);
+        let modifier2 = AdaptableModifier::from_str_list(vec![("_*1 / _*2", "_*1 * (_*2 ^ -1)")]);
 
         let modifier3 = modifier1 + modifier2;
 
         let mut expr1 = Expression::from_str("1 - 2").unwrap();
         let expected_expr1 = Expression::from_str("1 + -2").unwrap();
-        modifier3.modify(&mut expr1);
+        modifier3.modify_immut(&mut expr1);
 
         assert_eq!(expr1, expected_expr1);
 
         let mut expr2 = Expression::from_str("1 / 2").unwrap();
         let expected_expr2 = Expression::from_str("1 * (2 ^ -1)").unwrap();
-        modifier3.modify(&mut expr2);
+        modifier3.modify_immut(&mut expr2);
 
         assert_eq!(expr2, expected_expr2);
     }
 
     #[test]
     fn test_adaptable_complex() {
-        let mut modifier = AdaptableModifier::from_str_list(vec![
-            ("_*1 - -_*2", "_*1 + _*2"),
-        ]);
+        let mut modifier = AdaptableModifier::from_str_list(vec![("_*1 - -_*2", "_*1 + _*2")]);
 
         let numeric_add = Box::new(move |map: &LinearMap<Atom, Expression, 8>| {
-            match (map.get(&Atom::Escape('A', 1)).unwrap(), map.get(&Atom::Escape('A', 2)).unwrap()) {
+            match (
+                map.get(&Atom::Escape('A', 1)).unwrap(),
+                map.get(&Atom::Escape('A', 2)).unwrap(),
+            ) {
                 (Expression::Atom(a), Expression::Atom(b)) => match (a, b) {
-                    (Atom::Numeric(a), Atom::Numeric(b)) => (Expression::Atom(Atom::Numeric(*a + *b)), true),
-                    _ => (Expression::Atom(*a) + Expression::Atom(*b), false)
-                }
-                _ => unreachable!()
+                    (Atom::Numeric(a), Atom::Numeric(b)) => {
+                        (Expression::Atom(Atom::Numeric(*a + *b)), true)
+                    }
+                    _ => (Expression::Atom(*a) + Expression::Atom(*b), false),
+                },
+                _ => unreachable!(),
             }
         });
 
@@ -442,7 +569,7 @@ mod tests {
 
         let mut expr1 = Expression::from_str("1 - -2").unwrap();
         let expected_expr1 = Expression::from_str("3").unwrap();
-        expr1.simplify::<AdaptableModifier, 2>(&modifier);
+        expr1.simplify_im::<AdaptableModifier, 2>(&modifier);
 
         assert_eq!(expr1, expected_expr1);
     }
@@ -451,18 +578,18 @@ mod tests {
     fn test_adaptable_vector() {
         let modifier = AdaptableModifier::from_str_list(vec![
             ("_V1 - _V2", "_V1 + -_V2"),
-            ("_V1 - <1, 2>", "50")
+            ("_V1 - <1, 2>", "50"),
         ]);
 
         let mut expr1 = Expression::from_str("<1, 2, 3, 4> - <1, 5, 7>").unwrap();
         let expected_expr1 = Expression::from_str("<1, 2, 3, 4> + -<1, 5, 7>").unwrap();
-        modifier.modify(&mut expr1);
+        modifier.modify_immut(&mut expr1);
 
         assert_eq!(expr1, expected_expr1);
 
         let mut expr2 = Expression::from_str("<1, 2, 3, 4> - <1, 2>").unwrap();
         let expected_expr2 = Expression::from_str("50").unwrap();
-        modifier.modify(&mut expr2);
+        modifier.modify_immut(&mut expr2);
 
         assert_eq!(expr2, expected_expr2);
     }
@@ -471,19 +598,252 @@ mod tests {
     fn test_adaptable_matrix() {
         let modifier = AdaptableModifier::from_str_list(vec![
             ("_M1 - _M2", "_M1 + -_M2"),
-            ("_M1 - [1; 3]", "50")
+            ("_M1 - [1; 3]", "50"),
+        ]);
+
+        let mut expr1 = Expression::from_str("[1, 2; 3, 4] - [1, 5; 6, 7]").unwrap();
+        let expected_expr1 = Expression::from_str("[1, 2; 3, 4] + -[1, 5; 6, 7]").unwrap();
+        modifier.modify_immut(&mut expr1);
+
+        assert_eq!(expr1, expected_expr1);
+
+        let mut expr2 = Expression::from_str("[1, 2; 3, 4] - [1; 3]").unwrap();
+        let expected_expr2 = Expression::from_str("50").unwrap();
+        modifier.modify_immut(&mut expr2);
+
+        assert_eq!(expr2, expected_expr2);
+    }
+
+    #[test]
+    fn test_adaptable_simple_mutable() {
+        let mut modifier = AdaptableModifier::from_str_list(vec![("_*1 - _*2", "_*1 + -_*2")]);
+
+        let mut expr = Expression::from_str("1*2 - 3*4").unwrap();
+        let expected_expr = Expression::from_str("1*2 + -(3*4)").unwrap();
+        modifier.modify_mut(&mut expr);
+
+        assert_eq!(expr, expected_expr);
+    }
+
+    #[test]
+    fn test_adaptable_order_mutable() {
+        let mut modifier2 = AdaptableModifier::from_str_list(vec![
+            ("_A1 + _A2", "3"),
+            ("_A1 * _A2", "4"),
+            ("_F1 + _A1", "1"),
+            ("_F1 * _A1", "2"),
+        ]);
+
+        let mut expr3 = "sin(x) * 5".parse::<Expression>().unwrap();
+        expr3.simplify::<AdaptableModifier, 100>(&mut modifier2);
+
+        assert_eq!(expr3, "2".parse::<Expression>().unwrap());
+
+        let mut modifier1 = AdaptableModifier::from_str_list(vec![
+            ("_F1 + _A1", "1"),
+            ("_F1 * _A1", "2"),
+            ("_A1 + _A2", "3"),
+            ("_A1 * _A2", "4"),
+        ]);
+
+        let mut expr1 = "x + 5".parse::<Expression>().unwrap();
+        expr1.simplify::<AdaptableModifier, 100>(&mut modifier1);
+
+        assert_eq!(expr1, "3".parse::<Expression>().unwrap());
+
+        let mut expr4 = "sin(x) * 5".parse::<Expression>().unwrap();
+        expr4.simplify::<AdaptableModifier, 100>(&mut modifier1);
+
+        assert_eq!(expr4, "2".parse::<Expression>().unwrap());
+    }
+
+    #[test]
+    fn test_adaptable_truth_mutable() {
+        let mut modifier = AdaptableModifier::from_str_list(vec![("_*1 - _*2", "_*1 + -_*2")]);
+
+        let mut expr = Expression::from_str("1 - 2").unwrap();
+
+        assert_eq!(modifier.modify_mut(&mut expr), true);
+
+        let mut expr = Expression::from_str("1 + 2").unwrap();
+
+        assert_eq!(modifier.modify_mut(&mut expr), false);
+    }
+
+    #[test]
+    fn test_adaptable_insert_mutable() {
+        let mut modifier = AdaptableModifier::from_str_list(vec![("_*1 - _*2", "_*1 + -_*2")]);
+
+        modifier.insert_rule(
+            Expression::from_str("1 + 2").unwrap(),
+            Box::new(|_| (Expression::from_str("3").unwrap(), true)),
+        );
+
+        let mut expr = Expression::from_str("1 + 2").unwrap();
+        let expected_expr = Expression::from_str("3").unwrap();
+        modifier.modify_mut(&mut expr);
+
+        assert_eq!(expr, expected_expr);
+    }
+
+    #[test]
+    fn test_adaptable_overlap_mutable() {
+        let mut modifier =
+            AdaptableModifier::from_str_list(vec![("_*1 - _*2", "_*1 + -_*2"), ("_*1 - 5", "50")]);
+
+        let mut expr1 = Expression::from_str("1 - 5").unwrap();
+        let expected_expr1 = Expression::from_str("50").unwrap();
+        modifier.modify_mut(&mut expr1);
+
+        assert_eq!(expr1, expected_expr1);
+
+        let mut expr2 = Expression::from_str("1 - 2").unwrap();
+        let expected_expr2 = Expression::from_str("1 + -2").unwrap();
+
+        modifier.modify_mut(&mut expr2);
+
+        assert_eq!(expr2, expected_expr2);
+    }
+
+    #[test]
+    fn test_adaptable_recursive_mutable() {
+        let mut modifier = AdaptableModifier::from_str_list(vec![
+            ("_*1 * _*2 + _*3", "_*1 / _*3"),
+            ("5 * 6", "30"),
+            ("_*1 / _*2", "5"),
+            ("_*1 ^ _*2", "6"),
+        ]);
+
+        let mut expr = Expression::from_str("(8 * 9 + 5) * (2 ^ 10)").unwrap();
+        let expected_expr = Expression::from_str("30").unwrap();
+        expr.simplify::<AdaptableModifier, 50>(&mut modifier);
+
+        assert_eq!(expr, expected_expr);
+    }
+
+    #[test]
+    fn test_adaptable_atom_mutable() {
+        let mut modifier = AdaptableModifier::from_str_list(vec![("_*1 ^ _A1", "log(_A1)")]);
+
+        let mut expr1 = Expression::from_str("2 ^ 10").unwrap();
+        let expected_expr1 = Expression::from_str("log(10)").unwrap();
+        expr1.simplify::<AdaptableModifier, 50>(&mut modifier);
+
+        assert_eq!(expr1, expected_expr1);
+
+        let mut expr2 = Expression::from_str("2 ^ (10 + 5)").unwrap();
+        let expected_expr2 = Expression::from_str("2 ^ (10 + 5)").unwrap();
+        expr2.simplify::<AdaptableModifier, 50>(&mut modifier);
+
+        assert_eq!(expr2, expected_expr2);
+
+        let mut expr3 = Expression::from_str("2 ^ x").unwrap();
+        let expected_expr3 = Expression::from_str("log(x)").unwrap();
+        expr3.simplify::<AdaptableModifier, 50>(&mut modifier);
+
+        assert_eq!(expr3, expected_expr3);
+    }
+
+    #[test]
+    fn test_adaptable_function_mutable() {
+        let mut modifier = AdaptableModifier::from_str_list(vec![
+            ("_F1 * 15", "cos(25)"),
+            ("_F1 + _F2", "_F2 * 15"),
+        ]);
+
+        let mut expr1 = Expression::from_str("sin(10) + cos(10)").unwrap();
+        let expected_expr1 = Expression::from_str("cos(25)").unwrap();
+        expr1.simplify::<AdaptableModifier, 50>(&mut modifier);
+
+        assert_eq!(expr1, expected_expr1);
+    }
+
+    #[test]
+    fn test_adaptable_addition_mutable() {
+        let modifier1 = AdaptableModifier::from_str_list(vec![("_*1 - _*2", "_*1 + -_*2")]);
+
+        let modifier2 = AdaptableModifier::from_str_list(vec![("_*1 / _*2", "_*1 * (_*2 ^ -1)")]);
+
+        let mut modifier3 = modifier1 + modifier2;
+
+        let mut expr1 = Expression::from_str("1 - 2").unwrap();
+        let expected_expr1 = Expression::from_str("1 + -2").unwrap();
+        modifier3.modify_mut(&mut expr1);
+
+        assert_eq!(expr1, expected_expr1);
+
+        let mut expr2 = Expression::from_str("1 / 2").unwrap();
+        let expected_expr2 = Expression::from_str("1 * (2 ^ -1)").unwrap();
+        modifier3.modify_mut(&mut expr2);
+
+        assert_eq!(expr2, expected_expr2);
+    }
+
+    #[test]
+    fn test_adaptable_complex_mutable() {
+        let mut modifier = AdaptableModifier::from_str_list(vec![("_*1 - -_*2", "_*1 + _*2")]);
+
+        let numeric_add = Box::new(move |map: &LinearMap<Atom, Expression, 8>| {
+            match (
+                map.get(&Atom::Escape('A', 1)).unwrap(),
+                map.get(&Atom::Escape('A', 2)).unwrap(),
+            ) {
+                (Expression::Atom(a), Expression::Atom(b)) => match (a, b) {
+                    (Atom::Numeric(a), Atom::Numeric(b)) => {
+                        (Expression::Atom(Atom::Numeric(*a + *b)), true)
+                    }
+                    _ => (Expression::Atom(*a) + Expression::Atom(*b), false),
+                },
+                _ => unreachable!(),
+            }
+        });
+
+        modifier.insert_rule("_A1 + _A2".parse::<Expression>().unwrap(), numeric_add);
+
+        let mut expr1 = Expression::from_str("1 - -2").unwrap();
+        let expected_expr1 = Expression::from_str("3").unwrap();
+        expr1.simplify::<AdaptableModifier, 2>(&mut modifier);
+
+        assert_eq!(expr1, expected_expr1);
+    }
+
+    #[test]
+    fn test_adaptable_vector_mutable() {
+        let mut modifier = AdaptableModifier::from_str_list(vec![
+            ("_V1 - _V2", "_V1 + -_V2"),
+            ("_V1 - <1, 2>", "50"),
+        ]);
+
+        let mut expr1 = Expression::from_str("<1, 2, 3, 4> - <1, 5, 7>").unwrap();
+        let expected_expr1 = Expression::from_str("<1, 2, 3, 4> + -<1, 5, 7>").unwrap();
+        modifier.modify_mut(&mut expr1);
+
+        assert_eq!(expr1, expected_expr1);
+
+        let mut expr2 = Expression::from_str("<1, 2, 3, 4> - <1, 2>").unwrap();
+        let expected_expr2 = Expression::from_str("50").unwrap();
+        modifier.modify_mut(&mut expr2);
+
+        assert_eq!(expr2, expected_expr2);
+    }
+
+    #[test]
+    fn test_adaptable_matrix_mutable() {
+        let mut modifier = AdaptableModifier::from_str_list(vec![
+            ("_M1 - _M2", "_M1 + -_M2"),
+            ("_M1 - [1; 3]", "50"),
         ]);
 
         let mut expr1 = Expression::from_str("[1, 2; 3, 4] - [1, 5; 6, 7]").unwrap();
         let expected_expr1 = Expression::from_str("[1, 2; 3, 4] + -[1, 5; 6, 7]").unwrap();
-        modifier.modify(&mut expr1);
+        modifier.modify_mut(&mut expr1);
 
         assert_eq!(expr1, expected_expr1);
 
         let mut expr2 = Expression::from_str("[1, 2; 3, 4] - [1; 3]").unwrap();
         let expected_expr2 = Expression::from_str("50").unwrap();
-        modifier.modify(&mut expr2);
+        modifier.modify_mut(&mut expr2);
 
         assert_eq!(expr2, expected_expr2);
     }
-}
\ No newline at end of file
+}
diff --git a/src/modifier/default.rs b/src/modifier/default.rs
index 28bd3d2..a69c79f 100644
--- a/src/modifier/default.rs
+++ b/src/modifier/default.rs
@@ -1,4 +1,4 @@
-use alloc::{vec, boxed::Box};
+use alloc::{boxed::Box, vec};
 use heapless::LinearMap;
 
 use crate::expression::expression_tree::{Atom, Expression, Numeric};
@@ -13,11 +13,26 @@ pub fn simplify() -> AdaptableModifier {
 //an AdaptableModifier that can reorganize the expression tree
 pub fn reorganize() -> AdaptableModifier {
     let num = AdaptableModifier::from_fn_list(vec![
-        ("_A1 + _A2".parse::<Expression>().unwrap(), Box::new(switch_atoms_add)),
-        ("_*1 + _A1 + _A2".parse::<Expression>().unwrap(), Box::new(switch_atoms_ext_add)),
-        ("_A1 * _A2".parse::<Expression>().unwrap(), Box::new(switch_atoms_mul)),
-        ("_*1 * _A1 * _A2".parse::<Expression>().unwrap(), Box::new(switch_atoms_ext_mul)),
-        ("_A1".parse::<Expression>().unwrap(), Box::new(denegate_internal)),
+        (
+            "_A1 + _A2".parse::<Expression>().unwrap(),
+            Box::new(switch_atoms_add),
+        ),
+        (
+            "_*1 + _A1 + _A2".parse::<Expression>().unwrap(),
+            Box::new(switch_atoms_ext_add),
+        ),
+        (
+            "_A1 * _A2".parse::<Expression>().unwrap(),
+            Box::new(switch_atoms_mul),
+        ),
+        (
+            "_*1 * _A1 * _A2".parse::<Expression>().unwrap(),
+            Box::new(switch_atoms_ext_mul),
+        ),
+        (
+            "_A1".parse::<Expression>().unwrap(),
+            Box::new(denegate_internal),
+        ),
     ]);
 
     let shift = AdaptableModifier::from_str_list(vec![
@@ -25,7 +40,6 @@ pub fn reorganize() -> AdaptableModifier {
         ("_*1 + (_*2 - _*3)", "_*1 + _*2 - _*3"),
         ("_*1 - (_*2 + _*3)", "_*1 - _*2 + _*3"),
         ("_*1 - (_*2 - _*3)", "_*1 - _*2 - _*3"),
-
         ("_*1 * (_*2 * _*3)", "_*1 * _*2 * _*3"),
         ("_*1 * (_*2 / _*3)", "_*1 * _*2 / _*3"),
         ("_*1 / (_*2 * _*3)", "_*1 / _*2 * _*3"),
@@ -41,33 +55,83 @@ pub fn reorganize() -> AdaptableModifier {
 }
 
 fn switch_atoms_add(map: &LinearMap<Atom, Expression, 8>) -> (Expression, bool) {
-    match (map.get(&Atom::Escape('A', 1)).unwrap(), map.get(&Atom::Escape('A', 2)).unwrap()) {
-        (Expression::Atom(Atom::Variable(a)), Expression::Atom(Atom::Numeric(b))) => (Expression::Atom(Atom::Numeric(*b)) + Expression::Atom(Atom::Variable(*a)), true),
-        (Expression::Atom(Atom::Variable(a)), Expression::Atom(Atom::Variable(b))) => (Expression::Atom(Atom::Variable(*a.min(b))) + Expression::Atom(Atom::Variable(*a.max(b))), *a.min(b) != *a),
-        (e1, e2) => (Expression::Add(Box::new(e1.clone()), Box::new(e2.clone())), false)
+    match (
+        map.get(&Atom::Escape('A', 1)).unwrap(),
+        map.get(&Atom::Escape('A', 2)).unwrap(),
+    ) {
+        (Expression::Atom(Atom::Variable(a)), Expression::Atom(Atom::Numeric(b))) => (
+            Expression::Atom(Atom::Numeric(*b)) + Expression::Atom(Atom::Variable(*a)),
+            true,
+        ),
+        (Expression::Atom(Atom::Variable(a)), Expression::Atom(Atom::Variable(b))) => (
+            Expression::Atom(Atom::Variable(*a.min(b)))
+                + Expression::Atom(Atom::Variable(*a.max(b))),
+            *a.min(b) != *a,
+        ),
+        (e1, e2) => (
+            Expression::Add(Box::new(e1.clone()), Box::new(e2.clone())),
+            false,
+        ),
     }
 }
 
 fn switch_atoms_ext_add(map: &LinearMap<Atom, Expression, 8>) -> (Expression, bool) {
-    match (map.get(&Atom::Escape('*', 1)).unwrap(), map.get(&Atom::Escape('A', 1)).unwrap(), map.get(&Atom::Escape('A', 2)).unwrap(),) {
-        (e, Expression::Atom(Atom::Variable(a)), Expression::Atom(Atom::Numeric(b))) => (e.clone() + Expression::Atom(Atom::Numeric(*b)) + Expression::Atom(Atom::Variable(*a)), true),
-        (e, Expression::Atom(Atom::Variable(a)), Expression::Atom(Atom::Variable(b))) => (e.clone() + Expression::Atom(Atom::Variable(*a.min(b))) + Expression::Atom(Atom::Variable(*a.max(b))), *a.min(b) != *a),
+    match (
+        map.get(&Atom::Escape('*', 1)).unwrap(),
+        map.get(&Atom::Escape('A', 1)).unwrap(),
+        map.get(&Atom::Escape('A', 2)).unwrap(),
+    ) {
+        (e, Expression::Atom(Atom::Variable(a)), Expression::Atom(Atom::Numeric(b))) => (
+            e.clone() + Expression::Atom(Atom::Numeric(*b)) + Expression::Atom(Atom::Variable(*a)),
+            true,
+        ),
+        (e, Expression::Atom(Atom::Variable(a)), Expression::Atom(Atom::Variable(b))) => (
+            e.clone()
+                + Expression::Atom(Atom::Variable(*a.min(b)))
+                + Expression::Atom(Atom::Variable(*a.max(b))),
+            *a.min(b) != *a,
+        ),
         (e1, e2, e3) => (e1.clone() + e2.clone() + e3.clone(), false),
     }
 }
 
 fn switch_atoms_mul(map: &LinearMap<Atom, Expression, 8>) -> (Expression, bool) {
-    match (map.get(&Atom::Escape('A', 1)).unwrap(), map.get(&Atom::Escape('A', 2)).unwrap()) {
-        (Expression::Atom(Atom::Variable(a)), Expression::Atom(Atom::Numeric(b))) => (Expression::Atom(Atom::Numeric(*b)) * Expression::Atom(Atom::Variable(*a)), true),
-        (Expression::Atom(Atom::Variable(a)), Expression::Atom(Atom::Variable(b))) => (Expression::Atom(Atom::Variable(*a.min(b))) * Expression::Atom(Atom::Variable(*a.max(b))), *a.min(b) != *a),
-        (e1, e2) => (Expression::Multiply(Box::new(e1.clone()), Box::new(e2.clone())), false)
+    match (
+        map.get(&Atom::Escape('A', 1)).unwrap(),
+        map.get(&Atom::Escape('A', 2)).unwrap(),
+    ) {
+        (Expression::Atom(Atom::Variable(a)), Expression::Atom(Atom::Numeric(b))) => (
+            Expression::Atom(Atom::Numeric(*b)) * Expression::Atom(Atom::Variable(*a)),
+            true,
+        ),
+        (Expression::Atom(Atom::Variable(a)), Expression::Atom(Atom::Variable(b))) => (
+            Expression::Atom(Atom::Variable(*a.min(b)))
+                * Expression::Atom(Atom::Variable(*a.max(b))),
+            *a.min(b) != *a,
+        ),
+        (e1, e2) => (
+            Expression::Multiply(Box::new(e1.clone()), Box::new(e2.clone())),
+            false,
+        ),
     }
 }
 
 fn switch_atoms_ext_mul(map: &LinearMap<Atom, Expression, 8>) -> (Expression, bool) {
-    match (map.get(&Atom::Escape('*', 1)).unwrap(), map.get(&Atom::Escape('A', 1)).unwrap(), map.get(&Atom::Escape('A', 2)).unwrap(),) {
-        (e, Expression::Atom(Atom::Variable(a)), Expression::Atom(Atom::Numeric(b))) => (e.clone() * Expression::Atom(Atom::Numeric(*b)) * Expression::Atom(Atom::Variable(*a)), true),
-        (e, Expression::Atom(Atom::Variable(a)), Expression::Atom(Atom::Variable(b))) => (e.clone() * Expression::Atom(Atom::Variable(*a.min(b))) * Expression::Atom(Atom::Variable(*a.max(b))), *a.min(b) != *a),
+    match (
+        map.get(&Atom::Escape('*', 1)).unwrap(),
+        map.get(&Atom::Escape('A', 1)).unwrap(),
+        map.get(&Atom::Escape('A', 2)).unwrap(),
+    ) {
+        (e, Expression::Atom(Atom::Variable(a)), Expression::Atom(Atom::Numeric(b))) => (
+            e.clone() * Expression::Atom(Atom::Numeric(*b)) * Expression::Atom(Atom::Variable(*a)),
+            true,
+        ),
+        (e, Expression::Atom(Atom::Variable(a)), Expression::Atom(Atom::Variable(b))) => (
+            e.clone()
+                * Expression::Atom(Atom::Variable(*a.min(b)))
+                * Expression::Atom(Atom::Variable(*a.max(b))),
+            *a.min(b) != *a,
+        ),
         (e1, e2, e3) => (e1.clone() * e2.clone() * e3.clone(), false),
     }
 }
@@ -75,25 +139,57 @@ fn switch_atoms_ext_mul(map: &LinearMap<Atom, Expression, 8>) -> (Expression, bo
 fn denegate_internal(map: &LinearMap<Atom, Expression, 8>) -> (Expression, bool) {
     match map.get(&Atom::Escape('A', 1)).unwrap() {
         Expression::Atom(Atom::Numeric(n)) => match n {
-            Numeric::Integer(i) => if i < &0 {
-                (Expression::Negate(Box::new(Expression::Atom(Atom::Numeric(Numeric::Integer(-i))))), true)
-            } else {
-                (Expression::Atom(Atom::Numeric(Numeric::Integer(*i))), false)
-            },
-            Numeric::Decimal(f) => if f < &0.0 {
-                (Expression::Negate(Box::new(Expression::Atom(Atom::Numeric(Numeric::Decimal(-f))))), true)
-            } else {
-                (Expression::Atom(Atom::Numeric(Numeric::Decimal(*f))), false)
-            },
-            Numeric::Fraction(r1, r2) => if r1 < &0 && r2 < &0 {
-                (Expression::Atom(Atom::Numeric(Numeric::Fraction(-r1, -r2))), true)
-            } else if r1 < &0 {
-                (Expression::Negate(Box::new(Expression::Atom(Atom::Numeric(Numeric::Fraction(-r1, *r2))))), true)
-            } else if r2 < &0 {
-                (Expression::Negate(Box::new(Expression::Atom(Atom::Numeric(Numeric::Fraction(*r1, -r2))))), true)
-            } else {
-                (Expression::Atom(Atom::Numeric(Numeric::Fraction(*r1, *r2))), false)
-            },
+            Numeric::Integer(i) => {
+                if i < &0 {
+                    (
+                        Expression::Negate(Box::new(Expression::Atom(Atom::Numeric(
+                            Numeric::Integer(-i),
+                        )))),
+                        true,
+                    )
+                } else {
+                    (Expression::Atom(Atom::Numeric(Numeric::Integer(*i))), false)
+                }
+            }
+            Numeric::Decimal(f) => {
+                if f < &0.0 {
+                    (
+                        Expression::Negate(Box::new(Expression::Atom(Atom::Numeric(
+                            Numeric::Decimal(-f),
+                        )))),
+                        true,
+                    )
+                } else {
+                    (Expression::Atom(Atom::Numeric(Numeric::Decimal(*f))), false)
+                }
+            }
+            Numeric::Fraction(r1, r2) => {
+                if r1 < &0 && r2 < &0 {
+                    (
+                        Expression::Atom(Atom::Numeric(Numeric::Fraction(-r1, -r2))),
+                        true,
+                    )
+                } else if r1 < &0 {
+                    (
+                        Expression::Negate(Box::new(Expression::Atom(Atom::Numeric(
+                            Numeric::Fraction(-r1, *r2),
+                        )))),
+                        true,
+                    )
+                } else if r2 < &0 {
+                    (
+                        Expression::Negate(Box::new(Expression::Atom(Atom::Numeric(
+                            Numeric::Fraction(*r1, -r2),
+                        )))),
+                        true,
+                    )
+                } else {
+                    (
+                        Expression::Atom(Atom::Numeric(Numeric::Fraction(*r1, *r2))),
+                        false,
+                    )
+                }
+            }
         },
         e => (e.clone(), false),
     }
@@ -106,176 +202,196 @@ pub fn reduce() -> AdaptableModifier {
         ("_A1 * _*1 + _*1", "(1 + _A1) * _*1"),
         ("_*1 + _A1 * _*1", "(1 + _A1) * _*1"),
         ("_A1 * _*1 + _A2 * _*1", "(_A1 + _A2) * _*1"),
-
         ("_*1 + _*2 + _*2", "_*1 + 2 * _*2"),
         ("_*1 + _A1 * _*2 + _*2", "_*1 + (1 + _A1) * _*2"),
         ("_*1 + _*2 + _A1 * _*2", "_*1 + (1 + _A1) * _*2"),
         ("_*1 + _A1 * _*2 + _A2 * _*2", "_*1 + (_A1 + _A2) * _*2"),
-
         ("_*1 - _*1", "0"),
         ("_A1 * _*1 - _*1", "(_A1 - 1) * _*1"),
         ("_*1 - _A1 * _*1", "(-_A1 + 1) * _*1"),
         ("_A1 * _*1 - _A2 * _*1", "(_A1 - _A2) * _*1"),
-
         ("_*1 + _*2 - _*2", "_*1"),
         ("_*1 + _A1 * _*2 - _*2", "_*1 + (_A1 - 1) * _*2"),
         ("_*1 + _*2 - _A1 * _*2", "_*1 + (-_A1 + 1) * _*2"),
         ("_*1 + _A1 * _*2 - _A2 * _*2", "_*1 + (_A1 - _A2) * _*2"),
-
         ("--_*1", "_*1"),
-
         ("0 + _*1", "_*1"),
         ("_*1 + -_*2", "_*1 - _*2"),
         ("-_*1 + _*2", "_*2 - _*1"),
-
         ("1 * _*1", "_*1"),
         ("0 * _*1", "0"),
         ("-_*1 * _*2", "-(_*1 * _*2)"),
         ("_*1 * -_*2", "-(_*1 * _*2)"),
         ("-_*1 * -_*2", "_*1 * _*2"),
-
         ("_*1 / 1", "_*1"),
-        ("0 / _*1", "0")
+        ("0 / _*1", "0"),
     ])
 }
 
 //an AdaptableModifier that simplifies numerics in an expression tree
 pub fn numeric_simplify() -> AdaptableModifier {
     AdaptableModifier::from_fn_list(vec![
-        ("_A1 + _A2".parse::<Expression>().unwrap(), Box::new(add_numeric)),
-        ("_A1 - _A2".parse::<Expression>().unwrap(), Box::new(sub_numeric)),
-        ("_A1 * _A2".parse::<Expression>().unwrap(), Box::new(mul_numeric)),
-        ("_A1 / _A2".parse::<Expression>().unwrap(), Box::new(div_numeric)),
-/*         ("_A1 ^ _A2".parse::<Expression>().unwrap(), Box::new(pow_numeric)),
+        (
+            "_A1 + _A2".parse::<Expression>().unwrap(),
+            Box::new(add_numeric),
+        ),
+        (
+            "_A1 - _A2".parse::<Expression>().unwrap(),
+            Box::new(sub_numeric),
+        ),
+        (
+            "_A1 * _A2".parse::<Expression>().unwrap(),
+            Box::new(mul_numeric),
+        ),
+        (
+            "_A1 / _A2".parse::<Expression>().unwrap(),
+            Box::new(div_numeric),
+        ),
+        /*         ("_A1 ^ _A2".parse::<Expression>().unwrap(), Box::new(pow_numeric)),
         ("_A1 % _A2".parse::<Expression>().unwrap(), Box::new(mod_numeric)),
         ("_A1!".parse::<Expression>().unwrap(), Box::new(fact_numeric)), */
     ])
 }
 
 fn add_numeric(map: &LinearMap<Atom, Expression, 8>) -> (Expression, bool) {
-    match (map.get(&Atom::Escape('A', 1)).unwrap(), map.get(&Atom::Escape('A', 2)).unwrap()) {
-        (Expression::Atom(a1), Expression::Atom(a2)) => {
-            match (a1, a2) {
-                (Atom::Numeric(n1), Atom::Numeric(n2)) => {
-                    (Expression::Atom(Atom::Numeric(*n1 + *n2)), true)
-                }
-                _ => (Expression::Atom(*a1) + Expression::Atom(*a2), false),
+    match (
+        map.get(&Atom::Escape('A', 1)).unwrap(),
+        map.get(&Atom::Escape('A', 2)).unwrap(),
+    ) {
+        (Expression::Atom(a1), Expression::Atom(a2)) => match (a1, a2) {
+            (Atom::Numeric(n1), Atom::Numeric(n2)) => {
+                (Expression::Atom(Atom::Numeric(*n1 + *n2)), true)
             }
-        }
+            _ => (Expression::Atom(*a1) + Expression::Atom(*a2), false),
+        },
         _ => unreachable!("this pointer was called with non-atom expressions"),
     }
 }
 
 fn sub_numeric(map: &LinearMap<Atom, Expression, 8>) -> (Expression, bool) {
-    match (map.get(&Atom::Escape('A', 1)).unwrap(), map.get(&Atom::Escape('A', 2)).unwrap()) {
-        (Expression::Atom(a1), Expression::Atom(a2)) => {
-            match (a1, a2) {
-                (Atom::Numeric(n1), Atom::Numeric(n2)) => {
-                    (Expression::Atom(Atom::Numeric(*n1 - *n2)), true)
-                }
-                _ => (Expression::Atom(*a1) - Expression::Atom(*a2), false),
+    match (
+        map.get(&Atom::Escape('A', 1)).unwrap(),
+        map.get(&Atom::Escape('A', 2)).unwrap(),
+    ) {
+        (Expression::Atom(a1), Expression::Atom(a2)) => match (a1, a2) {
+            (Atom::Numeric(n1), Atom::Numeric(n2)) => {
+                (Expression::Atom(Atom::Numeric(*n1 - *n2)), true)
             }
-        }
+            _ => (Expression::Atom(*a1) - Expression::Atom(*a2), false),
+        },
         _ => unreachable!("this pointer was called with non-atom expressions"),
     }
 }
 
 fn mul_numeric(map: &LinearMap<Atom, Expression, 8>) -> (Expression, bool) {
-    match (map.get(&Atom::Escape('A', 1)).unwrap(), map.get(&Atom::Escape('A', 2)).unwrap()) {
-        (Expression::Atom(a1), Expression::Atom(a2)) => {
-            match (a1, a2) {
-                (Atom::Numeric(n1), Atom::Numeric(n2)) => {
-                    (Expression::Atom(Atom::Numeric(*n1 * *n2)), true)
-                }
-                _ => (Expression::Atom(*a1) * Expression::Atom(*a2), false),
+    match (
+        map.get(&Atom::Escape('A', 1)).unwrap(),
+        map.get(&Atom::Escape('A', 2)).unwrap(),
+    ) {
+        (Expression::Atom(a1), Expression::Atom(a2)) => match (a1, a2) {
+            (Atom::Numeric(n1), Atom::Numeric(n2)) => {
+                (Expression::Atom(Atom::Numeric(*n1 * *n2)), true)
             }
-        }
+            _ => (Expression::Atom(*a1) * Expression::Atom(*a2), false),
+        },
         _ => unreachable!("this pointer was called with non-atom expressions"),
     }
 }
 
 fn div_numeric(map: &LinearMap<Atom, Expression, 8>) -> (Expression, bool) {
-    match (map.get(&Atom::Escape('A', 1)).unwrap(), map.get(&Atom::Escape('A', 2)).unwrap()) {
-        (Expression::Atom(a1), Expression::Atom(a2)) => {
-            match (a1, a2) {
-                (Atom::Numeric(n1), Atom::Numeric(n2)) => {
-                    (Expression::Atom(Atom::Numeric(*n1 / *n2)), true)
-                }
-                _ => (Expression::Atom(*a1) / Expression::Atom(*a2), false),
+    match (
+        map.get(&Atom::Escape('A', 1)).unwrap(),
+        map.get(&Atom::Escape('A', 2)).unwrap(),
+    ) {
+        (Expression::Atom(a1), Expression::Atom(a2)) => match (a1, a2) {
+            (Atom::Numeric(n1), Atom::Numeric(n2)) => {
+                (Expression::Atom(Atom::Numeric(*n1 / *n2)), true)
             }
-        }
+            _ => (Expression::Atom(*a1) / Expression::Atom(*a2), false),
+        },
         _ => unreachable!("this pointer was called with non-atom expressions"),
     }
 }
 
-
 #[cfg(test)]
 mod tests {
-    use crate::{expression::expression_tree::Expression, modifier::{default::{simplify, reorganize, reduce, numeric_simplify,}, adaptable_modifier::AdaptableModifier}};
+    use crate::{
+        expression::expression_tree::Expression,
+        modifier::{
+            adaptable_modifier::AdaptableModifier,
+            default::{numeric_simplify, reduce, reorganize, simplify},
+        },
+    };
 
     #[test]
     fn test_reorganize() {
         let reo = reorganize();
 
         let mut expr2 = "sin(5) + x".parse::<Expression>().unwrap();
-        expr2.simplify::<AdaptableModifier, 100>(&reo);
+        expr2.simplify_im::<AdaptableModifier, 100>(&reo);
 
         assert_eq!(expr2, "x + sin(5)".parse::<Expression>().unwrap());
 
         let mut expr3 = "x + 3".parse::<Expression>().unwrap();
-        expr3.simplify::<AdaptableModifier, 100>(&reo);
+        expr3.simplify_im::<AdaptableModifier, 100>(&reo);
 
         assert_eq!(expr3, "3 + x".parse::<Expression>().unwrap());
 
         let mut expr4 = "sin(p) * 5".parse::<Expression>().unwrap();
-        expr4.simplify::<AdaptableModifier, 100>(&reo);
+        expr4.simplify_im::<AdaptableModifier, 100>(&reo);
 
         assert_eq!(expr4, "5 * sin(p)".parse::<Expression>().unwrap());
 
         let mut expr5 = "z + a + x".parse::<Expression>().unwrap();
-        expr5.simplify::<AdaptableModifier, 100>(&reo);
+        expr5.simplify_im::<AdaptableModifier, 100>(&reo);
 
         assert_eq!(expr5, "a + x + z".parse::<Expression>().unwrap());
 
         let mut expr6 = "x + 3 + 5".parse::<Expression>().unwrap();
-        expr6.simplify::<AdaptableModifier, 100>(&reo);
+        expr6.simplify_im::<AdaptableModifier, 100>(&reo);
 
         assert_eq!(expr6, "3 + 5 + x".parse::<Expression>().unwrap());
 
         let mut expr7 = "z + y + x + w + v".parse::<Expression>().unwrap();
-        expr7.simplify::<AdaptableModifier, 100>(&reo);
+        expr7.simplify_im::<AdaptableModifier, 100>(&reo);
 
         assert_eq!(expr7, "v + w + x + y + z".parse::<Expression>().unwrap());
 
         let mut expr8 = "x + 3 + y + 7".parse::<Expression>().unwrap();
-        expr8.simplify::<AdaptableModifier, 100>(&reo);
+        expr8.simplify_im::<AdaptableModifier, 100>(&reo);
 
         assert_eq!(expr8, "3 + 7 + x + y".parse::<Expression>().unwrap());
 
         let mut expr9 = "x * 3 * y * 7 * z".parse::<Expression>().unwrap();
-        expr9.simplify::<AdaptableModifier, 100>(&reo);
+        expr9.simplify_im::<AdaptableModifier, 100>(&reo);
 
         assert_eq!(expr9, "3 * 7 * x * y * z".parse::<Expression>().unwrap());
 
         let mut expr10 = "7 * z * 5".parse::<Expression>().unwrap();
-        expr10.simplify::<AdaptableModifier, 100>(&reo);
+        expr10.simplify_im::<AdaptableModifier, 100>(&reo);
 
         assert_eq!(expr10, "7 * 5 * z".parse::<Expression>().unwrap());
 
         let mut expr11 = "a + 7 * z * 5".parse::<Expression>().unwrap();
-        expr11.simplify::<AdaptableModifier, 100>(&reo);
+        expr11.simplify_im::<AdaptableModifier, 100>(&reo);
 
         assert_eq!(expr11, "a + 7 * 5 * z".parse::<Expression>().unwrap());
 
         let mut expr12 = "6 * y * x + 7 * z * 5".parse::<Expression>().unwrap();
-        expr12.simplify::<AdaptableModifier, 100>(&reo);
+        expr12.simplify_im::<AdaptableModifier, 100>(&reo);
 
-        assert_eq!(expr12, "6 * x * y + 7 * 5 * z".parse::<Expression>().unwrap());
+        assert_eq!(
+            expr12,
+            "6 * x * y + 7 * 5 * z".parse::<Expression>().unwrap()
+        );
 
         let mut expr13 = "6 * y * x + sin(x) * x".parse::<Expression>().unwrap();
-        expr13.simplify::<AdaptableModifier, 100>(&reo);
+        expr13.simplify_im::<AdaptableModifier, 100>(&reo);
 
-        assert_eq!(expr13, "6 * x * y + x * sin(x)".parse::<Expression>().unwrap());
+        assert_eq!(
+            expr13,
+            "6 * x * y + x * sin(x)".parse::<Expression>().unwrap()
+        );
     }
 
     #[test]
@@ -283,42 +399,42 @@ mod tests {
         let red = reduce();
 
         let mut expr1 = "0 + x".parse::<Expression>().unwrap();
-        expr1.simplify::<AdaptableModifier, 100>(&red);
+        expr1.simplify_im::<AdaptableModifier, 100>(&red);
 
         assert_eq!(expr1, "x".parse::<Expression>().unwrap());
 
         let mut expr2 = "0 * x".parse::<Expression>().unwrap();
-        expr2.simplify::<AdaptableModifier, 100>(&red);
+        expr2.simplify_im::<AdaptableModifier, 100>(&red);
 
         assert_eq!(expr2, "0".parse::<Expression>().unwrap());
 
         let mut expr3 = "0 + 0".parse::<Expression>().unwrap();
-        expr3.simplify::<AdaptableModifier, 100>(&red);
+        expr3.simplify_im::<AdaptableModifier, 100>(&red);
 
         assert_eq!(expr3, "0".parse::<Expression>().unwrap());
 
         let mut expr4 = "0 * x + 0 * y".parse::<Expression>().unwrap();
-        expr4.simplify::<AdaptableModifier, 100>(&red);
+        expr4.simplify_im::<AdaptableModifier, 100>(&red);
 
         assert_eq!(expr4, "0".parse::<Expression>().unwrap());
 
         let mut expr5 = "x + x".parse::<Expression>().unwrap();
-        expr5.simplify::<AdaptableModifier, 100>(&red);
+        expr5.simplify_im::<AdaptableModifier, 100>(&red);
 
         assert_eq!(expr5, "2 * x".parse::<Expression>().unwrap());
 
         let mut expr6 = "x / 1".parse::<Expression>().unwrap();
-        expr6.simplify::<AdaptableModifier, 100>(&red);
+        expr6.simplify_im::<AdaptableModifier, 100>(&red);
 
         assert_eq!(expr6, "x".parse::<Expression>().unwrap());
 
         let mut expr7 = "1 * x".parse::<Expression>().unwrap();
-        expr7.simplify::<AdaptableModifier, 100>(&red);
+        expr7.simplify_im::<AdaptableModifier, 100>(&red);
 
         assert_eq!(expr7, "x".parse::<Expression>().unwrap());
 
         let mut expr8 = "x - x".parse::<Expression>().unwrap();
-        expr8.simplify::<AdaptableModifier, 100>(&red);
+        expr8.simplify_im::<AdaptableModifier, 100>(&red);
 
         assert_eq!(expr8, "0".parse::<Expression>().unwrap());
     }
@@ -328,37 +444,37 @@ mod tests {
         let num = numeric_simplify();
 
         let mut expr1 = "1 + 2".parse::<Expression>().unwrap();
-        expr1.simplify::<AdaptableModifier, 100>(&num);
+        expr1.simplify_im::<AdaptableModifier, 100>(&num);
 
         assert_eq!(expr1, "3".parse::<Expression>().unwrap());
 
         let mut expr2 = "1 + 2 + 3".parse::<Expression>().unwrap();
-        expr2.simplify::<AdaptableModifier, 100>(&num);
+        expr2.simplify_im::<AdaptableModifier, 100>(&num);
 
         assert_eq!(expr2, "6".parse::<Expression>().unwrap());
 
         let mut expr3 = "5 * 5".parse::<Expression>().unwrap();
-        expr3.simplify::<AdaptableModifier, 100>(&num);
+        expr3.simplify_im::<AdaptableModifier, 100>(&num);
 
         assert_eq!(expr3, "25".parse::<Expression>().unwrap());
 
         let mut expr4 = "5.4/1.2".parse::<Expression>().unwrap();
-        expr4.simplify::<AdaptableModifier, 100>(&num);
+        expr4.simplify_im::<AdaptableModifier, 100>(&num);
 
         assert_eq!(expr4, "4.5".parse::<Expression>().unwrap());
 
         let mut expr5 = "5.4/1.2 + x".parse::<Expression>().unwrap();
-        expr5.simplify::<AdaptableModifier, 100>(&num);
+        expr5.simplify_im::<AdaptableModifier, 100>(&num);
 
         assert_eq!(expr5, "4.5 + x".parse::<Expression>().unwrap());
 
         let mut expr6 = "5.4/1.2 + 1".parse::<Expression>().unwrap();
-        expr6.simplify::<AdaptableModifier, 100>(&num);
+        expr6.simplify_im::<AdaptableModifier, 100>(&num);
 
         assert_eq!(expr6, "5.5".parse::<Expression>().unwrap());
 
         let mut expr7 = "5.4 * x / 1.2".parse::<Expression>().unwrap();
-        expr7.simplify::<AdaptableModifier, 100>(&num);
+        expr7.simplify_im::<AdaptableModifier, 100>(&num);
 
         assert_eq!(expr7, "5.4 * x / 1.2".parse::<Expression>().unwrap()); //numeric_simplify shouldn't reorganize the expression
     }
@@ -368,64 +484,67 @@ mod tests {
         let simp = simplify();
 
         let mut expr2 = "sin(5) + x".parse::<Expression>().unwrap();
-        expr2.simplify::<AdaptableModifier, 100>(&simp);
+        expr2.simplify_im::<AdaptableModifier, 100>(&simp);
 
         assert_eq!(expr2, "x + sin(5)".parse::<Expression>().unwrap());
 
         let mut expr3 = "x + 3".parse::<Expression>().unwrap();
-        expr3.simplify::<AdaptableModifier, 100>(&simp);
+        expr3.simplify_im::<AdaptableModifier, 100>(&simp);
 
         assert_eq!(expr3, "3 + x".parse::<Expression>().unwrap());
 
         let mut expr4 = "sin(p) * 5".parse::<Expression>().unwrap();
-        expr4.simplify::<AdaptableModifier, 100>(&simp);
+        expr4.simplify_im::<AdaptableModifier, 100>(&simp);
 
         assert_eq!(expr4, "5 * sin(p)".parse::<Expression>().unwrap());
 
         let mut expr5 = "z + a + x".parse::<Expression>().unwrap();
-        expr5.simplify::<AdaptableModifier, 100>(&simp);
+        expr5.simplify_im::<AdaptableModifier, 100>(&simp);
 
         assert_eq!(expr5, "a + x + z".parse::<Expression>().unwrap());
 
         let mut expr6 = "x + 3 + 5".parse::<Expression>().unwrap();
-        expr6.simplify::<AdaptableModifier, 100>(&simp);
+        expr6.simplify_im::<AdaptableModifier, 100>(&simp);
 
         assert_eq!(expr6, "8 + x".parse::<Expression>().unwrap());
 
         let mut expr7 = "z + y + x + w + v".parse::<Expression>().unwrap();
-        expr7.simplify::<AdaptableModifier, 100>(&simp);
+        expr7.simplify_im::<AdaptableModifier, 100>(&simp);
 
         assert_eq!(expr7, "v + w + x + y + z".parse::<Expression>().unwrap());
 
         let mut expr8 = "x + 3 + y + 7".parse::<Expression>().unwrap();
-        expr8.simplify::<AdaptableModifier, 100>(&simp);
+        expr8.simplify_im::<AdaptableModifier, 100>(&simp);
 
         assert_eq!(expr8, "10 + x + y".parse::<Expression>().unwrap());
 
         let mut expr9 = "x * 3 * y * 7 * z".parse::<Expression>().unwrap();
-        expr9.simplify::<AdaptableModifier, 100>(&simp);
+        expr9.simplify_im::<AdaptableModifier, 100>(&simp);
 
         assert_eq!(expr9, "21 * x * y * z".parse::<Expression>().unwrap());
 
         let mut expr10 = "7 * z * 5".parse::<Expression>().unwrap();
-        expr10.simplify::<AdaptableModifier, 100>(&simp);
+        expr10.simplify_im::<AdaptableModifier, 100>(&simp);
 
         assert_eq!(expr10, "35 * z".parse::<Expression>().unwrap());
 
         let mut expr11 = "a + 7 * z * 5".parse::<Expression>().unwrap();
-        expr11.simplify::<AdaptableModifier, 100>(&simp);
+        expr11.simplify_im::<AdaptableModifier, 100>(&simp);
 
         assert_eq!(expr11, "a + 35 * z".parse::<Expression>().unwrap());
 
         let mut expr12 = "6 * y * x + 7 * z * 5".parse::<Expression>().unwrap();
-        expr12.simplify::<AdaptableModifier, 100>(&simp);
+        expr12.simplify_im::<AdaptableModifier, 100>(&simp);
 
         assert_eq!(expr12, "6 * x * y + 35 * z".parse::<Expression>().unwrap());
 
         let mut expr13 = "6 * y * x + sin(x) * x".parse::<Expression>().unwrap();
-        expr13.simplify::<AdaptableModifier, 100>(&simp);
+        expr13.simplify_im::<AdaptableModifier, 100>(&simp);
 
-        assert_eq!(expr13, "6 * x * y + x * sin(x)".parse::<Expression>().unwrap());
+        assert_eq!(
+            expr13,
+            "6 * x * y + x * sin(x)".parse::<Expression>().unwrap()
+        );
     }
 
     #[test]
@@ -433,42 +552,42 @@ mod tests {
         let simp = simplify();
 
         let mut expr1 = "0 + x".parse::<Expression>().unwrap();
-        expr1.simplify::<AdaptableModifier, 100>(&simp);
+        expr1.simplify_im::<AdaptableModifier, 100>(&simp);
 
         assert_eq!(expr1, "x".parse::<Expression>().unwrap());
 
         let mut expr2 = "0 * x".parse::<Expression>().unwrap();
-        expr2.simplify::<AdaptableModifier, 100>(&simp);
+        expr2.simplify_im::<AdaptableModifier, 100>(&simp);
 
         assert_eq!(expr2, "0".parse::<Expression>().unwrap());
 
         let mut expr3 = "0 + 0".parse::<Expression>().unwrap();
-        expr3.simplify::<AdaptableModifier, 100>(&simp);
+        expr3.simplify_im::<AdaptableModifier, 100>(&simp);
 
         assert_eq!(expr3, "0".parse::<Expression>().unwrap());
 
         let mut expr4 = "0 * x + 0 * y".parse::<Expression>().unwrap();
-        expr4.simplify::<AdaptableModifier, 100>(&simp);
+        expr4.simplify_im::<AdaptableModifier, 100>(&simp);
 
         assert_eq!(expr4, "0".parse::<Expression>().unwrap());
 
         let mut expr5 = "x + x".parse::<Expression>().unwrap();
-        expr5.simplify::<AdaptableModifier, 100>(&simp);
+        expr5.simplify_im::<AdaptableModifier, 100>(&simp);
 
         assert_eq!(expr5, "2 * x".parse::<Expression>().unwrap());
 
         let mut expr6 = "x / 1".parse::<Expression>().unwrap();
-        expr6.simplify::<AdaptableModifier, 100>(&simp);
+        expr6.simplify_im::<AdaptableModifier, 100>(&simp);
 
         assert_eq!(expr6, "x".parse::<Expression>().unwrap());
 
         let mut expr7 = "1 * x".parse::<Expression>().unwrap();
-        expr7.simplify::<AdaptableModifier, 100>(&simp);
+        expr7.simplify_im::<AdaptableModifier, 100>(&simp);
 
         assert_eq!(expr7, "x".parse::<Expression>().unwrap());
 
         let mut expr8 = "x - x".parse::<Expression>().unwrap();
-        expr8.simplify::<AdaptableModifier, 100>(&simp);
+        expr8.simplify_im::<AdaptableModifier, 100>(&simp);
 
         assert_eq!(expr8, "0".parse::<Expression>().unwrap());
     }
@@ -478,55 +597,59 @@ mod tests {
         let simp = simplify();
 
         let mut expr1 = "1 + 2".parse::<Expression>().unwrap();
-        expr1.simplify::<AdaptableModifier, 100>(&simp);
+        expr1.simplify_im::<AdaptableModifier, 100>(&simp);
 
         assert_eq!(expr1, "3".parse::<Expression>().unwrap());
 
         let mut expr2 = "1 + 2 + 3".parse::<Expression>().unwrap();
-        expr2.simplify::<AdaptableModifier, 100>(&simp);
+        expr2.simplify_im::<AdaptableModifier, 100>(&simp);
 
         assert_eq!(expr2, "6".parse::<Expression>().unwrap());
 
         let mut expr3 = "5 * 5".parse::<Expression>().unwrap();
-        expr3.simplify::<AdaptableModifier, 100>(&simp);
+        expr3.simplify_im::<AdaptableModifier, 100>(&simp);
 
         assert_eq!(expr3, "25".parse::<Expression>().unwrap());
 
         let mut expr4 = "5.4/1.2".parse::<Expression>().unwrap();
-        expr4.simplify::<AdaptableModifier, 100>(&simp);
+        expr4.simplify_im::<AdaptableModifier, 100>(&simp);
 
         assert_eq!(expr4, "4.5".parse::<Expression>().unwrap());
 
         let mut expr5 = "5.4/1.2 + x".parse::<Expression>().unwrap();
-        expr5.simplify::<AdaptableModifier, 100>(&simp);
+        expr5.simplify_im::<AdaptableModifier, 100>(&simp);
 
         assert_eq!(expr5, "4.5 + x".parse::<Expression>().unwrap());
 
         let mut expr6 = "5.4/1.2 + 1".parse::<Expression>().unwrap();
-        expr6.simplify::<AdaptableModifier, 100>(&simp);
+        expr6.simplify_im::<AdaptableModifier, 100>(&simp);
 
         assert_eq!(expr6, "5.5".parse::<Expression>().unwrap());
 
         let mut expr7 = "5.4 * x / 1.2".parse::<Expression>().unwrap();
-        expr7.simplify::<AdaptableModifier, 100>(&simp);
+        expr7.simplify_im::<AdaptableModifier, 100>(&simp);
 
         assert_eq!(expr7, "5.4 * x / 1.2".parse::<Expression>().unwrap()); //numeric_simplify shouldn't reorganize the expression
     }
 
     #[test]
     fn test_simplify() {
+        let simp = simplify();
+
         let mut expr1 = "8 + x + 4 + x".parse::<Expression>().unwrap();
-        expr1.simplify::<AdaptableModifier, 100>(&simplify());
+        expr1.simplify_im::<AdaptableModifier, 100>(&simp);
 
         assert_eq!(expr1, "12 + 2 * x".parse::<Expression>().unwrap());
 
         let mut expr2 = "8 + x + 4 + x + 2 * x".parse::<Expression>().unwrap();
-        expr2.simplify::<AdaptableModifier, 100>(&simplify());
+        expr2.simplify_im::<AdaptableModifier, 100>(&simp);
 
         assert_eq!(expr2, "12 + 4 * x".parse::<Expression>().unwrap());
 
-        let mut expr3 = "8 + x + 4 + x - 2 * x + 3 * x".parse::<Expression>().unwrap();
-        expr3.simplify::<AdaptableModifier, 100>(&simplify());
+        let mut expr3 = "8 + x + 4 + x - 2 * x + 3 * x"
+            .parse::<Expression>()
+            .unwrap();
+        expr3.simplify_im::<AdaptableModifier, 100>(&simp);
 
         assert_eq!(expr3, "12 + 3 * x".parse::<Expression>().unwrap());
 
@@ -535,5 +658,5 @@ mod tests {
         expr4.simplify::<AdaptableModifier, 100>(&simplify());
 
         assert_eq!(expr4, "0".parse::<Expression>().unwrap()); */
-    }    
-}
\ No newline at end of file
+    }
+}
diff --git a/src/modifier/mod.rs b/src/modifier/mod.rs
index 9a2f76f..bc26f66 100644
--- a/src/modifier/mod.rs
+++ b/src/modifier/mod.rs
@@ -1,52 +1,50 @@
 use crate::expression::expression_tree::Expression;
 
 //Modifier: objects which can modify an expression
-pub trait Modifier {
-    fn modify(&self, expression: &mut Expression) -> bool; //returns true if modified
+pub trait ModifierImmutable {
+    fn modify_immut(&self, expression: &mut Expression) -> bool; //returns true if modified
+}
+
+//modifiers which can modify themselves
+pub trait ModifierMutable {
+    fn modify_mut(&mut self, expression: &mut Expression) -> bool; //returns true if modified
 }
 
-pub mod default;
 pub mod adaptable_modifier;
+pub mod default;
 
 #[cfg(test)]
 mod tests {
-    use core::str::FromStr;
-    use alloc::{vec, boxed::Box};
+    use alloc::{boxed::Box, string::ToString, vec};
 
     use libm::sinf;
 
-    use crate::expression::expression_tree::{Expression, Atom, Numeric};
-    use super::Modifier;
+    use super::ModifierImmutable;
+    use crate::expression::expression_tree::{Atom, Expression, Numeric};
 
     struct SimpleMod;
 
-    impl Modifier for SimpleMod {
-        fn modify(&self, expression: &mut Expression) -> bool {
+    impl ModifierImmutable for SimpleMod {
+        fn modify_immut(&self, expression: &mut Expression) -> bool {
             match expression {
-                Expression::Function { name, args } => {
-                    match name.as_str() {
-                        "sin" => {
-                            *expression = Expression::Atom(
-                                Atom::Numeric(
-                                    Numeric::Decimal(
-                                        sinf(match &*args[0] {
-                                            Expression::Atom(a) => match a {
-                                                Atom::Numeric(n) => match n {
-                                                    Numeric::Decimal(d) => *d,
-                                                    _ => unimplemented!(),
-                                                },
-                                                _ => panic!("sin expects a numeric argument"),
-                                            },
-                                            _ => return false,
-                                        })
-                                    )
-                                )
-                            );
-                            true
-                        }
-                        _ => false,
+                Expression::Function { name, args } => match name.as_str() {
+                    "sin" => {
+                        *expression = Expression::Atom(Atom::Numeric(Numeric::Decimal(sinf(
+                            match &*args[0] {
+                                Expression::Atom(a) => match a {
+                                    Atom::Numeric(n) => match n {
+                                        Numeric::Decimal(d) => *d,
+                                        _ => unimplemented!(),
+                                    },
+                                    _ => panic!("sin expects a numeric argument"),
+                                },
+                                _ => return false,
+                            },
+                        ))));
+                        true
                     }
-                }
+                    _ => false,
+                },
                 _ => false,
             }
         }
@@ -54,8 +52,8 @@ mod tests {
 
     struct NothingMod;
 
-    impl Modifier for NothingMod {
-        fn modify(&self, _expression: &mut Expression) -> bool {
+    impl ModifierImmutable for NothingMod {
+        fn modify_immut(&self, _expression: &mut Expression) -> bool {
             false
         }
     }
@@ -63,16 +61,21 @@ mod tests {
     #[test]
     fn test_modifier_approximate() {
         let expr = Expression::Function {
-            name: heapless::String::from_str("sin").unwrap(),
-            args: vec![Box::new(Expression::Atom(
-                Atom::Numeric(
-                    Numeric::Decimal(20.0)
-                )
-            )),
-            ].into_iter().collect(),
+            name: "sin".to_string(),
+            args: vec![Box::new(Expression::Atom(Atom::Numeric(Numeric::Decimal(
+                20.0,
+            ))))]
+            .into_iter()
+            .collect(),
         };
 
-        assert_eq!(expr.approximate::<SimpleMod, NothingMod, NothingMod, 50>(&SimpleMod, &NothingMod, &NothingMod), Ok(Numeric::Decimal(0.91294525073)));
+        assert_eq!(
+            expr.approximate_im::<SimpleMod, NothingMod, NothingMod, 50>(
+                &SimpleMod,
+                &NothingMod,
+                &NothingMod
+            ),
+            Ok(Numeric::Decimal(0.91294525073))
+        );
     }
-
-}
\ No newline at end of file
+}


Test patch: