# HG changeset patch # User Claus Gittinger # Date 1576599369 -3600 # Node ID 663805b3e3efe914b0393dfc5fd755809d4555fa # Parent 03ac6dae4ff8fb9376c4329d57e1060c20a63e20 #OTHER by cg class: Number class changed: #readFrom:decimalPointCharacters:thousandsSeparator:allowCStyle:onError: number scanning diff -r 03ac6dae4ff8 -r 663805b3e3ef Integer.st --- 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