[gnome-calculator/60-split-out-a-backend-library] gcalc: implemented power operator



commit ddfa9f57e2b851f92c2306cc4f73cba856c91671
Author: Daniel Espinosa Ortiz <esodan gmail com>
Date:   Fri Jan 4 20:51:48 2019 -0600

    gcalc: implemented power operator

 gcalc/gcalc-constant.vala      |  1 +
 gcalc/gcalc-gconstant.vala     | 10 ++++++
 gcalc/gcalc-gpow.vala          | 26 ++++++++++++++
 gcalc/gcalc-parser.vala        | 26 +++++++++-----
 gcalc/gcalc-pow.vala           | 22 ++++++++++++
 gcalc/gcalc-term.vala          |  3 ++
 gcalc/meson.build              |  2 ++
 tests/gcalc-parsing.vala       | 55 +++++++++++++++++++++++++++++
 tests/gcalc-solving-basic.vala | 80 ++++++++++++++++++++++++++++++++++++++++++
 9 files changed, 217 insertions(+), 8 deletions(-)
---
diff --git a/gcalc/gcalc-constant.vala b/gcalc/gcalc-constant.vala
index d7d1b6b1..15d1c644 100644
--- a/gcalc/gcalc-constant.vala
+++ b/gcalc/gcalc-constant.vala
@@ -26,5 +26,6 @@ public interface GCalc.Constant : Object, Expression {
   public abstract Constant multiply (Constant c);
   public abstract Constant divide (Constant c);
   public abstract Constant neg ();
+  public abstract Constant pow (Constant c);
 }
 
diff --git a/gcalc/gcalc-gconstant.vala b/gcalc/gcalc-gconstant.vala
index 9d54b4f0..88ea0bc3 100644
--- a/gcalc/gcalc-gconstant.vala
+++ b/gcalc/gcalc-gconstant.vala
@@ -101,6 +101,16 @@ public class GCalc.GConstant : GExpression, Constant {
     var nc = new GConstant.internal_complex (res);
     return nc as Constant;
   }
