#OTHER by cg
class: Number class
changed: #readFrom:decimalPointCharacters:thousandsSeparator:allowCStyle:onError:
number scanning
--- a/Integer.st Tue Dec 17 16:58:31 2019 +0100
+++ b/Integer.st Tue Dec 17 17:16:09 2019 +0100
@@ -1,3 +1,5 @@
+"{ Encoding: utf8 }"
+
"
COPYRIGHT (c) 1988 by Claus Gittinger
All Rights Reserved
@@ -377,8 +379,8 @@
!
readFrom:aStringOrStream radix:radix
- "return the next UNSIGNED Integer from the (character-)stream aStream in radix;
- (assumes that the initial XXr has already been read).
+ "return the next possibly signed Integer from the (character-)stream aStream in radix;
+ (assumes that any initial XXr has already been read).
No whitespace-skipping is done.
Returns 0 if no number available.
@@ -392,67 +394,21 @@
!
readFrom:aStringOrStream radix:radix onError:exceptionBlock
- "return the next UNSIGNED Integer from the (character-)stream aStream in radix;
- (assumes that the initial XXr has already been read).
+ "return the next possibly signed Integer from the (character-)stream aStream in radix;
+ (assumes that any initial XXr has already been read).
No whitespace-skipping is done.
Returns the value of exceptionBlock, if no number is available."
- |str nextChar value
- r "{ Class: SmallInteger }"
- r2 "{ Class: SmallInteger }"
- r3 "{ Class: SmallInteger }"
- r4 "{ Class: SmallInteger }"
- digit1 digit2 digit3 digit4 |
+ |str nextChar|
str := aStringOrStream readStream.
nextChar := str peekOrNil.
- (nextChar isNil or:[(value := nextChar digitValueRadix:radix) isNil]) ifTrue:[
- ^ exceptionBlock value
+ nextChar == $- ifTrue:[
+ str next.
+ ^ self readUnsignedFrom:str radix:radix sign:-1 onError:exceptionBlock
].
-
-"/ OLD code
-"/ [nextChar notNil and:[nextChar isDigitRadix:radix]] whileTrue:[
-"/ str next.
-"/ value := value * radix + nextChar digitValue.
-"/ nextChar := str peekOrNil.
-"/ ].
-"/ ^ value.
-
- "/ the code below does the same, but is much faster, if the
- "/ converted number is large
- "/ (requires only half as many LargeInt multiplications and additions)
- "/ It should not be slower for smallIntegers.
-
- r := radix.
- r2 := r * r.
- r4 := r2 * r2.
-
- [
- nextChar := str nextPeekOrNil.
- nextChar notNil and:[(digit1 := nextChar digitValueRadix:r) notNil]
- ] whileTrue:[
- "/ read 4 chars and pre-compute their value to avoid largeInt operations.
-
- nextChar := str nextPeekOrNil.
- (nextChar isNil or:[(digit2 := nextChar digitValueRadix:r) isNil]) ifTrue:[
- ^ (value * r) + digit1.
- ].
-
- nextChar := str nextPeekOrNil.
- (nextChar isNil or:[(digit3 := nextChar digitValueRadix:r) isNil]) ifTrue:[
- ^ (value * r2) + ((digit1*r) + digit2) .
- ].
-
- nextChar := str nextPeekOrNil.
- (nextChar isNil or:[ (digit4 := nextChar digitValueRadix:r) isNil]) ifTrue:[
- r3 := r2 * r.
- ^ (value * r3) + ((((digit1*r) + digit2)*r) + digit3).
- ].
-
- value := (value * r4) + ((((((digit1*r) + digit2)*r) + digit3)*r) + digit4).
- ].
- ^ value
+ ^ self readUnsignedFrom:str radix:radix sign:1 onError:exceptionBlock
"
Integer readFrom:(ReadStream on:'12345') radix:10
@@ -807,6 +763,156 @@
Integer readFromString:'1234 ' radix:10 onError:[nil] - I do not accept anything after the number
"
+!
+
+readUnsignedFrom:aStringOrStream radix:radix
+ "return the next UNSIGNED Integer from the (character-)stream aStream in radix;
+ (assumes that any initial XXr or sign has already been read).
+ No whitespace-skipping is done.
+ Returns 0 if no number available.
+
+ NOTICE:
+ This behaves different from the default readFrom:, in returning
+ 0 (instead of raising an error) in case no number can be read.
+ It is unclear, if this is the correct behavior (ST-80 does this)
+ - depending on the upcoming ANSI standard, this may change."
+
+ ^ self readUnsignedFrom:aStringOrStream radix:radix sign:1 onError:0
+!
+
+readUnsignedFrom:aStringOrStream radix:radix onError:exceptionBlock
+ "return the next UNSIGNED Integer from the (character-)stream aStream in radix;
+ (assumes that any initial XXr or sign has already been read).
+ No whitespace-skipping is done.
+ Returns the value of exceptionBlock, if no number is available."
+
+ ^ self readUnsignedFrom:aStringOrStream radix:radix sign:1 onError:exceptionBlock
+
+ "
+ Integer readUnsignedFrom:(ReadStream on:'12345') radix:10
+ Integer readUnsignedFrom:(ReadStream on:'FFFF') radix:16
+ Integer readUnsignedFrom:(ReadStream on:'1010') radix:2
+ Integer readUnsignedFrom:(ReadStream on:'foobar') radix:10
+ Integer readUnsignedFrom:(ReadStream on:'foobar') radix:10 onError:nil
+ Integer readUnsignedFrom:'gg' radix:10 onError:0
+ Integer readUnsignedFrom:'' radix:10 onError:'wrong'
+
+ |s|
+ s := String new:1000 withAll:$1.
+ Time millisecondsToRun:[
+ 1000 timesRepeat:[
+ s asInteger
+ ]
+ ]
+ "
+
+ "Modified: / 14.4.1998 / 19:16:46 / cg"
+!
+
+readUnsignedFrom:aStringOrStream radix:radix sign:sign
+ "return the next UNSIGNED Integer from the (character-)stream aStream in radix;
+ (assumes that any initial XXr or sign has already been read).
+ No whitespace-skipping is done.
+ Returns 0 if no number available.
+
+ NOTICE:
+ This behaves different from the default readFrom:, in returning
+ 0 (instead of raising an error) in case no number can be read.
+ It is unclear, if this is the correct behavior (ST-80 does this)
+ - depending on the upcoming ANSI standard, this may change."
+
+ ^ self readUnsignedFrom:aStringOrStream radix:radix sign:sign onError:0
+!
+
+readUnsignedFrom:aStringOrStream radix:radix sign:sign onError:exceptionBlock
+ "return the next UNSIGNED Integer from the (character-)stream aStream in radix;
+ (assumes that any initial XXr or sign has already been read).
+ No whitespace-skipping is done.
+ Returns the value of exceptionBlock, if no number is available."
+
+ |str nextChar value ret
+ r "{ Class: SmallInteger }"
+ r2 "{ Class: SmallInteger }"
+ r3 "{ Class: SmallInteger }"
+ r4 "{ Class: SmallInteger }"
+ digit1 digit2 digit3 digit4 |
+
+ str := aStringOrStream readStream.
+
+ nextChar := str peekOrNil.
+ (nextChar isNil or:[(value := nextChar digitValueRadix:radix) isNil]) ifTrue:[
+ ^ exceptionBlock value
+ ].
+
+"/ OLD code
+"/ [nextChar notNil and:[nextChar isDigitRadix:radix]] whileTrue:[
+"/ str next.
+"/ value := value * radix + nextChar digitValue.
+"/ nextChar := str peekOrNil.
+"/ ].
+"/ ^ value.
+
+ "/ the code below does the same, but is much faster, if the
+ "/ converted number is large
+ "/ (requires only half as many LargeInt multiplications and additions)
+ "/ It should not be slower for smallIntegers.
+
+ r := radix.
+ r2 := r * r.
+ r4 := r2 * r2.
+
+ [
+ nextChar := str nextPeekOrNil.
+ nextChar notNil and:[(digit1 := nextChar digitValueRadix:r) notNil]
+ ] whileTrue:[
+ "/ read 4 chars and pre-compute their value to avoid largeInt operations.
+
+ nextChar := str nextPeekOrNil.
+ (nextChar isNil or:[(digit2 := nextChar digitValueRadix:r) isNil]) ifTrue:[
+ ret := (value * r) + digit1.
+ sign == -1 ifTrue:[^ ret negated].
+ ^ ret
+ ].
+
+ nextChar := str nextPeekOrNil.
+ (nextChar isNil or:[(digit3 := nextChar digitValueRadix:r) isNil]) ifTrue:[
+ ret := (value * r2) + ((digit1*r) + digit2) .
+ sign == -1 ifTrue:[^ ret negated].
+ ^ ret
+ ].
+
+ nextChar := str nextPeekOrNil.
+ (nextChar isNil or:[ (digit4 := nextChar digitValueRadix:r) isNil]) ifTrue:[
+ r3 := r2 * r.
+ ret := (value * r3) + ((((digit1*r) + digit2)*r) + digit3).
+ sign == -1 ifTrue:[^ ret negated].
+ ^ ret
+ ].
+
+ value := (value * r4) + ((((((digit1*r) + digit2)*r) + digit3)*r) + digit4).
+ ].
+ sign == -1 ifTrue:[^ value negated].
+ ^ value
+
+ "
+ Integer readFrom:(ReadStream on:'12345') radix:10
+ Integer readFrom:(ReadStream on:'FFFF') radix:16
+ Integer readFrom:(ReadStream on:'1010') radix:2
+ Integer readFrom:(ReadStream on:'foobar') radix:10
+ Integer readFrom:(ReadStream on:'foobar') radix:10 onError:nil
+ Integer readFrom:'gg' radix:10 onError:0
+ Integer readFrom:'' radix:10 onError:'wrong'
+
+ |s|
+ s := String new:1000 withAll:$1.
+ Time millisecondsToRun:[
+ 1000 timesRepeat:[
+ s asInteger
+ ]
+ ]
+ "
+
+ "Modified: / 14.4.1998 / 19:16:46 / cg"
! !
!Integer class methodsFor:'Compatibility-Squeak'!
@@ -828,8 +934,6 @@
"Modified: / 15.11.1999 / 20:35:20 / cg"
! !
-
-
!Integer class methodsFor:'class initialization'!
initialize
@@ -886,7 +990,6 @@
"Modified: 18.7.1996 / 12:26:38 / cg"
! !
-
!Integer class methodsFor:'prime numbers'!
flushPrimeCache
@@ -1262,7 +1365,6 @@
^ self == Integer
! !
-
!Integer methodsFor:'Compatibility-Dolphin'!
highWord
@@ -4147,7 +4249,7 @@
^ fibUsingDict value:self
"the running time is mostly dictated by the LargeInteger multiplication performance...
- (therefore, we get O(n²) execution times, even for a linear number of multiplications)
+ (therefore, we get O(n²) execution times, even for a linear number of multiplications)
Time millisecondsToRun:[50000 fib_iterative] 312 (DUO 1.7Ghz CPU)
Time millisecondsToRun:[50000 fib_helper] 109
@@ -5742,7 +5844,6 @@
"Created: / 09-01-2012 / 17:18:06 / cg"
! !
-
!Integer methodsFor:'special modulo arithmetic'!
add_32:anInteger