[gnome-calculator] GCalc; New calculator, vector and unit converted objects



commit a8d3fe02016832c588888767d9dc805820397dd6
Author: Daniel Espinosa <esodan gmail com>
Date:   Thu Apr 14 20:31:04 2022 -0500

    GCalc; New calculator, vector and unit converted objects

 gcalc/gcalc-calculator.vala           | 239 ++++++++++++++++++++++++++++++++++
 gcalc/gcalc-constant.vala             |  35 ++++-
 gcalc/gcalc-math-constant-vector.vala |  42 ++++++
 gcalc/gcalc-units.vala                |  71 ++++++++++
 gcalc/meson.build                     |   3 +
 lib/number.vala                       |   2 +-
 meson.build                           |   2 +-
 vapi/mpfr.vapi                        |   7 +
 8 files changed, 397 insertions(+), 4 deletions(-)
---
diff --git a/gcalc/gcalc-calculator.vala b/gcalc/gcalc-calculator.vala
new file mode 100644
index 00000000..f116f103
--- /dev/null
+++ b/gcalc/gcalc-calculator.vala
@@ -0,0 +1,239 @@
+/* gcalc-calculator.vala
+ *
+ * Copyright (C) 2022  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>
+ */
+/**
+ * A constant calculator for different operations.
+ */
+public class GCalc.Calculator : GLib.Object {
+    public static MathConstant add (MathConstant c1, MathConstant c2) {
+        var c = new Constant.assign (c1);
+        return c.add (c2);
+    }
+    /**
+     * Substract C2 to C1 operation (c1 - c2)
+     */
+    public static MathConstant subtract (MathConstant c1, MathConstant c2) {
+        var c = new Constant.assign (c1);
+        return c.subtract (c2);
+    }
+    public static MathConstant multiply (MathConstant c1, MathConstant c2) {
+        var c = new Constant.assign (c1);
+        return c.multiply (c2);
+    }
+    /**
+     * Divide c1/c2
+     */
+    public static MathConstant divide (MathConstant c1, MathConstant c2) {
+        var c = new Constant.assign (c1);
+        c.divide (c2);
+        return c;
+    }
+    /**
+     * Calculates the negative value of c
+     */
+    public static MathConstant neg (MathConstant c) {
+        var rc = new Constant.assign (c);
+        return rc.neg ();
+    }
+    /**
+     * Calculates c raised to p
+     */
+    public static MathConstant pow (MathConstant c, MathConstant p) {
+        var rc = new Constant.assign (c);
+        return rc.pow (p);
+    }
+    /**
+     * Calculates square root of c
+     */
+    public static MathConstant sqrt (MathConstant c) {
+        var rc = new Constant.assign (c);
+        rc.get_complex ().get_real ().val.sqrt (rc.get_complex ().get_real ().val);
+        return rc;
+    }
+    /**
+     * Creates a constant with the value of constant PI
+     */
+    public static MathConstant pi () {
+        var rc = new Constant ();
+        rc.get_complex ().get_real ().val.const_pi ();
+        return rc;
+    }
+    /**
+     * Creates a constant with the value of constant logarithm of 2
+     */
+    public static MathConstant log2 () {
+        var rc = new Constant ();
+        rc.get_complex ().get_real ().val.const_log2 ();
+        return rc;
+    }
+    /**
+     * Creates a constant with the value of constant EULER
+     */
+    public static MathConstant euler () {
+        var rc = new Constant ();
+        rc.get_complex ().get_real ().val.const_euler ();
+        return rc;
+    }
+    /**
+     * Creates a constant with the value of constant CATALAN
+     */
+    public static MathConstant catalan () {
+        var rc = new Constant ();
+        rc.get_complex ().get_real ().val.const_catalan ();
+        return rc;
+    }
+    /**
+     * Operator c1 = c2 (equal)
+     */
+    public static bool eq (MathConstant c1, MathConstant c2) {
+        if (!(c1 is Constant) || !(c2 is Constant)) {
+            return false;
+        }
+
+        return ((Constant) c1).get_complex ().cmp (((Constant) c2).get_complex ()) == 0 ? true : false;
+    }
+    /**
+     * Operator c1 > c2
+     */
+    public static bool gt (MathConstant c1, MathConstant c2) {
+        if (!(c1 is Constant) || !(c2 is Constant)) {
+            return false;
+        }
+
+        return ((Constant) c1).get_complex ().cmp (((Constant) c2).get_complex ()) > 0 ? true : false;
+    }
+    /**
+     * Operator c1 < c2
+     */
+    public static bool lt (MathConstant c1, MathConstant c2) {
+        if (!(c1 is Constant) || !(c2 is Constant)) {
+            return false;
+        }
+
+        return ((Constant) c1).get_complex ().cmp (((Constant) c2).get_complex ()) < 0 ? true : false;
+    }
+    /**
+     * Calculates the cosine of c1 angle at the given units
+     */
+    public static MathConstant cos (MathConstant c1, GCalc.AngleUnit units = GCalc.AngleUnit.RADIANS) {
+        var a = new Constant.assign (c1);
+        if (units != GCalc.AngleUnit.RADIANS) {
+            a = (Constant) UnitConverter.angle (c1, units, GCalc.AngleUnit.RADIANS);
+        }
+
+        var rc = new Constant ();
+        rc.get_complex ().get_real ().val.cos (a.get_complex ().get_real ().val);
+        return rc;
+    }
+    /**
+     * Calculates the sine of c1 angle at the given units
+     */
+    public static MathConstant sin (MathConstant c1, GCalc.AngleUnit units = GCalc.AngleUnit.RADIANS) {
+        var a = new Constant.assign (c1);
+        if (units != GCalc.AngleUnit.RADIANS) {
+            a = (Constant) UnitConverter.angle (c1, units, GCalc.AngleUnit.RADIANS);
+        }
+
+        var rc = new Constant ();
+        rc.get_complex ().get_real ().val.sin (a.get_complex ().get_real ().val);
+        return rc;
+    }
+    /**
+     * Calculates the tangent of c1 angle at the given units
+     */
+    public static MathConstant tan (MathConstant c1, GCalc.AngleUnit units = GCalc.AngleUnit.RADIANS) {
+        var a = new Constant.assign (c1);
+        if (units != GCalc.AngleUnit.RADIANS) {
+            a = (Constant) UnitConverter.angle (c1, units, GCalc.AngleUnit.RADIANS);
+        }
+
+        var rc = new Constant ();
+        rc.get_complex ().get_real ().val.tan (a.get_complex ().get_real ().val);
+        return rc;
+    }
+    /**
+     * Calculates the arc, in the given units, represented by the cosine of c1
+     */
+    public static MathConstant acos (MathConstant c1, GCalc.AngleUnit units = GCalc.AngleUnit.RADIANS) {
+        if (!(c1 is Constant)) {
+            return new Constant  ();
+        }
+
+        var rc = new Constant ();
+        rc.get_complex ().get_real ().val.acos (((Constant) c1).get_complex ().get_real ().val);
+
+        if (units != GCalc.AngleUnit.RADIANS) {
+            return (Constant) UnitConverter.angle (rc, GCalc.AngleUnit.RADIANS, units);
+        }
+
+        return rc;
+    }
+    /**
+     * Calculates the arc, in the given units, represented by the sine of c1
+     */
+    public static MathConstant asin (MathConstant c1, GCalc.AngleUnit units = GCalc.AngleUnit.RADIANS) {
+        if (!(c1 is Constant)) {
+            return new Constant  ();
+        }
+
+        var rc = new Constant ();
+        rc.get_complex ().get_real ().val.acos (((Constant) c1).get_complex ().get_real ().val);
+
+        if (units != GCalc.AngleUnit.RADIANS) {
+            return (Constant) UnitConverter.angle (rc, GCalc.AngleUnit.RADIANS, units);
+        }
+
+        return rc;
+    }
+    /**
+     * Calculates the arc, with the given units, represented by the tangent of c1
+     */
+    public static MathConstant atan (MathConstant c1, GCalc.AngleUnit units = GCalc.AngleUnit.RADIANS) {
+        if (!(c1 is Constant)) {
+            return new Constant  ();
+        }
+
+        var rc = new Constant ();
+        rc.get_complex ().get_real ().val.atan (((Constant) c1).get_complex ().get_real ().val);
+
+        if (units != GCalc.AngleUnit.RADIANS) {
+            return (Constant) UnitConverter.angle (rc, GCalc.AngleUnit.RADIANS, units);
+        }
+
+        return rc;
+    }
+    /**
+     * Calculates the logarithm base 10 of given c1
+     */
+    public static MathConstant log10 (MathConstant c1) {
+        var rc = new Constant ();
+        rc.get_complex ().get_real ().val.log10 (((Constant) c1).get_complex ().get_real ().val);
+        return rc;
+    }
+    /**
+     * Calculates the the exponential of iven c1
+     */
+    public static MathConstant exp (MathConstant c1) {
+        var rc = new Constant ();
+        rc.get_complex ().get_real ().val.exp (((Constant) c1).get_complex ().get_real ().val);
+        return rc;
+    }
+}
+
diff --git a/gcalc/gcalc-constant.vala b/gcalc/gcalc-constant.vala
index 24ee2561..7bf8872e 100644
--- a/gcalc/gcalc-constant.vala
+++ b/gcalc/gcalc-constant.vala
@@ -24,14 +24,15 @@
 public class GCalc.Constant : Expression,
                               MathConstant,
                               MathConstantNumber,
