[gnome-calculator/60-split-out-a-backend-library] gcalc: implemented function sqrt()



commit cb6e4d694ab985cdd2c947e74120206ae16127ee
Author: Daniel Espinosa Ortiz <esodan gmail com>
Date:   Fri Jan 4 15:21:45 2019 -0600

    gcalc: implemented function sqrt()

 gcalc/gcalc-function-sqrt.vala          | 53 +++++++++++++++++++++++++++++++++
 gcalc/gcalc-function.vala               | 16 ++++++++++
 gcalc/gcalc-gexpression.vala            |  2 +-
 gcalc/gcalc-gfunction.vala              | 16 ++++++++--
 gcalc/gcalc-gmath-equation-manager.vala |  5 ++++
 gcalc/gcalc-parser.vala                 |  9 +-----
 gcalc/meson.build                       |  1 +
 tests/gcalc-solving-basic.vala          | 14 +++++++++
 8 files changed, 105 insertions(+), 11 deletions(-)
---
diff --git a/gcalc/gcalc-function-sqrt.vala b/gcalc/gcalc-function-sqrt.vala
new file mode 100644
index 00000000..fa337023
--- /dev/null
+++ b/gcalc/gcalc-function-sqrt.vala
@@ -0,0 +1,53 @@
+/* gcalc-gfunction.vala
+ *
+ * Copyright (C) 2018  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.GFunctionSqrt : GFunction {
+  public GFunctionSqrt () {
+    base ("sqrt", 1);
+    param_types.add (new GConstant ());
+  }
+
+  public override Expression call () throws GLib.Error
+  {
+    verify_params ();
+    GConstant c = null;
+    var exp = parameters.get_item (0) as Expression;
+    if (exp == null) {
+      throw new FunctionError.INVOCATION_ERROR ("Invalid parameter type. Expected %s", 
typeof(Expression).name ());
+    }
+    var ev = exp.solve ();
+    if (ev is ErrorResult) {
+       throw new FunctionError.INVOCATION_ERROR ("Invalid expression: %s", ((ErrorResult) ev).to_string ());
+    }
+    if (ev is Result) {
+      c = ((Result) ev).expression as GConstant;
+    }
+    if (c == null) {
+       throw new FunctionError.INVOCATION_ERROR ("Invalid expression in result");
+    }
+    var p1 = MPC.Complex (1000);
+    p1.set (c.get_complex ());
+    var res = MPC.Complex (1000);
+    res.sqrt (p1);
+    var nc = new GConstant.internal_complex (res);
+    return nc as Expression;
+  }
+}
+
diff --git a/gcalc/gcalc-function.vala b/gcalc/gcalc-function.vala
index f63e359d..4ca01b92 100644
--- a/gcalc/gcalc-function.vala
+++ b/gcalc/gcalc-function.vala
@@ -19,6 +19,22 @@
  *      Daniel Espinosa <esodan gmail com>
  */
 public interface GCalc.Function : Object, Expression {
+  public abstract ExpressionContainer parameters { get; }
+  public abstract ExpressionContainer param_types { get; }
   public abstract string name { get; construct set; }
+  public abstract uint n_params { get; construct set; }
+  public abstract Expression call () throws GLib.Error;
+  public virtual bool verify_params () throws GLib.Error {
+    if (parameters.get_n_items () != n_params) {
+      throw new FunctionError.INVALID_PARAMETERS_ERROR ("Invalid number of parameters. Required %u, 
provided: %u",
+                                                  n_params, parameters.get_n_items ());
+    }
+    return true;
+  }
+}
+
+public errordomain GCalc.FunctionError {
+  INVALID_PARAMETERS_ERROR,
+  INVOCATION_ERROR
 }
 
diff --git a/gcalc/gcalc-gexpression.vala b/gcalc/gcalc-gexpression.vala
index 5ca735c6..10685a8a 100644
--- a/gcalc/gcalc-gexpression.vala
+++ b/gcalc/gcalc-gexpression.vala
@@ -35,7 +35,7 @@ public class GCalc.GExpression : Object, Expression {
   }
   public new virtual Result solve () {
     var e = new GErrorResult ("Invalid expression");
-    return new GResult.with_error (this, e as ErrorResult);
+    return new GResult.with_error (new GErrorExpression (), e as ErrorResult);
   }
 }
 
