Integer.st
changeset 1 a27a279701f8
child 3 24d81bf47225
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Integer.st	Fri Jul 16 11:39:45 1993 +0200
@@ -0,0 +1,641 @@
+"
+ COPYRIGHT (c) 1988-93 by Claus Gittinger
+              All Rights Reserved
+
+ This software is furnished under a license and may be used
+ only in accordance with the terms of that license and with the
+ inclusion of the above copyright notice.   This software may not
+ be provided or otherwise made available to, or used by, any
+ other person.  No title to or ownership of the software is
+ hereby transferred.
+"
+
+Number subclass:#Integer
+       instanceVariableNames:''
+       classVariableNames:''
+       poolDictionaries:''
+       category:'Magnitude-Numbers'
+!
+
+Integer comment:'
+
+COPYRIGHT (c) 1988-93 by Claus Gittinger
+              All Rights Reserved
+
+abstract superclass for all integer numbers
+
+%W% %E%
+written 88 by claus
+'!
+
+!Integer class methodsFor:'constants'!
+
+zero
+    ^ 0
+!
+
+unity
+    ^ 1
+! !
+
+!Integer methodsFor:'arithmetic'!
+
+quo:aNumber
+    "Return the integer quotient of dividing the receiver by aNumber with
+    truncation towards zero. For Integers this is same as //"
+
+    ^ self // aNumber
+
+! !
+
+!Integer methodsFor:'double dispatching'!
+
+sumFromFraction:aFraction
+    "sent when a fraction does not know how to add the recevier, an integer"
+
+    ^ (Fraction numerator:(aFraction numerator
+                           + (self * aFraction denominator))
+              denominator:aFraction denominator) reduced
+!
+
+differenceFromFraction:aFraction
+    "sent when a fraction does not know how to subtract the recevier, an integer"
+
+    ^ (Fraction numerator:((self * aFraction denominator) - aFraction numerator)
+              denominator:aFraction denominator) reduced
+!
+
+productFromFraction:aFraction
+    "sent when a fraction does not know how to multiply the recevier, an integer"
+
+    ^ (Fraction numerator:(self * aFraction numerator)
+              denominator:aFraction denominator) reduced
+! !
+
+!Integer methodsFor:'truncation & rounding'!
+
+ceiling
+    "I am my ceiling"
+
+    ^ self
+!
+
+floor
+    "I am my floor"
+
+    ^ self
+!
+
+rounded
+    "return the receiver rounded toward the next Integer -
+     for integers this is self"
+
+    ^ self
+!
+
+truncated
+    "return the receiver truncated towards zero - 
+     for integers this is self"
+
+    ^ self
+! !
+
+!Integer methodsFor:'queries'!
+
+digitLength
+    "return the number of bytes needed for the binary representation
+     of the receiver"
+
+    ^ (self log:256) ceiling asInteger
+!
+
+digitAt:n
+    "return the n-th byte of the binary representation"
+
+    |num count|
+
+    num := self.
+    count := n.
+    [count > 1] whileTrue:[
+        num := num // 256.
+        count := count - 1
+    ].
+    ^ num \\ 256
+!
+
+isInteger
+    "return true, if the receiver is some kind of integer number"
+
+    ^ true
+! !
+
+!Integer methodsFor:'misc math'!
+
+factorial
+    "return 1*2*3...*self"
+
+    (self > 1) ifTrue:[
+        ^ self * (self - 1) factorial
+    ].
+    ^ self
+!
+
+gcd:anInteger
+    "return the greatest common divisor (Euclid's algorithm)"
+
+    |ttt selfInteger temp|
+
+    ttt := anInteger.
+    selfInteger := self.
+    [ttt ~~ 0] whileTrue:[
+        temp := selfInteger \\ ttt.
+        selfInteger := ttt.
+        ttt := temp
+    ].
+    ^ selfInteger
+!
+
+lcm:anInteger
+    ^(self * anInteger) abs // (self gcd: anInteger)
+!
+
+fib
+    "dont use this method if you need fibionacci numbers -
+     this method is for benchmarking purposes only.
+     (use fastFib instead and dont ever try 60 fib ...)"
+
+    (self > 1) ifTrue:[
+        ^ (self - 1) fib + (self - 2) fib
+    ].
+    ^ 1
+
+    "Time millisecondsToRun:[30 fib]"
+!
+
+fastFib
+    "this method just to show how a changed algorithm can
+     change things much more drastic than tuning ...
+     (compare 30 fib with 30 fastFib / dont even try 60 fib)"
+
+    |fib|
+
+    self <= 1 ifTrue:[^ 1].
+
+    FibCache isNil ifTrue:[
+        FibCache := OrderedCollection new
+    ].
+    FibCache size >= self ifTrue:[
+        ^ FibCache at:self
+    ].
+    fib := (self - 2) fastFib + (self - 1) fastFib.
+
+    FibCache grow:self.
+    FibCache at:self put:fib.
+    ^ fib
+
+    "Time millisecondsToRun:[30 fastFib]"
+!
+
+acker:n
+    "return the value of acker(self, n)"
+
+    (self == 0) ifTrue:[^ n + 1].
+    (n == 0) ifTrue:[^ (self - 1) acker: 1].
+    ^ (self - 1) acker:(self acker:(n - 1))
+
+    "3 acker:2"
+! !
+
+!Integer methodsFor:'coercing and converting'!
+
+asFraction
+    "return a Fraction with same value as receiver"
+
+    ^ Fraction numerator:self denominator:1
+!
+
+asInteger
+    "return the receiver truncated towards zero - 
+     for integers this is self"
+
+    ^ self
+! !
+
+!Integer methodsFor:'printing & storing'!
+
+storeString
+    "return a string for storing - printString will do"
+
+    ^ self printString
+!
+
+printString
+    "return a string representation of the receiver"
+
+    ^ self printStringRadix:10
+!
+
+radixPrintStringRadix:aRadix
+    "return a string representation of the receiver in the specified
+     radix; prepend XXr to the string"
+
+    ^ (aRadix printString) , 'r', (self printStringRadix:aRadix)
+
+    "31 radixPrintStringRadix:2 "
+    "31 radixPrintStringRadix:3 "
+    "31 radixPrintStringRadix:36 "
+!
+
+printStringRadix:aRadix
+    "return a string representation of the receiver in the specified
+     radix (without the initial XXr)"
+
+    |leftPart|
+
+    (self = 0) ifTrue:[^ '0'].
+    (self < 0) ifTrue:[
+        ^ '-' , (self negated printStringRadix:aRadix)
+    ].
+    leftPart := self // aRadix.
+    (leftPart ~= 0) ifTrue:[
+        ^ (leftPart printStringRadix:aRadix) copyWith:(Character digitValue:(self \\ aRadix))
+    ].
+    ^ (Character digitValue:self) asString
+!
+
+printStringRadix:aRadix size:sz fill:fillCharacter
+    "return a string representation of the receiver in the specified
+     radix. The string is padded on the left with fillCharacter to make
+     its size as specified in sz."
+
+     |s|
+
+    s := self printStringRadix:aRadix.
+    s size < sz ifTrue:[
+        s := ((String new:(sz - s size)) atAllPut:fillCharacter) , s
+    ].
+    ^ s
+
+    "1024 printStringRadix:16 size:4 fill:$0"
+! !
+
+!Integer class methodsFor:'instance creation'!
+
+readFrom:aStream radix:radix
+    "return the next Integer from the (character-)stream aStream in radix;
+     (assumes that the initial XXR has already been read)
+     no whitespace-skipping; returns 0 if no number available"
+
+    |nextChar value|
+
+    nextChar := aStream peek.
+    value := 0.
+    [nextChar notNil and:[nextChar isDigitRadix:radix]] whileTrue:[
+        value := value * radix + nextChar digitValue.
+        nextChar := aStream nextPeek
+    ].
+    ^ value
+!
+
+readFrom:aStream
+    "return the next Integer from the (character-)stream aStream,
+     handling initial XXr for arbitrary radix numbers and initial
+     sign.
+     skipping all whitespace first; return nil if no number"
+
+    |nextChar value negative|
+
+    nextChar := aStream skipSeparators.
+    (nextChar == $-) ifTrue:[
+        negative := true.
+        nextChar := aStream nextPeek
+    ] ifFalse:[
+        negative := false
+    ].
+    nextChar isDigit ifFalse:[ ^ nil].
+    value := Integer readFrom:aStream radix:10.
+    nextChar := aStream peek.
+    ((nextChar == $r) or:[ nextChar == $R]) ifTrue:[
+        aStream next.
+        value := Integer readFrom:aStream radix:value
+    ].
+    negative ifTrue:[
+        ^ value negated
+    ].
+    ^ value
+! !
+
+!Integer methodsFor:'benchmarking'!
+
+sieve
+    "sieve the primes self times"
+
+    |num i k prime count flags time|
+
+    num := 8191.
+    flags := Array new:num.
+
+    Transcript show:'Sieve running ...'.
+    Transcript cr.
+
+    time := Time millisecondsToRun:[
+        self timesRepeat:[
+            count := 0.
+            flags atAllPut:1.
+            i := 1.
+            num timesRepeat:[
+                (flags at:i) == 1 ifTrue:[
+                    prime := i + i + 3.
+                    k := i + prime.
+                    [k <= num] whileTrue:[
+                        flags at:k put:0.
+                        k := k + prime
+                    ].
+                    count := count + 1
+                ].
+                i := i + 1
+            ].
+        ].
+    ].
+    Transcript show:'Sieve in Smalltalk: '.
+    Transcript show:self printString. 
+    Transcript showCr:' iteration(s).'.
+    Transcript show:'found '. 
+    Transcript show:count printString. 
+    Transcript showCr:' primes.' .
+    Transcript show:'time per run: '. 
+    Transcript show:(time / self) printString. 
+    Transcript showCr:' ms.'
+
+    "1 sieve"
+!
+
+sieveWithIntegers
+    "sieve the primes self times"
+
+    |num        "<SmallInteger>"
+     i          "<SmallInteger>"
+     k          "<SmallInteger>"
+     prime      "<SmallInteger>"
+     count      "<SmallInteger>"
+     flags time|
+
+    num := 8191.
+    flags := Array new:num.
+
+    Transcript show:'Sieve running ...'.
+    Transcript cr.
+
+    time := Time millisecondsToRun:[
+        self timesRepeat:[
+            count := 0.
+            flags atAllPut:1.
+            i := 1.
+            num timesRepeat:[
+                (flags at:i) == 1 ifTrue:[
+                    prime := i + i + 3.
+                    k := i + prime.
+                    [k <= num] whileTrue:[
+                        flags at:k put:0.
+                        k := k + prime
+                    ].
+                    count := count + 1
+                ].
+                i := i + 1
+            ].
+        ].
+    ].
+    Transcript show:'Sieve in Smalltalk: '.
+    Transcript show:self printString. 
+    Transcript showCr:' iteration(s).'.
+    Transcript show:'found '. 
+    Transcript show:count printString. 
+    Transcript showCr:' primes.' .
+    Transcript show:'time per run: '. 
+    Transcript show:(time / self) printString. 
+    Transcript showCr:' ms.'
+
+    "1 sieveWithIntegers"
+!
+
+recur1:num
+    "actual recursion method for recur1"
+
+    (num = 0) ifTrue:[^ self].
+    self recur1:(num - 1).
+    ^ self recur1:(num - 1)
+!
+
+recur1
+    "lots of recursion for testing send with arg"
+
+    |t|
+
+    t := Time millisecondsToRun:[
+        1 recur1:15
+    ].
+    Transcript showCr:(t printString)
+
+    "1 recur1"
+!
+
+recur2
+    "lots of recursion for testing send without arg"
+
+    (self > 0) ifTrue:[
+        (self - 1) recur2.
+        ^ (self - 1) recur2
+    ]
+
+    "Transcript showCr:(
+        Time millisecondsToRun:[
+            15 recur2
+        ]
+     ) printString"
+!
+
+countDown
+    |t index|
+
+    t := Time millisecondsToRun:[
+        index := 100000.
+        [index > 0] whileTrue:[
+            index := index - 1
+        ].
+    ].
+    Transcript showCr:(t printString)
+
+    "1 countDown"
+!
+
+countDown2
+    |t|
+
+    t := Time millisecondsToRun:[
+        |index|
+
+        index := 100000.
+        [index > 0] whileTrue:[
+            index := index - 1
+        ].
+    ].
+    Transcript showCr:(t printString)
+
+    "1 countDown2"
+!
+
+noop
+    ^ self
+!
+
+send:num
+    "lots of message sends"
+
+    |t|
+
+    t := Time millisecondsToRun:[
+        num timesRepeat:[
+            self noop
+        ].
+    ].
+    Transcript showCr:(t printString)
+
+    "1 send:100000"
+!
+
+memory
+    "lots of memory allocation"
+
+    |t|
+
+    t := Time millisecondsToRun:[
+        self timesRepeat:[
+            Array new:500
+        ].
+    ].
+    Transcript showCr:(t printString)
+
+    "10000 memory"
+!
+
+benchArithmetic
+    "arithmetic speed bench"
+
+    |p n m t|
+
+    n := 3.0.
+    m := 5.5.
+
+    t := Time millisecondsToRun:[
+        self timesRepeat:[
+            p := 5 / n + m
+        ]
+    ].
+    Transcript showCr:(t printString)
+
+    "10000 benchArithmetic"
+!
+
+sumTo
+    |val|
+
+    100 timesRepeat:[
+        val := 0.
+        1 to:10000 do:[:i |
+            val := val + i
+        ]
+    ].
+    "Time millisecondsToRun:[1 sumTo]"
+!
+
+fastSumTo
+    |val i|
+
+    100 timesRepeat:[
+        val := 0.
+        i := 1.
+        [i <= 10000] whileTrue:[
+            val := val + i.
+            i := i + 1
+        ].
+    ].
+    "Time millisecondsToRun:[1 fastSumTo]"
+!
+
+nestedLoop
+    |i|
+
+    100 timesRepeat:[
+        i := 0.
+        1 to:100 do:[:l1 |
+            1 to:100 do:[:l2 |
+                i := i + 1
+            ]
+        ]
+    ]
+    "Time millisecondsToRun:[1 nestedLoop]"
+!
+
+atAllPut
+    |vec t|
+
+    vec := Array new:100000.
+    t := Time millisecondsToRun:[
+        1 to:100000 do:[:i |
+            vec at:i put:7
+        ]
+    ].
+    ^ t
+
+    "1  atAllPut"
+!
+
+atAllPut2
+    |array t|
+
+    array := Array new:100000.
+    t := Time millisecondsToRun:[
+        1 to:100000 do:[:i |
+            array at:i put:7
+        ]
+    ].
+    ^ t
+
+    "1  atAllPut2"
+!
+
+sumAll 
+    |vec t s|
+
+    vec := Array new:100000.
+    1 to:100000 do:[:i |
+        vec at:i put:7
+    ].
+    s := 0.
+    t := Time millisecondsToRun:[
+        1 to:100000 do:[:i |
+            s := s + (vec at:i)
+        ]
+    ].
+    ^ t
+
+    "1  sumAll"
+!
+
+sumAll2 
+    |array t s|
+
+    array := Array new:100000.
+    1 to:100000 do:[:i |
+        array at:i put:7
+    ].
+    s := 0.
+    t := Time millisecondsToRun:[
+        1 to:100000 do:[:i |
+            s := s + (array at:i)
+        ]
+    ].
+    ^ t
+
+    "1  sumAll2"
+! !