--- a/LargeInteger.st Wed Jul 05 16:56:30 2017 +0200
+++ b/LargeInteger.st Wed Jul 05 16:57:09 2017 +0200
@@ -577,14 +577,14 @@
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.
+ -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:.
@@ -594,22 +594,22 @@
nrClass := aNumber class.
((nrClass == SmallInteger) or:[nrClass == self class]) ifFalse:[
- ^ self retry:#\\ coercing:aNumber
+ ^ self retry:#\\ coercing:aNumber
].
- rem := (self absDivMod:aNumber) at:2.
+ rem := self absMod:aNumber.
rem ~~ 0 ifTrue:[
- negativeDivisor := aNumber negative.
- negativeDivisor ifTrue:[
- rem := rem setSign:-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 := aNumber negative.
+ negativeDivisor ifTrue:[
+ rem := rem setSign:-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
@@ -639,8 +639,8 @@
-9000000000 rem: -4000000000
"
- "Modified: / 5.11.1996 / 17:10:10 / cg"
- "Modified: / 27.4.1999 / 20:03:40 / stefan"
+ "Modified: / 27-04-1999 / 20:03:40 / stefan"
+ "Modified: / 05-07-2017 / 16:12:47 / cg"
!
abs
@@ -854,20 +854,20 @@
"return the remainder of division of the receiver by the argument, aNumber.
The returned remainder has the same sign as the receiver.
The following is always true:
- (receiver quo: aNumber) * aNumber + (receiver rem: aNumber) = receiver
+ (receiver quo: aNumber) * aNumber + (receiver rem: aNumber) = receiver
"
|nrClass rem|
nrClass := aNumber class.
((nrClass == SmallInteger) or:[ nrClass == self class ]) ifFalse:[
- ^ self retry:#rem coercing:aNumber
+ ^ self retry:#rem coercing:aNumber
].
- rem := (self absDivMod:aNumber) at:2.
+ rem := self absMod:aNumber.
rem ~~ 0 ifTrue:[
- sign < 0 ifTrue:[
- ^ rem setSign:-1
- ].
+ sign < 0 ifTrue:[
+ ^ rem setSign:-1
+ ].
].
^ rem
@@ -893,8 +893,8 @@
-9000000000 rem: -4000000000
"
- "Modified: / 5.11.1996 / 14:02:59 / cg"
- "Modified: / 29.4.1999 / 11:26:51 / stefan"
+ "Modified: / 29-04-1999 / 11:26:51 / stefan"
+ "Modified: / 05-07-2017 / 16:13:33 / cg"
! !
!LargeInteger methodsFor:'bit operators'!
@@ -4403,58 +4403,68 @@
!
absMod:anInteger
- "return a LargeIntegers representing
- abs(self) \\ abs(theArgument).
+ "return the remainder from the expression:
+ abs(self) \\ abs(theArgument).
Used as a helper for \\ and rem:"
|dividend divisor
+ modOrNil
shift "{ Class: SmallInteger }" |
anInteger == 0 ifTrue:[
- ^ ZeroDivide raiseRequestWith:thisContext
+ ^ ZeroDivide raiseRequestWith:thisContext
+ ].
+
+ anInteger class == SmallInteger ifTrue:[
+ divisor := anInteger abs.
+ modOrNil := self absFastMod:divisor.
+ modOrNil notNil ifTrue:[^ modOrNil].
+ divisor := divisor asLargeInteger.
+ ] ifFalse:[
+ divisor := anInteger.
].
self = anInteger ifTrue:[
- ^ 0
+ ^ 0
].
- shift := self highBit - anInteger highBit.
+ shift := self highBit - divisor highBit.
dividend := self class digitBytes:digitByteArray copy. "/ self simpleDeepCopy sign:1.
shift < 0 ifTrue:[
- ^ dividend compressed.
+ ^ dividend compressed.
].
shift == 0 ifTrue:[
- divisor := LargeInteger digitBytes:(anInteger digitBytes copy). "/ anInteger simpleDeepCopy
+ divisor := self class digitBytes:(divisor digitBytes copy). "/ anInteger simpleDeepCopy
] ifFalse:[
- divisor := anInteger bitShift:shift.
+ divisor := divisor bitShift:shift.
].
-
shift := shift + 1.
[shift > 0] whileTrue:[
- (dividend absLess:divisor) ifFalse:[
- (dividend absDestructiveSubtract: divisor) ifFalse:[ "result == 0"
- ^ 0
- ].
- ].
- shift := shift - 1.
- divisor div2.
+ (dividend absLess:divisor) ifFalse:[
+ (dividend absDestructiveSubtract: divisor) ifFalse:[ "result == 0"
+ ^ 0
+ ].
+ ].
+ shift := shift - 1.
+ divisor div2.
].
^ dividend compressed
"
-Time millisecondsToRun:[ 10000 timesRepeat:[ 16000000001 absMod:4000000001] ]
-Time millisecondsToRun:[ 10000 timesRepeat:[ 16000000001 absDivMod:4000000001] ]
+Time millisecondsToRun:[ 100000 timesRepeat:[ 16000000000000000000001 absDivMod:4000000000000000000001] ]
+Time millisecondsToRun:[ 100000 timesRepeat:[ 16000000000000000000001 absMod:4000000000000000000001] ]
+
16000000000 absMod:4000000000
16000000000 absMod:3000000000
16000000000000000000 absMod:16000000000000000000
"
- "Modified: / 5.11.1996 / 18:40:24 / cg"
- "Created: / 27.4.1999 / 19:45:44 / stefan"
- "Modified: / 26.7.1999 / 10:46:18 / stefan"
+ "Created: / 27-04-1999 / 19:45:44 / stefan"
+ "Modified: / 26-07-1999 / 10:46:18 / stefan"
+ "Modified: / 05-07-2017 / 16:17:47 / cg"
!
absMul:aLargeInteger