LargeInteger.st
changeset 21985 bc1731b1a6aa
parent 21820 3825bcd2e2c7
child 21986 ff209ce4ed7f
--- 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