-                              MathConstantComplex
+                              MathConstantComplex,
+                              MathConstantVector
 {
   private MPC.Complex _complex = MPC.Complex (1000);
 
   internal unowned MPC.Complex get_complex () { return _complex; }
 
   construct {
-    _complex.set_double (0.0);
+    _complex.set_double (0.0, 0.0);
   }
   internal Constant.internal_complex (MPC.Complex complex) {
     _complex.set (complex);
@@ -49,6 +50,12 @@ public class GCalc.Constant : Expression,
     _complex.set_double (real, imag);
   }
 
+  public Constant.assign (MathConstant c) {
+    if (!(c is Constant)) {
+        return;
+    }
+    _complex.set (((Constant) c).get_complex ());
+  }
   // MathConstantComplex Interface
   internal double real () {
     return _complex.get_real_double ();
@@ -124,6 +131,30 @@ public class GCalc.Constant : Expression,
     return new Constant.internal_complex (res);
   }
 
+  internal MathConstant mag () {
+    var x = this.x ();
+    var y = this.y ();
+    x = x.pow (new Constant.@double (2.0));
+    y = y.pow (new Constant.@double (2.0));
+    var a = x.add (y);
+    return Calculator.sqrt (a);
+  }
+  internal MathConstant ang () {
+    var x = this.x ();
+    var y = this.y ();
+    return Calculator.atan (y.divide (x));
+  }
+  internal MathConstant x () {
+    var rc = new Constant ();
+    rc.get_complex ().get_real ().val.set (_complex.get_real ().val);
+    return rc;
+  }
+  internal MathConstant y () {
+    var rc = new Constant ();
+    rc.get_complex ().get_real ().val.set (_complex.get_real ().val);
+    return rc;
+  }
+
   // Expression interface
   internal override string to_string () {
     string s = "";
diff --git a/gcalc/gcalc-math-constant-vector.vala b/gcalc/gcalc-math-constant-vector.vala
new file mode 100644
index 00000000..ce50094d
--- /dev/null
+++ b/gcalc/gcalc-math-constant-vector.vala
@@ -0,0 +1,42 @@
+/* gcalc-math-constant-vector.vala
+ *
+ * Copyright (C) 2022  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>
+ */
+/**
+ * A constant as a complex number with real and imaginary parts
+ */
+public interface GCalc.MathConstantVector : Object, MathExpression, MathConstant {
+  /**
+   * Vector's magnitud
+   */
+  public abstract MathConstant mag ();
+  /**
+   * Vector's angle in radians
+   */
+  public abstract MathConstant ang ();
+  /**
+   * Magnitud on x axis
+   */
+  public abstract MathConstant x ();
+  /**
+   * Magnitud on y axis
+   */
+  public abstract MathConstant y ();
+}
+
diff --git a/gcalc/gcalc-units.vala b/gcalc/gcalc-units.vala
new file mode 100644
index 00000000..461118ed
--- /dev/null
+++ b/gcalc/gcalc-units.vala
@@ -0,0 +1,71 @@
+/* gcalc-units.vala
+ *
+ * Copyright (C) 2022  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 enum GCalc.AngleUnit
+{
+    RADIANS,
+    DEGREES,
+    GRADIANS
+}
+
+public class GCalc.UnitConverter : GLib.Object {
+    public static MathConstant angle (MathConstant c, AngleUnit ori, AngleUnit dst) {
+        Constant rc = new Constant.assign (c);
+        if (ori == dst) {
+            return rc;
+        }
+
+        var pi = Calculator.pi ();
+        if (Calculator.gt (rc, pi.multiply (new Constant.@double (2.0)))) {
+            var t = rc.divide (pi);
+            rc = (Constant) rc.subtract (pi.multiply (t));
+        }
+
+
+        if (ori == AngleUnit.DEGREES && dst == AngleUnit.RADIANS) {
+            var d = new Constant.@double (180.0);
+            var g = pi.divide (d);
+            return rc.multiply (g);
+        }
+
+        if (ori == AngleUnit.GRADIANS && dst == AngleUnit.RADIANS) {
+            var d = new Constant.@double (400.0);
+            var grd = pi.divide (d);
+            return rc.multiply (grd);
+        }
+
+        if (ori == AngleUnit.DEGREES && dst == AngleUnit.GRADIANS) {
+            var d = new Constant.@double (9.0);
+            var g = new Constant.@double (10.0);
+            var grd = g.divide (d);
+            return rc.multiply (grd);
+        }
+
+        if (ori == AngleUnit.GRADIANS && dst == AngleUnit.DEGREES) {
+            var d = new Constant.@double (9.0);
+            var g = new Constant.@double (10.0);
+            var dg = d.divide (g);
+            return rc.multiply (dg);
+        }
+
+        return rc;
+    }
+}
diff --git a/gcalc/meson.build b/gcalc/meson.build
index a0ea2692..2e3b15c9 100644
--- a/gcalc/meson.build
+++ b/gcalc/meson.build
@@ -40,6 +40,7 @@ configure_file(output : 'config.h',
 
 gcalc_sources = files([
        'gcalc-assign.vala',
+       'gcalc-calculator.vala',
        'gcalc-constant.vala',
        'gcalc-division.vala',
        'gcalc-equation.vala',
@@ -71,6 +72,7 @@ gcalc_sources = files([
        'gcalc-math-constant.vala',
        'gcalc-math-constant-complex.vala',
        'gcalc-math-constant-number.vala',
+       'gcalc-math-constant-vector.vala',
        'gcalc-math-division.vala',
        'gcalc-math-equation.vala',
        'gcalc-math-equation-manager.vala',
@@ -98,6 +100,7 @@ gcalc_sources = files([
        'gcalc-result.vala',
        'gcalc-solver.vala',
        'gcalc-term.vala',
+       'gcalc-units.vala',
        'gcalc-variable.vala',
 ])
 
diff --git a/lib/number.vala b/lib/number.vala
index c1d5c741..b32272e3 100644
--- a/lib/number.vala
+++ b/lib/number.vala
@@ -38,7 +38,7 @@ public enum AngleUnit
 }
 
 /* Object for a high precision floating point number representation */
-public class Number : Object
+public class Number : GLib.Object
 {
     /* real and imaginary part of a Number */
     private Complex num = Complex (precision);
diff --git a/meson.build b/meson.build
index 9062dc63..cecc19d2 100644
--- a/meson.build
+++ b/meson.build
@@ -1,6 +1,6 @@
 project('gnome-calculator', ['c', 'vala'],
   version: '42.0',
-  meson_version: '>= 0.57.0',
+  meson_version: '>= 0.56.0',
   license: 'GPLv3+',
 )
 
diff --git a/vapi/mpfr.vapi b/vapi/mpfr.vapi
index 52b80441..8d01ea75 100644
--- a/vapi/mpfr.vapi
+++ b/vapi/mpfr.vapi
@@ -67,6 +67,12 @@ namespace MPFR {
         public double get_double (Round rnd = Round.NEAREST);
 
         public int const_pi (Round rnd = Round.NEAREST);
+
+        public int const_log2 (Round rnd = Round.NEAREST);
+
+        public int const_euler (Round rnd = Round.NEAREST);
+
+        public int const_catalan (Round rnd = Round.NEAREST);
         
         public int const_tau (Round rnd = Round.NEAREST) {
             int i = const_pi (rnd);
@@ -118,6 +124,7 @@ namespace MPFR {
         public int ceil (Real op);
         public int trunc (Real op);
         public int round (Real op);
+        public int log10 (Real op, Round rnd = Round.NEAREST);
         [CCode (cname="mpfr_integer_p")]
         public int is_integer ();
         public int gamma (Real op, Round rnd = Round.NEAREST);


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