Integer.st
branchjv
changeset 19167 699eef1bc815
parent 19137 199b5e15b1da
parent 19164 16e88ae992a1
child 19236 e6403ba50de1
equal deleted inserted replaced
19158:cdce727939ab 19167:699eef1bc815
    13 "{ Package: 'stx:libbasic' }"
    13 "{ Package: 'stx:libbasic' }"
    14 
    14 
    15 "{ NameSpace: Smalltalk }"
    15 "{ NameSpace: Smalltalk }"
    16 
    16 
    17 Number subclass:#Integer
    17 Number subclass:#Integer
    18         instanceVariableNames:''
    18 	instanceVariableNames:''
    19         classVariableNames:'BCDConversionErrorSignal PrimeCache'
    19 	classVariableNames:'BCDConversionErrorSignal PrimeCache'
    20         poolDictionaries:''
    20 	poolDictionaries:''
    21         category:'Magnitude-Numbers'
    21 	category:'Magnitude-Numbers'
    22 !
    22 !
    23 
    23 
    24 Object subclass:#ModuloNumber
    24 Object subclass:#ModuloNumber
    25         instanceVariableNames:'modulus reciprocal shift'
    25 	instanceVariableNames:'modulus reciprocal shift'
    26         classVariableNames:''
    26 	classVariableNames:''
    27         poolDictionaries:''
    27 	poolDictionaries:''
    28         privateIn:Integer
    28 	privateIn:Integer
    29 !
    29 !
    30 
    30 
    31 !Integer class methodsFor:'documentation'!
    31 !Integer class methodsFor:'documentation'!
    32 
    32 
    33 copyright
    33 copyright
  3030     "Modified: / 18.11.1999 / 16:19:24 / stefan"
  3030     "Modified: / 18.11.1999 / 16:19:24 / stefan"
  3031 !
  3031 !
  3032 
  3032 
  3033 factorial
  3033 factorial
  3034     "return fac(self) (i.e. 1*2*3...*self) using an iterative algorithm.
  3034     "return fac(self) (i.e. 1*2*3...*self) using an iterative algorithm.
  3035      This is slightly faster than the recursive algorithm, and does not
  3035      This chooses a good algorithm, based on the receiver.
  3036      suffer from stack overflow problems (with big receivers)"
  3036      Some heuristics here, which has to do with the speed of largeInteger
  3037 
  3037      arrithmetic."
  3038     |p i|
  3038 
  3039 
  3039     (self <= 20) ifTrue:[
  3040     (self < 2) ifTrue:[
       
  3041         self < 0 ifTrue:[
  3040         self < 0 ifTrue:[
  3042             "/
  3041             "/
  3043             "/ requested factorial of a negative number
  3042             "/ requested factorial of a negative number
  3044             "/
  3043             "/
  3045             ^ self class
  3044             ^ self class
  3047                 receiver:self
  3046                 receiver:self
  3048                 selector:#factorial
  3047                 selector:#factorial
  3049                 arguments:#()
  3048                 arguments:#()
  3050                 errorString:'factorial of negative number'
  3049                 errorString:'factorial of negative number'
  3051         ].
  3050         ].
  3052         ^ 1
  3051         ^ #(1 1 2 6 24 120 720 5040 40320 362880 3628800 39916800
  3053     ].
  3052           479001600 6227020800 87178291200 1307674368000 20922789888000 
       
  3053           355687428096000 6402373705728000 121645100408832000
       
  3054           2432902008176640000) at:self+1
       
  3055     ].
       
  3056     
       
  3057 "/    self < 80000 ifTrue:[
       
  3058 "/        ^ self factorialHalf
       
  3059 "/    ].    
       
  3060     ^ self factorialEvenOdd
       
  3061 
       
  3062     "
       
  3063      10 factorial
       
  3064      100 factorial
       
  3065      1000 factorial
       
  3066      10000 factorial
       
  3067      100000 factorial
       
  3068      200000 factorial
       
  3069      300000 factorial
       
  3070      1000000 factorial
       
  3071 
       
  3072      Time millisecondsToRun:[10000 factorial]40
       
  3073      Time millisecondsToRun:[100000 factorial]3220
       
  3074      Time millisecondsToRun:[1000000 factorial]357120
       
  3075 
       
  3076     #(factorialIter factorialHalf factorialEvenOdd factorial)
       
  3077     do:[:sel |
       
  3078       #( (10000 10) 
       
  3079          (20000 10)
       
  3080          (50000 10)
       
  3081          (70000 10)
       
  3082          (100000 5)
       
  3083          (200000 3)
       
  3084          (300000 3)
       
  3085          (400000 3)) pairsDo:[:n :repeat |
       
  3086          |times|
       
  3087         times := (1 to:repeat) collect:[:i |
       
  3088                 Time millisecondsToRun:[ n perform:sel]
       
  3089                ].
       
  3090 
       
  3091         Transcript printf:'%12s %6d: %5d\n' with:sel with:n with:times min 
       
  3092       ]
       
  3093     ].
       
  3094 
       
  3095     factorialIter  10000:    30
       
  3096     factorialIter  20000:   130
       
  3097     factorialIter  50000:   790
       
  3098     factorialIter  70000:  1710
       
  3099     factorialIter 100000:  4880
       
  3100     factorialIter 200000: 24980
       
  3101     factorialIter 300000: 60060
       
  3102     factorialIter 400000: 112310
       
  3103     factorialHalf  10000:    20
       
  3104     factorialHalf  20000:   100
       
  3105     factorialHalf  50000:   690
       
  3106     factorialHalf  70000:  1430
       
  3107     factorialHalf 100000:  3220
       
  3108     factorialHalf 200000: 28340
       
  3109     factorialHalf 300000: 68740
       
  3110     factorialHalf 400000: 127490
       
  3111     factorialEvenOdd  10000:    10
       
  3112     factorialEvenOdd  20000:    60
       
  3113     factorialEvenOdd  50000:   390
       
  3114     factorialEvenOdd  70000:   810
       
  3115     factorialEvenOdd 100000:  2020
       
  3116     factorialEvenOdd 200000:  9960
       
  3117     factorialEvenOdd 300000: 24480
       
  3118     factorialEvenOdd 400000: 45340
       
  3119     factorial  10000:    20
       
  3120     factorial  20000:   100
       
  3121     factorial  50000:   680
       
  3122     factorial  70000:  1400
       
  3123     factorial 100000:  2040
       
  3124     factorial 200000: 10130
       
  3125     factorial 300000: 24670
       
  3126     "
       
  3127 !
       
  3128 
       
  3129 factorialEvenOdd
       
  3130     "an recursive odd-even algorithm, which processes smaller largeInts in the loop."
       
  3131 
       
  3132     |pO i s2 t stop|
       
  3133 
       
  3134     (self <= 20) ifTrue:[
       
  3135         ^ #(1 1 2 6 24 120 720 5040 40320 362880 3628800 39916800
       
  3136           479001600 6227020800 87178291200 1307674368000 20922789888000 
       
  3137           355687428096000 6402373705728000 121645100408832000
       
  3138           2432902008176640000) at:self+1
       
  3139     ].
       
  3140 
       
  3141     "/
       
  3142     "/ 3 * 4 * 5 * 6 *7 * 8 .... * n
       
  3143     "/ odd numbers:
       
  3144     "/   3 5 7 9 ... n
       
  3145     "/ half even:
       
  3146     "/   2 4 6 8 ... n
       
  3147     "/   1 2 3 4 ... n//2
       
  3148     "/ is (n/2)!! << n-1
       
  3149                  
       
  3150     pO := 1.
       
  3151     i := 3.
       
  3152  
       
  3153     "/ odds only in pairs as
       
  3154     "/      i * (i + 2)
       
  3155     "/ to get to the next pair,
       
  3156     "/      (i+4)(i+6)
       
  3157     "/ we add: 8i + 24
       
  3158     "/ (i+4)(i+6)-(i*(i+2))
       
  3159     "/ i^2 + 10i + 24 - i^2 - 2i
       
  3160     "/ 8i + 24
       
  3161     stop := self-2.
       
  3162     t := i*(i+2).
       
  3163     [i <= stop] whileTrue:[
       
  3164         "/ odd*next odd
       
  3165         pO := pO * t.
       
  3166         t := t + ((i*8) + 24).
       
  3167         i := i + 4.
       
  3168     ].
       
  3169     
       
  3170     [i <= self] whileTrue:[
       
  3171         "/ odd
       
  3172         pO := pO * i.
       
  3173         i := i + 2.
       
  3174     ].
       
  3175 
       
  3176     "/ the factorial of the evens...
       
  3177     s2 := (self//2).
       
  3178     ^ (s2 factorialEvenOdd * pO) << s2.
       
  3179 
       
  3180     "
       
  3181      (6 to:2000) conform:[:i | i factorialIter = i factorialEvenOdd]
       
  3182      
       
  3183      Time millisecondsToRun:[20000 factorialIter]
       
  3184      Time millisecondsToRun:[50000 factorialIter]
       
  3185      Time millisecondsToRun:[70000 factorialIter]
       
  3186      Time millisecondsToRun:[100000 factorialIter]
       
  3187      Time millisecondsToRun:[200000 factorialIter] 
       
  3188 
       
  3189      Time millisecondsToRun:[20000 factorialEvenOdd]
       
  3190      Time millisecondsToRun:[50000 factorialEvenOdd]
       
  3191      Time millisecondsToRun:[70000 factorialEvenOdd]
       
  3192      Time millisecondsToRun:[100000 factorialEvenOdd]
       
  3193      Time millisecondsToRun:[200000 factorialEvenOdd]
       
  3194     "
       
  3195 !
       
  3196 
       
  3197 factorialHalf
       
  3198     "an algorithm, which processes does it with half the number of multiplications.
       
  3199      this is faster than factorialPM to roughly 60000."
       
  3200 
       
  3201     |p i d|
       
  3202 
       
  3203     i := self.
       
  3204     self odd ifTrue:[
       
  3205         i := i - 1.
       
  3206     ].
       
  3207     
       
  3208     p := i.
       
  3209     d := i - 2.
       
  3210     [d >= 2] whileTrue:[
       
  3211         i := i + d.
       
  3212         p := p * i.
       
  3213         d := d - 2.
       
  3214     ].
       
  3215     self odd ifTrue:[
       
  3216         p := p * self
       
  3217     ].    
       
  3218     ^ p
       
  3219 
       
  3220     "
       
  3221      10 factorial 3628800
       
  3222      10 factorialHalf 3628800
       
  3223      
       
  3224      11 factorial 39916800
       
  3225      11 factorialHalf 39916800
       
  3226 
       
  3227      12 factorial 479001600
       
  3228      12 factorialHalf 479001600 
       
  3229 
       
  3230      10000 factorial = 10000 factorialHalf
       
  3231 
       
  3232      (6 to:2000) conform:[:i | i factorialIter = i factorialHalf]
       
  3233      
       
  3234      Time microsecondsToRun:[30 factorialIter]
       
  3235      Time microsecondsToRun:[30 factorialHalf]
       
  3236      Time microsecondsToRun:[50 factorialIter]
       
  3237      Time microsecondsToRun:[50 factorialHalf]
       
  3238      Time microsecondsToRun:[75 factorialIter]
       
  3239      Time microsecondsToRun:[75 factorialHalf]
       
  3240      Time microsecondsToRun:[100 factorialIter]
       
  3241      Time microsecondsToRun:[100 factorialHalf]
       
  3242      Time microsecondsToRun:[500 factorialIter]
       
  3243      Time microsecondsToRun:[500 factorialHalf]
       
  3244      Time microsecondsToRun:[1000 factorialIter]
       
  3245      Time microsecondsToRun:[1000 factorialHalf]
       
  3246      Time microsecondsToRun:[2000 factorialIter]
       
  3247      Time microsecondsToRun:[2000 factorialHalf]
       
  3248 
       
  3249      Time microsecondsToRun:[500 factorial]118 120 120
       
  3250      Time microsecondsToRun:[1000 factorial]339 355 406
       
  3251      Time microsecondsToRun:[5000 factorial]15703 13669 7715
       
  3252      Time millisecondsToRun:[10000 factorial]40 30 50
       
  3253      Time millisecondsToRun:[20000 factorial]140 150 150
       
  3254      Time millisecondsToRun:[40000 factorial]600 570 560 570
       
  3255      Time millisecondsToRun:[60000 factorial]1220 1240 1340
       
  3256      Time millisecondsToRun:[80000 factorial]2600 2580 2540
       
  3257      Time millisecondsToRun:[100000 factorial]4680 4810 5280
       
  3258      Time millisecondsToRun:[120000 factorial]8100 8010 7920
       
  3259      Time millisecondsToRun:[150000 factorial]13830 14040 13360
       
  3260      Time millisecondsToRun:[200000 factorial]23880 23740 
       
  3261 
       
  3262      Time microsecondsToRun:[500 factorialHalf]150 142 192
       
  3263      Time microsecondsToRun:[1000 factorialHalf]383 527 684
       
  3264      Time microsecondsToRun:[5000 factorialHalf]6654 9221 4629
       
  3265      Time millisecondsToRun:[10000 factorialHalf]20 30 20
       
  3266      Time millisecondsToRun:[20000 factorialHalf]110 110 110
       
  3267      Time millisecondsToRun:[40000 factorialHalf]490 490 490
       
  3268      Time millisecondsToRun:[60000 factorialHalf]1100 1090 1070
       
  3269      Time millisecondsToRun:[80000 factorialHalf]1920 1920 1880
       
  3270      Time millisecondsToRun:[100000 factorialHalf]3030 3010 3000
       
  3271      Time millisecondsToRun:[120000 factorialHalf]4830 4770 4760
       
  3272      Time millisecondsToRun:[150000 factorialHalf]14510 13940 13900
       
  3273      Time millisecondsToRun:[200000 factorialHalf]28730 28160 
       
  3274     "
       
  3275 !
       
  3276 
       
  3277 factorialIter
       
  3278     "return fac(self) (i.e. 1*2*3...*self) using an iterative algorithm.
       
  3279      This is slightly faster than the recursive algorithm, and does not
       
  3280      suffer from stack overflow problems (with big receivers)"
       
  3281 
       
  3282     |p i|
       
  3283 
  3054     p := 2.
  3284     p := 2.
  3055     i := 3.
  3285     i := 3.
  3056     [i <= self] whileTrue:[
  3286     [i <= self] whileTrue:[
  3057         p := p * i.
  3287         p := p * i.
  3058         i := i + 1.
  3288         i := i + 1.
  3075 
  3305 
  3076 factorialR
  3306 factorialR
  3077     "return fac(self) (i.e. 1*2*3...*self) using a recursive algorithm.
  3307     "return fac(self) (i.e. 1*2*3...*self) using a recursive algorithm.
  3078 
  3308 
  3079      This is included to demonstration purposes - if you really need
  3309      This is included to demonstration purposes - if you really need
  3080      factorial numbers, use the iterative #factorial, which is slightly
  3310      factorial numbers, use the iterative #factorial, which is
  3081      faster and does not suffer from stack overflow problems (with big receivers)."
  3311      faster and does not suffer from stack overflow problems (with big receivers)."
  3082 
  3312 
  3083     (self >= 2) ifTrue:[
  3313     (self >= 2) ifTrue:[
  3084         ^ self * (self - 1) factorialR
  3314         ^ self * (self - 1) factorialR
  3085     ].
  3315     ].
  3902         nD := 6.
  4132         nD := 6.
  3903     ] ifFalse:[
  4133     ] ifFalse:[
  3904         r := r4*base.    "/ radix^5 (chunks of 5 digits)
  4134         r := r4*base.    "/ radix^5 (chunks of 5 digits)
  3905         nD := 5.
  4135         nD := 5.
  3906     ].
  4136     ].
  3907 
  4137     SmallInteger maxBits >= 63 ifTrue:[
  3908     "/ JV@2015-12-28: I have to admit I don't understand this code,
  4138         r := r*r2.    "/ radix^7 (chunks of 6 digits)
  3909     "/ however, the following if made printing with base of 16 to
  4139         nD := nD + 2.
  3910     "/ diverge on 64bit builds (causing RegressionTests::IntegerTest>>testLargeIntegerHelpers
  4140     ].
  3911     "/ to fail). When disabled, everything seems to be OK.
       
  3912     "/ Therefore I disabled the code, even though it might slower.
       
  3913 
       
  3914 "/    SmallInteger maxBits >= 63 ifTrue:[
       
  3915 "/        r := r*r.    "/ radix^10 / radix^12 (chunks of 10/12 digits)
       
  3916 "/        nD := nD * 2.
       
  3917 "/    ].
       
  3918 
  4141 
  3919     "get a Stream with space for the digits we are going to print.
  4142     "get a Stream with space for the digits we are going to print.
  3920      We need ((num log:base) ceiling) digits, which is equivalent
  4143      We need ((num log:base) ceiling) digits, which is equivalent
  3921      to ((num log:2)/(base log:2) ceiling)
  4144      to ((num log:2)/(base log:2) ceiling)
  3922     "
  4145     "
  3954         31 printOn:Transcript base:3
  4177         31 printOn:Transcript base:3
  3955         10 printOn:Transcript base:2
  4178         10 printOn:Transcript base:2
  3956         31 printOn:Transcript base:2
  4179         31 printOn:Transcript base:2
  3957         -20  printOn:Transcript base:16
  4180         -20  printOn:Transcript base:16
  3958         -20  printOn:Transcript base:10
  4181         -20  printOn:Transcript base:10
  3959         Time millisecondsToRun:[10000 factorial printString] 610  7650
  4182         Time millisecondsToRun:[10000 factorial printString]
       
  4183         '%012d' printf:{  (2 raisedTo:20) }
  3960     "
  4184     "
  3961 
  4185 
  3962     "Modified: / 20-01-1998 / 18:05:02 / stefan"
  4186     "Modified: / 20-01-1998 / 18:05:02 / stefan"
  3963     "Created: / 07-09-2001 / 13:51:33 / cg"
  4187     "Created: / 07-09-2001 / 13:51:33 / cg"
  3964     "Modified: / 02-08-2010 / 12:24:14 / cg"
  4188     "Modified: / 02-08-2010 / 12:24:14 / cg"