--- a/components/gnome/gnome-calculator/patches/01-no-mpfr.patch Thu Apr 13 17:10:44 2017 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,3543 +0,0 @@
-A new version of mpfr is expected which isn't in Solaris yet, so we
-are removing that functionality till we can get mpfr updated and
-then will revert back these changes.
-
-Not suitable for upstream
-
---- a/data/org.gnome.calculator.gschema.xml Fri Jan 29 15:39:20 2016
-+++ b/data/org.gnome.calculator.gschema.xml Fri Jan 29 15:40:20 2016
[email protected]@ -22,6 +22,7 @@
- <schema path="/org/gnome/calculator/" id="org.gnome.calculator" gettext-domain="calculator">
- <key type="i" name="accuracy">
- <default>9</default>
-+ <range min="0" max="9"/>
- <summary>Accuracy value</summary>
- <description>The number of digits displayed after the numeric point</description>
- </key>
[email protected]@ -82,10 +83,5 @@
- <summary>Target units</summary>
- <description>Units to convert the current calculation into</description>
- </key>
-- <key type="i" name="precision">
-- <default>2000</default>
-- <summary>Internal precision</summary>
-- <description>The internal precision used with the MPFR library</description>
-- </key>
- </schema>
- </schemalist>
---- a/src/Makefile.am Fri Jan 29 15:40:46 2016
-+++ b/src/Makefile.am Fri Jan 29 15:41:34 2016
[email protected]@ -33,8 +33,7 @@
- --pkg gtk+-3.0 \
- --pkg gtksourceview-3.0 \
- --pkg libxml-2.0 \
-- $(top_builddir)/lib/libcalculator.vapi \
-- $(top_builddir)/lib/mpfr.vapi
-+ $(top_builddir)/lib/libcalculator.vapi
-
- gnome_calculator_CPPFLAGS = \
- $(AM_CPPFLAGS) \
[email protected]@ -54,8 +53,7 @@
- --pkg gio-2.0 \
- --pkg gtksourceview-3.0 \
- --pkg libxml-2.0 \
-- $(top_builddir)/lib/libcalculator.vapi \
-- $(top_builddir)/lib/mpfr.vapi
-+ $(top_builddir)/lib/libcalculator.vapi
-
- gcalccmd_LDADD = \
- $(top_builddir)/lib/libcalculator.la
---- a/lib/Makefile.am Fri Jan 29 15:42:13 2016
-+++ b/lib/Makefile.am Fri Jan 29 15:42:24 2016
[email protected]@ -10,7 +10,6 @@
-
- libcalculator_la_SOURCES = \
- config.vapi \
-- mpfr.vapi \
- currency.vala \
- equation.vala \
- equation-lexer.vala \
[email protected]@ -37,8 +36,7 @@
- libcalculator_la_LIBADD = \
- $(LIBCALCULATOR_LIBS) \
- -lgmp \
-- -lm \
-- -lmpfr
-+ -lm
-
- EXTRA_DIST = \
- libcalculator.h \
---- a/lib/equation-parser.vala Fri Jan 29 15:47:35 2016
-+++ b/lib/equation-parser.vala Fri Jan 29 16:00:51 2016
[email protected]@ -78,20 +78,8 @@
- var r = right.solve ();
- if (r == null)
- return null;
-- var z = solve_r (r);
-+ return solve_r (r);
-
-- /* check for errors */
-- Number.check_flags ();
-- if (Number.error != null)
-- {
-- var tmpleft = right;
-- var tmpright = right;
-- while (tmpleft.left != null) tmpleft = tmpleft.left;
-- while (tmpright.right != null) tmpright = tmpright.right;
-- parser.set_error (ErrorCode.MP, Number.error, tmpleft.token.start_index, tmpright.token.end_index);
-- Number.error = null;
-- }
-- return z;
- }
-
- public abstract Number solve_r (Number r);
[email protected]@ -110,20 +98,7 @@
- var r = right.solve ();
- if (l == null || r == null)
- return null;
-- var z = solve_lr (l, r);
--
-- /* check for errors */
-- Number.check_flags ();
-- if (Number.error != null)
-- {
-- var tmpleft = left;
-- var tmpright = right;
-- while (tmpleft.left != null) tmpleft = tmpleft.left;
-- while (tmpright.right != null) tmpright = tmpright.right;
-- parser.set_error (ErrorCode.MP, Number.error, tmpleft.token.start_index, tmpright.token.end_index);
-- Number.error = null;
-- }
-- return z;
-+ return solve_lr (l, r);
- }
-
- public abstract Number solve_lr (Number left, Number r);
[email protected]@ -261,18 +236,6 @@
- value = value.multiply (t);
- }
-
-- /* check for errors */
-- Number.check_flags ();
-- if (Number.error != null)
-- {
-- var tmpleft = left;
-- var tmpright = right;
-- while (tmpleft.left != null) tmpleft = tmpleft.left;
-- while (tmpright.right != null) tmpright = tmpright.right;
-- parser.set_error (ErrorCode.MP, Number.error, tmpleft.token.start_index, tmpright.token.end_index);
-- Number.error = null;
-- }
--
- return value;
- }
- }
[email protected]@ -392,14 +355,6 @@
- if (tmp != null)
- tmp = tmp.xpowy_integer (pow);
-
-- /* check for errors */
-- Number.check_flags ();
-- if (Number.error != null)
-- {
-- parser.set_error (ErrorCode.MP, Number.error);
-- Number.error = null;
-- }
--
- return tmp;
- }
- }
[email protected]@ -574,17 +529,7 @@
-
- public override Number solve_lr (Number l, Number r)
- {
-- var z = l.divide (r);
-- if (Number.error != null)
-- {
-- var tmpleft = right;
-- var tmpright = right;
-- while (tmpleft.left != null) tmpleft = tmpleft.left;
-- while (tmpright.right != null) tmpright = tmpright.right;
-- parser.set_error (ErrorCode.MP, Number.error, tmpleft.token.start_index, tmpright.token.end_index);
-- Number.error = null;
-- }
-- return z;
-+ return l.divide (r);
- }
- }
-
[email protected]@ -604,21 +549,8 @@
- var mod = right.solve ();
- if (base_value == null || exponent == null || mod == null)
- return null;
-- var z = base_value.modular_exponentiation (exponent, mod);
-+ return base_value.modular_exponentiation (exponent, mod);
-
-- /* check for errors */
-- Number.check_flags ();
-- if (Number.error != null)
-- {
-- var tmpleft = left;
-- var tmpright = right;
-- while (tmpleft.left != null) tmpleft = tmpleft.left;
-- while (tmpright.right != null) tmpright = tmpright.right;
-- parser.set_error (ErrorCode.MP, Number.error, tmpleft.token.start_index, tmpright.token.end_index);
-- Number.error = null;
-- }
--
-- return z;
- }
- else
- {
[email protected]@ -626,21 +558,8 @@
- var r = right.solve ();
- if (l == null || r == null)
- return null;
-- var z = solve_lr (l, r);
-+ return solve_lr (l, r);
-
-- /* check for errors */
-- Number.check_flags ();
-- if (Number.error != null)
-- {
-- var tmpleft = left;
-- var tmpright = right;
-- while (tmpleft.left != null) tmpleft = tmpleft.left;
-- while (tmpright.right != null) tmpright = tmpright.right;
-- parser.set_error (ErrorCode.MP, Number.error, tmpleft.token.start_index, tmpright.token.end_index);
-- Number.error = null;
-- }
--
-- return z;
- }
- }
-
[email protected]@ -709,21 +628,8 @@
- if (val == null)
- return null;
-
-- var z = val.xpowy_integer (pow);
-+ return val.xpowy_integer (pow);
-
-- /* check for errors */
-- Number.check_flags ();
-- if (Number.error != null)
-- {
-- var tmpleft = left;
-- var tmpright = right;
-- while (tmpleft.left != null) tmpleft = tmpleft.left;
-- while (tmpright.right != null) tmpright = tmpright.right;
-- parser.set_error (ErrorCode.MP, Number.error, tmpleft.token.start_index, tmpright.token.end_index);
-- Number.error = null;
-- }
--
-- return z;
- }
- }
-
[email protected]@ -1036,10 +942,10 @@
- }
-
- representation_base = this.representation_base;
-- error_code = this.error;
-- error_token = this.error_token;
-- error_start = this.error_token_start;
-- error_end = this.error_token_end;
-+ error_code = ErrorCode.NONE;
-+ error_token = null;
-+ error_start = 0;
-+ error_end = 0;
- return ans;
- }
-
---- a/lib/equation.vala Fri Jan 29 16:01:11 2016
-+++ b/lib/equation.vala Fri Jan 29 16:02:09 2016
[email protected]@ -117,17 +117,15 @@
- public new Number? parse (out uint representation_base = null, out ErrorCode error_code = null, out string? error_token = null, out uint? error_start = null, out uint? error_end = null)
- {
- var parser = new EquationParser (this, expression);
-- Number.error = null;
-+ mp_clear_error();
-
- var z = parser.parse (out representation_base, out error_code, out error_token, out error_start, out error_end);
-
- /* Error during parsing */
- if (error_code != ErrorCode.NONE)
-- {
- return null;
-- }
-
-- if (Number.error != null)
-+ if (mp_get_error() != null)
- {
- error_code = ErrorCode.MP;
- return null;
---- a/src/gnome-calculator.vala Fri Jan 29 16:05:17 2016
-+++ b/src/gnome-calculator.vala Fri Jan 29 16:06:27 2016
[email protected]@ -56,7 +56,6 @@
- var target_currency = settings.get_string ("target-currency");
- var source_units = settings.get_string ("source-units");
- var target_units = settings.get_string ("target-units");
-- var precision = settings.get_int ("precision");
-
- var equation = new MathEquation ();
- equation.accuracy = accuracy;
[email protected]@ -69,7 +68,6 @@
- equation.target_currency = target_currency;
- equation.source_units = source_units;
- equation.target_units = target_units;
-- Number.precision = precision;
-
- add_action_entries (app_entries, this);
-
[email protected]@ -173,7 +171,7 @@
- }
- else if (error == ErrorCode.MP)
- {
-- stderr.printf ("Error: %s\n", Number.error);
-+ stderr.printf ("Error: %s\n", mp_get_error());
- return Posix.EXIT_FAILURE;
- }
- else
---- a/src/gcalccmd.vala Fri Jan 29 16:03:42 2016
-+++ b/src/gcalccmd.vala Fri Jan 29 16:04:56 2016
[email protected]@ -34,18 +34,9 @@
-
- result_serializer.set_representation_base (representation_base);
- if (z != null)
-- {
-- var str = result_serializer.to_string (z);
-- if (result_serializer.error != null)
-- {
-- stderr.printf ("%s\n", result_serializer.error);
-- result_serializer.error = null;
-- }
-- else
-- stdout.printf ("%s\n", str);
-- }
-+ stdout.printf ("%s\n", result_serializer.to_string (z));
- else if (ret == ErrorCode.MP)
-- stderr.printf ("Error %s\n", Number.error);
-+ stderr.printf ("Error %s\n", mp_get_error());
- else
- stderr.printf ("Error %d\n", ret);
- }
---- a/lib/math-equation.vala Fri Jan 29 16:33:36 2016
-+++ b/lib/math-equation.vala Fri Jan 29 16:39:56 2016
[email protected]@ -786,11 +786,6 @@
- ans_end_mark = create_mark (null, end, true);
- apply_tag (ans_tag, start, end);
-
-- if (serializer.error != null)
-- {
-- status = serializer.error;
-- serializer.error = null;
-- }
- }
-
- public new void insert (string text)
[email protected]@ -964,13 +959,11 @@
- break;
-
- case ErrorCode.MP:
-- if (Number.error != null) // LEGACY, should never be run
-+ if (mp_get_error () != null)
-+ solvedata.error = mp_get_error ();
-+ else if (error_token != null)
- {
-- solvedata.error = Number.error;
-- }
-- else if (error_token != null) // should always be run
-- {
-- solvedata.error = _("%s").printf (error_token);
-+ solvedata.error = _("Malformed expression at token '%s'").printf(error_token);
- solvedata.error_start = error_start;
- solvedata.error_end = error_end;
- }
[email protected]@ -1015,8 +1008,6 @@
-
- /* Fix thousand separator offsets in the start and end offsets of error token. */
- error_token_fix_thousands_separator ();
-- /* Fix missing Parenthesis before the start and after the end offsets of error token */
-- error_token_fix_parenthesis ();
-
- /* Notify the GUI about the change in error token locations. */
- notify_property ("error-token-end");
[email protected]@ -1087,70 +1078,6 @@
- end.forward_chars (length);
- }
- }
--
-- /* Fix the offsets to consider starting and ending parenthesis */
-- private void error_token_fix_parenthesis ()
-- {
-- unichar c;
-- int count = 0;
-- int real_end = display.index_of_nth_char (error_token_end);
-- int real_start = display.index_of_nth_char (error_token_start);
--
-- /* checks if there are more opening/closing parenthesis than closing/opening parenthesis */
-- for (int i = real_start; display.get_next_char (ref i, out c) && i <= real_end;)
-- {
-- if (c.to_string () == "(") count++;
-- if (c.to_string () == ")") count--;
-- }
--
-- /* if there are more opening than closing parenthesis and there are closing parenthesis
-- after the end offset, include those in the offsets */
-- for (int i = real_end; display.get_next_char (ref i, out c) && count > 0;)
-- {
-- if (c.to_string () == ")")
-- {
-- state.error_token_end++;
-- count--;
-- }
-- else
-- {
-- break;
-- }
-- }
--
-- /* the same for closing parenthesis */
-- for (int i = real_start; display.get_prev_char (ref i, out c) && count < 0;)
-- {
-- if (c.to_string () == "(")
-- {
-- state.error_token_start--;
-- count++;
-- }
-- else
-- {
-- break;
-- }
-- }
--
-- real_end = display.index_of_nth_char (error_token_end);
-- real_start = display.index_of_nth_char (error_token_start);
--
-- unichar d;
--
-- /* if there are opening parenthesis directly before aswell as closing parenthesis directly after the offsets, include those aswell */
-- while (display.get_next_char (ref real_end, out d) && display.get_prev_char (ref real_start, out c))
-- {
-- if (c.to_string () == "(" && d.to_string () == ")")
-- {
-- state.error_token_start--;
-- state.error_token_end++;
-- }
-- else
-- {
-- break;
-- }
-- }
-- }
-
- private void* factorize_real ()
- {
---- a/src/math-preferences.vala Fri Jan 29 16:40:37 2016
-+++ b/src/math-preferences.vala Fri Jan 29 16:43:30 2016
[email protected]@ -90,7 +90,7 @@
- var string = _("Show %d decimal _places");
- var tokens = string.split ("%d", 2);
-
-- var decimal_places_adjustment = new Gtk.Adjustment (0.0, 0.0, 100.0, 1.0, 1.0, 0.0);
-+ var decimal_places_adjustment = new Gtk.Adjustment (0.0, 0.0, 9.0, 1.0, 1.0, 0.0);
- decimal_places_spin = new Gtk.SpinButton (decimal_places_adjustment, 0.0, 0);
-
- if (tokens.length > 0)
---- a/lib/serializer.vala Mon Feb 1 10:45:23 2016
-+++ b/lib/serializer.vala Mon Feb 1 10:46:37 2016
[email protected]@ -32,9 +32,6 @@
- private unichar tsep; /* Locale specific thousands separator. */
- private int tsep_count; /* Number of digits between separator. */
-
-- /* is set when an error (for example precision error while converting) occurs */
-- public string? error { get; set; default = null; }
--
- public Serializer (DisplayFormat format, int number_base, int trailing_digits)
- {
- var radix_string = Posix.nl_langinfo (Posix.NLItem.RADIXCHAR);
[email protected]@ -322,17 +319,8 @@
-
- var d = t3.to_integer ();
-
-- if (d < 16 && d >= 0)
-- {
-- string.prepend_c (digits[d]);
-- }
-- else
-- {
-- string.prepend_c ('?');
-- error = _("Precision error");
-- string.assign ("0");
-- break;
-- }
-+ string.prepend_c (d < 16 ? digits[d] : '?');
-+
- n_digits++;
-
- temp = t;
---- a/tests/test-number.vala Mon Feb 1 10:48:08 2016
-+++ b/tests/test-number.vala Mon Feb 1 10:49:35 2016
[email protected]@ -72,6 +72,22 @@
- pass ();
- }
-
-+private void test_float ()
-+{
-+ for (var a = -10.0f; a <= 10.0f; a += 0.5f)
-+ {
-+ var z = new Number.float (a);
-+ if (z.to_float () != a)
-+ {
-+ fail ("Number.float (%f).to_float () -> %f, expected %f".printf (a, z.to_float (), a));
-+ return;
-+ }
-+ }
-+
-+ pass ();
-+}
-+
-+
- private void test_double ()
- {
- for (var a = -10.0; a <= 10.0; a += 0.5)
[email protected]@ -1074,6 +1090,7 @@
- test_integer ();
- test_unsigned_integer ();
- test_fraction ();
-+ test_float ();
- test_double ();
- test_complex ();
- test_polar ();
---- a/tests/test-equation.c Mon Feb 1 12:22:33 2016
-+++ b/tests/test-equation.c Mon Feb 1 12:22:47 2016
[email protected]@ -95,7 +95,7 @@
- const gchar* _tmp1_ = NULL;
- const gchar* _tmp2_ = NULL;
- gchar* _tmp3_ = NULL;
-- _tmp1_ = number_get_error ();
-+ _tmp1_ = mp_get_error ();
- _tmp2_ = _tmp1_;
- _tmp3_ = g_strdup_printf ("ErrorCode.MP(\"%s\")", _tmp2_);
- result = _tmp3_;
-
---- a/lib/number.vala Fri Jan 29 16:44:36 2016
-+++ b/lib/number.vala Mon Feb 1 12:02:40 2016
[email protected]@ -27,8 +27,15 @@
- * THE MP USERS GUIDE.
- */
-
--using MPFR;
-
-+/* Size of the multiple precision values */
-+private const int SIZE = 1000;
-+
-+/* Base for numbers */
-+private const int BASE = 10000;
-+
-+private const int T = 100;
-+
- private delegate int BitwiseFunc (int v1, int v2);
-
- public enum AngleUnit
[email protected]@ -41,37 +48,69 @@
- /* Object for a high precision floating point number representation */
- public class Number : Object
- {
-- /* real and imaginary part of a Number */
-- private MPFloat re_num { get; set; }
-- private MPFloat im_num { get; set; }
-+ /* Sign (+1, -1) or 0 for the value zero */
-+ public int re_sign;
-+ public int im_sign;
-
-- public static ulong precision { get; set; default = 1000; }
-+ /* Exponent (to base BASE) */
-+ public int re_exponent;
-+ public int im_exponent;
-
-- /* Stores the error msg if an error occurs during calculation. Otherwise should be null */
-- public static string? error { get; set; default = null; }
-+ /* Normalized fraction */
-+ public int re_fraction[1000]; // SIZE
-+ public int im_fraction[1000]; // SIZE
-
- public Number.integer (int64 value)
- {
-- 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;
-+ if (value < 0)
-+ {
-+ value = -value;
-+ re_sign = -1;
-+ }
-+ else if (value > 0)
-+ re_sign = 1;
-+ else
-+ re_sign = 0;
-+
-+ while (value != 0)
-+ {
-+ re_fraction[re_exponent] = (int) (value % BASE);
-+ re_exponent++;
-+ value /= BASE;
-+ }
-+ for (var i = 0; i < re_exponent / 2; i++)
-+ {
-+ int t = re_fraction[i];
-+ re_fraction[i] = re_fraction[re_exponent - i - 1];
-+ re_fraction[re_exponent - i - 1] = t;
-+ }
- }
-
- public Number.unsigned_integer (uint64 x)
- {
-- 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;
-+ if (x == 0)
-+ re_sign = 0;
-+ else
-+ re_sign = 1;
-+
-+ while (x != 0)
-+ {
-+ re_fraction[re_exponent] = (int) (x % BASE);
-+ x = x / BASE;
-+ re_exponent++;
-+ }
-+ for (var i = 0; i < re_exponent / 2; i++)
-+ {
-+ int t = re_fraction[i];
-+ re_fraction[i] = re_fraction[re_exponent - i - 1];
-+ re_fraction[re_exponent - i - 1] = t;
-+ }
- }
-
- public Number.fraction (int64 numerator, int64 denominator)
- {
-+ mp_gcd (ref numerator, ref denominator);
-+
- if (denominator < 0)
- {
- numerator = -numerator;
[email protected]@ -81,39 +120,203 @@
- Number.integer (numerator);
- if (denominator != 1)
- {
-- var tmp = re_num;
-- tmp.divide_signed_integer (re_num, (long) denominator, Round.NEAREST);
-- re_num = tmp;
-+ var z = divide_integer (denominator);
-+ re_sign = z.re_sign;
-+ im_sign = z.im_sign;
-+ re_exponent = z.re_exponent;
-+ im_exponent = z.im_exponent;
-+ for (var i = 0; i < z.re_fraction.length; i++)
-+ {
-+ re_fraction[i] = z.re_fraction[i];
-+ im_fraction[i] = z.im_fraction[i];
-+ }
- }
- }
-
-- /* Helper constructor. Creates new Number from already existing MPFloat. */
-- public Number.mpfloat (MPFloat value)
-+ public Number.float (float value)
- {
-- re_num = value;
-- var tmp = MPFloat.init2 ((Precision) precision);
-- tmp.set_unsigned_integer (0, Round.NEAREST);
-- im_num = tmp;
-+ var z = new Number.integer (0);
-+
-+ if (value != 0)
-+ {
-+ /* CHECK SIGN */
-+ var rj = 0f;
-+ if (value < 0.0f)
-+ {
-+ z.re_sign = -1;
-+ rj = -value;
-+ }
-+ else if (value > 0.0f)
-+ {
-+ z.re_sign = 1;
-+ rj = value;
-+ }
-+
-+ /* INCREASE IE AND DIVIDE RJ BY 16. */
-+ var ie = 0;
-+ while (rj >= 1.0f)
-+ {
-+ ie++;
-+ rj *= 0.0625f;
-+ }
-+ while (rj < 0.0625f)
-+ {
-+ ie--;
-+ rj *= 16.0f;
-+ }
-+
-+ /* NOW RJ IS DY DIVIDED BY SUITABLE POWER OF 16.
-+ * SET re_exponent TO 0
-+ */
-+ z.re_exponent = 0;
-+
-+ /* CONVERSION LOOP (ASSUME SINGLE-PRECISION OPS. EXACT) */
-+ for (var i = 0; i < T + 4; i++)
-+ {
-+ rj *= BASE;
-+ z.re_fraction[i] = (int) rj;
-+ rj -= z.re_fraction[i];
-+ }
-+
-+ /* NORMALIZE RESULT */
-+ mp_normalize (ref z);
-+
-+ /* Computing MAX */
-+ var ib = int.max (BASE * 7 * BASE, 32767) / 16;
-+ var tp = 1;
-+
-+ /* NOW MULTIPLY BY 16**IE */
-+ if (ie < 0)
-+ {
-+ var k = -ie;
-+ for (var i = 1; i <= k; i++)
-+ {
-+ tp <<= 4;
-+ if (tp <= ib && tp != BASE && i < k)
-+ continue;
-+ z = z.divide_integer (tp);
-+ tp = 1;
-+ }
-+ }
-+ else if (ie > 0)
-+ {
-+ for (var i = 1; i <= ie; i++)
-+ {
-+ tp <<= 4;
-+ if (tp <= ib && tp != BASE && i < ie)
-+ continue;
-+ z = z.multiply_integer (tp);
-+ tp = 1;
-+ }
-+ }
-+ }
-+
-+ re_sign = z.re_sign;
-+ im_sign = z.im_sign;
-+ re_exponent = z.re_exponent;
-+ im_exponent = z.im_exponent;
-+ for (var i = 0; i < z.re_fraction.length; i++)
-+ {
-+ re_fraction[i] = z.re_fraction[i];
-+ im_fraction[i] = z.im_fraction[i];
-+ }
- }
-
- public Number.double (double value)
- {
-- 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;
-+ var z = new Number.integer (0);
-+
-+ if (value != 0)
-+ {
-+ /* CHECK SIGN */
-+ var dj = 0.0;
-+ if (value < 0.0)
-+ {
-+ z.re_sign = -1;
-+ dj = -value;
-+ }
-+ else if (value > 0.0)
-+ {
-+ z.re_sign = 1;
-+ dj = value;
-+ }
-+
-+ /* INCREASE IE AND DIVIDE DJ BY 16. */
-+ var ie = 0;
-+ for (ie = 0; dj >= 1.0; ie++)
-+ dj *= 1.0/16.0;
-+
-+ for ( ; dj < 1.0/16.0; ie--)
-+ dj *= 16.0;
-+
-+ /* NOW DJ IS DY DIVIDED BY SUITABLE POWER OF 16
-+ * SET re_exponent TO 0
-+ */
-+ z.re_exponent = 0;
-+
-+ /* CONVERSION LOOP (ASSUME DOUBLE-PRECISION OPS. EXACT) */
-+ for (var i = 0; i < T + 4; i++)
-+ {
-+ dj *= (double) BASE;
-+ z.re_fraction[i] = (int) dj;
-+ dj -= (double) z.re_fraction[i];
-+ }
-+
-+ /* NORMALIZE RESULT */
-+ mp_normalize (ref z);
-+
-+ /* Computing MAX */
-+ var ib = int.max (BASE * 7 * BASE, 32767) / 16;
-+ var tp = 1;
-+
-+ /* NOW MULTIPLY BY 16**IE */
-+ if (ie < 0)
-+ {
-+ var k = -ie;
-+ for (var i = 1; i <= k; ++i)
-+ {
-+ tp <<= 4;
-+ if (tp <= ib && tp != BASE && i < k)
-+ continue;
-+ z = z.divide_integer (tp);
-+ tp = 1;
-+ }
-+ }
-+ else if (ie > 0)
-+ {
-+ for (var i = 1; i <= ie; ++i)
-+ {
-+ tp <<= 4;
-+ if (tp <= ib && tp != BASE && i < ie)
-+ continue;
-+ z = z.multiply_integer (tp);
-+ tp = 1;
-+ }
-+ }
-+ }
-+
-+ re_sign = z.re_sign;
-+ im_sign = z.im_sign;
-+ re_exponent = z.re_exponent;
-+ im_exponent = z.im_exponent;
-+ for (var i = 0; i < z.re_fraction.length; i++)
-+ {
-+ re_fraction[i] = z.re_fraction[i];
-+ im_fraction[i] = z.im_fraction[i];
-+ }
- }
-
- public Number.complex (Number x, Number y)
- {
-- var tmp = MPFloat.init2 ((Precision) precision);
-- [email protected] (x.re_num, Round.NEAREST);
-- re_num = tmp;
-- var tmp2 = MPFloat.init2 ((Precision) precision);
-- [email protected] (y.re_num, Round.NEAREST);
-- im_num = tmp2;
-+ re_sign = x.re_sign;
-+ re_exponent = x.re_exponent;
-+ for (var i = 0; i < im_fraction.length; i++)
-+ re_fraction[i] = x.re_fraction[i];
-+
-+ im_sign = y.re_sign;
-+ im_exponent = y.re_exponent;
-+ for (var i = 0; i < im_fraction.length; i++)
-+ im_fraction[i] = y.re_fraction[i];
- }
-
- public Number.polar (Number r, Number theta, AngleUnit unit = AngleUnit.RADIANS)
[email protected]@ -125,35 +328,28 @@
-
- public Number.eulers ()
- {
-- var tmp = MPFloat.init2 ((Precision) precision);
-- var tmp2 = MPFloat.init2 ((Precision) precision);
-- tmp2.set_unsigned_integer (1, Round.NEAREST);
-- /* 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;
-+ var z = new Number.integer (1).epowy ();
-+ re_sign = z.re_sign;
-+ im_sign = z.im_sign;
-+ re_exponent = z.re_exponent;
-+ im_exponent = z.im_exponent;
-+ for (var i = 0; i < z.re_fraction.length; i++)
-+ {
-+ re_fraction[i] = z.re_fraction[i];
-+ im_fraction[i] = z.im_fraction[i];
-+ }
- }
-
- 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;
-+ im_sign = 1;
-+ im_exponent = 1;
-+ im_fraction[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;
-+ Number.double (Math.PI);
- }
-
- /* Sets z to be a uniform random number in the range [0, 1] */
[email protected]@ -162,42 +358,123 @@
- Number.double (Random.next_double ());
- }
-
-- ~Number ()
-- {
-- re_num.clear ();
-- im_num.clear ();
-- }
--
- public int64 to_integer ()
- {
-- return re_num.get_signed_integer (Round.NEAREST);
-+ int64 z = 0;
-+
-+ /* |x| <= 1 */
-+ if (re_sign == 0 || re_exponent <= 0)
-+ return 0;
-+
-+ /* Multiply digits together */
-+ for (var i = 0; i < re_exponent; i++)
-+ {
-+ var t = z;
-+ z = z * BASE + re_fraction[i];
-+
-+ /* Check for overflow */
-+ if (z <= t)
-+ return 0;
-+ }
-+
-+ /* Validate result */
-+ var v = z;
-+ for (var i = re_exponent - 1; i >= 0; i--)
-+ {
-+ /* Get last digit */
-+ var digit = v - (v / BASE) * BASE;
-+ if (re_fraction[i] != digit)
-+ return 0;
-+
-+ v /= BASE;
-+ }
-+ if (v != 0)
-+ return 0;
-+
-+ return re_sign * z;
- }
-
- public uint64 to_unsigned_integer ()
- {
-- return re_num.get_unsigned_integer (Round.NEAREST);
-+ /* x <= 1 */
-+ if (re_sign <= 0 || re_exponent <= 0)
-+ return 0;
-+
-+ /* Multiply digits together */
-+ uint64 z = 0;
-+ for (var i = 0; i < re_exponent; i++)
-+ {
-+ var t = z;
-+ z = z * BASE + re_fraction[i];
-+
-+ /* Check for overflow */
-+ if (z <= t)
-+ return 0;
-+ }
-+
-+ /* Validate result */
-+ var v = z;
-+ for (var i = re_exponent - 1; i >= 0; i--)
-+ {
-+ /* Get last digit */
-+ var digit = (uint64) v - (v / BASE) * BASE;
-+ if (re_fraction[i] != digit)
-+ return 0;
-+
-+ v /= BASE;
-+ }
-+ if (v != 0)
-+ return 0;
-+
-+ return z;
- }
-
- public float to_float ()
- {
-- return re_num.get_float (Round.NEAREST);
-+ if (is_zero ())
-+ return 0f;
-+
-+ var z = 0f;
-+ for (var i = 0; i < T; i++)
-+ {
-+ if (re_fraction[i] != 0)
-+ z += re_fraction[i] * Math.powf (BASE, re_exponent - i - 1);
-+ }
-+
-+ if (re_sign < 0)
-+ return -z;
-+ else
-+ return z;
- }
-
- public double to_double ()
- {
-- return re_num.get_double (Round.NEAREST);
-+ if (is_zero ())
-+ return 0d;
-+
-+ var z = 0d;
-+ for (var i = 0; i < T; i++)
-+ {
-+ if (re_fraction[i] != 0)
-+ z += re_fraction[i] * Math.pow (BASE, re_exponent - i - 1);
-+ }
-+
-+ if (re_sign < 0)
-+ return -z;
-+ else
-+ return z;
- }
-
- /* Return true if the value is x == 0 */
- public bool is_zero ()
- {
-- return re_num.is_zero () && im_num.is_zero ();
-+ return re_sign == 0 && im_sign == 0;
- }
-
- /* Return true if x < 0 */
- public bool is_negative ()
- {
-- return re_num.sgn () < 0;
-+ return re_sign < 0;
- }
-
- /* Return true if x is integer */
[email protected]@ -205,8 +482,35 @@
- {
- if (is_complex ())
- return false;
-+ /* Multiplication and division by 10000 is used to get around a
-+ * limitation to the "fix" for Sun bugtraq bug #4006391 in the
-+ * floor () routine in mp.c, when the re_exponent is less than 1.
-+ */
-+ var t3 = new Number.integer (10000);
-+ var t1 = multiply (t3);
-+ t1 = t1.divide (t3);
-+ var t2 = t1.floor ();
-+ return t1.equals (t2);
-
-- return re_num.is_integer () != 0;
-+ /* Correct way to check for integer */
-+ /*
-+
-+ // Zero is an integer
-+ if (is_zero ())
-+ return true;
-+
-+ // fractional
-+ if (re_exponent <= 0)
-+ return false;
-+
-+ // Look for fractional components
-+ for (var i = re_exponent; i < SIZE; i++)
-+ {
-+ if (re_fraction[i] != 0)
-+ return false;
-+ }
-+
-+ return true;*/
- }
-
- /* Return true if x is a positive integer */
[email protected]@ -215,7 +519,7 @@
- if (is_complex ())
- return false;
- else
-- return re_num.sgn () >= 0 && is_integer ();
-+ return re_sign >= 0 && is_integer ();
- }
-
- /* Return true if x is a natural number (an integer ≥ 0) */
[email protected]@ -224,34 +528,19 @@
- if (is_complex ())
- return false;
- else
-- return re_num.sgn () > 0 && is_integer ();
-+ return re_sign > 0 && is_integer ();
- }
-
- /* Return true if x has an imaginary component */
- public bool is_complex ()
- {
-- return !im_num.is_zero ();
-+ return im_sign != 0;
- }
-
-- /* Return error if overflow or underflow */
-- public static void check_flags ()
-- {
-- if (mpfr_is_underflow () != 0)
-- {
-- /* Translators: Error displayed when underflow error occured */
-- error = _("Underflow error");
-- }
-- else if (mpfr_is_overflow () != 0)
-- {
-- /* Translators: Error displayed when overflow error occured */
-- error = _("Overflow error");
-- }
-- }
--
- /* Return true if x == y */
- public bool equals (Number y)
- {
-- return re_num.is_equal (y.re_num);
-+ return compare (y) == 0;
- }
-
- /* Returns:
[email protected]@ -261,25 +550,62 @@
- */
- public int compare (Number y)
- {
-- return re_num.cmp (y.re_num);
-+ if (re_sign != y.re_sign)
-+ {
-+ if (re_sign > y.re_sign)
-+ return 1;
-+ else
-+ return -1;
-+ }
-+
-+ /* x = y = 0 */
-+ if (is_zero ())
-+ return 0;
-+
-+ /* See if numbers are of different magnitude */
-+ if (re_exponent != y.re_exponent)
-+ {
-+ if (re_exponent > y.re_exponent)
-+ return re_sign;
-+ else
-+ return -re_sign;
-+ }
-+
-+ /* Compare fractions */
-+ for (var i = 0; i < SIZE; i++)
-+ {
-+ if (re_fraction[i] == y.re_fraction[i])
-+ continue;
-+
-+ if (re_fraction[i] > y.re_fraction[i])
-+ return re_sign;
-+ else
-+ return -re_sign;
-+ }
-+
-+ /* x = y */
-+ return 0;
- }
-
- /* Sets z = sgn (x) */
- public Number sgn ()
- {
-- var z = new Number.integer (re_num.sgn ());
-- return z;
-+ if (is_zero ())
-+ return new Number.integer (0);
-+ else if (is_negative ())
-+ return new Number.integer (-1);
-+ else
-+ return new Number.integer (1);
- }
-
- /* 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 = copy ();
-+
-+ z.re_sign = -z.re_sign;
-+ z.im_sign = -z.im_sign;
-+
- return z;
- }
-
[email protected]@ -294,13 +620,13 @@
- x_real = x_real.multiply (x_real);
- x_im = x_im.multiply (x_im);
- var z = x_real.add (x_im);
-- return z.sqrt ();
-+ return z.root (2);
- }
- else
- {
-- var tmp = MPFloat.init2 ((Precision) precision);
-- tmp.abs (re_num, Round.NEAREST);
-- var z = new Number.mpfloat (tmp);
-+ var z = copy ();
-+ if (z.re_sign < 0)
-+ z.re_sign = -z.re_sign;
- return z;
- }
- }
[email protected]@ -311,7 +637,7 @@
- if (is_zero ())
- {
- /* Translators: Error display when attempting to take argument of zero */
-- error = _("Argument not defined for zero");
-+ mperr (_("Argument not defined for zero"));
- return new Number.integer (0);
- }
-
[email protected]@ -355,12 +681,8 @@
- /* 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;
-+ z.im_sign = -z.im_sign;
- return z;
- }
-
[email protected]@ -368,11 +690,13 @@
- 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;
-+
-+ /* Clear imaginary component */
-+ z.im_sign = 0;
-+ z.im_exponent = 0;
-+ for (var i = 0; i < z.im_fraction.length; i++)
-+ z.im_fraction[i] = 0;
-+
- return z;
- }
-
[email protected]@ -380,30 +704,65 @@
- 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.re_sign = im_sign;
-+ z.re_exponent = im_exponent;
-+
-+ for (var i = 0; i < z.im_fraction.length; i++)
-+ z.re_fraction[i] = im_fraction[i];
-+
-+ /* Clear (old) imaginary component */
-+ z.im_sign = 0;
-+ z.im_exponent = 0;
-+ for (var i = 0; i < z.im_fraction.length; i++)
-+ z.im_fraction[i] = 0;
-+
- return z;
- }
-
- public Number integer_component ()
- {
-- var tmp = MPFloat.init2 ((Precision) precision);
-- tmp.trunc (re_num);
-- var z = new Number.mpfloat (tmp);
-+ /* Clear re_fraction */
-+ var z = copy ();
-+ for (var i = z.re_exponent; i < SIZE; i++)
-+ z.re_fraction[i] = 0;
-+ z.im_sign = 0;
-+ z.im_exponent = 0;
-+ for (var i = 0; i < z.im_fraction.length; i++)
-+ z.im_fraction[i] = 0;
-+
- 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);
-+ /* fractional component of zero is 0 */
-+ if (is_zero ())
-+ return new Number.integer (0);
-+
-+ /* All fractional */
-+ if (re_exponent <= 0)
-+ return this;
-+
-+ /* Shift fractional component */
-+ var shift = re_exponent;
-+ for (var i = shift; i < SIZE && re_fraction[i] == 0; i++)
-+ shift++;
-+ var z = new Number.integer (0);
-+ z.re_sign = re_sign;
-+ z.re_exponent = re_exponent - shift;
-+ for (var i = 0; i < SIZE; i++)
-+ {
-+ if (i + shift >= SIZE)
-+ z.re_fraction[i] = 0;
-+ else
-+ z.re_fraction[i] = re_fraction[i + shift];
-+ }
-+ if (z.re_fraction[0] == 0)
-+ z.re_sign = 0;
-+
- return z;
- }
-
[email protected]@ -416,9 +775,36 @@
- /* Sets z = ⌊x⌋ */
- public Number floor ()
- {
-- var tmp = MPFloat.init2 ((Precision) precision);
-- tmp.floor (re_num);
-- var z = new Number.mpfloat (tmp);
-+ /* Integer component of zero = 0 */
-+ if (is_zero ())
-+ return this;
-+
-+ /* If all fractional then no integer component */
-+ if (re_exponent <= 0)
-+ {
-+ if (is_negative ())
-+ return new Number.integer (-1);
-+ else
-+ return new Number.integer (0);
-+ }
-+
-+ /* Clear fractional component */
-+ var z = copy ();
-+ var have_fraction = false;
-+ for (var i = z.re_exponent; i < SIZE; i++)
-+ {
-+ if (z.re_fraction[i] != 0)
-+ have_fraction = true;
-+ z.re_fraction[i] = 0;
-+ }
-+ z.im_sign = 0;
-+ z.im_exponent = 0;
-+ for (var i = 0; i < z.im_fraction.length; i++)
-+ z.im_fraction[i] = 0;
-+
-+ if (have_fraction && is_negative ())
-+ z = z.add (new Number.integer (-1));
-+
- return z;
- }
-
[email protected]@ -425,19 +811,29 @@
- /* Sets z = ⌈x⌉ */
- public Number ceiling ()
- {
-- var tmp = MPFloat.init2 ((Precision) precision);
-- tmp.ceil (re_num);
-- var z = new Number.mpfloat (tmp);
-- return z;
-+ var z = floor ();
-+ var f = fractional_component ();
-+ if (f.is_zero ())
-+ return z;
-+ return z.add (new Number.integer (1));
- }
-
- /* Sets z = [x] */
- public Number round ()
- {
-- var tmp = MPFloat.init2 ((Precision) precision);
-- tmp.round (re_num);
-- var z = new Number.mpfloat (tmp);
-- return z;
-+ var do_floor = !is_negative ();
-+
-+ var f = fractional_component ();
-+ f = f.multiply_integer (2);
-+ f = f.abs ();
-+ if (f.compare (new Number.integer (1)) >= 0)
-+ do_floor = !do_floor;
-+
-+ if (do_floor)
-+ return floor ();
-+ else
-+ return ceiling ();
-+
- }
-
- /* Sets z = 1 ÷ x */
[email protected]@ -482,24 +878,10 @@
- /* Sets z = x^y */
- public Number xpowy (Number y)
- {
-- /* 0^-n invalid */
-- if (is_zero () && y.is_negative ())
-+ if (y.is_integer ())
-+ return xpowy_integer (y.to_integer ());
-+ else
- {
-- /* Translators: Error displayed when attempted to raise 0 to a negative re_exponent */
-- error = _("The power of zero is undefined for a negative exponent");
-- return new Number.integer (0);
-- }
--
-- /* 0^0 is indeterminate */
-- if (is_zero () && y.is_zero ())
-- {
-- /* Translators: Error displayed when attempted to raise 0 to power of zero */
-- error = _("Zero raised to zero is undefined");
-- return new Number.integer (0);
-- }
--
-- if (!y.is_integer ())
-- {
- var reciprocal = y.reciprocal ();
- if (reciprocal.is_integer ())
- return root (reciprocal.to_integer ());
[email protected]@ -506,29 +888,6 @@
- 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);
-- [email protected] (t.im_num, Round.NEAREST);
-- z.im_num = tmp;
-- return z;
- }
-
- /* Sets z = x^y */
[email protected]@ -538,7 +897,7 @@
- if (is_zero () && n < 0)
- {
- /* Translators: Error displayed when attempted to raise 0 to a negative re_exponent */
-- error = _("The power of zero is undefined for a negative exponent");
-+ mperr (_("The power of zero is undefined for a negative exponent"));
- return new Number.integer (0);
- }
-
[email protected]@ -546,10 +905,22 @@
- if (is_zero () && n == 0)
- {
- /* Translators: Error displayed when attempted to raise 0 to power of zero */
-- error = _("Zero raised to zero is undefined");
-+ mperr (_("Zero raised to zero is undefined"));
- return new Number.integer (0);
- }
-
-+ /* x^0 = 1 */
-+ if (n == 0)
-+ return new Number.integer (1);
-+
-+ /* 0^n = 0 */
-+ if (is_zero ())
-+ return new Number.integer (0);
-+
-+ /* x^1 = x */
-+ if (n == 1)
-+ return this;
-+
- Number t;
- if (n < 0)
- {
[email protected]@ -557,44 +928,17 @@
- 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);
-- [email protected] (t.im_num, Round.NEAREST);
-- z.im_num = tmp;
-- return z;
-- }
--
-- private Number pwr (Number y)
-- {
-- /* (-x)^y imaginary */
-- /* FIXME: Make complex numbers optional */
-- /*if (re_sign < 0)
-+ var z = new Number.integer (1);
-+ while (n != 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);
-+ if (n % 2 == 1)
-+ z = z.multiply (t);
-+ t = t.multiply (t);
-+ n = n / 2;
- }
--
-- /* x^0 = 1 */
-- if (y.is_zero ())
-- return new Number.integer (1);
--
-- return y.multiply (ln ()).epowy ();
-+ return z;
- }
-
- /* Sets z = n√x */
[email protected]@ -623,10 +967,22 @@
- /* Sets z = √x */
- public Number sqrt ()
- {
-- var tmp = MPFloat.init2 ((Precision) precision);
-- tmp.sqrt (re_num, Round.NEAREST);
-- var z = new Number.mpfloat (tmp);
-- return z;
-+ if (is_zero ())
-+ return this;
-+
-+ /* FIXME: Make complex numbers optional */
-+ /*if (re_sign < 0)
-+ {
-+ mperr (_("Square root is undefined for negative values"));
-+ return new Number.integer (0);
-+ }*/
-+ else
-+ {
-+ var t = root (-2);
-+ var z = multiply (t);
-+ return z.ext (t.re_fraction[0], z.re_fraction[0]);
-+ }
-+
- }
-
- /* Sets z = ln x */
[email protected]@ -636,7 +992,7 @@
- if (is_zero ())
- {
- /* Translators: Error displayed when attempting to take logarithm of zero */
-- error = _("Logarithm of zero is undefined");
-+ mperr (_("Logarithm of zero is undefined"));
- return new Number.integer (0);
- }
-
[email protected]@ -669,7 +1025,7 @@
- if (is_zero ())
- {
- /* Translators: Error displayed when attempting to take logarithm of zero */
-- error = _("Logarithm of zero is undefined");
-+ mperr (_("Logarithm of zero is undefined"));
- return new Number.integer (0);
- }
-
[email protected]@ -691,17 +1047,17 @@
- if (is_negative () || is_complex ())
- {
- /* Translators: Error displayed when attempted take the factorial of a negative or complex number */
-- error = _("Factorial is only defined for non-negative real numbers");
-+ mperr (_("Factorial is only defined for non-negative real numbers"));
- return new Number.integer (0);
- }
-
-- var tmp = add (new Number.integer (1));
-- var tmp2 = MPFloat.init2 ((Precision) precision);
-+ var val = to_double ();
-
- /* Factorial(x) = Gamma(x+1) - This is the formula used to calculate Factorial.*/
-- tmp2.gamma (tmp.re_num, Round.NEAREST);
-+ var fact = Math.tgamma(val+1);
-
-- return new Number.mpfloat (tmp2);
-+ return new Number.double(fact);
-+
- }
-
- /* Convert to integer - if couldn't be converted then the factorial would be too big anyway */
[email protected]@ -716,41 +1072,23 @@
- /* 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);
-+ return add_with_sign (1, 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);
-- return z;
-- }
--
- /* Sets z = x − y */
- public Number subtract (Number y)
- {
-- return add (y.invert_sign ());
-+ return add_with_sign (-1, y);
- }
-
- /* Sets z = x × y */
- public Number multiply (Number y)
- {
-+ /* x*0 = 0*y = 0 */
-+ if (is_zero () || y.is_zero ())
-+ return new Number.integer (0);
-+
-+ /* (a+bi)(c+di) = (ac-bd)+(ad+bc)i */
- if (is_complex () || y.is_complex ())
- {
- Number t1, t2, real_z, im_z;
[email protected]@ -774,23 +1112,17 @@
- 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;
-- 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;
-- return z;
-+ if (is_complex ())
-+ {
-+ var re_z = real_component ().multiply_integer_real (y);;
-+ var im_z = imaginary_component ().multiply_integer_real (y);
-+ return new Number.complex (re_z, im_z);
-+ }
-+ else
-+ return multiply_integer_real (y);
- }
-
- /* Sets z = x ÷ y */
[email protected]@ -799,31 +1131,23 @@
- if (y.is_zero ())
- {
- /* Translators: Error displayed attempted to divide by zero */
-- error = _("Division by zero is undefined");
-+ mperr (_("Division by zero is undefined"));
- return new Number.integer (0);
- }
-+ /* 0/y = 0 */
-+ if (is_zero ())
-+ return this;
-
-- if (is_complex () || y.is_complex ())
-- {
-- var a = real_component ();
-- var b = imaginary_component ();
-- var c = y.real_component ();
-- var d = y.imaginary_component ();
-+ /* z = x × y⁻¹ */
-+ /* FIXME: Set re_exponent to zero to avoid overflow in multiply??? */
-+ var t = y.reciprocal ();
-+ var ie = t.re_exponent;
-+ t.re_exponent = 0;
-+ var i = t.re_fraction[0];
-+ var z = multiply (t);
-+ z = z.ext (i, z.re_fraction[0]);
-+ z.re_exponent += ie;
-
-- 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);
- return z;
- }
-
[email protected]@ -830,7 +1154,14 @@
- /* Sets z = x ÷ y */
- public Number divide_integer (int64 y)
- {
-- return divide (new Number.integer (y));
-+ if (is_complex ())
-+ {
-+ var re_z = real_component ().divide_integer_real (y);
-+ var im_z = imaginary_component ().divide_integer_real (y);
-+ return new Number.complex (re_z, im_z);
-+ }
-+ else
-+ return divide_integer_real (y);
- }
-
- /* Sets z = x mod y */
[email protected]@ -839,7 +1170,7 @@
- if (!is_integer () || !y.is_integer ())
- {
- /* Translators: Error displayed when attemping to do a modulus division on non-integer numbers */
-- error = _("Modulus division is only defined for integers");
-+ mperr (_("Modulus division is only defined for integers"));
- return new Number.integer (0);
- }
-
[email protected]@ -857,7 +1188,7 @@
- /* Sets z = x ^ y mod p */
- public Number modular_exponentiation (Number exp, Number mod)
- {
-- var base_value = copy ();
-+ var base_value = this.copy ();
- if (exp.is_negative ())
- base_value = base_value.reciprocal ();
- var exp_value = exp.abs ();
[email protected]@ -927,51 +1258,87 @@
- public Number tan (AngleUnit unit = AngleUnit.RADIANS)
- {
- /* Check for undefined values */
-- var x_radians = to_radians (unit);
-- var check = x_radians.subtract (new Number.pi ().divide_integer (2)).divide (new Number.pi ());
--
-- if (check.is_integer ())
-+ var cos_x = cos (unit);
-+ if (cos_x.is_zero ())
- {
- /* Translators: Error displayed when tangent value is undefined */
-- error = _("Tangent is undefined for angles that are multiples of π (180°) from π∕2 (90°)");
-+ mperr (_("Tangent is undefined for angles that are multiples of π (180°) from π∕2 (90°)"));
- 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);
-- return z;
-+ /* tan (x) = sin (x) / cos (x) */
-+ return sin (unit).divide (cos_x);
- }
-
- /* Sets z = sin⁻¹ x */
- public Number asin (AngleUnit unit = AngleUnit.RADIANS)
- {
-- if (compare (new Number.integer (1)) > 0 || compare (new Number.integer (-1)) < 0)
-- {
-- /* Translators: Error displayed when inverse sine value is undefined */
-- error = _("Inverse sine is undefined for values outside [-1, 1]");
-+ /* asin⁻¹(0) = 0 */
-+ if (is_zero ())
- return new Number.integer (0);
-+
-+ /* sin⁻¹(x) = tan⁻¹(x / √(1 - x²)), |x| < 1 */
-+ if (re_exponent <= 0)
-+ {
-+ var t1 = new Number.integer (1);
-+ var t2 = t1;
-+ t1 = t1.subtract (this);
-+ t2 = t2.add (this);
-+ t2 = t1.multiply (t2);
-+ t2 = t2.root (-2);
-+ var z = multiply (t2);
-+ z = z.atan (unit);
-+ return z;
- }
-
-- var tmp = MPFloat.init2 ((Precision) precision);
-- tmp.asin (re_num, Round.NEAREST);
-- var z = new Number.mpfloat (tmp);
-- return z.from_radians (unit);
-+ /* sin⁻¹(1) = π/2, sin⁻¹(-1) = -π/2 */
-+ var t2 = new Number.integer (re_sign);
-+ if (equals (t2))
-+ {
-+ var z = new Number.pi ().divide_integer (2 * t2.re_sign);
-+ return z.from_radians (unit);
-+ }
-+
-+ /* Translators: Error displayed when inverse sine value is undefined */
-+ mperr (_("Inverse sine is undefined for values outside [-1, 1]"));
-+ return new Number.integer (0);
- }
-
- /* Sets z = cos⁻¹ x */
- public Number acos (AngleUnit unit = AngleUnit.RADIANS)
- {
-- if (compare (new Number.integer (1)) > 0 || compare (new Number.integer (-1)) < 0)
-+ var pi = new Number.pi ();
-+ var t1 = new Number.integer (1);
-+ var n1 = new Number.integer (-1);
-+
-+ Number z;
-+ if (compare (t1) > 0 || compare (n1) < 0)
- {
- /* Translators: Error displayed when inverse cosine value is undefined */
-- error = _("Inverse cosine is undefined for values outside [-1, 1]");
-- return new Number.integer (0);
-+ mperr (_("Inverse cosine is undefined for values outside [-1, 1]"));
-+ z = new Number.integer (0);
- }
-+ else if (is_zero ())
-+ z = pi.divide_integer (2);
-+ else if (equals (t1))
-+ z = new Number.integer (0);
-+ else if (equals (n1))
-+ z = pi;
-+ else
-+ {
-+ /* cos⁻¹(x) = tan⁻¹(√(1 - x²) / x) */
-+ Number y;
-+ var t2 = multiply (this);
-+ t2 = t1.subtract (t2);
-+ t2 = t2.sqrt ();
-+ t2 = t2.divide (this);
-+ y = t2.atan (AngleUnit.RADIANS);
-+ if (re_sign > 0)
-+ z = y;
-+ else
-+ z = y.add (pi);
-+ }
-
-- var tmp = MPFloat.init2 ((Precision) precision);
-- tmp.acos (re_num, Round.NEAREST);
-- var z = new Number.mpfloat (tmp);
- return z.from_radians (unit);
- }
-
[email protected]@ -978,9 +1345,63 @@
- /* 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);
-+ if (is_zero ())
-+ return new Number.integer (0);
-+
-+ var t2 = this;
-+ var rx = 0f;
-+ if (re_exponent.abs () <= 2)
-+ rx = to_float ();
-+
-+ /* REDUCE ARGUMENT IF NECESSARY BEFORE USING SERIES */
-+ var q = 1;
-+ Number z;
-+ while (t2.re_exponent >= 0)
-+ {
-+ if (t2.re_exponent == 0 && 2 * (t2.re_fraction[0] + 1) <= BASE)
-+ break;
-+
-+ q *= 2;
-+
-+ /* t = t / (√(t² + 1) + 1) */
-+ z = t2.multiply (t2);
-+ z = z.add (new Number.integer (1));
-+ z = z.sqrt ();
-+ z = z.add (new Number.integer (1));
-+ t2 = t2.divide (z);
-+ }
-+
-+ /* USE POWER SERIES NOW ARGUMENT IN (-0.5, 0.5) */
-+ z = t2;
-+ var t1 = t2.multiply (t2);
-+
-+ /* SERIES LOOP. REDUCE T IF POSSIBLE. */
-+ for (var i = 1; ; i += 2)
-+ {
-+ if (T + 2 + t2.re_exponent <= 1)
-+ break;
-+
-+ t2 = t2.multiply (t1).multiply_integer (-i).divide_integer (i + 2);
-+
-+ z = z.add (t2);
-+ if (t2.is_zero ())
-+ break;
-+ }
-+
-+ /* CORRECT FOR ARGUMENT REDUCTION */
-+ z = z.multiply_integer (q);
-+
-+ /* CHECK THAT RELATIVE ERROR LESS THAN 0.01 UNLESS re_exponent
-+ * OF X IS LARGE (WHEN ATAN MIGHT NOT WORK)
-+ */
-+ if (re_exponent.abs () <= 2)
-+ {
-+ float ry = z.to_float ();
-+ /* THE FOLLOWING MESSAGE MAY INDICATE THAT B**(T-1) IS TOO SMALL. */
-+ if (Math.fabs (ry - Math.atan (rx)) >= Math.fabs (ry) * 0.01)
-+ mperr ("*** ERROR OCCURRED IN ATAN, RESULT INCORRECT ***");
-+ }
-+
- return z.from_radians (unit);
- }
-
[email protected]@ -987,27 +1408,88 @@
- /* 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);
-- return z;
-+ /* sinh (0) = 0 */
-+ if (is_zero ())
-+ return new Number.integer (0);
-+
-+ /* WORK WITH ABS (X) */
-+ var abs_x = abs ();
-+
-+ /* If |x| < 1 USE EXP TO AVOID CANCELLATION, otherwise IF TOO LARGE EPOWY GIVES ERROR MESSAGE */
-+ Number z;
-+ if (abs_x.re_exponent <= 0)
-+ {
-+ /* ((e^|x| + 1) * (e^|x| - 1)) / e^|x| */
-+ // FIXME: Solves to e^|x| - e^-|x|, why not lower branch always? */
-+ var exp_x = abs_x.epowy ();
-+ var a = exp_x.add (new Number.integer (1));
-+ var b = exp_x.add (new Number.integer (-1));
-+ z = a.multiply (b);
-+ z = z.divide (exp_x);
-+ }
-+ else
-+ {
-+ /* e^|x| - e^-|x| */
-+ var exp_x = abs_x.epowy ();
-+ z = exp_x.reciprocal ();
-+ z = exp_x.subtract (z);
-+ }
-+
-+ /* DIVIDE BY TWO AND RESTORE re_sign */
-+ z = z.divide_integer (2);
-+ return z.multiply_integer (re_sign);
- }
-
- /* 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);
-- return z;
-+ /* cosh (0) = 1 */
-+ if (is_zero ())
-+ return new Number.integer (1);
-+
-+ /* cosh (x) = (e^x + e^-x) / 2 */
-+ var t = abs ();
-+ t = t.epowy ();
-+ var z = t.reciprocal ();
-+ z = t.add (z);
-+ return z.divide_integer (2);
- }
-
- /* 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);
-+ /* tanh (0) = 0 */
-+ if (is_zero ())
-+ return new Number.integer (0);
-+
-+ var t = abs ();
-+
-+ /* SEE IF ABS (X) SO LARGE THAT RESULT IS +-1 */
-+ var r__1 = (float) T * 0.5 * Math.log ((float) BASE);
-+ var z = new Number.double (r__1);
-+ if (t.compare (z) > 0)
-+ return new Number.integer (re_sign);
-+
-+ /* If |x| >= 1/2 use ?, otherwise use ? to avoid cancellation */
-+ /* |tanh (x)| = (e^|2x| - 1) / (e^|2x| + 1) */
-+ t = t.multiply_integer (2);
-+ if (t.re_exponent > 0)
-+ {
-+ t = t.epowy ();
-+ z = t.add (new Number.integer (-1));
-+ t = t.add (new Number.integer (1));
-+ z = z.divide (t);
-+ }
-+ else
-+ {
-+ t = t.epowy ();
-+ z = t.add (new Number.integer (1));
-+ t = t.add (new Number.integer (-1));
-+ z = t.divide (z);
-+ }
-+
-+ /* Restore re_sign */
-+ z.re_sign = re_sign * z.re_sign;
- return z;
- }
-
[email protected]@ -1014,10 +1496,12 @@
- /* 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);
-- return z;
-+ /* sinh⁻¹(x) = ln (x + √(x² + 1)) */
-+ var t = multiply (this);
-+ t = t.add (new Number.integer (1));
-+ t = t.sqrt ();
-+ t = add (t);
-+ return t.ln ();
- }
-
- /* Sets z = cosh⁻¹ x */
[email protected]@ -1028,14 +1512,16 @@
- if (compare (t) < 0)
- {
- /* Translators: Error displayed when inverse hyperbolic cosine value is undefined */
-- error = _("Inverse hyperbolic cosine is undefined for values less than one");
-+ mperr (_("Inverse hyperbolic cosine is undefined for values less than one"));
- return new Number.integer (0);
- }
-
-- var tmp = MPFloat.init2 ((Precision) precision);
-- tmp.acosh (re_num, Round.NEAREST);
-- var z = new Number.mpfloat (tmp);
-- return z;
-+ /* cosh⁻¹(x) = ln (x + √(x² - 1)) */
-+ t = multiply (this);
-+ t = t.add (new Number.integer (-1));
-+ t = t.sqrt ();
-+ t = add (t);
-+ return t.ln ();
- }
-
- /* Sets z = tanh⁻¹ x */
[email protected]@ -1045,14 +1531,17 @@
- if (compare (new Number.integer (1)) >= 0 || compare (new Number.integer (-1)) <= 0)
- {
- /* Translators: Error displayed when inverse hyperbolic tangent value is undefined */
-- error = _("Inverse hyperbolic tangent is undefined for values outside [-1, 1]");
-+ mperr (_("Inverse hyperbolic tangent is undefined for values outside [-1, 1]"));
- return new Number.integer (0);
- }
-
-- var tmp = MPFloat.init2 ((Precision) precision);
-- tmp.atanh (re_num, Round.NEAREST);
-- var z = new Number.mpfloat (tmp);
-- return z;
-+ /* atanh (x) = 0.5 * ln ((1 + x) / (1 - x)) */
-+ var n = add (new Number.integer (1));
-+ var d = invert_sign ();
-+ d = d.add (new Number.integer (1));
-+ var z = n.divide (d);
-+ z = z.ln ();
-+ return z.divide_integer (2);
- }
-
- /* Sets z = boolean AND for each bit in x and z */
[email protected]@ -1062,7 +1551,7 @@
- is_positive_integer () || !y.is_positive_integer ())
- {
- /* Translators: Error displayed when boolean AND attempted on non-integer values */
-- error = _("Boolean AND is only defined for positive integers");
-+ mperr (_("Boolean AND is only defined for positive integers"));
- }
-
- return bitwise (y, (v1, v2) => { return v1 & v2; }, 0);
[email protected]@ -1074,7 +1563,7 @@
- if (!is_positive_integer () || !y.is_positive_integer ())
- {
- /* Translators: Error displayed when boolean OR attempted on non-integer values */
-- error = _("Boolean OR is only defined for positive integers");
-+ mperr (_("Boolean OR is only defined for positive integers"));
- }
-
- return bitwise (y, (v1, v2) => { return v1 | v2; }, 0);
[email protected]@ -1086,7 +1575,7 @@
- if (!is_positive_integer () || !y.is_positive_integer ())
- {
- /* Translators: Error displayed when boolean XOR attempted on non-integer values */
-- error = _("Boolean XOR is only defined for positive integers");
-+ mperr (_("Boolean XOR is only defined for positive integers"));
- }
-
- return bitwise (y, (v1, v2) => { return v1 ^ v2; }, 0);
[email protected]@ -1098,7 +1587,7 @@
- if (!is_positive_integer ())
- {
- /* Translators: Error displayed when boolean XOR attempted on non-integer values */
-- error = _("Boolean NOT is only defined for positive integers");
-+ mperr (_("Boolean NOT is only defined for positive integers"));
- }
-
- return bitwise (new Number.integer (0), (v1, v2) => { return v1 ^ 0xF; }, wordlen);
[email protected]@ -1121,7 +1610,7 @@
- if (!is_integer ())
- {
- /* Translators: Error displayed when bit shift attempted on non-integer values */
-- error = _("Shift is only possible on integer values");
-+ mperr (_("Shift is only possible on integer values"));
- return new Number.integer (0);
- }
-
[email protected]@ -1253,60 +1742,1056 @@
- private Number copy ()
- {
- var z = new Number ();
-- var tmp = MPFloat.init2 ((Precision) precision);
-- var tmp2 = MPFloat.init2 ((Precision) precision);
-- [email protected](re_num, Round.NEAREST);
-- [email protected](im_num, Round.NEAREST);
-- z.re_num = tmp;
-- z.im_num = tmp2;
-+ z.re_sign = re_sign;
-+ z.im_sign = im_sign;
-+ z.re_exponent = re_exponent;
-+ z.im_exponent = im_exponent;
-+ for (var i = 0; i < re_fraction.length; i++)
-+ {
-+ z.re_fraction[i] = re_fraction[i];
-+ z.im_fraction[i] = im_fraction[i];
-+ }
-+
- return z;
- }
-
-+ private Number add_with_sign (int y_sign, 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 (y_sign * y.re_sign, real_y);
-+ im_z = im_x.add_real (y_sign * y.im_sign, im_y);
-+
-+ return new Number.complex (real_z, im_z);
-+ }
-+ else
-+ return add_real (y_sign * y.re_sign, y);
-+ }
-+
-+
- private Number epowy_real ()
- {
-- var z = copy ();
-- var tmp = z.re_num;
-- tmp.exp (re_num, Round.NEAREST);
-- z.re_num = tmp;
-+ /* e^0 = 1 */
-+ if (is_zero ())
-+ return new Number.integer (1);
-+
-+ /* If |x| < 1 use exp */
-+ if (re_exponent <= 0)
-+ return exp ();
-+
-+ /* NOW SAFE TO CONVERT X TO REAL */
-+ var rx = to_double ();
-+
-+ /* SAVE re_sign AND WORK WITH ABS (X) */
-+ var xs = re_sign;
-+ var t2 = abs ();
-+
-+ /* GET fractional AND INTEGER PARTS OF ABS (X) */
-+ var ix = t2.to_integer ();
-+ t2 = t2.fractional_component ();
-+
-+ /* ATTACH re_sign TO fractional PART AND COMPUTE EXP OF IT */
-+ t2.re_sign *= xs;
-+ var z = t2.exp ();
-+
-+ /* COMPUTE E-2 OR 1/E USING TWO EXTRA DIGITS IN CASE ABS (X) LARGE
-+ * (BUT ONLY ONE EXTRA DIGIT IF T < 4)
-+ */
-+ var tss = 0;
-+ if (T < 4)
-+ tss = T + 1;
-+ else
-+ tss = T + 2;
-+
-+ /* LOOP FOR E COMPUTATION. DECREASE T IF POSSIBLE. */
-+ /* Computing MIN */
-+ var t1 = new Number.integer (xs);
-+
-+ t2.re_sign = 0;
-+ for (var i = 2 ; ; i++)
-+ {
-+ if (int.min (tss, tss + 2 + t1.re_exponent) <= 2)
-+ break;
-+
-+ t1 = t1.divide_integer (i * xs);
-+ t2 = t2.add (t1);
-+ if (t1.is_zero ())
-+ break;
-+ }
-+
-+ /* RAISE E OR 1/E TO POWER IX */
-+ if (xs > 0)
-+ t2 = t2.add (new Number.integer (2));
-+ t2 = t2.xpowy_integer (ix);
-+
-+ /* MULTIPLY EXPS OF INTEGER AND fractional PARTS */
-+ z = z.multiply (t2);
-+
-+ /* CHECK THAT RELATIVE ERROR LESS THAN 0.01 UNLESS ABS (X) LARGE
-+ * (WHEN EXP MIGHT OVERFLOW OR UNDERFLOW)
-+ */
-+ if (Math.fabs (rx) > 10.0f)
-+ return z;
-+ var rz = z.to_double ();
-+ var r__1 = rz - Math.exp (rx);
-+ if (Math.fabs (r__1) < rz * 0.01f)
-+ return z;
-+
-+ /* THE FOLLOWING MESSAGE MAY INDICATE THAT
-+ * B**(T-1) IS TOO SMALL, OR THAT M IS TOO SMALL SO THE
-+ * RESULT UNDERFLOWED.
-+ */
-+ mperr ("*** ERROR OCCURRED IN EPOWY, RESULT INCORRECT ***");
- return z;
-+
- }
-
-+ /* Return e^x for |x| < 1 USING AN o (SQRt (T).m (T)) ALGORITHM
-+ * DESCRIBED IN - R. P. BRENT, THE COMPLEXITY OF MULTIPLE-
-+ * PRECISION ARITHMETIC (IN COMPLEXITY OF COMPUTATIONAL PROBLEM
-+ * SOLVING, UNIV. OF QUEENSLAND PRESS, BRISBANE, 1976, 126-165).
-+ * ASYMPTOTICALLY FASTER METHODS EXIST, BUT ARE NOT USEFUL
-+ * UNLESS T IS VERY LARGE. SEE COMMENTS TO MP_ATAN AND MPPIGL.
-+ */
-+ private Number exp ()
-+ {
-+ /* e^0 = 1 */
-+ if (is_zero ())
-+ return new Number.integer (1);
-+
-+ /* Only defined for |x| < 1 */
-+ if (re_exponent > 0)
-+ {
-+ mperr ("*** ABS (X) NOT LESS THAN 1 IN CALL TO MP_EXP ***");
-+ return new Number.integer (0);
-+ }
-+
-+ var t1 = this;
-+ var rlb = Math.log (BASE);
-+
-+ /* Compute approximately optimal q (and divide x by 2^q) */
-+ var q = (int) (Math.sqrt (T * 0.48 * rlb) + re_exponent * 1.44 * rlb);
-+
-+ /* HALVE Q TIMES */
-+ if (q > 0)
-+ {
-+ var ib = BASE << 2;
-+ var ic = 1;
-+ for (var i = 1; i <= q; i++)
-+ {
-+ ic *= 2;
-+ if (ic < ib && ic != BASE && i < q)
-+ continue;
-+ t1 = t1.divide_integer (ic);
-+ ic = 1;
-+ }
-+ }
-+
-+ if (t1.is_zero ())
-+ return new Number.integer (0);
-+
-+ /* Sum series, reducing t where possible */
-+ var z = t1.copy ();
-+ var t2 = t1;
-+ for (var i = 2; T + t2.re_exponent - z.re_exponent > 0; i++)
-+ {
-+ t2 = t1.multiply (t2);
-+ t2 = t2.divide_integer (i);
-+ z = t2.add (z);
-+ if (t2.is_zero ())
-+ break;
-+ }
-+
-+ /* Apply (x+1)^2 - 1 = x (2 + x) for q iterations */
-+ for (var i = 1; i <= q; i++)
-+ {
-+ t1 = z.add (new Number.integer (2));
-+ z = t1.multiply (z);
-+ }
-+
-+ return z.add (new Number.integer (1));
-+ }
-+
-+ 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.re_sign < 0)
-+ mperr (_("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 ();
-+ }
-+
- private Number root_real (int64 n)
- {
-+ /* x^(1/1) = x */
-+ if (n == 1)
-+ return this;
-+
-+ /* x^(1/0) invalid */
-+ if (n == 0)
-+ {
-+ mperr (_("Root must be non-zero"));
-+ return new Number.integer (0);
-+ }
-+
-+ var np = n.abs ();
-+
-+ /* LOSS OF ACCURACY IF NP LARGE, SO ONLY ALLOW NP <= MAX (B, 64) */
-+ if (np > int.max (BASE, 64))
-+ {
-+ mperr ("*** ABS (N) TOO LARGE IN CALL TO ROOT ***");
-+ return new Number.integer (0);
-+ }
-+
-+ /* 0^(1/n) = 0 for positive n */
-+ if (is_zero ())
-+ {
-+ if (n <= 0)
-+ mperr (_("Negative root of zero is undefined"));
-+ return new Number.integer (0);
-+ }
-+
-+ // FIXME: Imaginary root
-+ if (re_sign < 0 && np % 2 == 0)
-+ {
-+ mperr (_("nth root of negative number is undefined for even n"));
-+ return new Number.integer (0);
-+ }
-+
-+ /* DIVIDE re_exponent BY NP */
-+ var ex = re_exponent / np;
-+
-+ /* Get initial approximation */
-+ var t1 = copy ();
-+ t1.re_exponent = 0;
-+ var approximation = Math.exp (((np * ex - re_exponent) * Math.log (BASE) - Math.log (Math.fabs (t1.to_float ()))) / np);
-+ t1 = new Number.double (approximation);
-+ t1.re_sign = re_sign;
-+ t1.re_exponent -= (int) ex;
-+
-+ /* MAIN ITERATION LOOP */
-+ var it0 = 3;
-+ var t = it0;
-+ Number t2;
-+ while (true)
-+ {
-+ /* t1 = t1 - ((t1 * ((x * t1^np) - 1)) / np) */
-+ t2 = t1.xpowy_integer (np);
-+ t2 = multiply (t2);
-+ t2 = t2.add (new Number.integer (-1));
-+ t2 = t1.multiply (t2);
-+ t2 = t2.divide_integer (np);
-+ t1 = t1.subtract (t2);
-+
-+ /* FOLLOWING LOOP ALMOST DOUBLES T (POSSIBLE BECAUSE
-+ * NEWTONS METHOD HAS 2ND ORDER CONVERGENCE).
-+ */
-+ if (t >= T)
-+ break;
-+
-+ var ts3 = t;
-+ var ts2 = t;
-+ t = T;
-+ do
-+ {
-+ ts2 = t;
-+ t = (t + it0) / 2;
-+ } while (t > ts3);
-+ t = int.min (ts2, T);
-+ }
-+
-+ /* NOW r (I2) IS X**(-1/NP)
-+ * CHECK THAT NEWTON ITERATION WAS CONVERGING
-+ */
-+ if (t2.re_sign != 0 && (t1.re_exponent - t2.re_exponent) << 1 < T - it0)
-+ {
-+ /* THE FOLLOWING MESSAGE MAY INDICATE THAT B**(T-1) IS TOO SMALL,
-+ * OR THAT THE INITIAL APPROXIMATION OBTAINED USING ALOG AND EXP
-+ * IS NOT ACCURATE ENOUGH.
-+ */
-+ mperr ("*** ERROR OCCURRED IN ROOT, NEWTON ITERATION NOT CONVERGING PROPERLY ***");
-+ }
-+
-+ if (n >= 0)
-+ {
-+ t1 = t1.xpowy_integer (n - 1);
-+ return multiply (t1);
-+ }
-+
-+ return t1;
-+
-+ }
-+
-+ /* ROUTINE CALLED BY DIVIDE AND SQRT TO ENSURE THAT
-+ * RESULTS ARE REPRESENTED EXACTLY IN T-2 DIGITS IF THEY
-+ * CAN BE. X IS AN MP NUMBER, I AND J ARE INTEGERS.
-+ */
-+ private Number ext (int i, int j)
-+ {
-+ if (is_zero () || T <= 2 || i == 0)
-+ return this;
-+
-+ /* COMPUTE MAXIMUM POSSIBLE ERROR IN THE LAST PLACE */
-+ var q = (j + 1) / i + 1;
-+ var s = BASE * re_fraction[T - 2] + re_fraction[T - 1];
-+
-+ /* SET LAST TWO DIGITS TO ZERO */
- var z = copy ();
-- var tmp = z.re_num;
-- tmp.root (re_num, (ulong) n, Round.NEAREST);
-- z.re_num = tmp;
-- return z;
-+ if (s <= q)
-+ {
-+ z.re_fraction[T - 2] = 0;
-+ z.re_fraction[T - 1] = 0;
-+ return z;
-+ }
-+
-+ if (s + q < BASE * BASE)
-+ return z;
-+
-+ /* ROUND UP HERE */
-+ z.re_fraction[T - 2] = BASE - 1;
-+ z.re_fraction[T - 1] = BASE;
-+
-+ /* NORMALIZE X (LAST DIGIT B IS OK IN MULTIPLY_INTEGER) */
-+ return z.multiply_integer (1);
- }
-
-+
- private Number ln_real ()
- {
-- var tmp = MPFloat.init2 ((Precision) precision);
-- tmp.log (re_num, Round.NEAREST);
-- var z = new Number.mpfloat (tmp);
-+ // ln(e^1) = 1, fixes precision loss
-+ if (equals (new Number.eulers ()))
-+ return new Number.integer (1);
-+
-+ /* LOOP TO GET APPROXIMATE Ln (X) USING SINGLE-PRECISION */
-+ var t1 = copy ();
-+ var z = new Number.integer (0);
-+ for (var k = 0; k < 10; k++)
-+ {
-+ /* COMPUTE FINAL CORRECTION ACCURATELY USING LNS */
-+ var t2 = t1.add (new Number.integer (-1));
-+ if (t2.is_zero () || t2.re_exponent + 1 <= 0)
-+ return z.add (t2.lns ());
-+
-+ /* REMOVE EXPONENT TO AVOID FLOATING-POINT OVERFLOW */
-+ var e = t1.re_exponent;
-+ t1.re_exponent = 0;
-+ var rx = t1.to_double ();
-+ t1.re_exponent = e;
-+ var rlx = Math.log (rx) + e * Math.log (BASE);
-+ t2 = new Number.double (-rlx);
-+
-+ /* UPDATE Z AND COMPUTE ACCURATE EXP OF APPROXIMATE LOG */
-+ z = z.subtract (t2);
-+ t2 = t2.epowy ();
-+
-+ /* COMPUTE RESIDUAL WHOSE LOG IS STILL TO BE FOUND */
-+ t1 = t1.multiply (t2);
-+ }
-+
-+ mperr ("*** ERROR IN LN, ITERATION NOT CONVERGING ***");
- return z;
-+
- }
-
-+ /* RETURNS MP Y = Ln (1+X) IF X IS AN MP NUMBER SATISFYING THE
-+ * CONDITION ABS (X) < 1/B, ERROR OTHERWISE.
-+ * USES NEWTONS METHOD TO SOLVE THE EQUATION
-+ * EXP1(-Y) = X, THEN REVERSES re_sign OF Y.
-+ */
-+ private Number lns ()
-+ {
-+ /* ln (1+0) = 0 */
-+ if (is_zero ())
-+ return this;
-+
-+ /* Get starting approximation -ln (1+x) ~= -x + x^2/2 - x^3/3 + x^4/4 */
-+ var t2 = copy ();
-+ var t1 = divide_integer (4);
-+ t1 = t1.add (new Number.fraction (-1, 3));
-+ t1 = multiply (t1);
-+ t1 = t1.add (new Number.fraction (1, 2));
-+ t1 = multiply (t1);
-+ t1 = t1.add (new Number.integer (-1));
-+ var z = multiply (t1);
-+
-+ /* Solve using Newtons method */
-+ var it0 = 5;
-+ var t = it0;
-+ Number t3;
-+ while (true)
-+ {
-+ /* t3 = (e^t3 - 1) */
-+ /* z = z - (t2 + t3 + (t2 * t3)) */
-+ t3 = z.epowy ();
-+ t3 = t3.add (new Number.integer (-1));
-+ t1 = t2.multiply (t3);
-+ t3 = t3.add (t1);
-+ t3 = t2.add (t3);
-+ z = z.subtract (t3);
-+ if (t >= T)
-+ break;
-+
-+ /* FOLLOWING LOOP COMPUTES NEXT VALUE OF T TO USE.
-+ * BECAUSE NEWTONS METHOD HAS 2ND ORDER CONVERGENCE,
-+ * WE CAN ALMOST DOUBLE T EACH TIME.
-+ */
-+ var ts3 = t;
-+ var ts2 = t;
-+ t = T;
-+ do
-+ {
-+ ts2 = t;
-+ t = (t + it0) / 2;
-+ } while (t > ts3);
-+ t = ts2;
-+ }
-+
-+ /* CHECK THAT NEWTON ITERATION WAS CONVERGING AS EXPECTED */
-+ if (t3.re_sign != 0 && t3.re_exponent << 1 > it0 - T)
-+ mperr ("*** ERROR OCCURRED IN LNS, NEWTON ITERATION NOT CONVERGING PROPERLY ***");
-+
-+ z.re_sign = -z.re_sign;
-+
-+ return z;
-+ }
-+
-+ private Number add_real (int y_sign, Number y)
-+ {
-+ var re_sign_prod = y_sign * re_sign;
-+
-+ /* 0 + y = y */
-+ if (is_zero ())
-+ {
-+ if (y_sign != y.re_sign)
-+ return y.invert_sign ();
-+ else
-+ return y;
-+ }
-+ /* x + 0 = x */
-+ else if (y.is_zero ())
-+ return this;
-+
-+ var exp_diff = re_exponent - y.re_exponent;
-+ var med = exp_diff.abs ();
-+ var x_largest = false;
-+ if (exp_diff < 0)
-+ x_largest = false;
-+ else if (exp_diff > 0)
-+ x_largest = true;
-+ else
-+ {
-+ /* EXPONENTS EQUAL SO COMPARE SIGNS, THEN FRACTIONS IF NEC. */
-+ if (re_sign_prod < 0)
-+ {
-+ /* signs are not equal. find out which mantissa is larger. */
-+ int j;
-+ for (j = 0; j < T; j++)
-+ {
-+ int i = re_fraction[j] - y.re_fraction[j];
-+ if (i != 0)
-+ {
-+ if (i < 0)
-+ x_largest = false;
-+ else if (i > 0)
-+ x_largest = true;
-+ break;
-+ }
-+ }
-+
-+ /* Both mantissas equal, so result is zero. */
-+ if (j >= T)
-+ return new Number.integer (0);
-+ }
-+ }
-+
-+ var z = new Number.integer (0);
-+ int[] big_fraction, small_fraction;
-+ if (x_largest)
-+ {
-+ z.re_sign = re_sign;
-+ z.re_exponent = re_exponent;
-+ big_fraction = re_fraction;
-+ small_fraction = y.re_fraction;
-+ }
-+ else
-+ {
-+ z.re_sign = y_sign;
-+ z.re_exponent = y.re_exponent;
-+ big_fraction = y.re_fraction;
-+ small_fraction = re_fraction;
-+ }
-+
-+ /* CLEAR GUARD DIGITS TO RIGHT OF X DIGITS */
-+ for (var i = 3; i >= med; i--)
-+ z.re_fraction[T + i] = 0;
-+
-+ if (re_sign_prod >= 0)
-+ {
-+ /* This is probably insufficient overflow detection, but it makes us not crash at least. */
-+ if (T + 3 < med)
-+ {
-+ mperr (_("Overflow: the result couldn't be calculated"));
-+ return new Number.integer (0);
-+ }
-+
-+ /* HERE DO ADDITION, re_exponent (Y) >= re_exponent (X) */
-+ var i = 0;
-+ for (i = T + 3; i >= T; i--)
-+ z.re_fraction[i] = small_fraction[i - med];
-+
-+ var c = 0;
-+ for (; i >= med; i--)
-+ {
-+ c = big_fraction[i] + small_fraction[i - med] + c;
-+
-+ if (c < BASE)
-+ {
-+ /* NO CARRY GENERATED HERE */
-+ z.re_fraction[i] = c;
-+ c = 0;
-+ }
-+ else
-+ {
-+ /* CARRY GENERATED HERE */
-+ z.re_fraction[i] = c - BASE;
-+ c = 1;
-+ }
-+ }
-+
-+ for (; i >= 0; i--)
-+ {
-+ c = big_fraction[i] + c;
-+ if (c < BASE)
-+ {
-+ z.re_fraction[i] = c;
-+ i--;
-+
-+ /* NO CARRY POSSIBLE HERE */
-+ for (; i >= 0; i--)
-+ z.re_fraction[i] = big_fraction[i];
-+
-+ c = 0;
-+ break;
-+ }
-+
-+ z.re_fraction[i] = 0;
-+ c = 1;
-+ }
-+
-+ /* MUST SHIFT RIGHT HERE AS CARRY OFF END */
-+ if (c != 0)
-+ {
-+ for (var j = T + 3; j > 0; j--)
-+ z.re_fraction[j] = z.re_fraction[j - 1];
-+ z.re_fraction[0] = 1;
-+ z.re_exponent++;
-+ }
-+ }
-+ else
-+ {
-+ var c = 0;
-+ var i = 0;
-+ for (i = T + med - 1; i >= T; i--)
-+ {
-+ /* HERE DO SUBTRACTION, ABS (Y) > ABS (X) */
-+ z.re_fraction[i] = c - small_fraction[i - med];
-+ c = 0;
-+
-+ /* BORROW GENERATED HERE */
-+ if (z.re_fraction[i] < 0)
-+ {
-+ c = -1;
-+ z.re_fraction[i] += BASE;
-+ }
-+ }
-+
-+ for (; i >= med; i--)
-+ {
-+ c = big_fraction[i] + c - small_fraction[i - med];
-+ if (c >= 0)
-+ {
-+ /* NO BORROW GENERATED HERE */
-+ z.re_fraction[i] = c;
-+ c = 0;
-+ }
-+ else
-+ {
-+ /* BORROW GENERATED HERE */
-+ z.re_fraction[i] = c + BASE;
-+ c = -1;
-+ }
-+ }
-+
-+ for (; i >= 0; i--)
-+ {
-+ c = big_fraction[i] + c;
-+
-+ if (c >= 0)
-+ {
-+ z.re_fraction[i] = c;
-+ i--;
-+
-+ /* NO CARRY POSSIBLE HERE */
-+ for (; i >= 0; i--)
-+ z.re_fraction[i] = big_fraction[i];
-+
-+ break;
-+ }
-+
-+ z.re_fraction[i] = c + BASE;
-+ c = -1;
-+ }
-+ }
-+
-+ mp_normalize (ref z);
-+
-+ return z;
-+ }
-+
-+ private Number multiply_real (Number y)
-+ {
-+ /* x*0 = 0*y = 0 */
-+ if (re_sign == 0 || y.re_sign == 0)
-+ return new Number.integer (0);
-+
-+ var z = new Number.integer (0);
-+ z.re_sign = re_sign * y.re_sign;
-+ z.re_exponent = re_exponent + y.re_exponent;
-+
-+ var r = new Number.integer (0);
-+
-+ /* PERFORM MULTIPLICATION */
-+ var c = 8;
-+ for (var i = 0; i < T; i++)
-+ {
-+ var xi = re_fraction[i];
-+
-+ /* FOR SPEED, PUT THE NUMBER WITH MANY ZEROS FIRST */
-+ if (xi == 0)
-+ continue;
-+
-+ /* Computing MIN */
-+ for (var j = 0; j < int.min (T, T + 3 - i); j++)
-+ r.re_fraction[i+j+1] += xi * y.re_fraction[j];
-+ c--;
-+ if (c > 0)
-+ continue;
-+
-+ /* CHECK FOR LEGAL BASE B DIGIT */
-+ if (xi < 0 || xi >= BASE)
-+ {
-+ mperr ("*** ILLEGAL BASE B DIGIT IN CALL TO MULTIPLY, POSSIBLE OVERWRITING PROBLEM ***");
-+ return new Number.integer (0);
-+ }
-+
-+ /* PROPAGATE CARRIES AT END AND EVERY EIGHTH TIME,
-+ * FASTER THAN DOING IT EVERY TIME.
-+ */
-+ for (var j = T + 3; j >= 0; j--)
-+ {
-+ int ri = r.re_fraction[j] + c;
-+ if (ri < 0)
-+ {
-+ mperr ("*** INTEGER OVERFLOW IN MULTIPLY, B TOO LARGE ***");
-+ return new Number.integer (0);
-+ }
-+ c = ri / BASE;
-+ r.re_fraction[j] = ri - BASE * c;
-+ }
-+ if (c != 0)
-+ {
-+ mperr ("*** ILLEGAL BASE B DIGIT IN CALL TO MULTIPLY, POSSIBLE OVERWRITING PROBLEM ***");
-+ return new Number.integer (0);
-+ }
-+ c = 8;
-+ }
-+
-+ if (c != 8)
-+ {
-+ c = 0;
-+ for (var i = T + 3; i >= 0; i--)
-+ {
-+ int ri = r.re_fraction[i] + c;
-+ if (ri < 0)
-+ {
-+ mperr ("*** INTEGER OVERFLOW IN MULTIPLY, B TOO LARGE ***");
-+ return new Number.integer (0);
-+ }
-+ c = ri / BASE;
-+ r.re_fraction[i] = ri - BASE * c;
-+ }
-+
-+ if (c != 0)
-+ {
-+ mperr ("*** ILLEGAL BASE B DIGIT IN CALL TO MULTIPLY, POSSIBLE OVERWRITING PROBLEM ***");
-+ return new Number.integer (0);
-+ }
-+ }
-+
-+ /* Clear complex part */
-+ z.im_sign = 0;
-+ z.im_exponent = 0;
-+ for (var i = 0; i < z.im_fraction.length; i++)
-+ z.im_fraction[i] = 0;
-+
-+ /* NORMALIZE AND ROUND RESULT */
-+ // FIXME: Use stack variable because of mp_normalize brokeness
-+ for (var i = 0; i < SIZE; i++)
-+ z.re_fraction[i] = r.re_fraction[i];
-+ mp_normalize (ref z);
-+
-+ return z;
-+ }
-+
-+ private Number multiply_integer_real (int64 y)
-+ {
-+ /* x*0 = 0*y = 0 */
-+ if (is_zero () || y == 0)
-+ return new Number.integer (0);
-+
-+ /* x*1 = x, x*-1 = -x */
-+ // FIXME: Why is this not working? mp_ext is using this function to do a normalization
-+ /*if (y == 1 || y == -1)
-+ {
-+ if (y < 0)
-+ z = invert_sign ();
-+ else
-+ z = this;
-+ return z;
-+ }*/
-+
-+ /* Copy x as z may also refer to x */
-+ var z = new Number.integer (0);
-+
-+ if (y < 0)
-+ {
-+ y = -y;
-+ z.re_sign = -re_sign;
-+ }
-+ else
-+ z.re_sign = re_sign;
-+ z.re_exponent = re_exponent + 4;
-+
-+ /* FORM PRODUCT IN ACCUMULATOR */
-+ int64 c = 0;
-+
-+ /* IF y*B NOT REPRESENTABLE AS AN INTEGER WE HAVE TO SIMULATE
-+ * DOUBLE-PRECISION MULTIPLICATION.
-+ */
-+
-+ /* Computing MAX */
-+ if (y >= int.max (BASE << 3, 32767 / BASE))
-+ {
-+ /* HERE J IS TOO LARGE FOR SINGLE-PRECISION MULTIPLICATION */
-+ var j1 = y / BASE;
-+ var j2 = y - j1 * BASE;
-+
-+ /* FORM PRODUCT */
-+ for (var i = T + 3; i >= 0; i--)
-+ {
-+ var c1 = c / BASE;
-+ var c2 = c - BASE * c1;
-+ var ix = 0;
-+ if (i > 3)
-+ ix = re_fraction[i - 4];
-+
-+ var t = j2 * ix + c2;
-+ var is = t / BASE;
-+ c = j1 * ix + c1 + is;
-+ z.re_fraction[i] = (int) (t - BASE * is);
-+ }
-+ }
-+ else
-+ {
-+ int64 ri = 0;
-+ for (var i = T + 3; i >= 4; i--)
-+ {
-+ ri = y * re_fraction[i - 4] + c;
-+ c = ri / BASE;
-+ z.re_fraction[i] = (int) (ri - BASE * c);
-+ }
-+
-+ /* CHECK FOR INTEGER OVERFLOW */
-+ if (ri < 0)
-+ {
-+ mperr ("*** INTEGER OVERFLOW IN multiply_integer, B TOO LARGE ***");
-+ return new Number.integer (0);
-+ }
-+
-+ /* HAVE TO TREAT FIRST FOUR WORDS OF R SEPARATELY */
-+ for (var i = 3; i >= 0; i--)
-+ {
-+ var t = c;
-+ c = t / BASE;
-+ z.re_fraction[i] = (int) (t - BASE * c);
-+ }
-+ }
-+
-+ /* HAVE TO SHIFT RIGHT HERE AS CARRY OFF END */
-+ while (c != 0)
-+ {
-+ for (var i = T + 3; i >= 1; i--)
-+ z.re_fraction[i] = z.re_fraction[i - 1];
-+ var t = c;
-+ c = t / BASE;
-+ z.re_fraction[0] = (int) (t - BASE * c);
-+ z.re_exponent++;
-+ }
-+
-+ if (c < 0)
-+ {
-+ mperr ("*** INTEGER OVERFLOW IN multiply_integer, B TOO LARGE ***");
-+ return new Number.integer (0);
-+ }
-+
-+ z.im_sign = 0;
-+ z.im_exponent = 0;
-+ for (var i = 0; i < z.im_fraction.length; i++)
-+ z.im_fraction[i] = 0;
-+ mp_normalize (ref z);
-+ return z;
-+ }
-+
- private Number reciprocal_real ()
- {
- /* 1/0 invalid */
- if (is_zero ())
- {
-- error = _("Reciprocal of zero is undefined");
-+ mperr (_("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;
-+ /* Start by approximating value using floating point */
-+ var t1 = copy ();
-+ t1.re_exponent = 0;
-+ t1 = new Number.double (1.0 / t1.to_double ());
-+ t1.re_exponent -= re_exponent;
-+
-+ var t = 3;
-+ var it0 = t;
-+ Number t2;
-+ while (true)
-+ {
-+ /* t1 = t1 - (t1 * ((x * t1) - 1)) (2*t1 - t1^2*x) */
-+ t2 = multiply (t1);
-+ t2 = t2.add (new Number.integer (-1));
-+ t2 = t1.multiply (t2);
-+ t1 = t1.subtract (t2);
-+ if (t >= T)
-+ break;
-+
-+ /* FOLLOWING LOOP ALMOST DOUBLES T (POSSIBLE
-+ * BECAUSE NEWTONS METHOD HAS 2ND ORDER CONVERGENCE).
-+ */
-+ var ts3 = t;
-+ var ts2 = 0;
-+ t = T;
-+ do
-+ {
-+ ts2 = t;
-+ t = (t + it0) / 2;
-+ } while (t > ts3);
-+ t = int.min (ts2, T);
-+ }
-+
-+ /* RETURN IF NEWTON ITERATION WAS CONVERGING */
-+ if (t2.re_sign != 0 && (t1.re_exponent - t2.re_exponent) << 1 < T - it0)
-+ {
-+ /* THE FOLLOWING MESSAGE MAY INDICATE THAT B**(T-1) IS TOO SMALL,
-+ * OR THAT THE STARTING APPROXIMATION IS NOT ACCURATE ENOUGH.
-+ */
-+ mperr ("*** ERROR OCCURRED IN RECIPROCAL, NEWTON ITERATION NOT CONVERGING PROPERLY ***");
-+ }
-+
-+ return t1;
- }
-
-+ private Number divide_integer_real (int64 y)
-+ {
-+ /* x/0 */
-+ if (y == 0)
-+ {
-+ /* Translators: Error displayed attempted to divide by zero */
-+ mperr (_("Division by zero is undefined"));
-+ return new Number.integer (0);
-+ }
-
-+ /* 0/y = 0 */
-+ if (is_zero ())
-+ return new Number.integer (0);
-+
-+ /* Division by -1 or 1 just changes re_sign */
-+ if (y == 1 || y == -1)
-+ {
-+ if (y < 0)
-+ return invert_sign ();
-+ else
-+ return this;
-+ }
-+
-+ var z = new Number.integer (0);
-+ if (y < 0)
-+ {
-+ y = -y;
-+ z.re_sign = -re_sign;
-+ }
-+ else
-+ z.re_sign = re_sign;
-+ z.re_exponent = re_exponent;
-+
-+ int64 c = 0;
-+ int64 i = 0;
-+
-+ /* IF y*B NOT REPRESENTABLE AS AN INTEGER HAVE TO SIMULATE
-+ * LONG DIVISION. ASSUME AT LEAST 16-BIT WORD.
-+ */
-+
-+ /* Computing MAX */
-+ var b2 = int.max (BASE << 3, 32767 / BASE);
-+ if (y < b2)
-+ {
-+ /* LOOK FOR FIRST NONZERO DIGIT IN QUOTIENT */
-+ int64 r1 = 0;
-+ do
-+ {
-+ c = BASE * c;
-+ if (i < T)
-+ c += re_fraction[i];
-+ i++;
-+ r1 = c / y;
-+ if (r1 < 0)
-+ {
-+ mperr ("*** INTEGER OVERFLOW IN DIVIDE_INTEGER, B TOO LARGE ***");
-+ return new Number.integer (0);
-+ }
-+ } while (r1 == 0);
-+
-+ /* ADJUST re_exponent AND GET T+4 DIGITS IN QUOTIENT */
-+ z.re_exponent += (int) (1 - i);
-+ z.re_fraction[0] = (int) r1;
-+ c = BASE * (c - y * r1);
-+ int64 kh = 1;
-+ if (i < T)
-+ {
-+ kh = T + 1 - i;
-+ for (var k = 1; k < kh; k++)
-+ {
-+ c += re_fraction[i];
-+ z.re_fraction[k] = (int) (c / y);
-+ c = BASE * (c - y * z.re_fraction[k]);
-+ i++;
-+ }
-+ if (c < 0)
-+ {
-+ mperr ("*** INTEGER OVERFLOW IN DIVIDE_INTEGER, B TOO LARGE ***");
-+ return new Number.integer (0);
-+ }
-+ }
-+
-+ for (var k = kh; k < T + 4; k++)
-+ {
-+ z.re_fraction[k] = (int) (c / y);
-+ c = BASE * (c - y * z.re_fraction[k]);
-+ }
-+ if (c < 0)
-+ {
-+ mperr ("*** INTEGER OVERFLOW IN DIVIDE_INTEGER, B TOO LARGE ***");
-+ return new Number.integer (0);
-+ }
-+
-+ mp_normalize (ref z);
-+ return z;
-+ }
-+
-+ /* HERE NEED SIMULATED DOUBLE-PRECISION DIVISION */
-+ var j1 = y / BASE;
-+ var j2 = y - j1 * BASE;
-+
-+ /* LOOK FOR FIRST NONZERO DIGIT */
-+ var c2 = 0;
-+ do
-+ {
-+ c = BASE * c + c2;
-+ c2 = i < T ? re_fraction[i] : 0;
-+ i++;
-+ } while (c < j1 || (c == j1 && c2 < j2));
-+
-+ /* COMPUTE T+4 QUOTIENT DIGITS */
-+ z.re_exponent += (int) (1 - i);
-+ i--;
-+
-+ /* MAIN LOOP FOR LARGE ABS (y) CASE */
-+ for (var k = 1; k <= T + 4; k++)
-+ {
-+ /* GET APPROXIMATE QUOTIENT FIRST */
-+ var ir = c / (j1 + 1);
-+
-+ /* NOW REDUCE SO OVERFLOW DOES NOT OCCUR */
-+ var iq = c - ir * j1;
-+ if (iq >= b2)
-+ {
-+ /* HERE IQ*B WOULD POSSIBLY OVERFLOW SO INCREASE IR */
-+ ir++;
-+ iq -= j1;
-+ }
-+
-+ iq = iq * BASE - ir * j2;
-+ if (iq < 0)
-+ {
-+ /* HERE IQ NEGATIVE SO IR WAS TOO LARGE */
-+ ir--;
-+ iq += y;
-+ }
-+
-+ if (i < T)
-+ iq += re_fraction[i];
-+ i++;
-+ var iqj = iq / y;
-+
-+ /* r (K) = QUOTIENT, C = REMAINDER */
-+ z.re_fraction[k - 1] = (int) (iqj + ir);
-+ c = iq - y * iqj;
-+
-+ if (c < 0)
-+ {
-+ /* CARRY NEGATIVE SO OVERFLOW MUST HAVE OCCURRED */
-+ mperr ("*** INTEGER OVERFLOW IN DIVIDE_INTEGER, B TOO LARGE ***");
-+ return new Number.integer (0);
-+ }
-+ }
-+
-+ mp_normalize (ref z);
-+
-+ /* CARRY NEGATIVE SO OVERFLOW MUST HAVE OCCURRED */
-+ mperr ("*** INTEGER OVERFLOW IN DIVIDE_INTEGER, B TOO LARGE ***");
-+ return new Number.integer (0);
-+ }
-+
-+
-+
- private Number from_radians (AngleUnit unit)
- {
- switch (unit)
[email protected]@ -1340,23 +2825,146 @@
- }
- }
-
-+ /* z = sin (x) -1 >= x >= 1, do_sin = 1
-+ * z = cos (x) -1 >= x >= 1, do_sin = 0
-+ */
-+ private Number sin1 (bool do_sin)
-+ {
-+ /* sin (0) = 0, cos (0) = 1 */
-+ if (is_zero ())
-+ {
-+ if (do_sin)
-+ return new Number.integer (0);
-+ else
-+ return new Number.integer (1);
-+ }
-+
-+ var t2 = multiply (this);
-+ if (t2.compare (new Number.integer (1)) > 0)
-+ mperr ("*** ABS (X) > 1 IN CALL TO SIN1 ***");
-+
-+ Number t1;
-+ int i;
-+ Number z;
-+ if (do_sin)
-+ {
-+ t1 = this;
-+ z = t1;
-+ i = 2;
-+ }
-+ else
-+ {
-+ t1 = new Number.integer (1);
-+ z = new Number.integer (0);
-+ i = 1;
-+ }
-+
-+ /* Taylor series */
-+ /* POWER SERIES LOOP. REDUCE T IF POSSIBLE */
-+ var b2 = 2 * int.max (BASE, 64);
-+ do
-+ {
-+ if (T + t1.re_exponent <= 0)
-+ break;
-+
-+ /* IF I*(I+1) IS NOT REPRESENTABLE AS AN INTEGER, THE FOLLOWING
-+ * DIVISION BY I*(I+1) HAS TO BE SPLIT UP.
-+ */
-+ t1 = t2.multiply (t1);
-+ if (i > b2)
-+ {
-+ t1 = t1.divide_integer (-i);
-+ t1 = t1.divide_integer (i + 1);
-+ }
-+ else
-+ t1 = t1.divide_integer (-i * (i + 1));
-+ z = t1.add (z);
-+
-+ i += 2;
-+ } while (t1.re_sign != 0);
-+
-+ if (!do_sin)
-+ z = z.add (new Number.integer (1));
-+
-+ return z;
-+ }
-+
-+
- private Number sin_real (AngleUnit unit)
- {
-+ /* sin (0) = 0 */
-+ if (is_zero ())
-+ return new Number.integer (0);
-+
- 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 xs = x_radians.re_sign;
-+ x_radians = x_radians.abs ();
-+
-+ /* USE SIN1 IF ABS (X) <= 1 */
-+ Number z;
-+ if (x_radians.compare (new Number.integer (1)) <= 0)
-+ z = x_radians.sin1 (true);
-+ /* FIND ABS (X) MODULO 2PI */
-+ else
-+ {
-+ z = new Number.pi ().divide_integer (4);
-+ x_radians = x_radians.divide (z);
-+ x_radians = x_radians.divide_integer (8);
-+ x_radians = x_radians.fractional_component ();
-+
-+ /* SUBTRACT 1/2, SAVE re_sign AND TAKE ABS */
-+ x_radians = x_radians.add (new Number.fraction (-1, 2));
-+ xs = -xs * x_radians.re_sign;
-+ if (xs == 0)
-+ return new Number.integer (0);
-+
-+ x_radians.re_sign = 1;
-+ x_radians = x_radians.multiply_integer (4);
-+
-+ /* IF NOT LESS THAN 1, SUBTRACT FROM 2 */
-+ if (x_radians.re_exponent > 0)
-+ x_radians = x_radians.add (new Number.integer (-2));
-+
-+ if (x_radians.is_zero ())
-+ return new Number.integer (0);
-+
-+ x_radians.re_sign = 1;
-+ x_radians = x_radians.multiply_integer (2);
-+
-+ /* NOW REDUCED TO FIRST QUADRANT, IF LESS THAN PI/4 USE
-+ * POWER SERIES, ELSE COMPUTE COS OF COMPLEMENT
-+ */
-+ if (x_radians.re_exponent > 0)
-+ {
-+ x_radians = x_radians.add (new Number.integer (-2));
-+ x_radians = x_radians.multiply (z);
-+ z = x_radians.sin1 (false);
-+ }
-+ else
-+ {
-+ x_radians = x_radians.multiply (z);
-+ z = x_radians.sin1 (true);
-+ }
-+ }
-+
-+ z.re_sign = xs;
- return z;
- }
-
- private Number cos_real (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);
-- return z;
-+ /* cos (0) = 1 */
-+ if (is_zero ())
-+ return new Number.integer (1);
-+
-+ /* Use power series if |x| <= 1 */
-+ var z = to_radians (unit).abs ();
-+ if (z.compare (new Number.integer (1)) <= 0)
-+ return z.sin1 (false);
-+ else
-+ /* cos (x) = sin (π/2 - |x|) */
-+ return new Number.pi ().divide_integer (2).subtract (z).sin (AngleUnit.RADIANS);
- }
-
- private Number bitwise (Number y, BitwiseFunc bitwise_operator, int wordlen)
[email protected]@ -1370,7 +2978,7 @@
- offset_out = offset1 > offset2 ? offset1 : offset2;
- if (offset_out > 0 && (offset_out < offset1 || offset_out < offset2))
- {
-- error = ("Overflow. Try a bigger word size");
-+ mperr ("Overflow. Try a bigger word size");
- return new Number.integer (0);
- }
-
[email protected]@ -1420,6 +3028,29 @@
-
- // FIXME: Re-add overflow and underflow detection
-
-+static string? mp_error = null;
-+
-+/* THIS ROUTINE IS CALLED WHEN AN ERROR CONDITION IS ENCOUNTERED, AND
-+ * AFTER A MESSAGE HAS BEEN WRITTEN TO STDERR.
-+ */
-+public void mperr (string text)
-+{
-+ mp_error = text;
-+}
-+
-+/* Returns error string or null if no error */
-+// FIXME: Global variable
-+public string mp_get_error ()
-+{
-+ return mp_error;
-+}
-+
-+/* Clear any current error */
-+public void mp_clear_error ()
-+{
-+ mp_error = null;
-+}
-+
- /* Sets z from a string representation in 'text'. */
- public Number? mp_set_from_string (string str, int default_base = 10)
- {
[email protected]@ -1468,7 +3099,6 @@
-
- /* Convert integer part */
- var z = new Number.integer (0);
--
- while (str.get_next_char (ref index, out c))
- {
- var i = char_val (c, number_base);
[email protected]@ -1600,6 +3230,73 @@
- return null;
- }
-
-+/* RETURNS K = K/GCD AND L = L/GCD, WHERE GCD IS THE
-+ * GREATEST COMMON DIVISOR OF K AND L.
-+ * SAVE INPUT PARAMETERS IN LOCAL VARIABLES
-+ */
-+public void mp_gcd (ref int64 k, ref int64 l)
-+{
-+ var i = k.abs ();
-+ var j = l.abs ();
-+ if (j == 0)
-+ {
-+ /* IF J = 0 RETURN (1, 0) UNLESS I = 0, THEN (0, 0) */
-+ k = 1;
-+ l = 0;
-+ if (i == 0)
-+ k = 0;
-+ return;
-+ }
-+
-+ /* EUCLIDEAN ALGORITHM LOOP */
-+ do
-+ {
-+ i %= j;
-+ if (i == 0)
-+ {
-+ k = k / j;
-+ l = l / j;
-+ return;
-+ }
-+ j %= i;
-+ } while (j != 0);
-+
-+ /* HERE J IS THE GCD OF K AND L */
-+ k = k / i;
-+ l = l / i;
-+}
-+
-+// FIXME: Is r.re_fraction large enough? It seems to be in practise but it may be T+4 instead of T
-+// FIXME: There is some sort of stack corruption/use of unitialised variables here. Some functions are
-+// using stack variables as x otherwise there are corruption errors. e.g. "Cos (45) - 1/Sqrt (2) = -0"
-+// (try in scientific mode)
-+public void mp_normalize (ref Number x)
-+{
-+ int start_index;
-+
-+ /* Find first non-zero digit */
-+ for (start_index = 0; start_index < SIZE && x.re_fraction[start_index] == 0; start_index++);
-+
-+ /* Mark as zero */
-+ if (start_index >= SIZE)
-+ {
-+ x.re_sign = 0;
-+ x.re_exponent = 0;
-+ return;
-+ }
-+
-+ /* Shift left so first digit is non-zero */
-+ if (start_index > 0)
-+ {
-+ x.re_exponent -= start_index;
-+ var i = 0;
-+ for (; (i + start_index) < SIZE; i++)
-+ x.re_fraction[i] = x.re_fraction[i + start_index];
-+ for (; i < SIZE; i++)
-+ x.re_fraction[i] = 0;
-+ }
-+}
-+
- /* Returns true if x is cannot be represented in a binary word of length 'wordlen' */
- public bool mp_is_overflow (Number x, int wordlen)
- {
-
---- gnome-calculator-3.18.2/configure.ac 2016-08-09 14:02:40.743464258 +0000
-+++ gnome-calculator-3.18.2/configure.ac 2016-08-09 14:02:52.623794159 +0000
[email protected]@ -25,9 +25,6 @@
-
- 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])])
--
- PKG_CHECK_MODULES(LIBCALCULATOR, [
- glib-2.0 >= $GLIB_REQUIRED
- gio-2.0 >= $GLIB_REQUIRED