Updated kn translations
[gcalctool.git] / src / number.vala
blobb8ad8aa564aca3a430fb2b3c412295bfdfd949ce
1 /*
2 * Copyright (C) 1987-2008 Sun Microsystems, Inc. All Rights Reserved.
3 * Copyright (C) 2008-2012 Robert Ancell
5 * This program is free software: you can redistribute it and/or modify it under
6 * the terms of the GNU General Public License as published by the Free Software
7 * Foundation, either version 2 of the License, or (at your option) any later
8 * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
9 * license.
12 /* This maths library is based on the MP multi-precision floating-point
13 * arithmetic package originally written in FORTRAN by Richard Brent,
14 * Computer Centre, Australian National University in the 1970's.
16 * It has been converted from FORTRAN into C using the freely available
17 * f2c translator, available via netlib on research.att.com.
19 * The subsequently converted C code has then been tidied up, mainly to
20 * remove any dependencies on the libI77 and libF77 support libraries.
22 * FOR A GENERAL DESCRIPTION OF THE PHILOSOPHY AND DESIGN OF MP,
23 * SEE - R. P. BRENT, A FORTRAN MULTIPLE-PRECISION ARITHMETIC
24 * PACKAGE, ACM TRANS. MATH. SOFTWARE 4 (MARCH 1978), 57-70.
25 * SOME ADDITIONAL DETAILS ARE GIVEN IN THE SAME ISSUE, 71-81.
26 * FOR DETAILS OF THE IMPLEMENTATION, CALLING SEQUENCES ETC. SEE
27 * THE MP USERS GUIDE.
30 /* Size of the multiple precision values */
31 private const int SIZE = 1000;
33 /* Base for numbers */
34 private const int BASE = 10000;
36 //2E0 BELOW ENSURES AT LEAST ONE GUARD DIGIT
37 //MP.t = (int) ((float) (accuracy) * Math.log ((float)10.) / Math.log ((float) BASE) + (float) 2.0);
38 //if (MP.t > SIZE)
39 //{
40 // mperr ("SIZE TOO SMALL IN CALL TO MPSET, INCREASE SIZE AND DIMENSIONS OF MP ARRAYS TO AT LEAST %d ***", MP.t);
41 // MP.t = SIZE;
42 //}
43 private const int T = 100;
45 private delegate int BitwiseFunc (int v1, int v2);
47 public enum AngleUnit
49 RADIANS,
50 DEGREES,
51 GRADIANS
54 /* Object for a high precision floating point number representation
56 * x = sign * (BASE^(exponent-1) + BASE^(exponent-2) + ...)
58 public class Number
60 /* Sign (+1, -1) or 0 for the value zero */
61 public int re_sign;
62 public int im_sign;
64 /* Exponent (to base BASE) */
65 public int re_exponent;
66 public int im_exponent;
68 /* Normalized fraction */
69 public int re_fraction[1000]; // SIZE
70 public int im_fraction[1000]; // SIZE
72 public Number.integer (int64 value)
74 if (value < 0)
76 value = -value;
77 re_sign = -1;
79 else if (value > 0)
80 re_sign = 1;
81 else
82 re_sign = 0;
84 while (value != 0)
86 re_fraction[re_exponent] = (int) (value % BASE);
87 re_exponent++;
88 value /= BASE;
90 for (var i = 0; i < re_exponent / 2; i++)
92 int t = re_fraction[i];
93 re_fraction[i] = re_fraction[re_exponent - i - 1];
94 re_fraction[re_exponent - i - 1] = t;
98 public Number.unsigned_integer (uint64 x)
100 if (x == 0)
101 re_sign = 0;
102 else
103 re_sign = 1;
105 while (x != 0)
107 re_fraction[re_exponent] = (int) (x % BASE);
108 x = x / BASE;
109 re_exponent++;
111 for (var i = 0; i < re_exponent / 2; i++)
113 int t = re_fraction[i];
114 re_fraction[i] = re_fraction[re_exponent - i - 1];
115 re_fraction[re_exponent - i - 1] = t;
119 public Number.fraction (int64 numerator, int64 denominator)
121 mp_gcd (ref numerator, ref denominator);
123 if (denominator < 0)
125 numerator = -numerator;
126 denominator = -denominator;
129 Number.integer (numerator);
130 if (denominator != 1)
132 var z = divide_integer (denominator);
133 re_sign = z.re_sign;
134 im_sign = z.im_sign;
135 re_exponent = z.re_exponent;
136 im_exponent = z.im_exponent;
137 for (var i = 0; i < z.re_fraction.length; i++)
139 re_fraction[i] = z.re_fraction[i];
140 im_fraction[i] = z.im_fraction[i];
145 public Number.float (float value)
147 var z = new Number.integer (0);
149 if (value != 0)
151 /* CHECK SIGN */
152 var rj = 0f;
153 if (value < 0.0f)
155 z.re_sign = -1;
156 rj = -value;
158 else if (value > 0.0f)
160 z.re_sign = 1;
161 rj = value;
164 /* INCREASE IE AND DIVIDE RJ BY 16. */
165 var ie = 0;
166 while (rj >= 1.0f)
168 ie++;
169 rj *= 0.0625f;
171 while (rj < 0.0625f)
173 ie--;
174 rj *= 16.0f;
177 /* NOW RJ IS DY DIVIDED BY SUITABLE POWER OF 16.
178 * SET re_exponent TO 0
180 z.re_exponent = 0;
182 /* CONVERSION LOOP (ASSUME SINGLE-PRECISION OPS. EXACT) */
183 for (var i = 0; i < T + 4; i++)
185 rj *= BASE;
186 z.re_fraction[i] = (int) rj;
187 rj -= z.re_fraction[i];
190 /* NORMALIZE RESULT */
191 mp_normalize (ref z);
193 /* Computing MAX */
194 var ib = int.max (BASE * 7 * BASE, 32767) / 16;
195 var tp = 1;
197 /* NOW MULTIPLY BY 16**IE */
198 if (ie < 0)
200 var k = -ie;
201 for (var i = 1; i <= k; i++)
203 tp <<= 4;
204 if (tp <= ib && tp != BASE && i < k)
205 continue;
206 z = z.divide_integer (tp);
207 tp = 1;
210 else if (ie > 0)
212 for (var i = 1; i <= ie; i++)
214 tp <<= 4;
215 if (tp <= ib && tp != BASE && i < ie)
216 continue;
217 z = z.multiply_integer (tp);
218 tp = 1;
223 re_sign = z.re_sign;
224 im_sign = z.im_sign;
225 re_exponent = z.re_exponent;
226 im_exponent = z.im_exponent;
227 for (var i = 0; i < z.re_fraction.length; i++)
229 re_fraction[i] = z.re_fraction[i];
230 im_fraction[i] = z.im_fraction[i];
234 public Number.double (double value)
236 var z = new Number.integer (0);
238 if (value != 0)
240 /* CHECK SIGN */
241 var dj = 0.0;
242 if (value < 0.0)
244 z.re_sign = -1;
245 dj = -value;
247 else if (value > 0.0)
249 z.re_sign = 1;
250 dj = value;
253 /* INCREASE IE AND DIVIDE DJ BY 16. */
254 var ie = 0;
255 for (ie = 0; dj >= 1.0; ie++)
256 dj *= 1.0/16.0;
258 for ( ; dj < 1.0/16.0; ie--)
259 dj *= 16.0;
261 /* NOW DJ IS DY DIVIDED BY SUITABLE POWER OF 16
262 * SET re_exponent TO 0
264 z.re_exponent = 0;
266 /* CONVERSION LOOP (ASSUME DOUBLE-PRECISION OPS. EXACT) */
267 for (var i = 0; i < T + 4; i++)
269 dj *= (double) BASE;
270 z.re_fraction[i] = (int) dj;
271 dj -= (double) z.re_fraction[i];
274 /* NORMALIZE RESULT */
275 mp_normalize (ref z);
277 /* Computing MAX */
278 var ib = int.max (BASE * 7 * BASE, 32767) / 16;
279 var tp = 1;
281 /* NOW MULTIPLY BY 16**IE */
282 if (ie < 0)
284 var k = -ie;
285 for (var i = 1; i <= k; ++i)
287 tp <<= 4;
288 if (tp <= ib && tp != BASE && i < k)
289 continue;
290 z = z.divide_integer (tp);
291 tp = 1;
294 else if (ie > 0)
296 for (var i = 1; i <= ie; ++i)
298 tp <<= 4;
299 if (tp <= ib && tp != BASE && i < ie)
300 continue;
301 z = z.multiply_integer (tp);
302 tp = 1;
307 re_sign = z.re_sign;
308 im_sign = z.im_sign;
309 re_exponent = z.re_exponent;
310 im_exponent = z.im_exponent;
311 for (var i = 0; i < z.re_fraction.length; i++)
313 re_fraction[i] = z.re_fraction[i];
314 im_fraction[i] = z.im_fraction[i];
318 public Number.complex (Number x, Number y)
320 re_sign = x.re_sign;
321 re_exponent = x.re_exponent;
322 for (var i = 0; i < im_fraction.length; i++)
323 re_fraction[i] = x.re_fraction[i];
325 im_sign = y.re_sign;
326 im_exponent = y.re_exponent;
327 for (var i = 0; i < im_fraction.length; i++)
328 im_fraction[i] = y.re_fraction[i];
331 public Number.polar (Number r, Number theta, AngleUnit unit = AngleUnit.RADIANS)
333 var x = theta.cos (unit);
334 var y = theta.sin (unit);
335 Number.complex (x.multiply (r), y.multiply (r));
338 public Number.eulers ()
340 var z = new Number.integer (1).epowy ();
341 re_sign = z.re_sign;
342 im_sign = z.im_sign;
343 re_exponent = z.re_exponent;
344 im_exponent = z.im_exponent;
345 for (var i = 0; i < z.re_fraction.length; i++)
347 re_fraction[i] = z.re_fraction[i];
348 im_fraction[i] = z.im_fraction[i];
352 public Number.i ()
354 im_sign = 1;
355 im_exponent = 1;
356 im_fraction[0] = 1;
359 public Number.pi ()
361 // FIXME: Should generate PI to required accuracy
362 Number.double (Math.PI);
365 /* Sets z to be a uniform random number in the range [0, 1] */
366 public Number.random ()
368 Number.double (Random.next_double ());
371 public int64 to_integer ()
373 int64 z = 0;
375 /* |x| <= 1 */
376 if (re_sign == 0 || re_exponent <= 0)
377 return 0;
379 /* Multiply digits together */
380 for (var i = 0; i < re_exponent; i++)
382 var t = z;
383 z = z * BASE + re_fraction[i];
385 /* Check for overflow */
386 if (z <= t)
387 return 0;
390 /* Validate result */
391 var v = z;
392 for (var i = re_exponent - 1; i >= 0; i--)
394 /* Get last digit */
395 var digit = v - (v / BASE) * BASE;
396 if (re_fraction[i] != digit)
397 return 0;
399 v /= BASE;
401 if (v != 0)
402 return 0;
404 return re_sign * z;
407 public uint64 to_unsigned_integer ()
409 /* x <= 1 */
410 if (re_sign <= 0 || re_exponent <= 0)
411 return 0;
413 /* Multiply digits together */
414 uint64 z = 0;
415 for (var i = 0; i < re_exponent; i++)
417 var t = z;
418 z = z * BASE + re_fraction[i];
420 /* Check for overflow */
421 if (z <= t)
422 return 0;
425 /* Validate result */
426 var v = z;
427 for (var i = re_exponent - 1; i >= 0; i--)
429 /* Get last digit */
430 var digit = (uint64) v - (v / BASE) * BASE;
431 if (re_fraction[i] != digit)
432 return 0;
434 v /= BASE;
436 if (v != 0)
437 return 0;
439 return z;
442 public float to_float ()
444 if (is_zero ())
445 return 0f;
447 var z = 0f;
448 for (var i = 0; i < T; i++)
450 if (re_fraction[i] != 0)
451 z += re_fraction[i] * Math.powf (BASE, re_exponent - i - 1);
454 if (re_sign < 0)
455 return -z;
456 else
457 return z;
460 public double to_double ()
462 if (is_zero ())
463 return 0d;
465 var z = 0d;
466 for (var i = 0; i < T; i++)
468 if (re_fraction[i] != 0)
469 z += re_fraction[i] * Math.pow (BASE, re_exponent - i - 1);
472 if (re_sign < 0)
473 return -z;
474 else
475 return z;
478 /* Return true if the value is x == 0 */
479 public bool is_zero ()
481 return re_sign == 0 && im_sign == 0;
484 /* Return true if x < 0 */
485 public bool is_negative ()
487 return re_sign < 0;
490 /* Return true if x is integer */
491 public bool is_integer ()
493 if (is_complex ())
494 return false;
496 /* This fix is required for 1/3 repiprocal not being detected as an integer */
497 /* Multiplication and division by 10000 is used to get around a
498 * limitation to the "fix" for Sun bugtraq bug #4006391 in the
499 * floor () routine in mp.c, when the re_exponent is less than 1.
501 var t3 = new Number.integer (10000);
502 var t1 = multiply (t3);
503 t1 = t1.divide (t3);
504 var t2 = t1.floor ();
505 return t1.equals (t2);
507 /* Correct way to check for integer */
510 // Zero is an integer
511 if (is_zero ())
512 return true;
514 // fractional
515 if (re_exponent <= 0)
516 return false;
518 // Look for fractional components
519 for (var i = re_exponent; i < SIZE; i++)
521 if (re_fraction[i] != 0)
522 return false;
525 return true;*/
528 /* Return true if x is a positive integer */
529 public bool is_positive_integer ()
531 if (is_complex ())
532 return false;
533 else
534 return re_sign >= 0 && is_integer ();
537 /* Return true if x is a natural number (an integer ≥ 0) */
538 public bool is_natural ()
540 if (is_complex ())
541 return false;
542 else
543 return re_sign > 0 && is_integer ();
546 /* Return true if x has an imaginary component */
547 public bool is_complex ()
549 return im_sign != 0;
552 /* Return true if x == y */
553 public bool equals (Number y)
555 return compare (y) == 0;
558 /* Returns:
559 * 0 if x == y
560 * <0 if x < y
561 * >0 if x > y
563 public int compare (Number y)
565 if (re_sign != y.re_sign)
567 if (re_sign > y.re_sign)
568 return 1;
569 else
570 return -1;
573 /* x = y = 0 */
574 if (is_zero ())
575 return 0;
577 /* See if numbers are of different magnitude */
578 if (re_exponent != y.re_exponent)
580 if (re_exponent > y.re_exponent)
581 return re_sign;
582 else
583 return -re_sign;
586 /* Compare fractions */
587 for (var i = 0; i < SIZE; i++)
589 if (re_fraction[i] == y.re_fraction[i])
590 continue;
592 if (re_fraction[i] > y.re_fraction[i])
593 return re_sign;
594 else
595 return -re_sign;
598 /* x = y */
599 return 0;
602 /* Sets z = sgn (x) */
603 public Number sgn ()
605 if (is_zero ())
606 return new Number.integer (0);
607 else if (is_negative ())
608 return new Number.integer (-1);
609 else
610 return new Number.integer (1);
613 /* Sets z = −x */
614 public Number invert_sign ()
616 var z = copy ();
618 z.re_sign = -z.re_sign;
619 z.im_sign = -z.im_sign;
621 return z;
624 /* Sets z = |x| */
625 public Number abs ()
627 if (is_complex ())
629 var x_real = real_component ();
630 var x_im = imaginary_component ();
632 x_real = x_real.multiply (x_real);
633 x_im = x_im.multiply (x_im);
634 var z = x_real.add (x_im);
635 return z.root (2);
637 else
639 var z = copy ();
640 if (z.re_sign < 0)
641 z.re_sign = -z.re_sign;
642 return z;
646 /* Sets z = Arg (x) */
647 public Number arg (AngleUnit unit = AngleUnit.RADIANS)
649 if (is_zero ())
651 /* Translators: Error display when attempting to take argument of zero */
652 mperr (_("Argument not defined for zero"));
653 return new Number.integer (0);
656 var x_real = real_component ();
657 var x_im = imaginary_component ();
658 var pi = new Number.pi ();
660 Number z;
661 if (x_im.is_zero ())
663 if (x_real.is_negative ())
664 z = pi;
665 else
666 return new Number.integer (0);
668 else if (x_real.is_zero ())
670 if (x_im.is_negative ())
671 z = pi.divide_integer (-2);
672 else
673 z = pi.divide_integer (2);
675 else if (x_real.is_negative ())
677 z = x_im.divide (x_real);
678 z = z.atan (AngleUnit.RADIANS);
679 if (x_im.is_negative ())
680 z = z.subtract (pi);
681 else
682 z = z.add (pi);
684 else
686 z = x_im.divide (x_real);
687 z = z.atan (AngleUnit.RADIANS);
690 return z.from_radians (unit);
693 /* Sets z = ‾̅x */
694 public Number conjugate ()
696 var z = copy ();
697 z.im_sign = -z.im_sign;
698 return z;
701 /* Sets z = Re (x) */
702 public Number real_component ()
704 var z = copy ();
706 /* Clear imaginary component */
707 z.im_sign = 0;
708 z.im_exponent = 0;
709 for (var i = 0; i < z.im_fraction.length; i++)
710 z.im_fraction[i] = 0;
712 return z;
715 /* Sets z = Im (x) */
716 public Number imaginary_component ()
718 /* Copy imaginary component to real component */
719 var z = new Number ();
720 z.re_sign = im_sign;
721 z.re_exponent = im_exponent;
723 for (var i = 0; i < z.im_fraction.length; i++)
724 z.re_fraction[i] = im_fraction[i];
726 /* Clear (old) imaginary component */
727 z.im_sign = 0;
728 z.im_exponent = 0;
729 for (var i = 0; i < z.im_fraction.length; i++)
730 z.im_fraction[i] = 0;
732 return z;
735 public Number integer_component ()
737 /* Clear re_fraction */
738 var z = copy ();
739 for (var i = z.re_exponent; i < SIZE; i++)
740 z.re_fraction[i] = 0;
741 z.im_sign = 0;
742 z.im_exponent = 0;
743 for (var i = 0; i < z.im_fraction.length; i++)
744 z.im_fraction[i] = 0;
746 return z;
749 /* Sets z = x mod 1 */
750 public Number fractional_component ()
752 /* fractional component of zero is 0 */
753 if (is_zero ())
754 return new Number.integer (0);
756 /* All fractional */
757 if (re_exponent <= 0)
758 return this;
760 /* Shift fractional component */
761 var shift = re_exponent;
762 for (var i = shift; i < SIZE && re_fraction[i] == 0; i++)
763 shift++;
764 var z = new Number.integer (0);
765 z.re_sign = re_sign;
766 z.re_exponent = re_exponent - shift;
767 for (var i = 0; i < SIZE; i++)
769 if (i + shift >= SIZE)
770 z.re_fraction[i] = 0;
771 else
772 z.re_fraction[i] = re_fraction[i + shift];
774 if (z.re_fraction[0] == 0)
775 z.re_sign = 0;
777 return z;
780 /* Sets z = {x} */
781 public Number fractional_part ()
783 return subtract (floor ());
786 /* Sets z = ⌊x⌋ */
787 public Number floor ()
789 /* Integer component of zero = 0 */
790 if (is_zero ())
791 return this;
793 /* If all fractional then no integer component */
794 if (re_exponent <= 0)
796 if (is_negative ())
797 return new Number.integer (-1);
798 else
799 return new Number.integer (0);
802 /* Clear fractional component */
803 var z = copy ();
804 var have_fraction = false;
805 for (var i = z.re_exponent; i < SIZE; i++)
807 if (z.re_fraction[i] != 0)
808 have_fraction = true;
809 z.re_fraction[i] = 0;
811 z.im_sign = 0;
812 z.im_exponent = 0;
813 for (var i = 0; i < z.im_fraction.length; i++)
814 z.im_fraction[i] = 0;
816 if (have_fraction && is_negative ())
817 z = z.add (new Number.integer (-1));
819 return z;
822 /* Sets z = ⌈x⌉ */
823 public Number ceiling ()
825 var z = floor ();
826 var f = fractional_component ();
827 if (f.is_zero ())
828 return z;
829 return z.add (new Number.integer (1));
832 /* Sets z = [x] */
833 public Number round ()
835 var do_floor = !is_negative ();
837 var f = fractional_component ();
838 f = f.multiply_integer (2);
839 f = f.abs ();
840 if (f.compare (new Number.integer (1)) >= 0)
841 do_floor = !do_floor;
843 if (do_floor)
844 return floor ();
845 else
846 return ceiling ();
849 /* Sets z = 1 ÷ x */
850 public Number reciprocal ()
852 if (is_complex ())
854 var real_x = real_component ();
855 var im_x = imaginary_component ();
857 /* 1/(a+bi) = (a-bi)/(a+bi)(a-bi) = (a-bi)/(a²+b²) */
858 var t1 = real_x.multiply (real_x);
859 var t2 = im_x.multiply (im_x);
860 t1 = t1.add (t2);
861 var z = t1.reciprocal_real ();
862 return conjugate ().multiply (z);
864 else
865 return reciprocal_real ();
868 /* Sets z = e^x */
869 public Number epowy ()
871 /* e^0 = 1 */
872 if (is_zero ())
873 return new Number.integer (1);
875 if (is_complex ())
877 var x_real = real_component ();
878 var theta = imaginary_component ();
880 var r = x_real.epowy_real ();
881 return new Number.polar (r, theta);
883 else
884 return epowy_real ();
887 /* Sets z = x^y */
888 public Number xpowy (Number y)
890 if (y.is_integer ())
891 return xpowy_integer (y.to_integer ());
892 else
894 var reciprocal = y.reciprocal ();
895 if (reciprocal.is_integer ())
896 return root (reciprocal.to_integer ());
897 else
898 return pwr (y);
902 /* Sets z = x^y */
903 public Number xpowy_integer (int64 n)
905 /* 0^-n invalid */
906 if (is_zero () && n < 0)
908 /* Translators: Error displayed when attempted to raise 0 to a negative re_exponent */
909 mperr (_("The power of zero is undefined for a negative exponent"));
910 return new Number.integer (0);
913 /* x^0 = 1 */
914 if (n == 0)
915 return new Number.integer (1);
917 /* 0^n = 0 */
918 if (is_zero ())
919 return new Number.integer (0);
921 /* x^1 = x */
922 if (n == 1)
923 return this;
925 Number t;
926 if (n < 0)
928 t = reciprocal ();
929 n = -n;
931 else
932 t = this;
934 /* Multply x n times */
935 // FIXME: Can do z = z.multiply (z) until close to answer (each call doubles number of multiples) */
936 var z = new Number.integer (1);
937 for (var i = 0; i < n; i++)
938 z = z.multiply (t);
939 return z;
942 /* Sets z = n√x */
943 public Number root (int64 n)
945 if (!is_complex () && is_negative () && n % 2 == 1)
947 var z = abs ();
948 z = z.root_real (n);
949 z = z.invert_sign ();
950 return z;
952 else if (is_complex () || is_negative ())
954 var r = abs ();
955 var theta = arg ();
957 r = r.root_real (n);
958 theta = theta.divide_integer (n);
959 return new Number.polar (r, theta);
961 else
962 return root_real (n);
965 /* Sets z = √x */
966 public Number sqrt ()
968 if (is_zero ())
969 return this;
971 /* FIXME: Make complex numbers optional */
972 /*if (re_sign < 0)
974 mperr (_("Square root is undefined for negative values"));
975 return new Number.integer (0);
977 else
979 var t = root (-2);
980 var z = multiply (t);
981 return z.ext (t.re_fraction[0], z.re_fraction[0]);
985 /* Sets z = ln x */
986 public Number ln ()
988 /* ln (0) undefined */
989 if (is_zero ())
991 /* Translators: Error displayed when attempting to take logarithm of zero */
992 mperr (_("Logarithm of zero is undefined"));
993 return new Number.integer (0);
996 /* ln (-x) complex */
997 /* FIXME: Make complex numbers optional */
998 /*if (is_negative ())
1000 // Translators: Error displayed attempted to take logarithm of negative value
1001 mperr (_("Logarithm of negative values is undefined"));
1002 return new Number.integer (0);
1005 if (is_complex () || is_negative ())
1007 /* ln (re^iθ) = e^(ln (r)+iθ) */
1008 var r = abs ();
1009 var theta = arg ();
1010 var z_real = r.ln_real ();
1012 return new Number.complex (z_real, theta);
1014 else
1015 return ln_real ();
1018 /* Sets z = log_n x */
1019 public Number logarithm (int64 n)
1021 /* log (0) undefined */
1022 if (is_zero ())
1024 /* Translators: Error displayed when attempting to take logarithm of zero */
1025 mperr (_("Logarithm of zero is undefined"));
1026 return new Number.integer (0);
1029 /* logn (x) = ln (x) / ln (n) */
1030 var t1 = new Number.integer (n);
1031 return ln ().divide (t1.ln ());
1034 /* Sets z = x! */
1035 public Number factorial ()
1037 /* 0! == 1 */
1038 if (is_zero ())
1039 return new Number.integer (1);
1040 if (!is_natural ())
1042 /* Translators: Error displayed when attempted take the factorial of a fractional number */
1043 mperr (_("Factorial is only defined for natural numbers"));
1044 return new Number.integer (0);
1047 /* Convert to integer - if couldn't be converted then the factorial would be too big anyway */
1048 var value = to_integer ();
1049 var z = this;
1050 for (var i = 2; i < value; i++)
1051 z = z.multiply_integer (i);
1053 return z;
1056 /* Sets z = x + y */
1057 public Number add (Number y)
1059 return add_with_sign (1, y);
1062 /* Sets z = x − y */
1063 public Number subtract (Number y)
1065 return add_with_sign (-1, y);
1068 /* Sets z = x × y */
1069 public Number multiply (Number y)
1071 /* x*0 = 0*y = 0 */
1072 if (is_zero () || y.is_zero ())
1073 return new Number.integer (0);
1075 /* (a+bi)(c+di) = (ac-bd)+(ad+bc)i */
1076 if (is_complex () || y.is_complex ())
1078 Number t1, t2, real_z, im_z;
1080 var real_x = real_component ();
1081 var im_x = imaginary_component ();
1082 var real_y = y.real_component ();
1083 var im_y = y.imaginary_component ();
1085 t1 = real_x.multiply_real (real_y);
1086 t2 = im_x.multiply_real (im_y);
1087 real_z = t1.subtract (t2);
1089 t1 = real_x.multiply_real (im_y);
1090 t2 = im_x.multiply_real (real_y);
1091 im_z = t1.add (t2);
1093 return new Number.complex (real_z, im_z);
1095 else
1096 return multiply_real (y);
1099 /* Sets z = x × y */
1100 public Number multiply_integer (int64 y)
1102 if (is_complex ())
1104 var re_z = real_component ().multiply_integer_real (y);;
1105 var im_z = imaginary_component ().multiply_integer_real (y);
1106 return new Number.complex (re_z, im_z);
1108 else
1109 return multiply_integer_real (y);
1112 /* Sets z = x ÷ y */
1113 public Number divide (Number y)
1115 /* x/0 */
1116 if (y.is_zero ())
1118 /* Translators: Error displayed attempted to divide by zero */
1119 mperr (_("Division by zero is undefined"));
1120 return new Number.integer (0);
1123 /* 0/y = 0 */
1124 if (is_zero ())
1125 return this;
1127 /* z = x × y⁻¹ */
1128 /* FIXME: Set re_exponent to zero to avoid overflow in multiply??? */
1129 var t = y.reciprocal ();
1130 var ie = t.re_exponent;
1131 t.re_exponent = 0;
1132 var i = t.re_fraction[0];
1133 var z = multiply (t);
1134 z = z.ext (i, z.re_fraction[0]);
1135 z.re_exponent += ie;
1137 return z;
1140 /* Sets z = x ÷ y */
1141 public Number divide_integer (int64 y)
1143 if (is_complex ())
1145 var re_z = real_component ().divide_integer_real (y);
1146 var im_z = imaginary_component ().divide_integer_real (y);
1147 return new Number.complex (re_z, im_z);
1149 else
1150 return divide_integer_real (y);
1153 /* Sets z = x mod y */
1154 public Number modulus_divide (Number y)
1156 if (!is_integer () || !y.is_integer ())
1158 /* Translators: Error displayed when attemping to do a modulus division on non-integer numbers */
1159 mperr (_("Modulus division is only defined for integers"));
1160 return new Number.integer (0);
1163 var t1 = divide (y).floor ();
1164 var t2 = t1.multiply (y);
1165 var z = subtract (t2);
1167 t1 = new Number.integer (0);
1168 if ((y.compare (t1) < 0 && z.compare (t1) > 0) || z.compare (t1) < 0)
1169 z = z.add (y);
1171 return z;
1174 /* Sets z = sin x */
1175 public Number sin (AngleUnit unit = AngleUnit.RADIANS)
1177 if (is_complex ())
1179 var x_real = real_component ();
1180 var x_im = imaginary_component ();
1182 var z_real = x_real.sin_real (unit);
1183 var t = x_im.cosh ();
1184 z_real = z_real.multiply (t);
1186 var z_im = x_real.cos_real (unit);
1187 t = x_im.sinh ();
1188 z_im = z_im.multiply (t);
1190 return new Number.complex (z_real, z_im);
1192 else
1193 return sin_real (unit);
1196 /* Sets z = cos x */
1197 public Number cos (AngleUnit unit = AngleUnit.RADIANS)
1199 if (is_complex ())
1201 var x_real = real_component ();
1202 var x_im = imaginary_component ();
1204 var z_real = x_real.cos_real (unit);
1205 var t = x_im.cosh ();
1206 z_real = z_real.multiply (t);
1208 var z_im = x_real.sin_real (unit);
1209 t = x_im.sinh ();
1210 z_im = z_im.multiply (t);
1211 z_im = z_im.invert_sign ();
1213 return new Number.complex (z_real, z_im);
1215 else
1216 return cos_real (unit);
1219 /* Sets z = tan x */
1220 public Number tan (AngleUnit unit = AngleUnit.RADIANS)
1222 /* Check for undefined values */
1223 var cos_x = cos (unit);
1224 if (cos_x.is_zero ())
1226 /* Translators: Error displayed when tangent value is undefined */
1227 mperr (_("Tangent is undefined for angles that are multiples of π (180°) from π∕2 (90°)"));
1228 return new Number.integer (0);
1231 /* tan (x) = sin (x) / cos (x) */
1232 return sin (unit).divide (cos_x);
1235 /* Sets z = sin⁻¹ x */
1236 public Number asin (AngleUnit unit = AngleUnit.RADIANS)
1238 /* asin⁻¹(0) = 0 */
1239 if (is_zero ())
1240 return new Number.integer (0);
1242 /* sin⁻¹(x) = tan⁻¹(x / √(1 - x²)), |x| < 1 */
1243 if (re_exponent <= 0)
1245 var t1 = new Number.integer (1);
1246 var t2 = t1;
1247 t1 = t1.subtract (this);
1248 t2 = t2.add (this);
1249 t2 = t1.multiply (t2);
1250 t2 = t2.root (-2);
1251 var z = multiply (t2);
1252 z = z.atan (unit);
1253 return z;
1256 /* sin⁻¹(1) = π/2, sin⁻¹(-1) = -π/2 */
1257 var t2 = new Number.integer (re_sign);
1258 if (equals (t2))
1260 var z = new Number.pi ().divide_integer (2 * t2.re_sign);
1261 return z.from_radians (unit);
1264 /* Translators: Error displayed when inverse sine value is undefined */
1265 mperr (_("Inverse sine is undefined for values outside [-1, 1]"));
1266 return new Number.integer (0);
1269 /* Sets z = cos⁻¹ x */
1270 public Number acos (AngleUnit unit = AngleUnit.RADIANS)
1272 var pi = new Number.pi ();
1273 var t1 = new Number.integer (1);
1274 var n1 = new Number.integer (-1);
1276 Number z;
1277 if (compare (t1) > 0 || compare (n1) < 0)
1279 /* Translators: Error displayed when inverse cosine value is undefined */
1280 mperr (_("Inverse cosine is undefined for values outside [-1, 1]"));
1281 z = new Number.integer (0);
1283 else if (is_zero ())
1284 z = pi.divide_integer (2);
1285 else if (equals (t1))
1286 z = new Number.integer (0);
1287 else if (equals (n1))
1288 z = pi;
1289 else
1291 /* cos⁻¹(x) = tan⁻¹(√(1 - x²) / x) */
1292 Number y;
1293 var t2 = multiply (this);
1294 t2 = t1.subtract (t2);
1295 t2 = t2.sqrt ();
1296 t2 = t2.divide (this);
1297 y = t2.atan (AngleUnit.RADIANS);
1298 if (re_sign > 0)
1299 z = y;
1300 else
1301 z = y.add (pi);
1304 return z.from_radians (unit);
1307 /* Sets z = tan⁻¹ x */
1308 public Number atan (AngleUnit unit = AngleUnit.RADIANS)
1310 if (is_zero ())
1311 return new Number.integer (0);
1313 var t2 = this;
1314 var rx = 0f;
1315 if (re_exponent.abs () <= 2)
1316 rx = to_float ();
1318 /* REDUCE ARGUMENT IF NECESSARY BEFORE USING SERIES */
1319 var q = 1;
1320 Number z;
1321 while (t2.re_exponent >= 0)
1323 if (t2.re_exponent == 0 && 2 * (t2.re_fraction[0] + 1) <= BASE)
1324 break;
1326 q *= 2;
1328 /* t = t / (√(t² + 1) + 1) */
1329 z = t2.multiply (t2);
1330 z = z.add (new Number.integer (1));
1331 z = z.sqrt ();
1332 z = z.add (new Number.integer (1));
1333 t2 = t2.divide (z);
1336 /* USE POWER SERIES NOW ARGUMENT IN (-0.5, 0.5) */
1337 z = t2;
1338 var t1 = t2.multiply (t2);
1340 /* SERIES LOOP. REDUCE T IF POSSIBLE. */
1341 for (var i = 1; ; i += 2)
1343 if (T + 2 + t2.re_exponent <= 1)
1344 break;
1346 t2 = t2.multiply (t1).multiply_integer (-i).divide_integer (i + 2);
1348 z = z.add (t2);
1349 if (t2.is_zero ())
1350 break;
1353 /* CORRECT FOR ARGUMENT REDUCTION */
1354 z = z.multiply_integer (q);
1356 /* CHECK THAT RELATIVE ERROR LESS THAN 0.01 UNLESS re_exponent
1357 * OF X IS LARGE (WHEN ATAN MIGHT NOT WORK)
1359 if (re_exponent.abs () <= 2)
1361 float ry = z.to_float ();
1362 /* THE FOLLOWING MESSAGE MAY INDICATE THAT B**(T-1) IS TOO SMALL. */
1363 if (Math.fabs (ry - Math.atan (rx)) >= Math.fabs (ry) * 0.01)
1364 mperr ("*** ERROR OCCURRED IN ATAN, RESULT INCORRECT ***");
1367 return z.from_radians (unit);
1370 /* Sets z = sinh x */
1371 public Number sinh ()
1373 /* sinh (0) = 0 */
1374 if (is_zero ())
1375 return new Number.integer (0);
1377 /* WORK WITH ABS (X) */
1378 var abs_x = abs ();
1380 /* If |x| < 1 USE EXP TO AVOID CANCELLATION, otherwise IF TOO LARGE EPOWY GIVES ERROR MESSAGE */
1381 Number z;
1382 if (abs_x.re_exponent <= 0)
1384 /* ((e^|x| + 1) * (e^|x| - 1)) / e^|x| */
1385 // FIXME: Solves to e^|x| - e^-|x|, why not lower branch always? */
1386 var exp_x = abs_x.epowy ();
1387 var a = exp_x.add (new Number.integer (1));
1388 var b = exp_x.add (new Number.integer (-1));
1389 z = a.multiply (b);
1390 z = z.divide (exp_x);
1392 else
1394 /* e^|x| - e^-|x| */
1395 var exp_x = abs_x.epowy ();
1396 z = exp_x.reciprocal ();
1397 z = exp_x.subtract (z);
1400 /* DIVIDE BY TWO AND RESTORE re_sign */
1401 z = z.divide_integer (2);
1402 return z.multiply_integer (re_sign);
1405 /* Sets z = cosh x */
1406 public Number cosh ()
1408 /* cosh (0) = 1 */
1409 if (is_zero ())
1410 return new Number.integer (1);
1412 /* cosh (x) = (e^x + e^-x) / 2 */
1413 var t = abs ();
1414 t = t.epowy ();
1415 var z = t.reciprocal ();
1416 z = t.add (z);
1417 return z.divide_integer (2);
1420 /* Sets z = tanh x */
1421 public Number tanh ()
1423 /* tanh (0) = 0 */
1424 if (is_zero ())
1425 return new Number.integer (0);
1427 var t = abs ();
1429 /* SEE IF ABS (X) SO LARGE THAT RESULT IS +-1 */
1430 var r__1 = (float) T * 0.5 * Math.log ((float) BASE);
1431 var z = new Number.double (r__1);
1432 if (t.compare (z) > 0)
1433 return new Number.integer (re_sign);
1435 /* If |x| >= 1/2 use ?, otherwise use ? to avoid cancellation */
1436 /* |tanh (x)| = (e^|2x| - 1) / (e^|2x| + 1) */
1437 t = t.multiply_integer (2);
1438 if (t.re_exponent > 0)
1440 t = t.epowy ();
1441 z = t.add (new Number.integer (-1));
1442 t = t.add (new Number.integer (1));
1443 z = z.divide (t);
1445 else
1447 t = t.epowy ();
1448 z = t.add (new Number.integer (1));
1449 t = t.add (new Number.integer (-1));
1450 z = t.divide (z);
1453 /* Restore re_sign */
1454 z.re_sign = re_sign * z.re_sign;
1455 return z;
1458 /* Sets z = sinh⁻¹ x */
1459 public Number asinh ()
1461 /* sinh⁻¹(x) = ln (x + √(x² + 1)) */
1462 var t = multiply (this);
1463 t = t.add (new Number.integer (1));
1464 t = t.sqrt ();
1465 t = add (t);
1466 return t.ln ();
1469 /* Sets z = cosh⁻¹ x */
1470 public Number acosh ()
1472 /* Check x >= 1 */
1473 var t = new Number.integer (1);
1474 if (compare (t) < 0)
1476 /* Translators: Error displayed when inverse hyperbolic cosine value is undefined */
1477 mperr (_("Inverse hyperbolic cosine is undefined for values less than one"));
1478 return new Number.integer (0);
1481 /* cosh⁻¹(x) = ln (x + √(x² - 1)) */
1482 t = multiply (this);
1483 t = t.add (new Number.integer (-1));
1484 t = t.sqrt ();
1485 t = add (t);
1486 return t.ln ();
1489 /* Sets z = tanh⁻¹ x */
1490 public Number atanh ()
1492 /* Check -1 <= x <= 1 */
1493 if (compare (new Number.integer (1)) >= 0 || compare (new Number.integer (-1)) <= 0)
1495 /* Translators: Error displayed when inverse hyperbolic tangent value is undefined */
1496 mperr (_("Inverse hyperbolic tangent is undefined for values outside [-1, 1]"));
1497 return new Number.integer (0);
1500 /* atanh (x) = 0.5 * ln ((1 + x) / (1 - x)) */
1501 var n = add (new Number.integer (1));
1502 var d = invert_sign ();
1503 d = d.add (new Number.integer (1));
1504 var z = n.divide (d);
1505 z = z.ln ();
1506 return z.divide_integer (2);
1509 /* Sets z = boolean AND for each bit in x and z */
1510 public Number and (Number y)
1512 if (!is_positive_integer () || !y.is_positive_integer ())
1514 /* Translators: Error displayed when boolean AND attempted on non-integer values */
1515 mperr (_("Boolean AND is only defined for positive integers"));
1518 return bitwise (y, (v1, v2) => { return v1 & v2; }, 0);
1521 /* Sets z = boolean OR for each bit in x and z */
1522 public Number or (Number y)
1524 if (!is_positive_integer () || !y.is_positive_integer ())
1526 /* Translators: Error displayed when boolean OR attempted on non-integer values */
1527 mperr (_("Boolean OR is only defined for positive integers"));
1530 return bitwise (y, (v1, v2) => { return v1 | v2; }, 0);
1533 /* Sets z = boolean XOR for each bit in x and z */
1534 public Number xor (Number y)
1536 if (!is_positive_integer () || !y.is_positive_integer ())
1538 /* Translators: Error displayed when boolean XOR attempted on non-integer values */
1539 mperr (_("Boolean XOR is only defined for positive integers"));
1542 return bitwise (y, (v1, v2) => { return v1 ^ v2; }, 0);
1545 /* Sets z = boolean NOT for each bit in x and z for word of length 'wordlen' */
1546 public Number not (int wordlen)
1548 if (!is_positive_integer ())
1550 /* Translators: Error displayed when boolean XOR attempted on non-integer values */
1551 mperr (_("Boolean NOT is only defined for positive integers"));
1554 return bitwise (new Number.integer (0), (v1, v2) => { return v1 ^ 0xF; }, wordlen);
1557 /* Sets z = x masked to 'wordlen' bits */
1558 public Number mask (Number x, int wordlen)
1560 /* Convert to a hexadecimal string and use last characters */
1561 var text = x.to_hex_string ();
1562 var len = text.length;
1563 var offset = wordlen / 4;
1564 offset = len > offset ? (int) len - offset: 0;
1565 return mp_set_from_string (text.substring (offset), 16);
1568 /* Sets z = x shifted by 'count' bits. Positive shift increases the value, negative decreases */
1569 public Number shift (int count)
1571 if (!is_integer ())
1573 /* Translators: Error displayed when bit shift attempted on non-integer values */
1574 mperr (_("Shift is only possible on integer values"));
1575 return new Number.integer (0);
1578 if (count >= 0)
1580 var multiplier = 1;
1581 for (var i = 0; i < count; i++)
1582 multiplier *= 2;
1583 return multiply_integer (multiplier);
1585 else
1587 var multiplier = 1;
1588 for (var i = 0; i < -count; i++)
1589 multiplier *= 2;
1590 return divide_integer (multiplier).floor ();
1594 /* Sets z to be the ones complement of x for word of length 'wordlen' */
1595 public Number ones_complement (int wordlen)
1597 return bitwise (new Number.integer (0), (v1, v2) => { return v1 ^ v2; }, wordlen).not (wordlen);
1600 /* Sets z to be the twos complement of x for word of length 'wordlen' */
1601 public Number twos_complement (int wordlen)
1603 return ones_complement (wordlen).add (new Number.integer (1));
1606 /* Returns a list of all prime factors in x as Numbers */
1607 public List<Number?> factorize ()
1609 var factors = new List<Number?> ();
1611 var value = abs ();
1613 if (value.is_zero ())
1615 factors.append (value);
1616 return factors;
1619 if (value.equals (new Number.integer (1)))
1621 factors.append (this);
1622 return factors;
1625 var divisor = new Number.integer (2);
1626 while (true)
1628 var tmp = value.divide (divisor);
1629 if (tmp.is_integer ())
1631 value = tmp;
1632 factors.append (divisor);
1634 else
1635 break;
1638 divisor = new Number.integer (3);
1639 var root = value.sqrt ();
1640 while (divisor.compare (root) <= 0)
1642 var tmp = value.divide (divisor);
1643 if (tmp.is_integer ())
1645 value = tmp;
1646 root = value.sqrt ();
1647 factors.append (divisor);
1649 else
1651 tmp = divisor.add (new Number.integer (2));
1652 divisor = tmp;
1656 if (value.compare (new Number.integer (1)) > 0)
1657 factors.append (value);
1659 if (is_negative ())
1660 factors.data = factors.data.invert_sign ();
1662 return factors;
1665 private Number copy ()
1667 var z = new Number ();
1668 z.re_sign = re_sign;
1669 z.im_sign = im_sign;
1670 z.re_exponent = re_exponent;
1671 z.im_exponent = im_exponent;
1672 for (var i = 0; i < re_fraction.length; i++)
1674 z.re_fraction[i] = re_fraction[i];
1675 z.im_fraction[i] = im_fraction[i];
1678 return z;
1681 private Number add_with_sign (int y_sign, Number y)
1683 if (is_complex () || y.is_complex ())
1685 Number real_z, im_z;
1687 var real_x = real_component ();
1688 var im_x = imaginary_component ();
1689 var real_y = y.real_component ();
1690 var im_y = y.imaginary_component ();
1692 real_z = real_x.add_real (y_sign * y.re_sign, real_y);
1693 im_z = im_x.add_real (y_sign * y.im_sign, im_y);
1695 return new Number.complex (real_z, im_z);
1697 else
1698 return add_real (y_sign * y.re_sign, y);
1701 private Number epowy_real ()
1703 /* e^0 = 1 */
1704 if (is_zero ())
1705 return new Number.integer (1);
1707 /* If |x| < 1 use exp */
1708 if (re_exponent <= 0)
1709 return exp ();
1711 /* NOW SAFE TO CONVERT X TO REAL */
1712 var rx = to_double ();
1714 /* SAVE re_sign AND WORK WITH ABS (X) */
1715 var xs = re_sign;
1716 var t2 = abs ();
1718 /* GET fractional AND INTEGER PARTS OF ABS (X) */
1719 var ix = t2.to_integer ();
1720 t2 = t2.fractional_component ();
1722 /* ATTACH re_sign TO fractional PART AND COMPUTE EXP OF IT */
1723 t2.re_sign *= xs;
1724 var z = t2.exp ();
1726 /* COMPUTE E-2 OR 1/E USING TWO EXTRA DIGITS IN CASE ABS (X) LARGE
1727 * (BUT ONLY ONE EXTRA DIGIT IF T < 4)
1729 var tss = 0;
1730 if (T < 4)
1731 tss = T + 1;
1732 else
1733 tss = T + 2;
1735 /* LOOP FOR E COMPUTATION. DECREASE T IF POSSIBLE. */
1736 /* Computing MIN */
1737 var t1 = new Number.integer (xs);
1739 t2.re_sign = 0;
1740 for (var i = 2 ; ; i++)
1742 if (int.min (tss, tss + 2 + t1.re_exponent) <= 2)
1743 break;
1745 t1 = t1.divide_integer (i * xs);
1746 t2 = t2.add (t1);
1747 if (t1.is_zero ())
1748 break;
1751 /* RAISE E OR 1/E TO POWER IX */
1752 if (xs > 0)
1753 t2 = t2.add (new Number.integer (2));
1754 t2 = t2.xpowy_integer (ix);
1756 /* MULTIPLY EXPS OF INTEGER AND fractional PARTS */
1757 z = z.multiply (t2);
1759 /* CHECK THAT RELATIVE ERROR LESS THAN 0.01 UNLESS ABS (X) LARGE
1760 * (WHEN EXP MIGHT OVERFLOW OR UNDERFLOW)
1762 if (Math.fabs (rx) > 10.0f)
1763 return z;
1765 var rz = z.to_double ();
1766 var r__1 = rz - Math.exp (rx);
1767 if (Math.fabs (r__1) < rz * 0.01f)
1768 return z;
1770 /* THE FOLLOWING MESSAGE MAY INDICATE THAT
1771 * B**(T-1) IS TOO SMALL, OR THAT M IS TOO SMALL SO THE
1772 * RESULT UNDERFLOWED.
1774 mperr ("*** ERROR OCCURRED IN EPOWY, RESULT INCORRECT ***");
1775 return z;
1778 /* Return e^x for |x| < 1 USING AN o (SQRt (T).m (T)) ALGORITHM
1779 * DESCRIBED IN - R. P. BRENT, THE COMPLEXITY OF MULTIPLE-
1780 * PRECISION ARITHMETIC (IN COMPLEXITY OF COMPUTATIONAL PROBLEM
1781 * SOLVING, UNIV. OF QUEENSLAND PRESS, BRISBANE, 1976, 126-165).
1782 * ASYMPTOTICALLY FASTER METHODS EXIST, BUT ARE NOT USEFUL
1783 * UNLESS T IS VERY LARGE. SEE COMMENTS TO MP_ATAN AND MPPIGL.
1785 private Number exp ()
1787 /* e^0 = 1 */
1788 if (is_zero ())
1789 return new Number.integer (1);
1791 /* Only defined for |x| < 1 */
1792 if (re_exponent > 0)
1794 mperr ("*** ABS (X) NOT LESS THAN 1 IN CALL TO MP_EXP ***");
1795 return new Number.integer (0);
1798 var t1 = this;
1799 var rlb = Math.log (BASE);
1801 /* Compute approximately optimal q (and divide x by 2^q) */
1802 var q = (int) (Math.sqrt (T * 0.48 * rlb) + re_exponent * 1.44 * rlb);
1804 /* HALVE Q TIMES */
1805 if (q > 0)
1807 var ib = BASE << 2;
1808 var ic = 1;
1809 for (var i = 1; i <= q; i++)
1811 ic *= 2;
1812 if (ic < ib && ic != BASE && i < q)
1813 continue;
1814 t1 = t1.divide_integer (ic);
1815 ic = 1;
1819 if (t1.is_zero ())
1820 return new Number.integer (0);
1822 /* Sum series, reducing t where possible */
1823 var z = t1.copy ();
1824 var t2 = t1;
1825 for (var i = 2; T + t2.re_exponent - z.re_exponent > 0; i++)
1827 t2 = t1.multiply (t2);
1828 t2 = t2.divide_integer (i);
1829 z = t2.add (z);
1830 if (t2.is_zero ())
1831 break;
1834 /* Apply (x+1)^2 - 1 = x (2 + x) for q iterations */
1835 for (var i = 1; i <= q; i++)
1837 t1 = z.add (new Number.integer (2));
1838 z = t1.multiply (z);
1841 return z.add (new Number.integer (1));
1844 private Number pwr (Number y)
1846 /* (-x)^y imaginary */
1847 /* FIXME: Make complex numbers optional */
1848 /*if (re_sign < 0)
1850 mperr (_("The power of negative numbers is only defined for integer exponents"));
1851 return new Number.integer (0);
1854 /* 0^y = 0, 0^-y undefined */
1855 if (is_zero ())
1857 if (y.re_sign < 0)
1858 mperr (_("The power of zero is undefined for a negative exponent"));
1859 return new Number.integer (0);
1862 /* x^0 = 1 */
1863 if (y.is_zero ())
1864 return new Number.integer (1);
1866 return y.multiply (ln ()).epowy ();
1869 private Number root_real (int64 n)
1871 /* x^(1/1) = x */
1872 if (n == 1)
1873 return this;
1875 /* x^(1/0) invalid */
1876 if (n == 0)
1878 mperr (_("Root must be non-zero"));
1879 return new Number.integer (0);
1882 var np = n.abs ();
1884 /* LOSS OF ACCURACY IF NP LARGE, SO ONLY ALLOW NP <= MAX (B, 64) */
1885 if (np > int.max (BASE, 64))
1887 mperr ("*** ABS (N) TOO LARGE IN CALL TO ROOT ***");
1888 return new Number.integer (0);
1891 /* 0^(1/n) = 0 for positive n */
1892 if (is_zero ())
1894 if (n <= 0)
1895 mperr (_("Negative root of zero is undefined"));
1896 return new Number.integer (0);
1899 // FIXME: Imaginary root
1900 if (re_sign < 0 && np % 2 == 0)
1902 mperr (_("nth root of negative number is undefined for even n"));
1903 return new Number.integer (0);
1906 /* DIVIDE re_exponent BY NP */
1907 var ex = re_exponent / np;
1909 /* Get initial approximation */
1910 var t1 = copy ();
1911 t1.re_exponent = 0;
1912 var approximation = Math.exp (((np * ex - re_exponent) * Math.log (BASE) - Math.log (Math.fabs (t1.to_float ()))) / np);
1913 t1 = new Number.double (approximation);
1914 t1.re_sign = re_sign;
1915 t1.re_exponent -= (int) ex;
1917 /* MAIN ITERATION LOOP */
1918 var it0 = 3;
1919 var t = it0;
1920 Number t2;
1921 while (true)
1923 /* t1 = t1 - ((t1 * ((x * t1^np) - 1)) / np) */
1924 t2 = t1.xpowy_integer (np);
1925 t2 = multiply (t2);
1926 t2 = t2.add (new Number.integer (-1));
1927 t2 = t1.multiply (t2);
1928 t2 = t2.divide_integer (np);
1929 t1 = t1.subtract (t2);
1931 /* FOLLOWING LOOP ALMOST DOUBLES T (POSSIBLE BECAUSE
1932 * NEWTONS METHOD HAS 2ND ORDER CONVERGENCE).
1934 if (t >= T)
1935 break;
1937 var ts3 = t;
1938 var ts2 = t;
1939 t = T;
1942 ts2 = t;
1943 t = (t + it0) / 2;
1944 } while (t > ts3);
1945 t = int.min (ts2, T);
1948 /* NOW r (I2) IS X**(-1/NP)
1949 * CHECK THAT NEWTON ITERATION WAS CONVERGING
1951 if (t2.re_sign != 0 && (t1.re_exponent - t2.re_exponent) << 1 < T - it0)
1953 /* THE FOLLOWING MESSAGE MAY INDICATE THAT B**(T-1) IS TOO SMALL,
1954 * OR THAT THE INITIAL APPROXIMATION OBTAINED USING ALOG AND EXP
1955 * IS NOT ACCURATE ENOUGH.
1957 mperr ("*** ERROR OCCURRED IN ROOT, NEWTON ITERATION NOT CONVERGING PROPERLY ***");
1960 if (n >= 0)
1962 t1 = t1.xpowy_integer (n - 1);
1963 return multiply (t1);
1966 return t1;
1969 /* ROUTINE CALLED BY DIVIDE AND SQRT TO ENSURE THAT
1970 * RESULTS ARE REPRESENTED EXACTLY IN T-2 DIGITS IF THEY
1971 * CAN BE. X IS AN MP NUMBER, I AND J ARE INTEGERS.
1973 private Number ext (int i, int j)
1975 if (is_zero () || T <= 2 || i == 0)
1976 return this;
1978 /* COMPUTE MAXIMUM POSSIBLE ERROR IN THE LAST PLACE */
1979 var q = (j + 1) / i + 1;
1980 var s = BASE * re_fraction[T - 2] + re_fraction[T - 1];
1982 /* SET LAST TWO DIGITS TO ZERO */
1983 var z = copy ();
1984 if (s <= q)
1986 z.re_fraction[T - 2] = 0;
1987 z.re_fraction[T - 1] = 0;
1988 return z;
1991 if (s + q < BASE * BASE)
1992 return z;
1994 /* ROUND UP HERE */
1995 z.re_fraction[T - 2] = BASE - 1;
1996 z.re_fraction[T - 1] = BASE;
1998 /* NORMALIZE X (LAST DIGIT B IS OK IN MULTIPLY_INTEGER) */
1999 return z.multiply_integer (1);
2002 private Number ln_real ()
2004 /* LOOP TO GET APPROXIMATE Ln (X) USING SINGLE-PRECISION */
2005 var t1 = copy ();
2006 var z = new Number.integer (0);
2007 for (var k = 0; k < 10; k++)
2009 /* COMPUTE FINAL CORRECTION ACCURATELY USING LNS */
2010 var t2 = t1.add (new Number.integer (-1));
2011 if (t2.is_zero () || t2.re_exponent + 1 <= 0)
2012 return z.add (t2.lns ());
2014 /* REMOVE EXPONENT TO AVOID FLOATING-POINT OVERFLOW */
2015 var e = t1.re_exponent;
2016 t1.re_exponent = 0;
2017 var rx = t1.to_float_old ();
2018 t1.re_exponent = e;
2019 var rlx = (float) (Math.log (rx) + e * Math.log (BASE));
2020 t2 = new Number.float (-(float)rlx);
2022 /* UPDATE Z AND COMPUTE ACCURATE EXP OF APPROXIMATE LOG */
2023 z = z.subtract (t2);
2024 t2 = t2.epowy ();
2026 /* COMPUTE RESIDUAL WHOSE LOG IS STILL TO BE FOUND */
2027 t1 = t1.multiply (t2);
2030 mperr ("*** ERROR IN LN, ITERATION NOT CONVERGING ***");
2031 return z;
2034 // FIXME: This is here becase ln e breaks if we use the symmetric to_float
2035 private float to_float_old ()
2037 if (is_zero ())
2038 return 0f;
2040 var z = 0f;
2041 var i = 0;
2042 for (; i < T; i++)
2044 z = BASE * z + re_fraction[i];
2046 /* CHECK IF FULL SINGLE-PRECISION ACCURACY ATTAINED */
2047 if (z + 1.0f <= z)
2048 break;
2051 /* NOW ALLOW FOR EXPONENT */
2052 z = (float) (z * mppow_ri (BASE, re_exponent - i - 1));
2054 if (re_sign < 0)
2055 return -z;
2056 else
2057 return z;
2060 private double mppow_ri (float ap, int bp)
2062 if (bp == 0)
2063 return 1.0f;
2065 if (bp < 0)
2067 if (ap == 0)
2068 return 1.0f;
2069 bp = -bp;
2070 ap = 1 / ap;
2073 var pow = 1.0;
2074 while (true)
2076 if ((bp & 01) != 0)
2077 pow *= ap;
2078 if ((bp >>= 1) != 0)
2079 ap *= ap;
2080 else
2081 break;
2084 return pow;
2087 /* RETURNS MP Y = Ln (1+X) IF X IS AN MP NUMBER SATISFYING THE
2088 * CONDITION ABS (X) < 1/B, ERROR OTHERWISE.
2089 * USES NEWTONS METHOD TO SOLVE THE EQUATION
2090 * EXP1(-Y) = X, THEN REVERSES re_sign OF Y.
2092 private Number lns ()
2094 /* ln (1+0) = 0 */
2095 if (is_zero ())
2096 return this;
2098 /* Get starting approximation -ln (1+x) ~= -x + x^2/2 - x^3/3 + x^4/4 */
2099 var t2 = copy ();
2100 var t1 = divide_integer (4);
2101 t1 = t1.add (new Number.fraction (-1, 3));
2102 t1 = multiply (t1);
2103 t1 = t1.add (new Number.fraction (1, 2));
2104 t1 = multiply (t1);
2105 t1 = t1.add (new Number.integer (-1));
2106 var z = multiply (t1);
2108 /* Solve using Newtons method */
2109 var it0 = 5;
2110 var t = it0;
2111 Number t3;
2112 while (true)
2114 /* t3 = (e^t3 - 1) */
2115 /* z = z - (t2 + t3 + (t2 * t3)) */
2116 t3 = z.epowy ();
2117 t3 = t3.add (new Number.integer (-1));
2118 t1 = t2.multiply (t3);
2119 t3 = t3.add (t1);
2120 t3 = t2.add (t3);
2121 z = z.subtract (t3);
2122 if (t >= T)
2123 break;
2125 /* FOLLOWING LOOP COMPUTES NEXT VALUE OF T TO USE.
2126 * BECAUSE NEWTONS METHOD HAS 2ND ORDER CONVERGENCE,
2127 * WE CAN ALMOST DOUBLE T EACH TIME.
2129 var ts3 = t;
2130 var ts2 = t;
2131 t = T;
2134 ts2 = t;
2135 t = (t + it0) / 2;
2136 } while (t > ts3);
2137 t = ts2;
2140 /* CHECK THAT NEWTON ITERATION WAS CONVERGING AS EXPECTED */
2141 if (t3.re_sign != 0 && t3.re_exponent << 1 > it0 - T)
2142 mperr ("*** ERROR OCCURRED IN LNS, NEWTON ITERATION NOT CONVERGING PROPERLY ***");
2144 z.re_sign = -z.re_sign;
2146 return z;
2149 private Number add_real (int y_sign, Number y)
2151 var re_sign_prod = y_sign * re_sign;
2153 /* 0 + y = y */
2154 if (is_zero ())
2156 if (y_sign != y.re_sign)
2157 return y.invert_sign ();
2158 else
2159 return y;
2161 /* x + 0 = x */
2162 else if (y.is_zero ())
2163 return this;
2165 var exp_diff = re_exponent - y.re_exponent;
2166 var med = exp_diff.abs ();
2167 var x_largest = false;
2168 if (exp_diff < 0)
2169 x_largest = false;
2170 else if (exp_diff > 0)
2171 x_largest = true;
2172 else
2174 /* EXPONENTS EQUAL SO COMPARE SIGNS, THEN FRACTIONS IF NEC. */
2175 if (re_sign_prod < 0)
2177 /* signs are not equal. find out which mantissa is larger. */
2178 int j;
2179 for (j = 0; j < T; j++)
2181 int i = re_fraction[j] - y.re_fraction[j];
2182 if (i != 0)
2184 if (i < 0)
2185 x_largest = false;
2186 else if (i > 0)
2187 x_largest = true;
2188 break;
2192 /* Both mantissas equal, so result is zero. */
2193 if (j >= T)
2194 return new Number.integer (0);
2198 var z = new Number.integer (0);
2200 int[] big_fraction, small_fraction;
2201 if (x_largest)
2203 z.re_sign = re_sign;
2204 z.re_exponent = re_exponent;
2205 big_fraction = re_fraction;
2206 small_fraction = y.re_fraction;
2208 else
2210 z.re_sign = y_sign;
2211 z.re_exponent = y.re_exponent;
2212 big_fraction = y.re_fraction;
2213 small_fraction = re_fraction;
2216 /* CLEAR GUARD DIGITS TO RIGHT OF X DIGITS */
2217 for (var i = 3; i >= med; i--)
2218 z.re_fraction[T + i] = 0;
2220 if (re_sign_prod >= 0)
2222 /* This is probably insufficient overflow detection, but it makes us not crash at least. */
2223 if (T + 3 < med)
2225 mperr (_("Overflow: the result couldn't be calculated"));
2226 return new Number.integer (0);
2229 /* HERE DO ADDITION, re_exponent (Y) >= re_exponent (X) */
2230 var i = 0;
2231 for (i = T + 3; i >= T; i--)
2232 z.re_fraction[i] = small_fraction[i - med];
2234 var c = 0;
2235 for (; i >= med; i--)
2237 c = big_fraction[i] + small_fraction[i - med] + c;
2239 if (c < BASE)
2241 /* NO CARRY GENERATED HERE */
2242 z.re_fraction[i] = c;
2243 c = 0;
2245 else
2247 /* CARRY GENERATED HERE */
2248 z.re_fraction[i] = c - BASE;
2249 c = 1;
2253 for (; i >= 0; i--)
2255 c = big_fraction[i] + c;
2256 if (c < BASE)
2258 z.re_fraction[i] = c;
2259 i--;
2261 /* NO CARRY POSSIBLE HERE */
2262 for (; i >= 0; i--)
2263 z.re_fraction[i] = big_fraction[i];
2265 c = 0;
2266 break;
2269 z.re_fraction[i] = 0;
2270 c = 1;
2273 /* MUST SHIFT RIGHT HERE AS CARRY OFF END */
2274 if (c != 0)
2276 for (var j = T + 3; j > 0; j--)
2277 z.re_fraction[j] = z.re_fraction[j - 1];
2278 z.re_fraction[0] = 1;
2279 z.re_exponent++;
2282 else
2284 var c = 0;
2285 var i = 0;
2286 for (i = T + med - 1; i >= T; i--)
2288 /* HERE DO SUBTRACTION, ABS (Y) > ABS (X) */
2289 z.re_fraction[i] = c - small_fraction[i - med];
2290 c = 0;
2292 /* BORROW GENERATED HERE */
2293 if (z.re_fraction[i] < 0)
2295 c = -1;
2296 z.re_fraction[i] += BASE;
2300 for (; i >= med; i--)
2302 c = big_fraction[i] + c - small_fraction[i - med];
2303 if (c >= 0)
2305 /* NO BORROW GENERATED HERE */
2306 z.re_fraction[i] = c;
2307 c = 0;
2309 else
2311 /* BORROW GENERATED HERE */
2312 z.re_fraction[i] = c + BASE;
2313 c = -1;
2317 for (; i >= 0; i--)
2319 c = big_fraction[i] + c;
2321 if (c >= 0)
2323 z.re_fraction[i] = c;
2324 i--;
2326 /* NO CARRY POSSIBLE HERE */
2327 for (; i >= 0; i--)
2328 z.re_fraction[i] = big_fraction[i];
2330 break;
2333 z.re_fraction[i] = c + BASE;
2334 c = -1;
2338 mp_normalize (ref z);
2340 return z;
2343 private Number multiply_real (Number y)
2345 /* x*0 = 0*y = 0 */
2346 if (re_sign == 0 || y.re_sign == 0)
2347 return new Number.integer (0);
2349 var z = new Number.integer (0);
2350 z.re_sign = re_sign * y.re_sign;
2351 z.re_exponent = re_exponent + y.re_exponent;
2353 var r = new Number.integer (0);
2355 /* PERFORM MULTIPLICATION */
2356 var c = 8;
2357 for (var i = 0; i < T; i++)
2359 var xi = re_fraction[i];
2361 /* FOR SPEED, PUT THE NUMBER WITH MANY ZEROS FIRST */
2362 if (xi == 0)
2363 continue;
2365 /* Computing MIN */
2366 for (var j = 0; j < int.min (T, T + 3 - i); j++)
2367 r.re_fraction[i+j+1] += xi * y.re_fraction[j];
2368 c--;
2369 if (c > 0)
2370 continue;
2372 /* CHECK FOR LEGAL BASE B DIGIT */
2373 if (xi < 0 || xi >= BASE)
2375 mperr ("*** ILLEGAL BASE B DIGIT IN CALL TO MULTIPLY, POSSIBLE OVERWRITING PROBLEM ***");
2376 return new Number.integer (0);
2379 /* PROPAGATE CARRIES AT END AND EVERY EIGHTH TIME,
2380 * FASTER THAN DOING IT EVERY TIME.
2382 for (var j = T + 3; j >= 0; j--)
2384 int ri = r.re_fraction[j] + c;
2385 if (ri < 0)
2387 mperr ("*** INTEGER OVERFLOW IN MULTIPLY, B TOO LARGE ***");
2388 return new Number.integer (0);
2390 c = ri / BASE;
2391 r.re_fraction[j] = ri - BASE * c;
2393 if (c != 0)
2395 mperr ("*** ILLEGAL BASE B DIGIT IN CALL TO MULTIPLY, POSSIBLE OVERWRITING PROBLEM ***");
2396 return new Number.integer (0);
2398 c = 8;
2401 if (c != 8)
2403 c = 0;
2404 for (var i = T + 3; i >= 0; i--)
2406 int ri = r.re_fraction[i] + c;
2407 if (ri < 0)
2409 mperr ("*** INTEGER OVERFLOW IN MULTIPLY, B TOO LARGE ***");
2410 return new Number.integer (0);
2412 c = ri / BASE;
2413 r.re_fraction[i] = ri - BASE * c;
2416 if (c != 0)
2418 mperr ("*** ILLEGAL BASE B DIGIT IN CALL TO MULTIPLY, POSSIBLE OVERWRITING PROBLEM ***");
2419 return new Number.integer (0);
2423 /* Clear complex part */
2424 z.im_sign = 0;
2425 z.im_exponent = 0;
2426 for (var i = 0; i < z.im_fraction.length; i++)
2427 z.im_fraction[i] = 0;
2429 /* NORMALIZE AND ROUND RESULT */
2430 // FIXME: Use stack variable because of mp_normalize brokeness
2431 for (var i = 0; i < SIZE; i++)
2432 z.re_fraction[i] = r.re_fraction[i];
2433 mp_normalize (ref z);
2435 return z;
2438 private Number multiply_integer_real (int64 y)
2440 /* x*0 = 0*y = 0 */
2441 if (is_zero () || y == 0)
2442 return new Number.integer (0);
2444 /* x*1 = x, x*-1 = -x */
2445 // FIXME: Why is this not working? mp_ext is using this function to do a normalization
2446 /*if (y == 1 || y == -1)
2448 if (y < 0)
2449 z = invert_sign ();
2450 else
2451 z = this;
2452 return z;
2455 /* Copy x as z may also refer to x */
2456 var z = new Number.integer (0);
2458 if (y < 0)
2460 y = -y;
2461 z.re_sign = -re_sign;
2463 else
2464 z.re_sign = re_sign;
2465 z.re_exponent = re_exponent + 4;
2467 /* FORM PRODUCT IN ACCUMULATOR */
2468 int64 c = 0;
2470 /* IF y*B NOT REPRESENTABLE AS AN INTEGER WE HAVE TO SIMULATE
2471 * DOUBLE-PRECISION MULTIPLICATION.
2474 /* Computing MAX */
2475 if (y >= int.max (BASE << 3, 32767 / BASE))
2477 /* HERE J IS TOO LARGE FOR SINGLE-PRECISION MULTIPLICATION */
2478 var j1 = y / BASE;
2479 var j2 = y - j1 * BASE;
2481 /* FORM PRODUCT */
2482 for (var i = T + 3; i >= 0; i--)
2484 var c1 = c / BASE;
2485 var c2 = c - BASE * c1;
2486 var ix = 0;
2487 if (i > 3)
2488 ix = re_fraction[i - 4];
2490 var t = j2 * ix + c2;
2491 var is = t / BASE;
2492 c = j1 * ix + c1 + is;
2493 z.re_fraction[i] = (int) (t - BASE * is);
2496 else
2498 int64 ri = 0;
2499 for (var i = T + 3; i >= 4; i--)
2501 ri = y * re_fraction[i - 4] + c;
2502 c = ri / BASE;
2503 z.re_fraction[i] = (int) (ri - BASE * c);
2506 /* CHECK FOR INTEGER OVERFLOW */
2507 if (ri < 0)
2509 mperr ("*** INTEGER OVERFLOW IN multiply_integer, B TOO LARGE ***");
2510 return new Number.integer (0);
2513 /* HAVE TO TREAT FIRST FOUR WORDS OF R SEPARATELY */
2514 for (var i = 3; i >= 0; i--)
2516 var t = c;
2517 c = t / BASE;
2518 z.re_fraction[i] = (int) (t - BASE * c);
2522 /* HAVE TO SHIFT RIGHT HERE AS CARRY OFF END */
2523 while (c != 0)
2525 for (var i = T + 3; i >= 1; i--)
2526 z.re_fraction[i] = z.re_fraction[i - 1];
2527 var t = c;
2528 c = t / BASE;
2529 z.re_fraction[0] = (int) (t - BASE * c);
2530 z.re_exponent++;
2533 if (c < 0)
2535 mperr ("*** INTEGER OVERFLOW IN multiply_integer, B TOO LARGE ***");
2536 return new Number.integer (0);
2539 z.im_sign = 0;
2540 z.im_exponent = 0;
2541 for (var i = 0; i < z.im_fraction.length; i++)
2542 z.im_fraction[i] = 0;
2543 mp_normalize (ref z);
2545 return z;
2548 private Number reciprocal_real ()
2550 /* 1/0 invalid */
2551 if (is_zero ())
2553 mperr (_("Reciprocal of zero is undefined"));
2554 return new Number.integer (0);
2557 /* Start by approximating value using floating point */
2558 var t1 = copy ();
2559 t1.re_exponent = 0;
2560 t1 = new Number.double (1.0 / t1.to_double ());
2561 t1.re_exponent -= re_exponent;
2563 var t = 3;
2564 var it0 = t;
2565 Number t2;
2566 while (true)
2568 /* t1 = t1 - (t1 * ((x * t1) - 1)) (2*t1 - t1^2*x) */
2569 t2 = multiply (t1);
2570 t2 = t2.add (new Number.integer (-1));
2571 t2 = t1.multiply (t2);
2572 t1 = t1.subtract (t2);
2573 if (t >= T)
2574 break;
2576 /* FOLLOWING LOOP ALMOST DOUBLES T (POSSIBLE
2577 * BECAUSE NEWTONS METHOD HAS 2ND ORDER CONVERGENCE).
2579 var ts3 = t;
2580 var ts2 = 0;
2581 t = T;
2584 ts2 = t;
2585 t = (t + it0) / 2;
2586 } while (t > ts3);
2587 t = int.min (ts2, T);
2590 /* RETURN IF NEWTON ITERATION WAS CONVERGING */
2591 if (t2.re_sign != 0 && (t1.re_exponent - t2.re_exponent) << 1 < T - it0)
2593 /* THE FOLLOWING MESSAGE MAY INDICATE THAT B**(T-1) IS TOO SMALL,
2594 * OR THAT THE STARTING APPROXIMATION IS NOT ACCURATE ENOUGH.
2596 mperr ("*** ERROR OCCURRED IN RECIPROCAL, NEWTON ITERATION NOT CONVERGING PROPERLY ***");
2599 return t1;
2602 private Number divide_integer_real (int64 y)
2604 /* x/0 */
2605 if (y == 0)
2607 /* Translators: Error displayed attempted to divide by zero */
2608 mperr (_("Division by zero is undefined"));
2609 return new Number.integer (0);
2612 /* 0/y = 0 */
2613 if (is_zero ())
2614 return new Number.integer (0);
2616 /* Division by -1 or 1 just changes re_sign */
2617 if (y == 1 || y == -1)
2619 if (y < 0)
2620 return invert_sign ();
2621 else
2622 return this;
2625 var z = new Number.integer (0);
2626 if (y < 0)
2628 y = -y;
2629 z.re_sign = -re_sign;
2631 else
2632 z.re_sign = re_sign;
2633 z.re_exponent = re_exponent;
2635 int64 c = 0;
2636 int64 i = 0;
2638 /* IF y*B NOT REPRESENTABLE AS AN INTEGER HAVE TO SIMULATE
2639 * LONG DIVISION. ASSUME AT LEAST 16-BIT WORD.
2642 /* Computing MAX */
2643 var b2 = int.max (BASE << 3, 32767 / BASE);
2644 if (y < b2)
2646 /* LOOK FOR FIRST NONZERO DIGIT IN QUOTIENT */
2647 int64 r1 = 0;
2650 c = BASE * c;
2651 if (i < T)
2652 c += re_fraction[i];
2653 i++;
2654 r1 = c / y;
2655 if (r1 < 0)
2657 mperr ("*** INTEGER OVERFLOW IN DIVIDE_INTEGER, B TOO LARGE ***");
2658 return new Number.integer (0);
2660 } while (r1 == 0);
2662 /* ADJUST re_exponent AND GET T+4 DIGITS IN QUOTIENT */
2663 z.re_exponent += (int) (1 - i);
2664 z.re_fraction[0] = (int) r1;
2665 c = BASE * (c - y * r1);
2666 int64 kh = 1;
2667 if (i < T)
2669 kh = T + 1 - i;
2670 for (var k = 1; k < kh; k++)
2672 c += re_fraction[i];
2673 z.re_fraction[k] = (int) (c / y);
2674 c = BASE * (c - y * z.re_fraction[k]);
2675 i++;
2677 if (c < 0)
2679 mperr ("*** INTEGER OVERFLOW IN DIVIDE_INTEGER, B TOO LARGE ***");
2680 return new Number.integer (0);
2684 for (var k = kh; k < T + 4; k++)
2686 z.re_fraction[k] = (int) (c / y);
2687 c = BASE * (c - y * z.re_fraction[k]);
2689 if (c < 0)
2691 mperr ("*** INTEGER OVERFLOW IN DIVIDE_INTEGER, B TOO LARGE ***");
2692 return new Number.integer (0);
2695 mp_normalize (ref z);
2696 return z;
2699 /* HERE NEED SIMULATED DOUBLE-PRECISION DIVISION */
2700 var j1 = y / BASE;
2701 var j2 = y - j1 * BASE;
2703 /* LOOK FOR FIRST NONZERO DIGIT */
2704 var c2 = 0;
2707 c = BASE * c + c2;
2708 c2 = i < T ? re_fraction[i] : 0;
2709 i++;
2710 } while (c < j1 || (c == j1 && c2 < j2));
2712 /* COMPUTE T+4 QUOTIENT DIGITS */
2713 z.re_exponent += (int) (1 - i);
2714 i--;
2716 /* MAIN LOOP FOR LARGE ABS (y) CASE */
2717 for (var k = 1; k <= T + 4; k++)
2719 /* GET APPROXIMATE QUOTIENT FIRST */
2720 var ir = c / (j1 + 1);
2722 /* NOW REDUCE SO OVERFLOW DOES NOT OCCUR */
2723 var iq = c - ir * j1;
2724 if (iq >= b2)
2726 /* HERE IQ*B WOULD POSSIBLY OVERFLOW SO INCREASE IR */
2727 ir++;
2728 iq -= j1;
2731 iq = iq * BASE - ir * j2;
2732 if (iq < 0)
2734 /* HERE IQ NEGATIVE SO IR WAS TOO LARGE */
2735 ir--;
2736 iq += y;
2739 if (i < T)
2740 iq += re_fraction[i];
2741 i++;
2742 var iqj = iq / y;
2744 /* r (K) = QUOTIENT, C = REMAINDER */
2745 z.re_fraction[k - 1] = (int) (iqj + ir);
2746 c = iq - y * iqj;
2748 if (c < 0)
2750 /* CARRY NEGATIVE SO OVERFLOW MUST HAVE OCCURRED */
2751 mperr ("*** INTEGER OVERFLOW IN DIVIDE_INTEGER, B TOO LARGE ***");
2752 return new Number.integer (0);
2756 mp_normalize (ref z);
2758 /* CARRY NEGATIVE SO OVERFLOW MUST HAVE OCCURRED */
2759 mperr ("*** INTEGER OVERFLOW IN DIVIDE_INTEGER, B TOO LARGE ***");
2760 return new Number.integer (0);
2763 private Number from_radians (AngleUnit unit)
2765 switch (unit)
2767 default:
2768 case AngleUnit.RADIANS:
2769 return this;
2771 case AngleUnit.DEGREES:
2772 return multiply_integer (180).divide (new Number.pi ());
2774 case AngleUnit.GRADIANS:
2775 return multiply_integer (200).divide (new Number.pi ());
2779 /* Convert x to radians */
2780 private Number to_radians (AngleUnit unit)
2782 switch (unit)
2784 default:
2785 case AngleUnit.RADIANS:
2786 return this;
2788 case AngleUnit.DEGREES:
2789 return multiply (new Number.pi ()).divide_integer (180);
2791 case AngleUnit.GRADIANS:
2792 return multiply (new Number.pi ()).divide_integer (200);
2796 /* z = sin (x) -1 >= x >= 1, do_sin = 1
2797 * z = cos (x) -1 >= x >= 1, do_sin = 0
2799 private Number sin1 (bool do_sin)
2801 /* sin (0) = 0, cos (0) = 1 */
2802 if (is_zero ())
2804 if (do_sin)
2805 return new Number.integer (0);
2806 else
2807 return new Number.integer (1);
2810 var t2 = multiply (this);
2811 if (t2.compare (new Number.integer (1)) > 0)
2812 mperr ("*** ABS (X) > 1 IN CALL TO SIN1 ***");
2814 Number t1;
2815 int i;
2816 Number z;
2817 if (do_sin)
2819 t1 = this;
2820 z = t1;
2821 i = 2;
2823 else
2825 t1 = new Number.integer (1);
2826 z = new Number.integer (0);
2827 i = 1;
2830 /* Taylor series */
2831 /* POWER SERIES LOOP. REDUCE T IF POSSIBLE */
2832 var b2 = 2 * int.max (BASE, 64);
2835 if (T + t1.re_exponent <= 0)
2836 break;
2838 /* IF I*(I+1) IS NOT REPRESENTABLE AS AN INTEGER, THE FOLLOWING
2839 * DIVISION BY I*(I+1) HAS TO BE SPLIT UP.
2841 t1 = t2.multiply (t1);
2842 if (i > b2)
2844 t1 = t1.divide_integer (-i);
2845 t1 = t1.divide_integer (i + 1);
2847 else
2848 t1 = t1.divide_integer (-i * (i + 1));
2849 z = t1.add (z);
2851 i += 2;
2852 } while (t1.re_sign != 0);
2854 if (!do_sin)
2855 z = z.add (new Number.integer (1));
2857 return z;
2860 private Number sin_real (AngleUnit unit)
2862 /* sin (0) = 0 */
2863 if (is_zero ())
2864 return new Number.integer (0);
2866 var x_radians = to_radians (unit);
2868 var xs = x_radians.re_sign;
2869 x_radians = x_radians.abs ();
2871 /* USE SIN1 IF ABS (X) <= 1 */
2872 Number z;
2873 if (x_radians.compare (new Number.integer (1)) <= 0)
2874 z = x_radians.sin1 (true);
2875 /* FIND ABS (X) MODULO 2PI */
2876 else
2878 z = new Number.pi ().divide_integer (4);
2879 x_radians = x_radians.divide (z);
2880 x_radians = x_radians.divide_integer (8);
2881 x_radians = x_radians.fractional_component ();
2883 /* SUBTRACT 1/2, SAVE re_sign AND TAKE ABS */
2884 x_radians = x_radians.add (new Number.fraction (-1, 2));
2885 xs = -xs * x_radians.re_sign;
2886 if (xs == 0)
2887 return new Number.integer (0);
2889 x_radians.re_sign = 1;
2890 x_radians = x_radians.multiply_integer (4);
2892 /* IF NOT LESS THAN 1, SUBTRACT FROM 2 */
2893 if (x_radians.re_exponent > 0)
2894 x_radians = x_radians.add (new Number.integer (-2));
2896 if (x_radians.is_zero ())
2897 return new Number.integer (0);
2899 x_radians.re_sign = 1;
2900 x_radians = x_radians.multiply_integer (2);
2902 /* NOW REDUCED TO FIRST QUADRANT, IF LESS THAN PI/4 USE
2903 * POWER SERIES, ELSE COMPUTE COS OF COMPLEMENT
2905 if (x_radians.re_exponent > 0)
2907 x_radians = x_radians.add (new Number.integer (-2));
2908 x_radians = x_radians.multiply (z);
2909 z = x_radians.sin1 (false);
2911 else
2913 x_radians = x_radians.multiply (z);
2914 z = x_radians.sin1 (true);
2918 z.re_sign = xs;
2919 return z;
2922 private Number cos_real (AngleUnit unit)
2924 /* cos (0) = 1 */
2925 if (is_zero ())
2926 return new Number.integer (1);
2928 /* Use power series if |x| <= 1 */
2929 var z = to_radians (unit).abs ();
2930 if (z.compare (new Number.integer (1)) <= 0)
2931 return z.sin1 (false);
2932 else
2933 /* cos (x) = sin (π/2 - |x|) */
2934 return new Number.pi ().divide_integer (2).subtract (z).sin (AngleUnit.RADIANS);
2937 private Number bitwise (Number y, BitwiseFunc bitwise_operator, int wordlen)
2939 var text1 = to_hex_string ();
2940 var text2 = y.to_hex_string ();
2941 var offset1 = text1.length - 1;
2942 var offset2 = text2.length - 1;
2943 var offset_out = wordlen / 4 - 1;
2944 if (offset_out <= 0)
2945 offset_out = offset1 > offset2 ? offset1 : offset2;
2946 if (offset_out > 0 && (offset_out < offset1 || offset_out < offset2))
2948 mperr ("Overflow. Try a bigger word size");
2949 return new Number.integer (0);
2952 var text_out = new char[offset_out + 1];
2954 /* Perform bitwise operator on each character from right to left */
2955 for (text_out[offset_out+1] = '\0'; offset_out >= 0; offset_out--)
2957 int v1 = 0, v2 = 0;
2958 const char digits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
2960 if (offset1 >= 0)
2962 v1 = hex_to_int (text1[offset1]);
2963 offset1--;
2965 if (offset2 >= 0)
2967 v2 = hex_to_int (text2[offset2]);
2968 offset2--;
2970 text_out[offset_out] = digits[bitwise_operator (v1, v2)];
2973 return mp_set_from_string ((string) text_out, 16);
2976 private int hex_to_int (char digit)
2978 if (digit >= '0' && digit <= '9')
2979 return digit - '0';
2980 if (digit >= 'A' && digit <= 'F')
2981 return digit - 'A' + 10;
2982 if (digit >= 'a' && digit <= 'f')
2983 return digit - 'a' + 10;
2984 return 0;
2987 private string to_hex_string ()
2989 var serializer = new Serializer (DisplayFormat.FIXED, 16, 0);
2990 return serializer.to_string (this);
2994 // FIXME: Should all be in the class
2996 // FIXME: Re-add overflow and underflow detection
2998 static string? mp_error = null;
3000 /* THIS ROUTINE IS CALLED WHEN AN ERROR CONDITION IS ENCOUNTERED, AND
3001 * AFTER A MESSAGE HAS BEEN WRITTEN TO STDERR.
3003 public void mperr (string text)
3005 mp_error = text;
3008 /* Returns error string or null if no error */
3009 // FIXME: Global variable
3010 public string mp_get_error ()
3012 return mp_error;
3015 /* Clear any current error */
3016 public void mp_clear_error ()
3018 mp_error = null;
3021 /* Sets z from a string representation in 'text'. */
3022 public Number? mp_set_from_string (string str, int default_base = 10)
3024 if (str.index_of_char ('°') >= 0)
3025 return set_from_sexagesimal (str);
3027 /* Find the base */
3028 const unichar base_digits[] = {'₀', '₁', '₂', '₃', '₄', '₅', '₆', '₇', '₈', '₉'};
3029 var index = 0;
3030 unichar c;
3031 while (str.get_next_char (ref index, out c));
3032 var end = index;
3033 var number_base = 0;
3034 var base_multiplier = 1;
3035 while (str.get_prev_char (ref index, out c))
3037 var value = -1;
3038 for (var i = 0; i < base_digits.length; i++)
3040 if (c == base_digits[i])
3042 value = i;
3043 break;
3046 if (value < 0)
3047 break;
3049 end = index;
3050 number_base += value * base_multiplier;
3051 base_multiplier *= 10;
3053 if (base_multiplier == 1)
3054 number_base = default_base;
3056 /* Check if this has a sign */
3057 var negate = false;
3058 index = 0;
3059 str.get_next_char (ref index, out c);
3060 if (c == '+')
3061 negate = false;
3062 else if (c == '-' || c == '−')
3063 negate = true;
3064 else
3065 str.get_prev_char (ref index, out c);
3067 /* Convert integer part */
3068 var z = new Number.integer (0);
3069 while (str.get_next_char (ref index, out c))
3071 var i = char_val (c, number_base);
3072 if (i > number_base)
3073 return null;
3074 if (i < 0)
3076 str.get_prev_char (ref index, out c);
3077 break;
3080 z = z.multiply_integer (number_base).add (new Number.integer (i));
3083 /* Look for fraction characters, e.g. ⅚ */
3084 const unichar fractions[] = {'½', '⅓', '⅔', '¼', '¾', '⅕', '⅖', '⅗', '⅘', '⅙', '⅚', '⅛', '⅜', '⅝', '⅞'};
3085 const int numerators[] = { 1, 1, 2, 1, 3, 1, 2, 3, 4, 1, 5, 1, 3, 5, 7};
3086 const int denominators[] = { 2, 3, 3, 4, 4, 5, 5, 5, 5, 6, 6, 8, 8, 8, 8};
3087 var has_fraction = false;
3088 if (str.get_next_char (ref index, out c))
3090 for (var i = 0; i < fractions.length; i++)
3092 if (c == fractions[i])
3094 var fraction = new Number.fraction (numerators[i], denominators[i]);
3095 z = z.add (fraction);
3097 /* Must end with fraction */
3098 if (!str.get_next_char (ref index, out c))
3099 return z;
3100 else
3101 return null;
3105 /* Check for decimal point */
3106 if (c == '.')
3107 has_fraction = true;
3108 else
3109 str.get_prev_char (ref index, out c);
3112 /* Convert fractional part */
3113 if (has_fraction)
3115 var numerator = new Number.integer (0);
3116 var denominator = new Number.integer (1);
3118 while (str.get_next_char (ref index, out c))
3120 var i = char_val (c, number_base);
3121 if (i < 0)
3123 str.get_prev_char (ref index, out c);
3124 break;
3127 denominator = denominator.multiply_integer (number_base);
3128 numerator = numerator.multiply_integer (number_base);
3129 numerator = numerator.add (new Number.integer (i));
3132 numerator = numerator.divide (denominator);
3133 z = z.add (numerator);
3136 if (index != end)
3137 return null;
3139 if (negate)
3140 z = z.invert_sign ();
3142 return z;
3145 private int char_val (unichar c, int number_base)
3147 if (!c.isxdigit ())
3148 return -1;
3150 var value = c.xdigit_value ();
3152 if (value >= number_base)
3153 return -1;
3155 return value;
3158 private Number? set_from_sexagesimal (string str)
3160 var degree_index = str.index_of_char ('°');
3161 if (degree_index < 0)
3162 return null;
3163 var degrees = mp_set_from_string (str.substring (0, degree_index));
3164 if (degrees == null)
3165 return null;
3166 var minute_start = degree_index;
3167 unichar c;
3168 str.get_next_char (ref minute_start, out c);
3170 if (str[minute_start] == '\0')
3171 return degrees;
3172 var minute_index = str.index_of_char ('\'', minute_start);
3173 if (minute_index < 0)
3174 return null;
3175 var minutes = mp_set_from_string (str.substring (minute_start, minute_index - minute_start));
3176 if (minutes == null)
3177 return null;
3178 degrees = degrees.add (minutes.divide_integer (60));
3179 var second_start = minute_index;
3180 str.get_next_char (ref second_start, out c);
3182 if (str[second_start] == '\0')
3183 return degrees;
3184 var second_index = str.index_of_char ('"', second_start);
3185 if (second_index < 0)
3186 return null;
3187 var seconds = mp_set_from_string (str.substring (second_start, second_index - second_start));
3188 if (seconds == null)
3189 return null;
3190 degrees = degrees.add (seconds.divide_integer (3600));
3191 str.get_next_char (ref second_index, out c);
3193 /* Skip over second marker and expect no more characters */
3194 if (str[second_index] == '\0')
3195 return degrees;
3196 else
3197 return null;
3200 /* RETURNS K = K/GCD AND L = L/GCD, WHERE GCD IS THE
3201 * GREATEST COMMON DIVISOR OF K AND L.
3202 * SAVE INPUT PARAMETERS IN LOCAL VARIABLES
3204 public void mp_gcd (ref int64 k, ref int64 l)
3206 var i = k.abs ();
3207 var j = l.abs ();
3208 if (j == 0)
3210 /* IF J = 0 RETURN (1, 0) UNLESS I = 0, THEN (0, 0) */
3211 k = 1;
3212 l = 0;
3213 if (i == 0)
3214 k = 0;
3215 return;
3218 /* EUCLIDEAN ALGORITHM LOOP */
3221 i %= j;
3222 if (i == 0)
3224 k = k / j;
3225 l = l / j;
3226 return;
3228 j %= i;
3229 } while (j != 0);
3231 /* HERE J IS THE GCD OF K AND L */
3232 k = k / i;
3233 l = l / i;
3236 // FIXME: Is r.re_fraction large enough? It seems to be in practise but it may be T+4 instead of T
3237 // FIXME: There is some sort of stack corruption/use of unitialised variables here. Some functions are
3238 // using stack variables as x otherwise there are corruption errors. e.g. "Cos (45) - 1/Sqrt (2) = -0"
3239 // (try in scientific mode)
3240 public void mp_normalize (ref Number x)
3242 int start_index;
3244 /* Find first non-zero digit */
3245 for (start_index = 0; start_index < SIZE && x.re_fraction[start_index] == 0; start_index++);
3247 /* Mark as zero */
3248 if (start_index >= SIZE)
3250 x.re_sign = 0;
3251 x.re_exponent = 0;
3252 return;
3255 /* Shift left so first digit is non-zero */
3256 if (start_index > 0)
3258 x.re_exponent -= start_index;
3259 var i = 0;
3260 for (; (i + start_index) < SIZE; i++)
3261 x.re_fraction[i] = x.re_fraction[i + start_index];
3262 for (; i < SIZE; i++)
3263 x.re_fraction[i] = 0;
3267 /* Returns true if x is cannot be represented in a binary word of length 'wordlen' */
3268 public bool mp_is_overflow (Number x, int wordlen)
3270 var t2 = new Number.integer (2).xpowy_integer (wordlen);
3271 return t2.compare (x) > 0;