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
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
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);
40 // mperr ("SIZE TOO SMALL IN CALL TO MPSET, INCREASE SIZE AND DIMENSIONS OF MP ARRAYS TO AT LEAST %d ***", MP.t);
43 private const int T
= 100;
45 private delegate
int BitwiseFunc (int v1
, int v2
);
54 /* Object for a high precision floating point number representation
56 * x = sign * (BASE^(exponent-1) + BASE^(exponent-2) + ...)
60 /* Sign (+1, -1) or 0 for the value zero */
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
)
86 re_fraction
[re_exponent
] = (int) (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
)
107 re_fraction
[re_exponent
] = (int) (x
% BASE
);
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
);
125 numerator
= -numerator
;
126 denominator
= -denominator
;
129 Number
.integer (numerator
);
130 if (denominator
!= 1)
132 var z
= divide_integer (denominator
);
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);
158 else if (value
> 0.0f
)
164 /* INCREASE IE AND DIVIDE RJ BY 16. */
177 /* NOW RJ IS DY DIVIDED BY SUITABLE POWER OF 16.
178 * SET re_exponent TO 0
182 /* CONVERSION LOOP (ASSUME SINGLE-PRECISION OPS. EXACT) */
183 for (var i
= 0; i
< T
+ 4; i
++)
186 z
.re_fraction
[i
] = (int) rj
;
187 rj
-= z
.re_fraction
[i
];
190 /* NORMALIZE RESULT */
191 mp_normalize (ref z
);
194 var ib
= int.max (BASE
* 7 * BASE
, 32767) / 16;
197 /* NOW MULTIPLY BY 16**IE */
201 for (var i
= 1; i
<= k
; i
++)
204 if (tp
<= ib
&& tp
!= BASE
&& i
< k
)
206 z
= z
.divide_integer (tp
);
212 for (var i
= 1; i
<= ie
; i
++)
215 if (tp
<= ib
&& tp
!= BASE
&& i
< ie
)
217 z
= z
.multiply_integer (tp
);
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);
247 else if (value
> 0.0)
253 /* INCREASE IE AND DIVIDE DJ BY 16. */
255 for (ie
= 0; dj
>= 1.0; ie
++)
258 for ( ; dj
< 1.0/16.0; ie
--)
261 /* NOW DJ IS DY DIVIDED BY SUITABLE POWER OF 16
262 * SET re_exponent TO 0
266 /* CONVERSION LOOP (ASSUME DOUBLE-PRECISION OPS. EXACT) */
267 for (var i
= 0; i
< T
+ 4; i
++)
270 z
.re_fraction
[i
] = (int) dj
;
271 dj
-= (double) z
.re_fraction
[i
];
274 /* NORMALIZE RESULT */
275 mp_normalize (ref z
);
278 var ib
= int.max (BASE
* 7 * BASE
, 32767) / 16;
281 /* NOW MULTIPLY BY 16**IE */
285 for (var i
= 1; i
<= k
; ++i
)
288 if (tp
<= ib
&& tp
!= BASE
&& i
< k
)
290 z
= z
.divide_integer (tp
);
296 for (var i
= 1; i
<= ie
; ++i
)
299 if (tp
<= ib
&& tp
!= BASE
&& i
< ie
)
301 z
= z
.multiply_integer (tp
);
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
)
321 re_exponent
= x
.re_exponent
;
322 for (var i
= 0; i
< im_fraction
.length
; i
++)
323 re_fraction
[i
] = x
.re_fraction
[i
];
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 ();
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
];
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 ()
376 if (re_sign
== 0 || re_exponent
<= 0)
379 /* Multiply digits together */
380 for (var i
= 0; i
< re_exponent
; i
++)
383 z
= z
* BASE
+ re_fraction
[i
];
385 /* Check for overflow */
390 /* Validate result */
392 for (var i
= re_exponent
- 1; i
>= 0; i
--)
395 var digit
= v
- (v
/ BASE
) * BASE
;
396 if (re_fraction
[i
] != digit
)
407 public uint64 to_unsigned_integer ()
410 if (re_sign
<= 0 || re_exponent
<= 0)
413 /* Multiply digits together */
415 for (var i
= 0; i
< re_exponent
; i
++)
418 z
= z
* BASE
+ re_fraction
[i
];
420 /* Check for overflow */
425 /* Validate result */
427 for (var i
= re_exponent
- 1; i
>= 0; i
--)
430 var digit
= (uint64) v
- (v
/ BASE
) * BASE
;
431 if (re_fraction
[i
] != digit
)
442 public float to_float ()
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);
460 public double to_double ()
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);
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 ()
490 /* Return true if x is integer */
491 public bool is_integer ()
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
);
504 var t2
= t1
.floor ();
505 return t1
.equals (t2
);
507 /* Correct way to check for integer */
510 // Zero is an integer
515 if (re_exponent <= 0)
518 // Look for fractional components
519 for (var i = re_exponent; i < SIZE; i++)
521 if (re_fraction[i] != 0)
528 /* Return true if x is a positive integer */
529 public bool is_positive_integer ()
534 return re_sign
>= 0 && is_integer ();
537 /* Return true if x is a natural number (an integer ≥ 0) */
538 public bool is_natural ()
543 return re_sign
> 0 && is_integer ();
546 /* Return true if x has an imaginary component */
547 public bool is_complex ()
552 /* Return true if x == y */
553 public bool equals (Number y
)
555 return compare (y
) == 0;
563 public int compare (Number y
)
565 if (re_sign
!= y
.re_sign
)
567 if (re_sign
> y
.re_sign
)
577 /* See if numbers are of different magnitude */
578 if (re_exponent
!= y
.re_exponent
)
580 if (re_exponent
> y
.re_exponent
)
586 /* Compare fractions */
587 for (var i
= 0; i
< SIZE
; i
++)
589 if (re_fraction
[i
] == y
.re_fraction
[i
])
592 if (re_fraction
[i
] > y
.re_fraction
[i
])
602 /* Sets z = sgn (x) */
606 return new Number
.integer (0);
607 else if (is_negative ())
608 return new Number
.integer (-1);
610 return new Number
.integer (1);
614 public Number
invert_sign ()
618 z
.re_sign
= -z
.re_sign
;
619 z
.im_sign
= -z
.im_sign
;
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
);
641 z
.re_sign
= -z
.re_sign
;
646 /* Sets z = Arg (x) */
647 public Number
arg (AngleUnit unit
= AngleUnit
.RADIANS
)
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 ();
663 if (x_real
.is_negative ())
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);
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 ())
686 z
= x_im
.divide (x_real
);
687 z
= z
.atan (AngleUnit
.RADIANS
);
690 return z
.from_radians (unit
);
694 public Number
conjugate ()
697 z
.im_sign
= -z
.im_sign
;
701 /* Sets z = Re (x) */
702 public Number
real_component ()
706 /* Clear imaginary component */
709 for (var i
= 0; i
< z
.im_fraction
.length
; i
++)
710 z
.im_fraction
[i
] = 0;
715 /* Sets z = Im (x) */
716 public Number
imaginary_component ()
718 /* Copy imaginary component to real component */
719 var z
= new
Number ();
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 */
729 for (var i
= 0; i
< z
.im_fraction
.length
; i
++)
730 z
.im_fraction
[i
] = 0;
735 public Number
integer_component ()
737 /* Clear re_fraction */
739 for (var i
= z
.re_exponent
; i
< SIZE
; i
++)
740 z
.re_fraction
[i
] = 0;
743 for (var i
= 0; i
< z
.im_fraction
.length
; i
++)
744 z
.im_fraction
[i
] = 0;
749 /* Sets z = x mod 1 */
750 public Number
fractional_component ()
752 /* fractional component of zero is 0 */
754 return new Number
.integer (0);
757 if (re_exponent
<= 0)
760 /* Shift fractional component */
761 var shift
= re_exponent
;
762 for (var i
= shift
; i
< SIZE
&& re_fraction
[i
] == 0; i
++)
764 var z
= new Number
.integer (0);
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;
772 z
.re_fraction
[i
] = re_fraction
[i
+ shift
];
774 if (z
.re_fraction
[0] == 0)
781 public Number
fractional_part ()
783 return subtract (floor ());
787 public Number
floor ()
789 /* Integer component of zero = 0 */
793 /* If all fractional then no integer component */
794 if (re_exponent
<= 0)
797 return new Number
.integer (-1);
799 return new Number
.integer (0);
802 /* Clear fractional component */
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;
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));
823 public Number
ceiling ()
826 var f
= fractional_component ();
829 return z
.add (new Number
.integer (1));
833 public Number
round ()
835 var do_floor
= !is_negative ();
837 var f
= fractional_component ();
838 f
= f
.multiply_integer (2);
840 if (f
.compare (new Number
.integer (1)) >= 0)
841 do_floor
= !do_floor
;
850 public Number
reciprocal ()
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
);
861 var z
= t1
.reciprocal_real ();
862 return conjugate ().multiply (z
);
865 return reciprocal_real ();
869 public Number
epowy ()
873 return new Number
.integer (1);
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
);
884 return epowy_real ();
888 public Number
xpowy (Number y
)
891 return xpowy_integer (y
.to_integer ());
894 var reciprocal
= y
.reciprocal ();
895 if (reciprocal
.is_integer ())
896 return root (reciprocal
.to_integer ());
903 public Number
xpowy_integer (int64 n
)
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);
915 return new Number
.integer (1);
919 return new Number
.integer (0);
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
++)
943 public Number
root (int64 n
)
945 if (!is_complex () && is_negative () && n
% 2 == 1)
949 z
= z
.invert_sign ();
952 else if (is_complex () || is_negative ())
958 theta
= theta
.divide_integer (n
);
959 return new Number
.polar (r
, theta
);
962 return root_real (n
);
966 public Number
sqrt ()
971 /* FIXME: Make complex numbers optional */
974 mperr (_("Square root is undefined for negative values"));
975 return new Number.integer (0);
980 var z
= multiply (t
);
981 return z
.ext (t
.re_fraction
[0], z
.re_fraction
[0]);
988 /* ln (0) undefined */
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θ) */
1010 var z_real
= r
.ln_real ();
1012 return new Number
.complex (z_real
, theta
);
1018 /* Sets z = log_n x */
1019 public Number
logarithm (int64 n
)
1021 /* log (0) undefined */
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 ());
1035 public Number
factorial ()
1039 return new Number
.integer (1);
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 ();
1050 for (var i
= 2; i
< value
; i
++)
1051 z
= z
.multiply_integer (i
);
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
)
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
);
1093 return new Number
.complex (real_z
, im_z
);
1096 return multiply_real (y
);
1099 /* Sets z = x × y */
1100 public Number
multiply_integer (int64 y
)
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
);
1109 return multiply_integer_real (y
);
1112 /* Sets z = x ÷ y */
1113 public Number
divide (Number y
)
1118 /* Translators: Error displayed attempted to divide by zero */
1119 mperr (_("Division by zero is undefined"));
1120 return new Number
.integer (0);
1128 /* FIXME: Set re_exponent to zero to avoid overflow in multiply??? */
1129 var t
= y
.reciprocal ();
1130 var ie
= t
.re_exponent
;
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
;
1140 /* Sets z = x ÷ y */
1141 public Number
divide_integer (int64 y
)
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
);
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)
1174 /* Sets z = sin x */
1175 public Number
sin (AngleUnit unit
= AngleUnit
.RADIANS
)
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
);
1188 z_im
= z_im
.multiply (t
);
1190 return new Number
.complex (z_real
, z_im
);
1193 return sin_real (unit
);
1196 /* Sets z = cos x */
1197 public Number
cos (AngleUnit unit
= AngleUnit
.RADIANS
)
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
);
1210 z_im
= z_im
.multiply (t
);
1211 z_im
= z_im
.invert_sign ();
1213 return new Number
.complex (z_real
, z_im
);
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
)
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);
1247 t1
= t1
.subtract (this
);
1249 t2
= t1
.multiply (t2
);
1251 var z
= multiply (t2
);
1256 /* sin⁻¹(1) = π/2, sin⁻¹(-1) = -π/2 */
1257 var t2
= new Number
.integer (re_sign
);
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);
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
))
1291 /* cos⁻¹(x) = tan⁻¹(√(1 - x²) / x) */
1293 var t2
= multiply (this
);
1294 t2
= t1
.subtract (t2
);
1296 t2
= t2
.divide (this
);
1297 y
= t2
.atan (AngleUnit
.RADIANS
);
1304 return z
.from_radians (unit
);
1307 /* Sets z = tan⁻¹ x */
1308 public Number
atan (AngleUnit unit
= AngleUnit
.RADIANS
)
1311 return new Number
.integer (0);
1315 if (re_exponent
.abs () <= 2)
1318 /* REDUCE ARGUMENT IF NECESSARY BEFORE USING SERIES */
1321 while (t2
.re_exponent
>= 0)
1323 if (t2
.re_exponent
== 0 && 2 * (t2
.re_fraction
[0] + 1) <= BASE
)
1328 /* t = t / (√(t² + 1) + 1) */
1329 z
= t2
.multiply (t2
);
1330 z
= z
.add (new Number
.integer (1));
1332 z
= z
.add (new Number
.integer (1));
1336 /* USE POWER SERIES NOW ARGUMENT IN (-0.5, 0.5) */
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)
1346 t2
= t2
.multiply (t1
).multiply_integer (-i
).divide_integer (i
+ 2);
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 ()
1375 return new Number
.integer (0);
1377 /* WORK WITH ABS (X) */
1380 /* If |x| < 1 USE EXP TO AVOID CANCELLATION, otherwise IF TOO LARGE EPOWY GIVES ERROR MESSAGE */
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));
1390 z
= z
.divide (exp_x
);
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 ()
1410 return new Number
.integer (1);
1412 /* cosh (x) = (e^x + e^-x) / 2 */
1415 var z
= t
.reciprocal ();
1417 return z
.divide_integer (2);
1420 /* Sets z = tanh x */
1421 public Number
tanh ()
1425 return new Number
.integer (0);
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)
1441 z
= t
.add (new Number
.integer (-1));
1442 t
= t
.add (new Number
.integer (1));
1448 z
= t
.add (new Number
.integer (1));
1449 t
= t
.add (new Number
.integer (-1));
1453 /* Restore re_sign */
1454 z
.re_sign
= re_sign
* z
.re_sign
;
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));
1469 /* Sets z = cosh⁻¹ x */
1470 public Number
acosh ()
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));
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
);
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
)
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);
1581 for (var i
= 0; i
< count
; i
++)
1583 return multiply_integer (multiplier
);
1588 for (var i
= 0; i
< -count
; i
++)
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?
> ();
1613 if (value
.is_zero ())
1615 factors
.append (value
);
1619 if (value
.equals (new Number
.integer (1)))
1621 factors
.append (this
);
1625 var divisor
= new Number
.integer (2);
1628 var tmp
= value
.divide (divisor
);
1629 if (tmp
.is_integer ())
1632 factors
.append (divisor
);
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 ())
1646 root
= value
.sqrt ();
1647 factors
.append (divisor
);
1651 tmp
= divisor
.add (new Number
.integer (2));
1656 if (value
.compare (new Number
.integer (1)) > 0)
1657 factors
.append (value
);
1660 factors
.data
= factors
.data
.invert_sign ();
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
];
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
);
1698 return add_real (y_sign
* y
.re_sign
, y
);
1701 private Number
epowy_real ()
1705 return new Number
.integer (1);
1707 /* If |x| < 1 use exp */
1708 if (re_exponent
<= 0)
1711 /* NOW SAFE TO CONVERT X TO REAL */
1712 var rx
= to_double ();
1714 /* SAVE re_sign AND WORK WITH ABS (X) */
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 */
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)
1735 /* LOOP FOR E COMPUTATION. DECREASE T IF POSSIBLE. */
1737 var t1
= new Number
.integer (xs
);
1740 for (var i
= 2 ; ; i
++)
1742 if (int.min (tss
, tss
+ 2 + t1
.re_exponent
) <= 2)
1745 t1
= t1
.divide_integer (i
* xs
);
1751 /* RAISE E OR 1/E TO POWER IX */
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
)
1765 var rz
= z
.to_double ();
1766 var r__1
= rz
- Math
.exp (rx
);
1767 if (Math
.fabs (r__1
) < rz
* 0.01f
)
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 ***");
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 ()
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);
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
);
1809 for (var i
= 1; i
<= q
; i
++)
1812 if (ic
< ib
&& ic
!= BASE
&& i
< q
)
1814 t1
= t1
.divide_integer (ic
);
1820 return new Number
.integer (0);
1822 /* Sum series, reducing t where possible */
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
);
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 */
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 */
1858 mperr (_("The power of zero is undefined for a negative exponent"));
1859 return new Number
.integer (0);
1864 return new Number
.integer (1);
1866 return y
.multiply (ln ()).epowy ();
1869 private Number
root_real (int64 n
)
1875 /* x^(1/0) invalid */
1878 mperr (_("Root must be non-zero"));
1879 return new Number
.integer (0);
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 */
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 */
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 */
1923 /* t1 = t1 - ((t1 * ((x * t1^np) - 1)) / np) */
1924 t2
= t1
.xpowy_integer (np
);
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).
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 ***");
1962 t1
= t1
.xpowy_integer (n
- 1);
1963 return multiply (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)
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 */
1986 z
.re_fraction
[T
- 2] = 0;
1987 z
.re_fraction
[T
- 1] = 0;
1991 if (s
+ q
< BASE
* BASE
)
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 */
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
;
2017 var rx
= t1
.to_float_old ();
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
);
2026 /* COMPUTE RESIDUAL WHOSE LOG IS STILL TO BE FOUND */
2027 t1
= t1
.multiply (t2
);
2030 mperr ("*** ERROR IN LN, ITERATION NOT CONVERGING ***");
2034 // FIXME: This is here becase ln e breaks if we use the symmetric to_float
2035 private float to_float_old ()
2044 z
= BASE
* z
+ re_fraction
[i
];
2046 /* CHECK IF FULL SINGLE-PRECISION ACCURACY ATTAINED */
2051 /* NOW ALLOW FOR EXPONENT */
2052 z
= (float) (z
* mppow_ri (BASE
, re_exponent
- i
- 1));
2060 private double mppow_ri (float ap
, int bp
)
2078 if ((bp
>>= 1) != 0)
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 ()
2098 /* Get starting approximation -ln (1+x) ~= -x + x^2/2 - x^3/3 + x^4/4 */
2100 var t1
= divide_integer (4);
2101 t1
= t1
.add (new Number
.fraction (-1, 3));
2103 t1
= t1
.add (new Number
.fraction (1, 2));
2105 t1
= t1
.add (new Number
.integer (-1));
2106 var z
= multiply (t1
);
2108 /* Solve using Newtons method */
2114 /* t3 = (e^t3 - 1) */
2115 /* z = z - (t2 + t3 + (t2 * t3)) */
2117 t3
= t3
.add (new Number
.integer (-1));
2118 t1
= t2
.multiply (t3
);
2121 z
= z
.subtract (t3
);
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.
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
;
2149 private Number
add_real (int y_sign
, Number y
)
2151 var re_sign_prod
= y_sign
* re_sign
;
2156 if (y_sign
!= y
.re_sign
)
2157 return y
.invert_sign ();
2162 else if (y
.is_zero ())
2165 var exp_diff
= re_exponent
- y
.re_exponent
;
2166 var med
= exp_diff
.abs ();
2167 var x_largest
= false;
2170 else if (exp_diff
> 0)
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. */
2179 for (j
= 0; j
< T
; j
++)
2181 int i
= re_fraction
[j
] - y
.re_fraction
[j
];
2192 /* Both mantissas equal, so result is zero. */
2194 return new Number
.integer (0);
2198 var z
= new Number
.integer (0);
2200 int[] big_fraction
, small_fraction
;
2203 z
.re_sign
= re_sign
;
2204 z
.re_exponent
= re_exponent
;
2205 big_fraction
= re_fraction
;
2206 small_fraction
= y
.re_fraction
;
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. */
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) */
2231 for (i
= T
+ 3; i
>= T
; i
--)
2232 z
.re_fraction
[i
] = small_fraction
[i
- med
];
2235 for (; i
>= med
; i
--)
2237 c
= big_fraction
[i
] + small_fraction
[i
- med
] + c
;
2241 /* NO CARRY GENERATED HERE */
2242 z
.re_fraction
[i
] = c
;
2247 /* CARRY GENERATED HERE */
2248 z
.re_fraction
[i
] = c
- BASE
;
2255 c
= big_fraction
[i
] + c
;
2258 z
.re_fraction
[i
] = c
;
2261 /* NO CARRY POSSIBLE HERE */
2263 z
.re_fraction
[i
] = big_fraction
[i
];
2269 z
.re_fraction
[i
] = 0;
2273 /* MUST SHIFT RIGHT HERE AS CARRY OFF END */
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;
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
];
2292 /* BORROW GENERATED HERE */
2293 if (z
.re_fraction
[i
] < 0)
2296 z
.re_fraction
[i
] += BASE
;
2300 for (; i
>= med
; i
--)
2302 c
= big_fraction
[i
] + c
- small_fraction
[i
- med
];
2305 /* NO BORROW GENERATED HERE */
2306 z
.re_fraction
[i
] = c
;
2311 /* BORROW GENERATED HERE */
2312 z
.re_fraction
[i
] = c
+ BASE
;
2319 c
= big_fraction
[i
] + c
;
2323 z
.re_fraction
[i
] = c
;
2326 /* NO CARRY POSSIBLE HERE */
2328 z
.re_fraction
[i
] = big_fraction
[i
];
2333 z
.re_fraction
[i
] = c
+ BASE
;
2338 mp_normalize (ref z
);
2343 private Number
multiply_real (Number y
)
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 */
2357 for (var i
= 0; i
< T
; i
++)
2359 var xi
= re_fraction
[i
];
2361 /* FOR SPEED, PUT THE NUMBER WITH MANY ZEROS FIRST */
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
];
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
;
2387 mperr ("*** INTEGER OVERFLOW IN MULTIPLY, B TOO LARGE ***");
2388 return new Number
.integer (0);
2391 r
.re_fraction
[j
] = ri
- BASE
* c
;
2395 mperr ("*** ILLEGAL BASE B DIGIT IN CALL TO MULTIPLY, POSSIBLE OVERWRITING PROBLEM ***");
2396 return new Number
.integer (0);
2404 for (var i
= T
+ 3; i
>= 0; i
--)
2406 int ri
= r
.re_fraction
[i
] + c
;
2409 mperr ("*** INTEGER OVERFLOW IN MULTIPLY, B TOO LARGE ***");
2410 return new Number
.integer (0);
2413 r
.re_fraction
[i
] = ri
- BASE
* c
;
2418 mperr ("*** ILLEGAL BASE B DIGIT IN CALL TO MULTIPLY, POSSIBLE OVERWRITING PROBLEM ***");
2419 return new Number
.integer (0);
2423 /* Clear complex part */
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
);
2438 private Number
multiply_integer_real (int64 y
)
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)
2455 /* Copy x as z may also refer to x */
2456 var z
= new Number
.integer (0);
2461 z
.re_sign
= -re_sign
;
2464 z
.re_sign
= re_sign
;
2465 z
.re_exponent
= re_exponent
+ 4;
2467 /* FORM PRODUCT IN ACCUMULATOR */
2470 /* IF y*B NOT REPRESENTABLE AS AN INTEGER WE HAVE TO SIMULATE
2471 * DOUBLE-PRECISION MULTIPLICATION.
2475 if (y
>= int.max (BASE
<< 3, 32767 / BASE
))
2477 /* HERE J IS TOO LARGE FOR SINGLE-PRECISION MULTIPLICATION */
2479 var j2
= y
- j1
* BASE
;
2482 for (var i
= T
+ 3; i
>= 0; i
--)
2485 var c2
= c
- BASE
* c1
;
2488 ix
= re_fraction
[i
- 4];
2490 var t
= j2
* ix
+ c2
;
2492 c
= j1
* ix
+ c1
+ is
;
2493 z
.re_fraction
[i
] = (int) (t
- BASE
* is
);
2499 for (var i
= T
+ 3; i
>= 4; i
--)
2501 ri
= y
* re_fraction
[i
- 4] + c
;
2503 z
.re_fraction
[i
] = (int) (ri
- BASE
* c
);
2506 /* CHECK FOR INTEGER OVERFLOW */
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
--)
2518 z
.re_fraction
[i
] = (int) (t
- BASE
* c
);
2522 /* HAVE TO SHIFT RIGHT HERE AS CARRY OFF END */
2525 for (var i
= T
+ 3; i
>= 1; i
--)
2526 z
.re_fraction
[i
] = z
.re_fraction
[i
- 1];
2529 z
.re_fraction
[0] = (int) (t
- BASE
* c
);
2535 mperr ("*** INTEGER OVERFLOW IN multiply_integer, B TOO LARGE ***");
2536 return new Number
.integer (0);
2541 for (var i
= 0; i
< z
.im_fraction
.length
; i
++)
2542 z
.im_fraction
[i
] = 0;
2543 mp_normalize (ref z
);
2548 private Number
reciprocal_real ()
2553 mperr (_("Reciprocal of zero is undefined"));
2554 return new Number
.integer (0);
2557 /* Start by approximating value using floating point */
2560 t1
= new Number
.double (1.0 / t1
.to_double ());
2561 t1
.re_exponent
-= re_exponent
;
2568 /* t1 = t1 - (t1 * ((x * t1) - 1)) (2*t1 - t1^2*x) */
2570 t2
= t2
.add (new Number
.integer (-1));
2571 t2
= t1
.multiply (t2
);
2572 t1
= t1
.subtract (t2
);
2576 /* FOLLOWING LOOP ALMOST DOUBLES T (POSSIBLE
2577 * BECAUSE NEWTONS METHOD HAS 2ND ORDER CONVERGENCE).
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 ***");
2602 private Number
divide_integer_real (int64 y
)
2607 /* Translators: Error displayed attempted to divide by zero */
2608 mperr (_("Division by zero is undefined"));
2609 return new Number
.integer (0);
2614 return new Number
.integer (0);
2616 /* Division by -1 or 1 just changes re_sign */
2617 if (y
== 1 || y
== -1)
2620 return invert_sign ();
2625 var z
= new Number
.integer (0);
2629 z
.re_sign
= -re_sign
;
2632 z
.re_sign
= re_sign
;
2633 z
.re_exponent
= re_exponent
;
2638 /* IF y*B NOT REPRESENTABLE AS AN INTEGER HAVE TO SIMULATE
2639 * LONG DIVISION. ASSUME AT LEAST 16-BIT WORD.
2643 var b2
= int.max (BASE
<< 3, 32767 / BASE
);
2646 /* LOOK FOR FIRST NONZERO DIGIT IN QUOTIENT */
2652 c
+= re_fraction
[i
];
2657 mperr ("*** INTEGER OVERFLOW IN DIVIDE_INTEGER, B TOO LARGE ***");
2658 return new Number
.integer (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
);
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
]);
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
]);
2691 mperr ("*** INTEGER OVERFLOW IN DIVIDE_INTEGER, B TOO LARGE ***");
2692 return new Number
.integer (0);
2695 mp_normalize (ref z
);
2699 /* HERE NEED SIMULATED DOUBLE-PRECISION DIVISION */
2701 var j2
= y
- j1
* BASE
;
2703 /* LOOK FOR FIRST NONZERO DIGIT */
2708 c2
= i
< T ? re_fraction
[i
] : 0;
2710 } while (c
< j1
|| (c
== j1
&& c2
< j2
));
2712 /* COMPUTE T+4 QUOTIENT DIGITS */
2713 z
.re_exponent
+= (int) (1 - 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
;
2726 /* HERE IQ*B WOULD POSSIBLY OVERFLOW SO INCREASE IR */
2731 iq
= iq
* BASE
- ir
* j2
;
2734 /* HERE IQ NEGATIVE SO IR WAS TOO LARGE */
2740 iq
+= re_fraction
[i
];
2744 /* r (K) = QUOTIENT, C = REMAINDER */
2745 z
.re_fraction
[k
- 1] = (int) (iqj
+ ir
);
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
)
2768 case AngleUnit
.RADIANS
:
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
)
2785 case AngleUnit
.RADIANS
:
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 */
2805 return new Number
.integer (0);
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 ***");
2825 t1
= new Number
.integer (1);
2826 z
= new Number
.integer (0);
2831 /* POWER SERIES LOOP. REDUCE T IF POSSIBLE */
2832 var b2
= 2 * int.max (BASE
, 64);
2835 if (T
+ t1
.re_exponent
<= 0)
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
);
2844 t1
= t1
.divide_integer (-i
);
2845 t1
= t1
.divide_integer (i
+ 1);
2848 t1
= t1
.divide_integer (-i
* (i
+ 1));
2852 } while (t1
.re_sign
!= 0);
2855 z
= z
.add (new Number
.integer (1));
2860 private Number
sin_real (AngleUnit unit
)
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 */
2873 if (x_radians
.compare (new Number
.integer (1)) <= 0)
2874 z
= x_radians
.sin1 (true);
2875 /* FIND ABS (X) MODULO 2PI */
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
;
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);
2913 x_radians
= x_radians
.multiply (z
);
2914 z
= x_radians
.sin1 (true);
2922 private Number
cos_real (AngleUnit unit
)
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);
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
--)
2958 const char digits
[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
2962 v1
= hex_to_int (text1
[offset1
]);
2967 v2
= hex_to_int (text2
[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')
2980 if (digit
>= 'A' && digit
<= 'F')
2981 return digit
- 'A' + 10;
2982 if (digit
>= 'a' && digit
<= 'f')
2983 return digit
- 'a' + 10;
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
)
3008 /* Returns error string or null if no error */
3009 // FIXME: Global variable
3010 public string mp_get_error ()
3015 /* Clear any current error */
3016 public void mp_clear_error ()
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
);
3028 const unichar base_digits
[] = {'₀', '₁', '₂', '₃', '₄', '₅', '₆', '₇', '₈', '₉'};
3031 while (str
.get_next_char (ref index
, out c
));
3033 var number_base
= 0;
3034 var base_multiplier
= 1;
3035 while (str
.get_prev_char (ref index
, out c
))
3038 for (var i
= 0; i
< base_digits
.length
; i
++)
3040 if (c
== base_digits
[i
])
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 */
3059 str
.get_next_char (ref index
, out c
);
3062 else if (c
== '-' || c
== '−')
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
)
3076 str
.get_prev_char (ref index
, out c
);
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
))
3105 /* Check for decimal point */
3107 has_fraction
= true;
3109 str
.get_prev_char (ref index
, out c
);
3112 /* Convert fractional part */
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
);
3123 str
.get_prev_char (ref index
, out c
);
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
);
3140 z
= z
.invert_sign ();
3145 private int char_val (unichar c
, int number_base
)
3150 var value
= c
.xdigit_value ();
3152 if (value
>= number_base
)
3158 private Number?
set_from_sexagesimal (string str
)
3160 var degree_index
= str
.index_of_char ('°');
3161 if (degree_index
< 0)
3163 var degrees
= mp_set_from_string (str
.substring (0, degree_index
));
3164 if (degrees
== null)
3166 var minute_start
= degree_index
;
3168 str
.get_next_char (ref minute_start
, out c
);
3170 if (str
[minute_start
] == '\0')
3172 var minute_index
= str
.index_of_char ('\'', minute_start
);
3173 if (minute_index
< 0)
3175 var minutes
= mp_set_from_string (str
.substring (minute_start
, minute_index
- minute_start
));
3176 if (minutes
== 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')
3184 var second_index
= str
.index_of_char ('"', second_start
);
3185 if (second_index
< 0)
3187 var seconds
= mp_set_from_string (str
.substring (second_start
, second_index
- second_start
));
3188 if (seconds
== 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')
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
)
3210 /* IF J = 0 RETURN (1, 0) UNLESS I = 0, THEN (0, 0) */
3218 /* EUCLIDEAN ALGORITHM LOOP */
3231 /* HERE J IS THE GCD OF K AND L */
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
)
3244 /* Find first non-zero digit */
3245 for (start_index
= 0; start_index
< SIZE
&& x
.re_fraction
[start_index
] == 0; start_index
++);
3248 if (start_index
>= SIZE
)
3255 /* Shift left so first digit is non-zero */
3256 if (start_index
> 0)
3258 x
.re_exponent
-= start_index
;
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;