[gnome-calculator/60-split-out-a-backend-library] gcalc: implemented adding terms in polynomial



commit d07f3eeca8f53bba78e13da5e18219e8273c5c32
Author: Daniel Espinosa Ortiz <esodan gmail com>
Date:   Fri Jan 4 10:12:27 2019 -0600

    gcalc: implemented adding terms in polynomial

 gcalc/gcalc-expression.vala    |  3 ++
 gcalc/gcalc-gexpression.vala   |  3 ++
 gcalc/gcalc-gpolynomial.vala   | 33 +++++---------------
 gcalc/gcalc-gterm.vala         | 10 ++++++-
 gcalc/gcalc-polynomial.vala    | 44 +++++++++++++++++++++++++++
 gcalc/gcalc-term.vala          | 27 +++++++++++++----
 tests/gcalc-solving-basic.vala | 68 ++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 156 insertions(+), 32 deletions(-)
---
diff --git a/gcalc/gcalc-expression.vala b/gcalc/gcalc-expression.vala
index 8842a4e8..4e86b3fb 100644
--- a/gcalc/gcalc-expression.vala
+++ b/gcalc/gcalc-expression.vala
@@ -24,3 +24,6 @@ public interface GCalc.Expression : Object {
   public abstract Result solve ();
 }
 
+public interface GCalc.ErrorExpression : Object, Expression {
+}
+
diff --git a/gcalc/gcalc-gexpression.vala b/gcalc/gcalc-gexpression.vala
index 23a77d47..aac356d4 100644
--- a/gcalc/gcalc-gexpression.vala
+++ b/gcalc/gcalc-gexpression.vala
@@ -30,3 +30,6 @@ public class GCalc.GExpression : Object, Expression {
   }
 }
 
+
+public class GCalc.GErrorExpression : GExpression, ErrorExpression {}
+
diff --git a/gcalc/gcalc-gpolynomial.vala b/gcalc/gcalc-gpolynomial.vala
index cc7abaeb..fa038d81 100644
--- a/gcalc/gcalc-gpolynomial.vala
+++ b/gcalc/gcalc-gpolynomial.vala
@@ -20,32 +20,15 @@
  */
 public class GCalc.GPolynomial : GExpression, Polynomial {
   public override Result solve () {
-    Expression res = null;
-    Term current = null;
-    foreach (Expression e in expressions) {
-      var r = e.solve ();
-      if (!r.is_valid) {
-        return r;
-      }
-      if (r.expression is Term) {
-        var t = r.expression as Term;
-        if (current == null) {
-          current = t;
-          continue;
-        }
-        try {
-          current = current.sum (t) as Term;
-        } catch (GLib.Error err) {
-          var nerr = new GErrorResult (err.message);
-          return new GResult.with_error ((Expression) new GExpression (), (ErrorResult) nerr) as Result;
-        }
-      }
-      if (r.expression is Constant) {
-        res = r.expression;
-        break;
-      }
+    Result res = null;
+    try {
+      var e = evaluate ();
+      res = new GResult (e) as Result;
+    } catch (GLib.Error err) {
+      var nerr = new GErrorResult (err.message);
+      res = new GResult.with_error ((Expression) new GErrorExpression (), (ErrorResult) nerr) as Result;
     }
-    return new GResult (res) as Result;
+    return res;
   }
 }
 
diff --git a/gcalc/gcalc-gterm.vala b/gcalc/gcalc-gterm.vala
index 8f9c53b8..92849ae2 100644
--- a/gcalc/gcalc-gterm.vala
+++ b/gcalc/gcalc-gterm.vala
@@ -26,9 +26,17 @@ public class GCalc.GTerm : GExpression, Term {
       res = new GResult (e) as Result;
     } catch (GLib.Error err) {
       var nerr = new GErrorResult (err.message);
-      res = new GResult.with_error ((Expression) new GExpression (), (ErrorResult) nerr) as Result;
+      res = new GResult.with_error ((Expression) new GErrorExpression (), (ErrorResult) nerr) as Result;
     }
     return res;
   }
+  // Expression
+  public override string to_string () {
+    string s = "";
+    foreach (Expression e in expressions) {
+      s += e.to_string ();
+    }
+    return s;
+  }
 }
 
diff --git a/gcalc/gcalc-polynomial.vala b/gcalc/gcalc-polynomial.vala
index e8efae06..e00e5c7d 100644
--- a/gcalc/gcalc-polynomial.vala
+++ b/gcalc/gcalc-polynomial.vala
@@ -19,5 +19,49 @@
  *      Daniel Espinosa <esodan gmail com>
  */
 public interface GCalc.Polynomial : Object, Expression {
+  public virtual Expression evaluate () throws GLib.Error {
+    Term current = null;
+    Expression res = null;
+    message ("Terms: %u", expressions.get_n_items ());
+    for (uint i = 0; i < expressions.get_n_items (); i++) {
+      var e = expressions.get_item (i) as Term;
+      if (e == null) {
+        message ("No Term: %s", e.get_type ().name ());
+        continue;
+      }
+      if (current == null) {
+        current = (Term) e;
+        if (i+1 < expressions.get_n_items ()) {
+          continue;
+        }
+        var er = ((Term) e).evaluate ();
+        if (res == null) {
+          res = er;
+          break;
+        }
+        if (res is Constant && er is Constant) {
+          message ("Adding: %s + %s", res.to_string (), er.to_string ());
+          res = ((Constant) res).add ((Constant) er);
+          break;
+        }
+      }
+      var re = current.add ((Term) e);
+      current = null;
+      message ("Current Terms Sum: %s", re.to_string ());
+      if (res == null) {
+        res = re;
+      } else if (res is Constant && re is Constant) {
+        message ("Adding: %s + %s", res.to_string (), re.to_string ());
+        res = ((Constant) res).add ((Constant) re);
+      }
+      if (res != null) {
+        message ("Current Sum: %s", res.to_string ());
+      }
+    }
+    if (res == null) {
+      return new GErrorExpression ();
+    }
+    return res;
+  }
 }
 