diff --git a/gcalc/gcalc-gfunction.vala b/gcalc/gcalc-gfunction.vala
index ab17b69f..2cda8938 100644
--- a/gcalc/gcalc-gfunction.vala
+++ b/gcalc/gcalc-gfunction.vala
@@ -19,15 +19,27 @@
  *      Daniel Espinosa <esodan gmail com>
  */
 public class GCalc.GFunction : GExpression, Function {
+  ExpressionContainer _parameters = new ExpressionContainer ();
+  ExpressionContainer _param_types = new ExpressionContainer ();
+
+  public ExpressionContainer parameters { get { return _parameters; } }
+  public ExpressionContainer param_types { get { return _param_types; } }
+  public uint n_params { get; construct set; }
   public string name { get; construct set; }
+
   construct {
     name = "NoName";
   }
-  public GFunction (string name) {
+  public GFunction (string name, int nparams) {
     this.name = name;
+    n_params = nparams;
   }
   public override string to_string () {
-    return name + " ()";
+    return name + "()";
+  }
+
+  public new virtual Expression call () throws GLib.Error {
+    return new GErrorExpression ();
   }
 }
 
diff --git a/gcalc/gcalc-gmath-equation-manager.vala b/gcalc/gcalc-gmath-equation-manager.vala
index 104aaea7..8d1007fb 100644
--- a/gcalc/gcalc-gmath-equation-manager.vala
+++ b/gcalc/gcalc-gmath-equation-manager.vala
@@ -25,5 +25,10 @@ public class GCalc.GMathEquationManager : Object, MathEquationManager {
   public ExpressionContainer equations { get { return _equations; } }
   public ExpressionContainer functions { get { return _functions; } }
   public ExpressionContainer variables { get { return _variables; } }
+
+  construct {
+    // Initialize default Functions
+    functions.add (new GFunctionSqrt ());
+  }
 }
 
diff --git a/gcalc/gcalc-parser.vala b/gcalc/gcalc-parser.vala
index 1033dc16..89c76d4f 100644
--- a/gcalc/gcalc-parser.vala
+++ b/gcalc/gcalc-parser.vala
@@ -127,14 +127,13 @@ public class GCalc.Parser : Object {
         case Vala.TokenType.WHILE:
         case Vala.TokenType.YIELD:
         case Vala.TokenType.IDENTIFIER:
-          message ("Found an identifier");
           var sfunc = eqman.functions.find_named (n);
           if (sfunc != null) {
             current = sfunc;
             expected.clear ();
             expected.add(Vala.TokenType.OPEN_PARENS);
           } else if (n.down () == "def" && current == null) {
-            var f = new GFunction (n) as Expression;
+            var f = new GFunction (n, 1) as Expression; // FIXME: Requires more work to identify parameters
             eqman.functions.add (f);
             current = f;
             expected.clear ();
@@ -142,10 +141,8 @@ public class GCalc.Parser : Object {
           } else if (n.down () == "def" && current is Function) {
             throw new ParserError.INVALID_TOKEN_ERROR ("Found an unexpected function definition expression");
           } else {
-            message ("Searching variable: %s", n);
             var v = new GVariable (n) as Expression;
             if (eqman.variables.find_named (n) == null) {
-              message ("Adding new variable named: '%s'", (v as Variable).name);
               eqman.variables.add (v);
             }
             if (current == null) {
@@ -245,10 +242,6 @@ public class GCalc.Parser : Object {
             var fexp = new GPolynomial ();
             current = fexp;
             expected.clear ();
-            expected.add (Vala.TokenType.IDENTIFIER);
-            expected.add (Vala.TokenType.INTEGER_LITERAL);
-            expected.add (Vala.TokenType.REAL_LITERAL);
-            expected.add (Vala.TokenType.CLOSE_PARENS);
           } else if (current is Operator && current_parent is Term && top_parent is Polynomial) {
             var g = new GGroup ();
             current_parent.expressions.add (g);
diff --git a/gcalc/meson.build b/gcalc/meson.build
index 42101824..a97375eb 100644
--- a/gcalc/meson.build
+++ b/gcalc/meson.build
@@ -46,6 +46,7 @@ sources = files([
        'gcalc-expression.vala',
        'gcalc-expression-container.vala',
        'gcalc-function.vala',
+       'gcalc-function-sqrt.vala',
        'gcalc-error-result.vala',
        'gcalc-gexpression.vala',
        'gcalc-gassign.vala',
diff --git a/tests/gcalc-solving-basic.vala b/tests/gcalc-solving-basic.vala
index a3603861..c4eb27c6 100644
--- a/tests/gcalc-solving-basic.vala
+++ b/tests/gcalc-solving-basic.vala
@@ -466,6 +466,20 @@ class Tests {
         warning ("Error: %s", e.message);
       }
     });
+    Test.add_func ("/gcalc/solve/function/sqrt",
+    ()=>{
+      try {
+        var c1 = new GConstant.@double (9.0);
+        var fsqrt = new GFunctionSqrt ();
+        fsqrt.parameters.add (c1);
+        var c2 = fsqrt.call () as Constant;
+        assert (c2 != null);
+        message (c2.to_string ());
+        assert (c2.real () == 3.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]