--- 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 $'
! !
-