LargeInteger.st
branchjv
changeset 18237 8457ae63fa44
parent 18120 e3a375d5f6a8
parent 18235 9f0914e019a8
child 18261 22bdfc405bca
--- a/LargeInteger.st	Sat Apr 18 06:57:35 2015 +0200
+++ b/LargeInteger.st	Mon Apr 20 06:40:26 2015 +0200
@@ -40,7 +40,7 @@
 
 documentation
 "
-    This class provides arbitrary precision integers. 
+    This class provides arbitrary precision integers.
     These are represented as:
       sign (-1/0/+1) and, if sign ~~ 0
       the absolute value in a ByteArray of digits with 8 bits per element;
@@ -55,9 +55,9 @@
     Also, results of LargeInteger operations are converted to back to
     SmallIntegers, when possible (see #compressed).
 
-    In contrast to ST-80, there is only one class for LargeIntegers, 
-    which keeps the sign as an instance variable 
-    (ST-80 has LargePositiveInteger and LargeNegativeInteger). 
+    In contrast to ST-80, there is only one class for LargeIntegers,
+    which keeps the sign as an instance variable
+    (ST-80 has LargePositiveInteger and LargeNegativeInteger).
     Another possible change is to use 2's complement instead of sign-magnitude
     representation, and to use the underlying CPU's native byte order (instead of LSB).
     This would allow us to use modern CPU vector/longword operations, at least for 64 and
@@ -66,12 +66,12 @@
     change in the future.
 
     [author:]
-        Claus Gittinger
+	Claus Gittinger
 
     [see also:]
-        Number
-        Float Fraction FixedPoint
-        SmallInteger
+	Number
+	Float Fraction FixedPoint
+	SmallInteger
 "
 !
 
@@ -259,9 +259,9 @@
     |digits|
 
     msb == false ifTrue:[
-        digits := aByteArrayOfDigits
+	digits := aByteArrayOfDigits
     ] ifFalse:[
-        digits := aByteArrayOfDigits reversed
+	digits := aByteArrayOfDigits reversed
     ].
     ^ self basicNew setDigits:digits
 
@@ -479,16 +479,16 @@
 
 // aNumber
     "return the integer part of the quotient of the receivers value
-     and the arguments value. 
+     and the arguments value.
      The result is truncated toward negative infinity
      and will be negative, if the operands signs differ.
      The following is always true:
-        (receiver // aNumber) * aNumber + (receiver \\ aNumber) = receiver
+	(receiver // aNumber) * aNumber + (receiver \\ aNumber) = receiver
 
      Be careful with negative results: 9 // 4 -> 2, while -9 // 4 -> -3.
-     Especially surprising:     
-        -1 // 10 -> -1 (because -(1/10) is truncated towards next smaller integer, which is -1.
-        -10 // 3 -> -4 (because -(10/3) is truncated towards next smaller integer, which is -4.
+     Especially surprising:
+	-1 // 10 -> -1 (because -(1/10) is truncated towards next smaller integer, which is -1.
+	-10 // 3 -> -4 (because -(10/3) is truncated towards next smaller integer, which is -4.
 
      See #quo: which returns -2 in the above case and #rem: which is the corresponding remainder."
 
@@ -502,38 +502,38 @@
      Use a special method for this case ...
     "
     (cls == SmallInteger) ifTrue:[
-        abs := aNumber.
-        abs := abs abs.
-        (abs between:1 and:(SmallInteger maxBytes == 8 ifTrue:16r00ffffffffff ifFalse:16r00ffffff)) ifTrue:[
-            divMod := self absFastDivMod:abs.
-        ] ifFalse:[
-            n := abs asLargeInteger.
-        ].
+	abs := aNumber.
+	abs := abs abs.
+	(abs between:1 and:(SmallInteger maxBytes == 8 ifTrue:16r00ffffffffff ifFalse:16r00ffffff)) ifTrue:[
+	    divMod := self absFastDivMod:abs.
+	] ifFalse:[
+	    n := abs asLargeInteger.
+	].
     ] ifFalse:[
-        "
-         if the argument is not a largeInteger, coerce
-        "
-        (cls == self class) ifFalse:[
-            ^ self retry:#// coercing:aNumber
-        ].
-        n := aNumber
+	"
+	 if the argument is not a largeInteger, coerce
+	"
+	(cls == self class) ifFalse:[
+	    ^ self retry:#// coercing:aNumber
+	].
+	n := aNumber
     ].
 
     divMod isNil ifTrue:[
-        divMod := self absDivMod:n.
+	divMod := self absDivMod:n.
     ].
     quo := divMod at:1.
     (sign == aNumber sign) ifFalse:[
-        "/ adjust for truncation if negative and there is a remainder ...
-        "/ be careful: there is one special case to care for here:
-        "/ if quo is maxInt+1, the negation can be represented as a smallInt.
-        quo := quo sign:-1.
-        (divMod at:2) == 0 ifFalse:[
-            ^ quo - 1
-        ].
-        quo digitLength == SmallInteger maxBytes ifTrue:[
-            ^ quo compressed
-        ].
+	"/ adjust for truncation if negative and there is a remainder ...
+	"/ be careful: there is one special case to care for here:
+	"/ if quo is maxInt+1, the negation can be represented as a smallInt.
+	quo := quo sign:-1.
+	(divMod at:2) == 0 ifFalse:[
+	    ^ quo - 1
+	].
+	quo digitLength == SmallInteger maxBytes ifTrue:[
+	    ^ quo compressed
+	].
     ].
     ^ quo
 
@@ -566,19 +566,19 @@
 
 \\ aNumber
     "Answer the integer remainder m defined by division with truncation toward
-     negative infinity. 
+     negative infinity.
      m < |aNumber| AND there is an integer k with (k * aNumber + m) = self
 
      The returned remainder has the same sign as aNumber.
      The following is always true:
-        (receiver // aNumber) * aNumber + (receiver \\ aNumber) = receiver
+	(receiver // aNumber) * aNumber + (receiver \\ aNumber) = receiver
 
      Be careful with negative results: 9 // 4 -> 2, while -9 // 4 -> -3.
-     Especially surprising:     
-        -1 \\ 10 -> 9  (because -(1/10) is truncated towards next smaller integer, which is -1,
-                        and -1 multiplied by 10 gives -10, so we have to add 9 to get the original -1).
-        -10 \\ 3 -> 2 (because -(10/3) is truncated towards next smaller integer, which is -4,
-                        and -4 * 4 gives -12, so we need to add 2 to get the original -10.
+     Especially surprising:
+	-1 \\ 10 -> 9  (because -(1/10) is truncated towards next smaller integer, which is -1,
+			and -1 multiplied by 10 gives -10, so we have to add 9 to get the original -1).
+	-10 \\ 3 -> 2 (because -(10/3) is truncated towards next smaller integer, which is -4,
+			and -4 * 4 gives -12, so we need to add 2 to get the original -10.
 
      See #rem: which is the corresponding remainder for division via #quo:.
 
@@ -587,11 +587,11 @@
     |abs rem negativeDivisor|
 
     aNumber negative ifTrue:[
-        negativeDivisor := true.
-        abs := aNumber negated.
+	negativeDivisor := true.
+	abs := aNumber negated.
     ] ifFalse:[
-        negativeDivisor := false.
-        abs := aNumber.
+	negativeDivisor := false.
+	abs := aNumber.
     ].
 
     "
@@ -599,33 +599,33 @@
      Use a special method for this case ...
     "
     (aNumber class == SmallInteger) ifTrue:[
-        (abs between:1 and:(SmallInteger maxBytes == 8 ifTrue:16r00ffffffffff ifFalse:16r00ffffff)) ifTrue:[
-            rem := (self absFastDivMod:abs) at:2.
-        ] ifFalse:[
-            rem := self absMod:abs asLargeInteger
-        ].
+	(abs between:1 and:(SmallInteger maxBytes == 8 ifTrue:16r00ffffffffff ifFalse:16r00ffffff)) ifTrue:[
+	    rem := (self absFastDivMod:abs) at:2.
+	] ifFalse:[
+	    rem := self absMod:abs asLargeInteger
+	].
     ] ifFalse:[
-        "
-         if the argument is not a largeInteger, coerce
-        "
-        (aNumber class == self class) ifFalse:[
-            ^ self retry:#\\ coercing:aNumber
-        ].
-
-        rem := self absMod:abs.
+	"
+	 if the argument is not a largeInteger, coerce
+	"
+	(aNumber class == self class) ifFalse:[
+	    ^ self retry:#\\ coercing:aNumber
+	].
+
+	rem := self absMod:abs.
     ].
 
     rem = 0 ifFalse:[
-        negativeDivisor ifTrue:[
-            rem := rem sign:-1
-        ].
-        (self negative ~~ negativeDivisor) ifTrue:[
-            "different sign, so remainder would have been negative.
-             rem has been rounded toward zero, this code will simulate
-             rounding to negative infinity."
-
-            rem := aNumber - rem.
-        ].
+	negativeDivisor ifTrue:[
+	    rem := rem sign:-1
+	].
+	(self negative ~~ negativeDivisor) ifTrue:[
+	    "different sign, so remainder would have been negative.
+	     rem has been rounded toward zero, this code will simulate
+	     rounding to negative infinity."
+
+	    rem := aNumber - rem.
+	].
     ].
     ^ rem
 
@@ -669,44 +669,44 @@
 !
 
 divMod:aNumber
-    "return an array filled with 
-        (self // aNumber) and (self \\ aNumber).
+    "return an array filled with
+	(self // aNumber) and (self \\ aNumber).
      The returned remainder has the same sign as aNumber.
      The following is always true:
-        (receiver // something) * something + (receiver \\ something) = receiver
+	(receiver // something) * something + (receiver \\ something) = receiver
 
      Be careful with negative results: 9 // 4 -> 2, while -9 // 4 -> -3.
-     Especially surprising:     
-        -1 \\ 10 -> 9  (because -(1/10) is truncated towards next smaller integer, which is -1,
-                        and -1 multiplied by 10 gives -10, so we have to add 9 to get the original -1).
-        -10 \\ 3 -> 2 (because -(10/3) is truncated towards next smaller integer, which is -4,
-                        and -4 * 4 gives -12, so we need to add 2 to get the original -10.
-
-     This is redefined here for more performance 
+     Especially surprising:
+	-1 \\ 10 -> 9  (because -(1/10) is truncated towards next smaller integer, which is -1,
+			and -1 multiplied by 10 gives -10, so we have to add 9 to get the original -1).
+	-10 \\ 3 -> 2 (because -(10/3) is truncated towards next smaller integer, which is -4,
+			and -4 * 4 gives -12, so we need to add 2 to get the original -10.
+
+     This is redefined here for more performance
      (as the remainder is generated as a side effect of division)"
 
     |cls n|
 
     ((self < 0) or:[aNumber <= 0]) ifTrue:[
-        ^ super divMod:aNumber
+	^ super divMod:aNumber
     ].
 
     "/ only handle the common case here
     cls := aNumber class.
     (cls == SmallInteger) ifTrue:[
-        "
-         this is the common case, dividing by a SmallInteger.
-         Use a special method for this case ...
-        "
-        (aNumber between:1 and:(SmallInteger maxBytes == 8 ifTrue:16r00ffffffffff ifFalse:16r00ffffff)) ifTrue:[
-            ^ self absFastDivMod:aNumber abs.
-        ].
-        n := aNumber asLargeInteger.
+	"
+	 this is the common case, dividing by a SmallInteger.
+	 Use a special method for this case ...
+	"
+	(aNumber between:1 and:(SmallInteger maxBytes == 8 ifTrue:16r00ffffffffff ifFalse:16r00ffffff)) ifTrue:[
+	    ^ self absFastDivMod:aNumber abs.
+	].
+	n := aNumber asLargeInteger.
     ] ifFalse:[
-        (cls == self class) ifFalse:[
-            ^ super divMod:aNumber
-        ].
-        n := aNumber.
+	(cls == self class) ifFalse:[
+	    ^ super divMod:aNumber
+	].
+	n := aNumber.
     ].
 
     ^ self absDivMod:n abs.
@@ -1552,6 +1552,11 @@
 digitAt:index
     "return 8 bits of value, starting at byte index"
 
+%{
+#ifdef __JAVA__
+    return context._RETURN( ((STLargeInteger)self).digitAt( index.intValue() ) );
+#endif
+%}.
     index > digitByteArray size ifTrue:[^ 0].
     ^ digitByteArray at:index
 !
@@ -1559,6 +1564,11 @@
 digitAt:index put:aByte
     "set the 8 bits, index is a byte index"
 
+%{
+#ifdef __JAVA__
+    ERROR("cannot modify the digits of a LargeInteger");
+#endif
+%}.
     digitByteArray at:index put:aByte
 !
 
@@ -1568,6 +1578,12 @@
      for negative ones, the actual bit representation is returned."
 
     |t digits|
+
+%{
+#ifdef __JAVA__
+    return context._RETURN( ((STLargeInteger)self).digitByteAt( index.intValue() ) );
+#endif
+%}.
     sign >= 0 ifTrue:[
 	index > digitByteArray size ifTrue:[
 	    ^ 0
@@ -1598,6 +1614,11 @@
      (8 bits of the absolute value per element).
      Least significant byte is first!!"
 
+%{
+#ifdef __JAVA__
+    return context._RETURN( ((STLargeInteger)self).digitBytes() );
+#endif
+%}.
     ^ digitByteArray
 
     "Modified: / 5.5.1999 / 14:57:03 / stefan"
@@ -1637,6 +1658,11 @@
     "
     |l "{ Class: SmallInteger }" |
 
+%{
+#ifdef __JAVA__
+    return context._RETURN( ((STLargeInteger)self).digitLength() );
+#endif
+%}.
     l := digitByteArray size.
     [l ~~ 0 and:[(digitByteArray at:l) == 0]] whileTrue:[
 	l := l - 1.
@@ -5363,6 +5389,11 @@
 negative
     "return true, if the receiver is < 0"
 
+%{
+#ifdef __JAVA__
+    return context._RETURN( ((STLargeInteger)self).largeValue.signum() < 0 ? STObject.True : STObject.False);
+#endif
+%}.
     ^ (sign < 0)
 !
 
@@ -5377,28 +5408,42 @@
 positive
     "return true, if the receiver is >= 0"
 
+%{
+#ifdef __JAVA__
+    return context._RETURN( ((STLargeInteger)self).largeValue.signum() >= 0 ? STObject.True : STObject.False);
+#endif
+%}.
     ^ (sign >= 0)
 !
 
 sign
     "return the sign of the receiver (-1, 0 or 1)"
 
+%{
+#ifdef __JAVA__
+    return context._RETURN( STInteger._new( ((STLargeInteger)self).largeValue.signum() ));
+#endif
+%}.
     ^ sign
 !
 
 strictlyPositive
     "return true, if the receiver is > 0"
 
+%{
+#ifdef __JAVA__
+    return context._RETURN( ((STLargeInteger)self).largeValue.signum() > 0 ? STObject.True : STObject.False);
+#endif
+%}.
     ^ (sign > 0)
 ! !
 
 !LargeInteger class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/LargeInteger.st,v 1.223 2015-03-25 14:12:51 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/LargeInteger.st,v 1.224 2015-04-19 22:31:45 cg Exp $'
 !
 
 version_CVS
-    ^ '$Header: /cvs/stx/stx/libbasic/LargeInteger.st,v 1.223 2015-03-25 14:12:51 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/LargeInteger.st,v 1.224 2015-04-19 22:31:45 cg Exp $'
 ! !
-