LargeInteger.st
changeset 17035 4b6d41ac41b6
parent 16916 62312c3220bf
child 17128 ec053282f87c
--- a/LargeInteger.st	Tue Nov 11 15:20:30 2014 +0100
+++ b/LargeInteger.st	Tue Nov 11 15:21:04 2014 +0100
@@ -467,12 +467,19 @@
 !
 
 // aNumber
-    "return the quotient of the receiver and the argument, aNumber.
-     The result is truncated toward negative infinity and negative,
-     if the operands signs differ.
+    "return the integer part of the quotient of the receivers 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.
+
+     See #quo: which returns -2 in the above case and #rem: which is the corresponding remainder."
 
     |cls divMod quo abs "{ Class: SmallInteger }" n|
 
@@ -548,11 +555,23 @@
 
 \\ aNumber
     "Answer the integer remainder m defined by division with truncation toward
-     negative infinity. The remainder has the same sign as aNumber.
+     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
-     Compare with #rem:"
+
+     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.
+
+     See #rem: which is the corresponding remainder for division via #quo:.
+
+     Redefined here for speed."
 
     |abs rem negativeDivisor|
 
@@ -639,13 +658,29 @@
 !
 
 divMod:aNumber
-    "return an array filled with self // aNumber and
-     self \\ aNumber.
-     The result is only defined for positive receiver and
-     argument."
+    "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
+
+     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 
+     (as the remainder is generated as a side effect of division)"
 
     |cls n|
 
+    ((self < 0) or:[aNumber <= 0]) ifTrue:[
+        ^ super divMod:aNumber
+    ].
+
+    "/ only handle the common case here
     cls := aNumber class.
     (cls == SmallInteger) ifTrue:[
         "
@@ -663,7 +698,7 @@
         n := aNumber.
     ].
 
-    ^ self absDivMod:n abs
+    ^ self absDivMod:n abs.
 
     "
      9000000000 // 4000000000   => 2
@@ -5342,10 +5377,10 @@
 !LargeInteger class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/LargeInteger.st,v 1.219 2014-11-05 22:35:20 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/LargeInteger.st,v 1.220 2014-11-11 14:21:04 cg Exp $'
 !
 
 version_CVS
-    ^ '$Header: /cvs/stx/stx/libbasic/LargeInteger.st,v 1.219 2014-11-05 22:35:20 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/LargeInteger.st,v 1.220 2014-11-11 14:21:04 cg Exp $'
 ! !