diff --git a/gcalc/gcalc-term.vala b/gcalc/gcalc-term.vala
index 985af4ef..9d604317 100644
--- a/gcalc/gcalc-term.vala
+++ b/gcalc/gcalc-term.vala
@@ -19,13 +19,20 @@
  *      Daniel Espinosa <esodan gmail com>
  */
 public interface GCalc.Term : Object, Expression {
-  public virtual Expression sum (Term t) throws GLib.Error {
+  public virtual Expression add (Term t) throws GLib.Error {
     if (t.expressions.get_n_items () == 0) {
-      return this;
+      return new GConstant.@double (1.0);
     }
-    return this;
+    Expression res = new GExpression ();
+    var e = evaluate ();
+    var e2 = t.evaluate ();
+    if (e is Constant && e2 is Constant) {
+      res = ((Constant) e).add ((Constant) e2);
+    }
+    return res;
   }
   public virtual Expression evaluate () throws GLib.Error {
+    message ("Evaluating term: %s", this.to_string ());
     Expression current = null;
     Operator current_operator = null;
     bool first = true;
@@ -35,18 +42,22 @@ public interface GCalc.Term : Object, Expression {
           throw new TermError.INVALID_OPERATOR ("Incorrect position for operator in expression");
         }
         if (e is Minus && first) {
-          var c = new GConstant.@double (1.0);
-          c = c.neg () as GConstant;
+          var c = new GConstant.@double (-1.0);
           current = c;
           first = false;
         }
+        message ("Setting current operator to: %s", e.get_type ().name());
         current_operator = e as Operator;
+        continue;
       } else if (e is Constant) {
         if (current == null) {
           current = e;
           first = false;
         } else if (current is Constant) {
           if (current_operator != null) {
+            if (current_operator is Minus) {
+              current = (current as Constant).multiply (e as Constant);
+            }
             if (current_operator is Multiply) {
               current = (current as Constant).multiply (e as Constant);
             }
@@ -57,11 +68,15 @@ public interface GCalc.Term : Object, Expression {
         }
       }
     }
+    if (current == null) {
+      throw new TermError.EVALUATION_FAIL ("Evaluation fail on Term");
+    }
     return current;
   }
 }
 
 public errordomain GCalc.TermError {
-  INVALID_OPERATOR
+  INVALID_OPERATOR,
+  EVALUATION_FAIL
 }
 
diff --git a/tests/gcalc-solving-basic.vala b/tests/gcalc-solving-basic.vala
index c67ad6d9..85ab7f14 100644
--- a/tests/gcalc-solving-basic.vala
+++ b/tests/gcalc-solving-basic.vala
@@ -177,6 +177,74 @@ class Tests {
         warning ("Error: %s", e.message);
       }
     });
+    Test.add_func ("/gcalc/solve/term/add/constant",
+    ()=>{
+      try {
+        var parser = new Parser ();
+        var eqman = new GMathEquationManager ();
+        parser.parse ("1+1", eqman);
+        assert (eqman.equations.get_n_items () == 1);
+        var eq = eqman.equations.get_item (0) as MathEquation;
+        assert (eq != null);
+        var e = eq.expressions.get_item (0) as Polynomial;
+        assert (e != null);
+        var t1 = e.expressions.get_item (0) as Term;
+        var t2 = e.expressions.get_item (1) as Term;
+        var res = t1.add (t2);
+        assert (res != null);
+        message (res.get_type ().name ());
+        var c = res as Constant;
+        assert (c != null);
+        message (c.to_string ());
+        assert (c.real () == 2.0);
+      } catch (GLib.Error e) {
+        warning ("Error: %s", e.message);
+      }
+    });
+    Test.add_func ("/gcalc/solve/term/add/constant-multiple",
+    ()=>{
+      try {
+        var parser = new Parser ();
+        var eqman = new GMathEquationManager ();
+        parser.parse ("1+1-9+8-3", eqman);
+        assert (eqman.equations.get_n_items () == 1);
+        var eq = eqman.equations.get_item (0) as MathEquation;
+        assert (eq != null);
+        var e = eq.expressions.get_item (0) as Polynomial;
+        assert (e != null);
+        var res = e.evaluate ();
+        assert (res != null);
+        message (res.get_type ().name ());
+        var c = res as Constant;
+        assert (c != null);
+        message (c.to_string ());
+        assert (c.real () == -2.0);
+      } catch (GLib.Error e) {
+        warning ("Error: %s", e.message);
+      }
+    });
+    Test.add_func ("/gcalc/solve/term/add-mult-div/constant-multiple",
+    ()=>{
+      try {
+        var parser = new Parser ();
+        var eqman = new GMathEquationManager ();
+        parser.parse ("15/3+18/6-27/9+4*2-3*2", eqman);
+        assert (eqman.equations.get_n_items () == 1);
+        var eq = eqman.equations.get_item (0) as MathEquation;
+        assert (eq != null);
+        var e = eq.expressions.get_item (0) as Polynomial;
+        assert (e != null);
+        var res = e.evaluate ();
+        assert (res != null);
+        message (res.get_type ().name ());
+        var c = res as Constant;
+        assert (c != null);
+        message (c.to_string ());
+        assert (c.real () == 7.0);
+      } catch (GLib.Error e) {
+        warning ("Error: %s", e.message);
+      }
+    });
     return Test.run ();
   }
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]