+  public Constant pow (Constant c)
+    requires (c is GConstant)
+  {
+    var res = MPC.Complex (1000);
+    var p1 = MPC.Complex (1000);
+    p1.set ((c as GConstant).get_complex ());
+    res.power (_complex, p1);
+    var nc = new GConstant.internal_complex (res);
+    return nc as Constant;
+  }
   // Expression interface
   public override string to_string () {
     if (imag () != 0.0) {
diff --git a/gcalc/gcalc-gpow.vala b/gcalc/gcalc-gpow.vala
new file mode 100644
index 00000000..c21cb561
--- /dev/null
+++ b/gcalc/gcalc-gpow.vala
@@ -0,0 +1,26 @@
+/* gcalc-gpow.vala
+ *
+ * Copyright (C) 2019  Daniel Espinosa <esodan gmail com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *      Daniel Espinosa <esodan gmail com>
+ */
+public class GCalc.GPow : GExpression, Operator, Pow {
+  public override string to_string () {
+    return "^";
+  }
+}
+
diff --git a/gcalc/gcalc-parser.vala b/gcalc/gcalc-parser.vala
index 55f0050f..7e4e167e 100644
--- a/gcalc/gcalc-parser.vala
+++ b/gcalc/gcalc-parser.vala
@@ -284,14 +284,18 @@ public class GCalc.Parser : Object {
           var par = current;
           while (par != null) {
             if (par is Group) {
-              foundp = true;
-              ((Group) par).closed = true;
-              break;
+              if (!((Group) par).closed) {
+                foundp = true;
+                ((Group) par).closed = true;
+                break;
+              }
             }
             if (par is Function) {
-              foundp = true;
-              ((Function) par).closed = true;
-              break;
+              if (!((Function) par).closed) {
+                foundp = true;
+                ((Function) par).closed = true;
+                break;
+              }
             }
             par = par.parent;
           }
@@ -301,6 +305,14 @@ public class GCalc.Parser : Object {
             top_parent = current_parent.parent;
           }
           break;
+        case Vala.TokenType.CARRET:
+          var op = new GPow ();
+          if (current == null) {
+            throw new ParserError.INVALID_TOKEN_ERROR ("Found an unexpected expression trying power 
expression");
+          } else {
+            process_term_operator (op, eq);
+          }
+          break;
         // braces
         case Vala.TokenType.CLOSE_BRACE:
         case Vala.TokenType.CLOSE_BRACKET:
@@ -338,8 +350,6 @@ public class GCalc.Parser : Object {
         case Vala.TokenType.OP_OR:
         case Vala.TokenType.OP_PTR:
         case Vala.TokenType.OP_SHIFT_LEFT:
-        // Carret?
-        case Vala.TokenType.CARRET:
         // templates and regex
         case Vala.TokenType.CLOSE_REGEX_LITERAL:
         case Vala.TokenType.CLOSE_TEMPLATE:
diff --git a/gcalc/gcalc-pow.vala b/gcalc/gcalc-pow.vala
new file mode 100644
index 00000000..39e2d84b
--- /dev/null
+++ b/gcalc/gcalc-pow.vala
@@ -0,0 +1,22 @@
+/* gcalc-pow.vala
+ *
+ * Copyright (C) 2019  Daniel Espinosa <esodan gmail com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *      Daniel Espinosa <esodan gmail com>
+ */
+public interface GCalc.Pow : Object, Expression, Operator {}
+
diff --git a/gcalc/gcalc-term.vala b/gcalc/gcalc-term.vala
index 6cc3e136..ba2554d8 100644
--- a/gcalc/gcalc-term.vala
+++ b/gcalc/gcalc-term.vala
@@ -99,6 +99,9 @@ public interface GCalc.Term : Object, Expression {
     if (op is Division) {
       res = (c1 as Constant).divide (c2 as Constant);
     }
+    if (op is Pow) {
+      res = (c1 as Constant).pow (c2 as Constant);
+    }
     if (res == null) {
       throw new TermError.INVALID_OPERATOR ("Unsupported operator in term's expression");
     }
diff --git a/gcalc/meson.build b/gcalc/meson.build
index e9d48f3f..f94054be 100644
--- a/gcalc/meson.build
+++ b/gcalc/meson.build
@@ -74,6 +74,7 @@ sources = files([
        'gcalc-gmultiply.vala',
        'gcalc-gplus.vala',
        'gcalc-gpolynomial.vala',
+       'gcalc-gpow.vala',
        'gcalc-gresult.vala',
        'gcalc-group.vala',
        'gcalc-ggroup.vala',
@@ -88,6 +89,7 @@ sources = files([
        'gcalc-parser.vala',
        'gcalc-plus.vala',
        'gcalc-polynomial.vala',
+       'gcalc-pow.vala',
        'gcalc-result.vala',
        'gcalc-solver.vala',
        'gcalc-term.vala',
diff --git a/tests/gcalc-parsing.vala b/tests/gcalc-parsing.vala
index 1631f2d2..b9b90d00 100644
--- a/tests/gcalc-parsing.vala
+++ b/tests/gcalc-parsing.vala
@@ -757,6 +757,61 @@ class Tests {
         warning ("Error: %s", error.message);
       }
     });
+    Test.add_func ("/gcalc/parser/pow/unique",
+    ()=>{
+      try {
+        var parser = new Parser ();
+        var eqman = new GMathEquationManager ();
+        parser.parse ("3^3", eqman);
+        assert (eqman.equations.get_n_items () == 1);
+        var eq = eqman.equations.get_item (0) as MathEquation;
+        assert (eq != null);
+        assert (eq.expressions.get_n_items () == 1);
+        var p = eq.expressions.get_item (0) as Polynomial;
+        assert (p != null);
+        assert (p.expressions.get_n_items () == 1);
+        var t = p.expressions.get_item (0) as Term;
+        assert (t != null);
+        assert (t.expressions.get_n_items () == 3);
+        var c1 = t.expressions.get_item (0) as Constant;
+        assert (c1 != null);
+        var pw = t.expressions.get_item (1) as Pow;
+        assert (pw != null);
+        var c2 = t.expressions.get_item (2) as Constant;
+        assert (c2 != null);
+      } catch (GLib.Error error) {
+        warning ("Error: %s", error.message);
+      }
+    });
+    Test.add_func ("/gcalc/parser/pow/polynomial",
+    ()=>{
+      try {
+        var parser = new Parser ();
+        var eqman = new GMathEquationManager ();
+        parser.parse ("3^(3+5*3)", eqman);
+        assert (eqman.equations.get_n_items () == 1);
+        var eq = eqman.equations.get_item (0) as MathEquation;
+        assert (eq != null);
+        assert (eq.expressions.get_n_items () == 1);
+        var p = eq.expressions.get_item (0) as Polynomial;
+        assert (p != null);
+        assert (p.expressions.get_n_items () == 1);
+        var t = p.expressions.get_item (0) as Term;
+        assert (t != null);
+        assert (t.expressions.get_n_items () == 3);
+        var c1 = t.expressions.get_item (0) as Constant;
+        assert (c1 != null);
+        var pw = t.expressions.get_item (1) as Pow;
+        assert (pw != null);
+        var g = t.expressions.get_item (2) as Group;
+        assert (g != null);
+        assert (g.expressions.get_n_items () == 1);
+        var p1 = g.expressions.get_item (0) as Polynomial;
+        assert (p1 != null);
+      } catch (GLib.Error error) {
+        warning ("Error: %s", error.message);
+      }
+    });
     return Test.run ();
   }
 }
diff --git a/tests/gcalc-solving-basic.vala b/tests/gcalc-solving-basic.vala
index f067e0e9..3116dee1 100644
--- a/tests/gcalc-solving-basic.vala
+++ b/tests/gcalc-solving-basic.vala
@@ -950,6 +950,86 @@ class Tests {
         warning ("Error: %s", e.message);
       }
     });
+    Test.add_func ("/gcalc/solve/pow",
+    ()=>{
+      try {
+        var parser = new Parser ();
+        var eqman = new GMathEquationManager ();
+        parser.parse ("3^3", eqman);
+        assert (eqman.equations.get_n_items () == 1);
+        var eq = eqman.equations.get_item (0) as MathEquation;
+        assert (eq != null);
+        message ("Equation: %s", eq.to_string ());
+        var e = eq.expressions.get_item (0) as Polynomial;
+        assert (e != null);
+        var res = e.evaluate () as Constant;
+        assert (res != null);
+        message ("Constant Result: %s", res.to_string ());
+        assert (res.real () == 27.0);
+      } catch (GLib.Error e) {
+        warning ("Error: %s", e.message);
+      }
+    });
+    Test.add_func ("/gcalc/solve/pow/polynomial/constants",
+    ()=>{
+      try {
+        var parser = new Parser ();
+        var eqman = new GMathEquationManager ();
+        parser.parse ("2^(3+5)", eqman);
+        assert (eqman.equations.get_n_items () == 1);
+        var eq = eqman.equations.get_item (0) as MathEquation;
+        assert (eq != null);
+        message ("Equation: %s", eq.to_string ());
+        var e = eq.expressions.get_item (0) as Polynomial;
+        assert (e != null);
+        var res = e.evaluate () as Constant;
+        assert (res != null);
+        message ("Constant Result: %s", res.to_string ());
+        assert (res.real () == 256.0);
+      } catch (GLib.Error e) {
+        warning ("Error: %s", e.message);
+      }
+    });
+    Test.add_func ("/gcalc/solve/pow/polynomial/function",
+    ()=>{
+      try {
+        var parser = new Parser ();
+        var eqman = new GMathEquationManager ();
+        parser.parse ("2^(3+5*cos(0))", eqman);
+        assert (eqman.equations.get_n_items () == 1);
+        var eq = eqman.equations.get_item (0) as MathEquation;
+        assert (eq != null);
+        message ("Equation: %s", eq.to_string ());
+        var e = eq.expressions.get_item (0) as Polynomial;
+        assert (e != null);
+        var res = e.evaluate () as Constant;
+        assert (res != null);
+        message ("Constant Result: %s", res.to_string ());
+        assert (res.real () == 256.0);
+      } catch (GLib.Error e) {
+        warning ("Error: %s", e.message);
+      }
+    });
+    Test.add_func ("/gcalc/solve/pow/polynomial/terms",
+    ()=>{
+      try {
+        var parser = new Parser ();
+        var eqman = new GMathEquationManager ();
+        parser.parse ("2^(3+5*cos(0))+5*3-3^(sin(0)+5/cos(0))", eqman);
+        assert (eqman.equations.get_n_items () == 1);
+        var eq = eqman.equations.get_item (0) as MathEquation;
+        assert (eq != null);
+        message ("Equation: %s", eq.to_string ());
+        var e = eq.expressions.get_item (0) as Polynomial;
+        assert (e != null);
+        var res = e.evaluate () as Constant;
+        assert (res != null);
+        message ("Constant Result: %s", res.to_string ());
+        assert (res.real () == 28.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]