[gnome-calculator] Use MPC for complex numbers
- From: Robert Roth <robertroth src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-calculator] Use MPC for complex numbers
- Date: Tue, 11 Oct 2016 07:58:07 +0000 (UTC)
commit 476df143a6c31e52fc52ef266b84d0c6ee8ce0b3
Author: Phillip Wood <phillip wood dunelm org uk>
Date: Thu Jan 14 12:24:14 2016 +0000
Use MPC for complex numbers
MPC is a library for complex numbers built on top of MPFR. Using it
fixes a number of issues with GNOME Calculators incomplete support for
complex numbers and simplifies the implementation of a number of
functions.
Thanks to Daniel Renninghoff this commit also reworks the MPFR bindings
to use vala's automatic memory management. I've added a default rounding
mode which makes the calling code cleaner.
The use of MPFR.RealRef is not ideal but there doesn't seem to be a
better way to deal with references to structs in vala.
The lvalue_allowed = false annotation is necessary to make MPC.abs() and
MPC.arg() work, otherwise vala stores the result in a copy of the target
variable.
The bindings for MPC and MPFR.RealRef are licensed GPL3+ as MPFR and
MPC are LGPL3 so it doesn't make sense to license them as GPL2+ as the
GPL2 is incompatible with LGPL3
https://bugzilla.gnome.org/show_bug.cgi?id=759439
configure.ac | 1 +
lib/Makefile.am | 5 +-
lib/mpc.vapi | 123 +++++++++
lib/mpfr-glue.vala | 28 ++
lib/mpfr.vapi | 123 ++++-----
lib/number.vala | 747 +++++++++++++++-------------------------------------
6 files changed, 432 insertions(+), 595 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index f31f829..ac8f412 100644
--- a/configure.ac
+++ b/configure.ac
@@ -28,6 +28,7 @@ AC_SUBST([GLIB_REQUIRED])
# FIXME We link to it too, so this check needs to be better....
AC_CHECK_HEADER([mpfr.h], [], [AC_MSG_ERROR([The mpfr header is missing. Please, install mpfr])])
+AC_CHECK_HEADER([mpc.h], [], [AC_MSG_ERROR([The mpc header is missing. Please, install mpc])])
PKG_CHECK_MODULES(LIBCALCULATOR, [
glib-2.0 >= $GLIB_REQUIRED
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 95634e7..6191dd6 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -7,6 +7,8 @@ AM_CPPFLAGS = \
libcalculator_la_SOURCES = \
mpfr.vapi \
+ mpfr-glue.vala \
+ mpc.vapi \
currency.vala \
equation.vala \
equation-lexer.vala \
@@ -35,7 +37,8 @@ libcalculator_la_LIBADD = \
$(LIBCALCULATOR_LIBS) \
-lgmp \
-lm \
- -lmpfr
+ -lmpfr \
+ -lmpc
EXTRA_DIST = \
libcalculator.h \
diff --git a/lib/mpc.vapi b/lib/mpc.vapi
new file mode 100644
index 0000000..d34521b
--- /dev/null
+++ b/lib/mpc.vapi
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2016 Phillip Wood <phillip wood dunelm org uk>
+ *
+ * GNOME Calculator - mpc.vapi
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Phillip Wood <phillip wood dunelm org uk>
+ */
+
+[CCode (cheader_filename="mpc.h")]
+namespace MPC {
+ [CCode (cname = "mpc_rnd_t", has_type_id = false)]
+ public enum Round {
+ [CCode (cname = "MPC_RNDNN")]
+ NEAREST,
+ [CCode (cname = "MPC_RNDZZ")]
+ ZERO,
+ [CCode (cname = "MPC_RNDUU")]
+ UP,
+ [CCode (cname = "MPC_RNDDD")]
+ DOWN
+ }
+
+ [CCode (cname="MPC_INEX_RE")]
+ public int inex_re (int inex);
+ [CCode (cname="MPC_INEX_IM")]
+ public int inex_im (int inex);
+ [CCode (cname="MPC_INEX1")]
+ public int inex1 (int inex);
+ [CCode (cname="MPC_INEX2")]
+ public int inex2 (int inex);
+
+ public int abs (MPFR.Real res, Complex op, MPFR.Round rnd = MPFR.Round.NEAREST);
+ public int arg (MPFR.Real res, Complex op, MPFR.Round rnd = MPFR.Round.NEAREST);
+
+ [CCode (cname = "__mpc_struct", cprefix = "mpc_", destroy_function = "mpc_clear", copy_function = "",
lvalue_access = false, has_type_id = false)]
+ public struct Complex {
+ [CCode (cname="mpc_init2")]
+ public Complex (MPFR.Precision prec);
+ public int @set (Complex op, Round rnd = Round.NEAREST);
+ [CCode (cname="mpc_set_ui_ui")]
+ public int set_unsigned_integer (ulong re, ulong im = 0, Round rnd = Round.NEAREST);
+ [CCode (cname="mpc_set_si_si")]
+ public int set_signed_integer (long re, long im = 0, Round rnd = Round.NEAREST);
+ private int set_fr (MPFR.Real re, Round rnd);
+ private int set_fr_fr (MPFR.Real re, MPFR.Real im, Round rnd);
+ public int set_mpreal (MPFR.Real re, MPFR.Real? im = null, Round rnd = Round.NEAREST)
+ {
+ if (im == null)
+ return set_fr (re, rnd);
+
+ return set_fr_fr (re, im, rnd);
+ }
+ [CCode (cname="mpc_set_d_d")]
+ public int set_double (double re, double im = 0, Round rnd = Round.NEAREST);
+ [CCode (cname="mpc_realref")]
+ public unowned MPFR.RealRef get_real ();
+ [CCode (cname="mpc_imagref")]
+ public unowned MPFR.RealRef get_imag ();
+ public bool is_zero () { var res = cmp_si_si (0, 0); return inex_re (res) == 0 && inex_im (res) ==
0; }
+ public bool is_equal (Complex c) { var res = cmp (c); return inex_re (res) == 0 && inex_im (res) ==
0; }
+ public int cmp (Complex op2);
+ public int cmp_si_si (long re, long im);
+ public int conj (Complex op, Round rnd = Round.NEAREST);
+ public int sqrt (Complex op, Round rnd = Round.NEAREST);
+ public int neg (Complex op, Round rnd = Round.NEAREST);
+ public int add (Complex op1, Complex op2, Round rnd = Round.NEAREST);
+ [CCode (cname="mpc_sub")]
+ public int subtract (Complex op1, Complex op2, Round rnd = Round.NEAREST);
+ [CCode (cname="mpc_mul")]
+ public int multiply (Complex op1, Complex op2, Round rnd = Round.NEAREST);
+ [CCode (cname="mpc_div")]
+ public int divide (Complex op1, Complex op2, Round rnd = Round.NEAREST);
+ [CCode (cname="mpc_pow_si")]
+ public int power_signed_integer (Complex op1, long op2, Round rnd = Round.NEAREST);
+ [CCode (cname="mpc_mul_si")]
+ public int multiply_signed_integer (Complex op1, long op2, Round rnd = Round.NEAREST);
+ [CCode (cname="mpc_mul_fr")]
+ public int multiply_mpreal (Complex op1, MPFR.Real op2, Round rnd = Round.NEAREST);
+ [CCode (cname="mpc_div_ui")]
+ public int divide_unsigned_integer (Complex op1, ulong op2, Round rnd = Round.NEAREST);
+ // Divide a uint by a complex
+ [CCode (cname="mpc_ui_div")]
+ public int unsigned_integer_divide (ulong op1, Complex op2, Round rnd = Round.NEAREST);
+ [CCode (cname="mpc_div_fr")]
+ public int divide_mpreal (Complex op1, MPFR.Real op2, Round rnd = Round.NEAREST);
+ // Divide a real by a complex
+ [CCode (cname="mpc_fr_div")]
+ public int mpreal_divide (MPFR.Real op1, Complex op2, Round rnd = Round.NEAREST);
+ [CCode (cname="mpc_pow")]
+ public int power (Complex op1, Complex op2, Round rnd = Round.NEAREST);
+ [CCode (cname="mpc_pow_si")]
+ public int power_integer (Complex op1, long op2, Round rnd = Round.NEAREST);
+ [CCode (cname="mpc_pow_fr")]
+ public int power_mpreal (Complex op1, MPFR.Real op2, Round rnd = Round.NEAREST);
+ public int exp (Complex op, Round rnd = Round.NEAREST);
+ public int log (Complex op, Round rnd = Round.NEAREST);
+ public int sin (Complex op, Round rnd = Round.NEAREST);
+ public int cos (Complex op, Round rnd = Round.NEAREST);
+ public int tan (Complex op, Round rnd = Round.NEAREST);
+ public int asin (Complex op, Round rnd = Round.NEAREST);
+ public int acos (Complex op, Round rnd = Round.NEAREST);
+ public int atan (Complex op, Round rnd = Round.NEAREST);
+ public int sinh (Complex op, Round rnd = Round.NEAREST);
+ public int cosh (Complex op, Round rnd = Round.NEAREST);
+ public int tanh (Complex op, Round rnd = Round.NEAREST);
+ public int asinh (Complex op, Round rnd = Round.NEAREST);
+ public int acosh (Complex op, Round rnd = Round.NEAREST);
+ public int atanh (Complex op, Round rnd = Round.NEAREST);
+ }
+}
diff --git a/lib/mpfr-glue.vala b/lib/mpfr-glue.vala
new file mode 100644
index 0000000..e52c0f6
--- /dev/null
+++ b/lib/mpfr-glue.vala
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2016 Phillip Wood <phillip wood dunelm org uk>
+ *
+ * GNOME Calculator - mpfr-glue.vala
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Phillip Wood <phillip wood dunelm org uk>
+ */
+
+namespace MPFR
+{
+ [Compact]
+ public class RealRef {
+ public MPFR.Real val;
+ }
+}
diff --git a/lib/mpfr.vapi b/lib/mpfr.vapi
index 5baa4de..ec48491 100644
--- a/lib/mpfr.vapi
+++ b/lib/mpfr.vapi
@@ -8,23 +8,10 @@
* license.
*/
-/* A small guide on using MPFR with gnome-calculator:
- * Using it is pretty much self-explanatory when you look at the code in
- * number.vala.
- * C syntax: mpfr_add (result, op1, op2, MPFR_RNDN);
- * Vala syntax: result.add (op1, op2, Round.NEAREST);
- *
- * The result has to be initialized with init2() before using it (same in C).
- * Since MPFR is a C library you have to do manual memory management. This means
- * that after init2()ing something, you have to clear() it at the end. Clearing
- * re_num and im_num is taken are of by the destructor of Number. Just make sure
- * to manually clear any temporary helper variables you use.
- */
-
[CCode (cheader_filename="mpfr.h")]
namespace MPFR {
[SimpleType]
- [IntegerType]
+ [IntegerType (rank = 9)]
[CCode (cname = "mpfr_prec_t", has_type_id = false)]
public struct Precision {}
@@ -46,83 +33,87 @@ namespace MPFR {
NEARESTAWAY
}
- [CCode (cname = "__mpfr_struct", cprefix = "mpfr_", has_destroy_function = false, copy_function = "",
has_type_id = false)]
- public struct MPFloat {
+ [CCode (cname = "__mpfr_struct", cprefix = "mpfr_", destroy_function = "mpfr_clear", copy_function = "",
lvalue_access = false, has_type_id = false)]
+ public struct Real {
[CCode (cname="mpfr_init2")]
- public MPFloat.init2 (Precision prec);
-
+ public Real (Precision prec);
+ public Precision get_precision ();
[CCode (cname="mpfr_set_ui")]
- public int set_unsigned_integer (ulong op, Round rnd);
+ public int set_unsigned_integer (ulong op, Round rnd = Round.NEAREST);
[CCode (cname="mpfr_set_si")]
- public int set_signed_integer (long op, Round rnd);
+ public int set_signed_integer (long op, Round rnd = Round.NEAREST);
[CCode (cname="mpfr_set_flt")]
- public int set_float (float op, Round rnd);
+ public int set_float (float op, Round rnd = Round.NEAREST);
[CCode (cname="mpfr_set_d")]
- public int set_double (double op, Round rnd);
+ public int set_double (double op, Round rnd = Round.NEAREST);
[CCode (cname="mpfr_set")]
- public int set (MPFloat op, Round rnd);
-
- public void clear ();
-
- public int add (MPFloat op1, MPFloat op2, Round rnd);
+ public int set (Real op, Round rnd = Round.NEAREST);
+ public int set_zero (Round rnd = Round.NEAREST);
+ public int add (Real op1, Real op2, Round rnd = Round.NEAREST);
[CCode (cname="mpfr_sub")]
- public int subtract (MPFloat op1, MPFloat op2, Round rnd);
+ public int subtract (Real op1, Real op2, Round rnd = Round.NEAREST);
[CCode (cname="mpfr_mul")]
- public int multiply (MPFloat op1, MPFloat op2, Round rnd);
+ public int multiply (Real op1, Real op2, Round rnd = Round.NEAREST);
[CCode (cname="mpfr_div")]
- public int divide (MPFloat op1, MPFloat op2, Round rnd);
+ public int divide (Real op1, Real op2, Round rnd = Round.NEAREST);
[CCode (cname="mpfr_get_si")]
- public long get_signed_integer (Round rnd);
+ public long get_signed_integer (Round rnd = Round.NEAREST);
[CCode (cname="mpfr_get_ui")]
- public ulong get_unsigned_integer (Round rnd);
+ public ulong get_unsigned_integer (Round rnd = Round.NEAREST);
[CCode (cname="mpfr_get_flt")]
- public float get_float (Round rnd);
+ public float get_float (Round rnd = Round.NEAREST);
[CCode (cname="mpfr_get_d")]
- public double get_double (Round rnd);
+ public double get_double (Round rnd = Round.NEAREST);
- public int const_pi (Round rnd);
+ public int const_pi (Round rnd = Round.NEAREST);
[CCode (cname="mpfr_zero_p")]
public bool is_zero ();
public int sgn ();
[CCode (cname="mpfr_equal_p")]
- public bool is_equal (MPFloat op2);
- public int cmp (MPFloat op2);
- public int sqrt (MPFloat op, Round rnd);
- public int neg (MPFloat op, Round rnd);
+ public bool is_equal (Real op2);
+ public int cmp (Real op2);
+ public int sqrt (Real op, Round rnd = Round.NEAREST);
+ public int neg (Real op, Round rnd = Round.NEAREST);
[CCode (cname="mpfr_pow_si")]
- public int power_signed_integer (MPFloat op1, long op2, Round rnd);
+ public int power_signed_integer (Real op1, long op2, Round rnd = Round.NEAREST);
[CCode (cname="mpfr_mul_si")]
- public int multiply_signed_integer (MPFloat op1, long op2, Round rnd);
+ public int multiply_signed_integer (Real op1, long op2, Round rnd = Round.NEAREST);
[CCode (cname="mpfr_div_si")]
- public int divide_signed_integer (MPFloat op1, long op2, Round rnd);
- public int floor (MPFloat op);
+ public int divide_signed_integer (Real op1, long op2, Round rnd = Round.NEAREST);
+ [CCode (cname="mpfr_si_div")]
+ public int signed_integer_divide (long op1, Real op2, Round rnd = Round.NEAREST);
+ [CCode (cname="mpfr_div_ui")]
+ public int divide_unsigned_integer (Real op1, ulong op2, Round rnd = Round.NEAREST);
+ [CCode (cname="mpfr_ui_div")]
+ public int unsigned_integer_divide (ulong op1, Real op2, Round rnd = Round.NEAREST);
+ public int floor (Real op);
[CCode (cname="mpfr_pow")]
- public int power (MPFloat op1, MPFloat op2, Round rnd);
- public int exp (MPFloat op, Round rnd);
- public int log (MPFloat op, Round rnd);
- public int sin (MPFloat op, Round rnd);
- public int cos (MPFloat op, Round rnd);
- public int tan (MPFloat op, Round rnd);
- public int asin (MPFloat op, Round rnd);
- public int acos (MPFloat op, Round rnd);
- public int atan (MPFloat op, Round rnd);
- public int sinh (MPFloat op, Round rnd);
- public int cosh (MPFloat op, Round rnd);
- public int tanh (MPFloat op, Round rnd);
- public int asinh (MPFloat op, Round rnd);
- public int acosh (MPFloat op, Round rnd);
- public int atanh (MPFloat op, Round rnd);
- public int abs (MPFloat op, Round rnd);
- public int root (MPFloat op, ulong k, Round rnd);
- public int rint (MPFloat op, Round rnd);
- public int frac (MPFloat op, Round rnd);
- public int ceil (MPFloat op);
- public int trunc (MPFloat op);
- public int round (MPFloat op);
+ public int power (Real op1, Real op2, Round rnd = Round.NEAREST);
+ public int exp (Real op, Round rnd = Round.NEAREST);
+ public int log (Real op, Round rnd = Round.NEAREST);
+ public int sin (Real op, Round rnd = Round.NEAREST);
+ public int cos (Real op, Round rnd = Round.NEAREST);
+ public int tan (Real op, Round rnd = Round.NEAREST);
+ public int asin (Real op, Round rnd = Round.NEAREST);
+ public int acos (Real op, Round rnd = Round.NEAREST);
+ public int atan (Real op, Round rnd = Round.NEAREST);
+ public int sinh (Real op, Round rnd = Round.NEAREST);
+ public int cosh (Real op, Round rnd = Round.NEAREST);
+ public int tanh (Real op, Round rnd = Round.NEAREST);
+ public int asinh (Real op, Round rnd = Round.NEAREST);
+ public int acosh (Real op, Round rnd = Round.NEAREST);
+ public int atanh (Real op, Round rnd = Round.NEAREST);
+ public int abs (Real op, Round rnd = Round.NEAREST);
+ public int root (Real op, ulong k, Round rnd = Round.NEAREST);
+ public int rint (Real op, Round rnd = Round.NEAREST);
+ public int frac (Real op, Round rnd = Round.NEAREST);
+ public int ceil (Real op);
+ public int trunc (Real op);
+ public int round (Real op);
[CCode (cname="mpfr_integer_p")]
public int is_integer ();
- public int gamma (MPFloat op, Round rnd);
+ public int gamma (Real op, Round rnd = Round.NEAREST);
}
[CCode (cname = "mpfr_underflow_p")]
diff --git a/lib/number.vala b/lib/number.vala
index bab6afc..8dc72d0 100644
--- a/lib/number.vala
+++ b/lib/number.vala
@@ -27,7 +27,7 @@
* THE MP USERS GUIDE.
*/
-using MPFR;
+using MPC;
private delegate int BitwiseFunc (int v1, int v2);
@@ -42,32 +42,21 @@ public enum AngleUnit
public class Number : Object
{
/* real and imaginary part of a Number */
- private MPFloat re_num { get; set; }
- private MPFloat im_num { get; set; }
+ private Complex num = Complex (precision);
- public static ulong precision { get; set; default = 1000; }
+ public static MPFR.Precision precision { get; set; default = 1000; }
/* Stores the error msg if an error occurs during calculation. Otherwise should be null */
public static string? error { get; set; default = null; }
- public Number.integer (int64 value)
+ public Number.integer (int64 real, int64 imag = 0)
{
- var tmp = MPFloat.init2 ((Precision) precision);
- tmp.set_signed_integer ((long)value, Round.NEAREST);
- re_num = tmp;
- var tmp2 = MPFloat.init2 ((Precision) precision);
- tmp2.set_unsigned_integer (0, Round.NEAREST);
- im_num = tmp2;
+ num.set_signed_integer ((long) real, (long) imag);
}
- public Number.unsigned_integer (uint64 x)
+ public Number.unsigned_integer (uint64 real, uint64 imag = 0)
{
- var tmp = MPFloat.init2 ((Precision) precision);
- tmp.set_unsigned_integer ((ulong)x, Round.NEAREST);
- re_num = tmp;
- var tmp2 = MPFloat.init2 ((Precision) precision);
- tmp2.set_unsigned_integer (0, Round.NEAREST);
- im_num = tmp2;
+ num.set_unsigned_integer ((ulong) real, (ulong) imag);
}
public Number.fraction (int64 numerator, int64 denominator)
@@ -81,39 +70,24 @@ public class Number : Object
Number.integer (numerator);
if (denominator != 1)
{
- var tmp = re_num;
- tmp.divide_signed_integer (re_num, (long) denominator, Round.NEAREST);
- re_num = tmp;
+ num.divide_unsigned_integer (num, (long) denominator);
}
}
- /* Helper constructor. Creates new Number from already existing MPFloat. */
- public Number.mpfloat (MPFloat value)
+ /* Helper constructor. Creates new Number from already existing MPFR.Real. */
+ public Number.mpreal (MPFR.Real real, MPFR.Real? imag = null)
{
- re_num = value;
- var tmp = MPFloat.init2 ((Precision) precision);
- tmp.set_unsigned_integer (0, Round.NEAREST);
- im_num = tmp;
+ num.set_mpreal (real, imag);
}
- public Number.double (double value)
+ public Number.double (double real, double imag = 0)
{
- var tmp = MPFloat.init2 ((Precision) precision);
- tmp.set_double (value, Round.NEAREST);
- re_num = tmp;
- var tmp2 = MPFloat.init2 ((Precision) precision);
- tmp2.set_unsigned_integer (0, Round.NEAREST);
- im_num = tmp2;
+ num.set_double (real, imag);
}
- public Number.complex (Number x, Number y)
+ public Number.complex (Number r, Number i)
{
- var tmp = MPFloat.init2 ((Precision) precision);
- tmp.@set (x.re_num, Round.NEAREST);
- re_num = tmp;
- var tmp2 = MPFloat.init2 ((Precision) precision);
- tmp2.@set (y.re_num, Round.NEAREST);
- im_num = tmp2;
+ num.set_mpreal (r.num.get_real ().val, i.num.get_real ().val);
}
public Number.polar (Number r, Number theta, AngleUnit unit = AngleUnit.RADIANS)
@@ -125,35 +99,21 @@ public class Number : Object
public Number.eulers ()
{
- var tmp = MPFloat.init2 ((Precision) precision);
- var tmp2 = MPFloat.init2 ((Precision) precision);
- tmp2.set_unsigned_integer (1, Round.NEAREST);
+ num.get_real ().val.set_unsigned_integer (1);
/* e^1, since mpfr doesn't have a function to return e */
- tmp.exp (tmp2, Round.NEAREST);
- re_num = tmp;
- var tmp3 = MPFloat.init2 ((Precision) precision);
- tmp3.set_unsigned_integer (0, Round.NEAREST);
- im_num = tmp3;
+ num.get_real ().val.exp (num.get_real ().val);
+ num.get_imag ().val.set_zero ();
}
public Number.i ()
{
- var tmp = MPFloat.init2 ((Precision) precision);
- var tmp2 = MPFloat.init2 ((Precision) precision);
- tmp.set_unsigned_integer (0, Round.NEAREST);
- tmp2.set_unsigned_integer (1, Round.NEAREST);
- re_num = tmp;
- im_num = tmp2;
+ num.set_signed_integer (0, 1);
}
public Number.pi ()
{
- var tmp = MPFloat.init2 ((Precision) precision);
- tmp.const_pi (Round.NEAREST);
- re_num = tmp;
- var tmp2 = MPFloat.init2 ((Precision) precision);
- tmp2.set_unsigned_integer (0, Round.NEAREST);
- im_num = tmp2;
+ num.get_real ().val.const_pi ();
+ num.get_imag ().val.set_zero ();
}
/* Sets z to be a uniform random number in the range [0, 1] */
@@ -162,42 +122,36 @@ public class Number : Object
Number.double (Random.next_double ());
}
- ~Number ()
- {
- re_num.clear ();
- im_num.clear ();
- }
-
public int64 to_integer ()
{
- return re_num.get_signed_integer (Round.NEAREST);
+ return num.get_real ().val.get_signed_integer ();
}
public uint64 to_unsigned_integer ()
{
- return re_num.get_unsigned_integer (Round.NEAREST);
+ return num.get_real ().val.get_unsigned_integer ();
}
public float to_float ()
{
- return re_num.get_float (Round.NEAREST);
+ return num.get_real ().val.get_float (MPFR.Round.NEAREST);
}
public double to_double ()
{
- return re_num.get_double (Round.NEAREST);
+ return num.get_real ().val.get_double (MPFR.Round.NEAREST);
}
/* Return true if the value is x == 0 */
public bool is_zero ()
{
- return re_num.is_zero () && im_num.is_zero ();
+ return num.is_zero ();
}
/* Return true if x < 0 */
public bool is_negative ()
{
- return re_num.sgn () < 0;
+ return num.get_real ().val.sgn () < 0;
}
/* Return true if x is integer */
@@ -206,7 +160,7 @@ public class Number : Object
if (is_complex ())
return false;
- return re_num.is_integer () != 0;
+ return num.get_real ().val.is_integer () != 0;
}
/* Return true if x is a positive integer */
@@ -215,7 +169,7 @@ public class Number : Object
if (is_complex ())
return false;
else
- return re_num.sgn () >= 0 && is_integer ();
+ return num.get_real ().val.sgn () >= 0 && is_integer ();
}
/* Return true if x is a natural number (an integer ≥ 0) */
@@ -224,24 +178,24 @@ public class Number : Object
if (is_complex ())
return false;
else
- return re_num.sgn () > 0 && is_integer ();
+ return num.get_real ().val.sgn () > 0 && is_integer ();
}
/* Return true if x has an imaginary component */
public bool is_complex ()
{
- return !im_num.is_zero ();
+ return !num.get_imag ().val.is_zero ();
}
/* Return error if overflow or underflow */
public static void check_flags ()
{
- if (mpfr_is_underflow () != 0)
+ if (MPFR.mpfr_is_underflow () != 0)
{
/* Translators: Error displayed when underflow error occured */
error = _("Underflow error");
}
- else if (mpfr_is_overflow () != 0)
+ else if (MPFR.mpfr_is_overflow () != 0)
{
/* Translators: Error displayed when overflow error occured */
error = _("Overflow error");
@@ -251,7 +205,7 @@ public class Number : Object
/* Return true if x == y */
public bool equals (Number y)
{
- return re_num.is_equal (y.re_num);
+ return num.is_equal (y.num);
}
/* Returns:
@@ -261,48 +215,31 @@ public class Number : Object
*/
public int compare (Number y)
{
- return re_num.cmp (y.re_num);
+ return num.get_real ().val.cmp (y.num.get_real ().val);
}
/* Sets z = sgn (x) */
public Number sgn ()
{
- var z = new Number.integer (re_num.sgn ());
+ var z = new Number.integer (num.get_real ().val.sgn ());
return z;
}
/* Sets z = −x */
public Number invert_sign ()
{
- var tmp = MPFloat.init2 ((Precision) precision);
- tmp.neg (re_num, Round.NEAREST);
- var z = new Number.mpfloat (tmp);
- var tmp_im = z.im_num;
- tmp_im.neg (im_num, Round.NEAREST);
- z.im_num = tmp_im;
+ var z = new Number ();
+ z.num.neg (num);
return z;
}
/* Sets z = |x| */
public Number abs ()
{
- if (is_complex ())
- {
- var x_real = real_component ();
- var x_im = imaginary_component ();
-
- x_real = x_real.multiply (x_real);
- x_im = x_im.multiply (x_im);
- var z = x_real.add (x_im);
- return z.sqrt ();
- }
- else
- {
- var tmp = MPFloat.init2 ((Precision) precision);
- tmp.abs (re_num, Round.NEAREST);
- var z = new Number.mpfloat (tmp);
- return z;
- }
+ var z = new Number ();
+ z.num.get_imag ().val.set_zero ();
+ MPC.abs (z.num.get_real ().val, num);
+ return z;
}
/* Sets z = Arg (x) */
@@ -314,65 +251,33 @@ public class Number : Object
error = _("Argument not defined for zero");
return new Number.integer (0);
}
+ var z = new Number ();
+ z.num.get_imag ().val.set_zero ();
+ MPC.arg (z.num.get_real ().val, num);
+ mpc_from_radians (z.num, z.num, unit);
+ // MPC returns -π for the argument of negative real numbers if
+ // their imaginary part is -0 (which it is in the numbers
+ // created by test-equation), we want +π for all real negative
+ // numbers
+ if (!is_complex () && is_negative ())
+ z.num.get_real ().val.abs (z.num.get_real ().val);
- var x_real = real_component ();
- var x_im = imaginary_component ();
- var pi = new Number.pi ();
-
- Number z;
- if (x_im.is_zero ())
- {
- if (x_real.is_negative ())
- z = pi;
- else
- return new Number.integer (0);
- }
- else if (x_real.is_zero ())
- {
- if (x_im.is_negative ())
- z = pi.divide_integer (-2);
- else
- z = pi.divide_integer (2);
- }
- else if (x_real.is_negative ())
- {
- z = x_im.divide (x_real);
- z = z.atan (AngleUnit.RADIANS);
- if (x_im.is_negative ())
- z = z.subtract (pi);
- else
- z = z.add (pi);
- }
- else
- {
- z = x_im.divide (x_real);
- z = z.atan (AngleUnit.RADIANS);
- }
-
- return z.from_radians (unit);
+ return z;
}
/* Sets z = ‾̅x */
public Number conjugate ()
{
- var tmp = MPFloat.init2 ((Precision) precision);
- tmp.neg (im_num, Round.NEAREST);
- var z = copy ();
- var tmp2 = z.im_num;
- tmp2.clear ();
- z.im_num = tmp;
+ var z = new Number ();
+ z.num.conj (num);
return z;
}
/* Sets z = Re (x) */
public Number real_component ()
{
- var z = copy ();
- var tmp = z.im_num;
- tmp.clear ();
- tmp = MPFloat.init2 ((Precision) precision);
- tmp.set_unsigned_integer (0, Round.NEAREST);
- z.im_num = tmp;
+ var z = new Number ();
+ z.num.set_mpreal (num.get_real ().val);
return z;
}
@@ -380,30 +285,25 @@ public class Number : Object
public Number imaginary_component ()
{
/* Copy imaginary component to real component */
- var z = copy ();
- var tmp = z.re_num;
- tmp.clear ();
- z.re_num = z.im_num;
- tmp = MPFloat.init2 ((Precision) precision);
- tmp.set_unsigned_integer (0, Round.NEAREST);
- z.im_num = tmp;
+ var z = new Number ();
+ z.num.set_mpreal (num.get_imag ().val);
return z;
}
public Number integer_component ()
{
- var tmp = MPFloat.init2 ((Precision) precision);
- tmp.trunc (re_num);
- var z = new Number.mpfloat (tmp);
+ var z = new Number ();
+ z.num.get_imag ().val.set_zero ();
+ z.num.get_real ().val.trunc (num.get_real ().val);
return z;
}
/* Sets z = x mod 1 */
public Number fractional_component ()
{
- var tmp = MPFloat.init2 ((Precision) precision);
- tmp.frac (re_num, Round.NEAREST);
- var z = new Number.mpfloat (tmp);
+ var z = new Number ();
+ z.num.get_imag ().val.set_zero ();
+ z.num.get_real ().val.frac (num.get_real ().val);
return z;
}
@@ -416,67 +316,45 @@ public class Number : Object
/* Sets z = ⌊x⌋ */
public Number floor ()
{
- var tmp = MPFloat.init2 ((Precision) precision);
- tmp.floor (re_num);
- var z = new Number.mpfloat (tmp);
+ var z = new Number ();
+ z.num.get_imag ().val.set_zero ();
+ z.num.get_real ().val.floor (num.get_real ().val);
return z;
}
/* Sets z = ⌈x⌉ */
public Number ceiling ()
{
- var tmp = MPFloat.init2 ((Precision) precision);
- tmp.ceil (re_num);
- var z = new Number.mpfloat (tmp);
+ var z = new Number ();
+ z.num.get_imag ().val.set_zero ();
+ z.num.get_real ().val.ceil (num.get_real ().val);
return z;
}
/* Sets z = [x] */
public Number round ()
{
- var tmp = MPFloat.init2 ((Precision) precision);
- tmp.round (re_num);
- var z = new Number.mpfloat (tmp);
+ var z = new Number ();
+ z.num.get_imag ().val.set_zero ();
+ z.num.get_real ().val.round (num.get_real ().val);
return z;
}
/* Sets z = 1 ÷ x */
public Number reciprocal ()
{
- if (is_complex ())
- {
- var real_x = real_component ();
- var im_x = imaginary_component ();
-
- /* 1/(a+bi) = (a-bi)/(a+bi)(a-bi) = (a-bi)/(a²+b²) */
- var t1 = real_x.multiply (real_x);
- var t2 = im_x.multiply (im_x);
- t1 = t1.add (t2);
- var z = t1.reciprocal_real ();
- return conjugate ().multiply (z);
- }
- else
- return reciprocal_real ();
+ var z = new Number ();
+ z.num.set_signed_integer (1);
+ z.num.mpreal_divide (z.num.get_real ().val, num);
+ return z;
}
/* Sets z = e^x */
public Number epowy ()
{
-
- /* e^0 = 1 */
- if (is_zero ())
- return new Number.integer (1);
-
- if (is_complex ())
- {
- var x_real = real_component ();
- var theta = imaginary_component ();
-
- var r = x_real.epowy_real ();
- return new Number.polar (r, theta);
- }
- else
- return epowy_real ();
+ var z = new Number ();
+ z.num.exp (num);
+ return z;
}
/* Sets z = x^y */
@@ -497,43 +375,15 @@ public class Number : Object
error = _("Zero raised to zero is undefined");
return new Number.integer (0);
}
-
- /* base or exponent are complex */
- if (is_complex () || y.is_complex ())
- {
- return pwr (y);
- }
-
- if (!y.is_integer ())
+ if (!is_complex () && !y.is_complex () && !y.is_integer ())
{
var reciprocal = y.reciprocal ();
- if (reciprocal.is_integer () && !reciprocal.is_negative())
+ if (reciprocal.is_integer ())
return root (reciprocal.to_integer ());
- else
- return pwr (y);
}
- Number t;
- Number t2;
- if (y.is_negative ())
- {
- t = reciprocal ();
- t2 = y.invert_sign ();
- }
- else
- {
- t = this;
- t2 = y;
- }
-
- var tmp = MPFloat.init2 ((Precision) precision);
- tmp.power (t.re_num, t2.re_num, Round.NEAREST);
- var z = new Number.mpfloat (tmp);
- var tmp2 = z.im_num;
- tmp2.clear ();
- tmp = MPFloat.init2 ((Precision) precision);
- tmp.@set (t.im_num, Round.NEAREST);
- z.im_num = tmp;
+ var z = new Number ();
+ z.num.power (num, y.num);
return z;
}
@@ -555,75 +405,39 @@ public class Number : Object
error = _("Zero raised to zero is undefined");
return new Number.integer (0);
}
-
- Number t;
- if (n < 0)
- {
- t = reciprocal ();
- n = -n;
- }
- else
- {
- t = this;
- }
-
- var tmp = MPFloat.init2 ((Precision) precision);
- tmp.power_signed_integer (t.re_num, (long) n, Round.NEAREST);
- var z = new Number.mpfloat (tmp);
- var tmp2 = z.im_num;
- tmp2.clear ();
- tmp = MPFloat.init2 ((Precision) precision);
- tmp.@set (t.im_num, Round.NEAREST);
- z.im_num = tmp;
+ var z = new Number ();
+ z.num.power_integer (num, (long) n);
return z;
}
- private Number pwr (Number y)
- {
- /* (-x)^y imaginary */
- /* FIXME: Make complex numbers optional */
- /*if (re_sign < 0)
- {
- mperr (_("The power of negative numbers is only defined for integer exponents"));
- return new Number.integer (0);
- }*/
-
- /* 0^y = 0, 0^-y undefined */
- if (is_zero ())
- {
- if (y.is_negative ())
- error = _("The power of zero is undefined for a negative exponent");
- return new Number.integer (0);
- }
-
- /* x^0 = 1 */
- if (y.is_zero ())
- return new Number.integer (1);
-
- return y.multiply (ln ()).epowy ();
- }
-
/* Sets z = n√x */
public Number root (int64 n)
{
- if (!is_complex () && is_negative () && n % 2 == 1)
+ uint64 p;
+ var z = new Number ();
+ if (n < 0)
{
- var z = abs ();
- z = z.root_real (n);
- z = z.invert_sign ();
- return z;
+ z.num.unsigned_integer_divide (1, num);
+ if (n == int64.MIN)
+ p = (uint64) int64.MAX + 1;
+ else
+ p = -n;
+ } else {
+ z.num.@set (num);
+ p = n;
}
- else if (is_complex () || is_negative ())
- {
- var r = abs ();
- var theta = arg ();
- r = r.root_real (n);
- theta = theta.divide_integer (n);
- return new Number.polar (r, theta);
+ if (!is_complex () && (!is_negative () || (p & 1) == 1))
+ {
+ z.num.get_real ().val.root (z.num.get_real ().val, (ulong) p);
+ z.num.get_imag().val.set_zero();
+ } else {
+ var tmp = MPFR.Real (precision);
+ tmp.set_unsigned_integer ((ulong) p);
+ tmp.unsigned_integer_divide (1, tmp);
+ z.num.power_mpreal (z.num, tmp);
}
- else
- return root_real (n);
+ return z;
}
/* Sets z = √x */
@@ -652,17 +466,15 @@ public class Number : Object
return new Number.integer (0);
}*/
- if (is_complex () || is_negative ())
- {
- /* ln (re^iθ) = e^(ln (r)+iθ) */
- var r = abs ();
- var theta = arg ();
- var z_real = r.ln_real ();
+ var z = new Number ();
+ z.num.log (num);
+ // MPC returns -π for the imaginary part of the log of
+ // negative real numbers if their imaginary part is -0 (which
+ // it is in the numbers created by test-equation), we want +π
+ if (!is_complex () && is_negative ())
+ z.num.get_imag ().val.abs (z.num.get_imag ().val);
- return new Number.complex (z_real, theta);
- }
- else
- return ln_real ();
+ return z;
}
/* Sets z = log_n x */
@@ -699,12 +511,12 @@ public class Number : Object
}
var tmp = add (new Number.integer (1));
- var tmp2 = MPFloat.init2 ((Precision) precision);
+ var tmp2 = MPFR.Real (precision);
/* Factorial(x) = Gamma(x+1) - This is the formula used to calculate Factorial.*/
- tmp2.gamma (tmp.re_num, Round.NEAREST);
+ tmp2.gamma (tmp.num.get_real ().val);
- return new Number.mpfloat (tmp2);
+ return new Number.mpreal (tmp2);
}
/* Convert to integer - if couldn't be converted then the factorial would be too big anyway */
@@ -719,80 +531,32 @@ public class Number : Object
/* Sets z = x + y */
public Number add (Number y)
{
- if (is_complex () || y.is_complex ())
- {
- Number real_z, im_z;
-
- var real_x = real_component ();
- var im_x = imaginary_component ();
- var real_y = y.real_component ();
- var im_y = y.imaginary_component ();
-
- real_z = real_x.add_real (real_y);
- im_z = im_x.add_real (im_y);
-
- return new Number.complex (real_z, im_z);
- }
- else
- return add_real (y);
- }
-
- public Number add_real (Number y)
- {
- var tmp = MPFloat.init2 ((Precision) precision);
- tmp.add (re_num, y.re_num, Round.NEAREST);
- var z = new Number.mpfloat (tmp);
+ var z = new Number ();
+ z.num.add (num, y.num);
return z;
}
/* Sets z = x − y */
public Number subtract (Number y)
{
- return add (y.invert_sign ());
+ var z = new Number ();
+ z.num.subtract (num, y.num);
+ return z;
}
/* Sets z = x × y */
public Number multiply (Number y)
{
- if (is_complex () || y.is_complex ())
- {
- Number t1, t2, real_z, im_z;
-
- var real_x = real_component ();
- var im_x = imaginary_component ();
- var real_y = y.real_component ();
- var im_y = y.imaginary_component ();
-
- t1 = real_x.multiply_real (real_y);
- t2 = im_x.multiply_real (im_y);
- real_z = t1.subtract (t2);
-
- t1 = real_x.multiply_real (im_y);
- t2 = im_x.multiply_real (real_y);
- im_z = t1.add (t2);
-
- return new Number.complex (real_z, im_z);
- }
- else
- return multiply_real (y);
- }
-
- public Number multiply_real (Number y)
- {
- var z = new Number.integer (0);
- var tmp = z.re_num;
- tmp.multiply (re_num, y.re_num, Round.NEAREST);
- z.re_num = tmp;
+ var z = new Number ();
+ z.num.multiply (num, y.num);
return z;
}
/* Sets z = x × y */
public Number multiply_integer (int64 y)
{
- var z = new Number.integer (0);
- var tmp = z.re_num;
- tmp.multiply_signed_integer (re_num, (long) y, Round.NEAREST);
- z.re_num = tmp;
+ var z = new Number ();
+ z.num.multiply_signed_integer (num, (long) y);
return z;
}
@@ -806,27 +570,8 @@ public class Number : Object
return new Number.integer (0);
}
- if (is_complex () || y.is_complex ())
- {
- var a = real_component ();
- var b = imaginary_component ();
- var c = y.real_component ();
- var d = y.imaginary_component ();
-
- var tmp = a.multiply (c).add (b.multiply (d));
- var tmp_2 = c.xpowy_integer (2).add (d.xpowy_integer (2));
- var z_1 = tmp.divide (tmp_2);
-
- tmp = b.multiply (c).subtract (a.multiply (d));
- var z_2 = tmp.divide (tmp_2);
-
- var z = new Number.complex (z_1, z_2);
- return z;
- }
-
- var tmp = MPFloat.init2 ((Precision) precision);
- tmp.divide (re_num, y.re_num, Round.NEAREST);
- var z = new Number.mpfloat (tmp);
+ var z = new Number ();
+ z.num.divide (num, y.num);
return z;
}
@@ -884,46 +629,25 @@ public class Number : Object
/* Sets z = sin x */
public Number sin (AngleUnit unit = AngleUnit.RADIANS)
{
+ var z = new Number ();
if (is_complex ())
- {
- var x_real = real_component ();
- var x_im = imaginary_component ();
-
- var z_real = x_real.sin_real (unit);
- var t = x_im.cosh ();
- z_real = z_real.multiply (t);
-
- var z_im = x_real.cos_real (unit);
- t = x_im.sinh ();
- z_im = z_im.multiply (t);
-
- return new Number.complex (z_real, z_im);
- }
+ z.num.@set (num);
else
- return sin_real (unit);
+ mpc_to_radians (z.num, num, unit);
+ z.num.sin (z.num);
+ return z;
}
/* Sets z = cos x */
public Number cos (AngleUnit unit = AngleUnit.RADIANS)
{
+ var z = new Number ();
if (is_complex ())
- {
- var x_real = real_component ();
- var x_im = imaginary_component ();
-
- var z_real = x_real.cos_real (unit);
- var t = x_im.cosh ();
- z_real = z_real.multiply (t);
-
- var z_im = x_real.sin_real (unit);
- t = x_im.sinh ();
- z_im = z_im.multiply (t);
- z_im = z_im.invert_sign ();
-
- return new Number.complex (z_real, z_im);
- }
+ z.num.@set (num);
else
- return cos_real (unit);
+ mpc_to_radians (z.num, num, unit);
+ z.num.cos (z.num);
+ return z;
}
/* Sets z = tan x */
@@ -940,9 +664,12 @@ public class Number : Object
return new Number.integer (0);
}
- var tmp = MPFloat.init2 ((Precision) precision);
- tmp.tan (x_radians.re_num, Round.NEAREST);
- var z = new Number.mpfloat (tmp);
+ var z = new Number ();
+ if (is_complex ())
+ z.num.@set (num);
+ else
+ mpc_to_radians (z.num, num, unit);
+ z.num.tan (z.num);
return z;
}
@@ -956,10 +683,11 @@ public class Number : Object
return new Number.integer (0);
}
- var tmp = MPFloat.init2 ((Precision) precision);
- tmp.asin (re_num, Round.NEAREST);
- var z = new Number.mpfloat (tmp);
- return z.from_radians (unit);
+ var z = new Number ();
+ z.num.asin (num);
+ if (!z.is_complex ())
+ mpc_from_radians (z.num, z.num, unit);
+ return z;
}
/* Sets z = cos⁻¹ x */
@@ -972,54 +700,52 @@ public class Number : Object
return new Number.integer (0);
}
- var tmp = MPFloat.init2 ((Precision) precision);
- tmp.acos (re_num, Round.NEAREST);
- var z = new Number.mpfloat (tmp);
- return z.from_radians (unit);
+ var z = new Number ();
+ z.num.acos (num);
+ if (!z.is_complex ())
+ mpc_from_radians (z.num, z.num, unit);
+ return z;
}
/* Sets z = tan⁻¹ x */
public Number atan (AngleUnit unit = AngleUnit.RADIANS)
{
- var tmp = MPFloat.init2 ((Precision) precision);
- tmp.atan (re_num, Round.NEAREST);
- var z = new Number.mpfloat (tmp);
- return z.from_radians (unit);
+ var z = new Number ();
+ z.num.atan (num);
+ if (!z.is_complex ())
+ mpc_from_radians (z.num, z.num, unit);
+ return z;
}
/* Sets z = sinh x */
public Number sinh ()
{
- var tmp = MPFloat.init2 ((Precision) precision);
- tmp.sinh (re_num, Round.NEAREST);
- var z = new Number.mpfloat (tmp);
+ var z = new Number ();
+ z.num.sinh (num);
return z;
}
/* Sets z = cosh x */
public Number cosh ()
{
- var tmp = MPFloat.init2 ((Precision) precision);
- tmp.cosh (re_num, Round.NEAREST);
- var z = new Number.mpfloat (tmp);
+ var z = new Number ();
+ z.num.cosh (num);
return z;
}
/* Sets z = tanh x */
public Number tanh ()
{
- var tmp = MPFloat.init2 ((Precision) precision);
- tmp.tanh (re_num, Round.NEAREST);
- var z = new Number.mpfloat (tmp);
+ var z = new Number ();
+ z.num.tanh (num);
return z;
}
/* Sets z = sinh⁻¹ x */
public Number asinh ()
{
- var tmp = MPFloat.init2 ((Precision) precision);
- tmp.asinh (re_num, Round.NEAREST);
- var z = new Number.mpfloat (tmp);
+ var z = new Number ();
+ z.num.asinh (num);
return z;
}
@@ -1035,9 +761,8 @@ public class Number : Object
return new Number.integer (0);
}
- var tmp = MPFloat.init2 ((Precision) precision);
- tmp.acosh (re_num, Round.NEAREST);
- var z = new Number.mpfloat (tmp);
+ var z = new Number ();
+ z.num.acosh (num);
return z;
}
@@ -1052,9 +777,8 @@ public class Number : Object
return new Number.integer (0);
}
- var tmp = MPFloat.init2 ((Precision) precision);
- tmp.atanh (re_num, Round.NEAREST);
- var z = new Number.mpfloat (tmp);
+ var z = new Number ();
+ z.num.atanh (num);
return z;
}
@@ -1256,109 +980,76 @@ public class Number : Object
private Number copy ()
{
var z = new Number ();
- var tmp = MPFloat.init2 ((Precision) precision);
- var tmp2 = MPFloat.init2 ((Precision) precision);
- tmp.@set(re_num, Round.NEAREST);
- tmp2.@set(im_num, Round.NEAREST);
- z.re_num = tmp;
- z.im_num = tmp2;
+ z.num.@set (num);
return z;
}
- private Number epowy_real ()
+ private static void mpc_from_radians (Complex res, Complex op, AngleUnit unit)
{
- var z = copy ();
- var tmp = z.re_num;
- tmp.exp (re_num, Round.NEAREST);
- z.re_num = tmp;
- return z;
- }
-
- private Number root_real (int64 n)
- {
- var z = copy ();
- var tmp = z.re_num;
- tmp.root (re_num, (ulong) n, Round.NEAREST);
- z.re_num = tmp;
- return z;
- }
-
- private Number ln_real ()
- {
- var tmp = MPFloat.init2 ((Precision) precision);
- tmp.log (re_num, Round.NEAREST);
- var z = new Number.mpfloat (tmp);
- return z;
- }
-
- private Number reciprocal_real ()
- {
- /* 1/0 invalid */
- if (is_zero ())
- {
- error = _("Reciprocal of zero is undefined");
- return new Number.integer (0);
- }
-
- var tmp = MPFloat.init2 ((Precision) precision);
- tmp.set_unsigned_integer (1, Round.NEAREST);
- tmp.divide (tmp, re_num, Round.NEAREST);
- var z = copy ();
- z.re_num.clear ();
- z.re_num = tmp;
- return z;
- }
-
+ int i;
- private Number from_radians (AngleUnit unit)
- {
switch (unit)
{
- default:
- case AngleUnit.RADIANS:
- return this;
+ default:
+ case AngleUnit.RADIANS:
+ if (res != op)
+ res.@set (op);
+ return;
+
+ case AngleUnit.DEGREES:
+ i = 180;
+ break;
- case AngleUnit.DEGREES:
- return multiply_integer (180).divide (new Number.pi ());
+ case AngleUnit.GRADIANS:
+ i=200;
+ break;
- case AngleUnit.GRADIANS:
- return multiply_integer (200).divide (new Number.pi ());
}
+ var scale = MPFR.Real (precision);
+ scale.const_pi ();
+ scale.signed_integer_divide (i, scale);
+ res.multiply_mpreal (op, scale);
}
- /* Convert x to radians */
- private Number to_radians (AngleUnit unit)
+ private static void mpc_to_radians (Complex res, Complex op, AngleUnit unit)
{
+ int i;
+
switch (unit)
{
- default:
- case AngleUnit.RADIANS:
- return this;
+ default:
+ case AngleUnit.RADIANS:
+ if (res != op)
+ res.@set (op);
+ return;
- case AngleUnit.DEGREES:
- return multiply (new Number.pi ()).divide_integer (180);
+ case AngleUnit.DEGREES:
+ i = 180;
+ break;
- case AngleUnit.GRADIANS:
- return multiply (new Number.pi ()).divide_integer (200);
+ case AngleUnit.GRADIANS:
+ i=200;
+ break;
}
+ var scale = MPFR.Real (precision);
+ scale.const_pi ();
+ scale.divide_signed_integer (scale, i);
+ res.multiply_mpreal (op, scale);
}
- private Number sin_real (AngleUnit unit)
+ private Number from_radians (AngleUnit unit)
{
- var x_radians = to_radians (unit);
- var z = new Number.integer (0);
- var tmp = z.re_num;
- tmp.sin (x_radians.re_num, Round.NEAREST);
- z.re_num = tmp;
+ var z = new Number ();
+ mpc_from_radians (z.num, num, unit);
return z;
}
- private Number cos_real (AngleUnit unit)
+
+ /* Convert x to radians */
+ private Number to_radians (AngleUnit unit)
{
- var x_radians = to_radians (unit);
- var tmp = MPFloat.init2 ((Precision) precision);
- tmp.cos (x_radians.re_num, Round.NEAREST);
- var z = new Number.mpfloat (tmp);
+ var z = new Number ();
+ mpc_to_radians (z.num, num, unit);
return z;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]