Number.st
changeset 24449 8f3ac8e3b265
parent 24448 466c98f76a4b
child 24462 8018d0dcfa28
--- a/Number.st	Sun Jul 21 19:13:44 2019 +0200
+++ b/Number.st	Sun Jul 21 21:09:05 2019 +0200
@@ -114,6 +114,44 @@
     "
 !
 
+fastFromString:aString at:startIndex
+    "return the next Float, Integer or ShortFloat from the string.
+     No spaces are skipped.
+
+     This is a specially tuned entry (using a low-level C-call), which
+     returns garbage if the argument string is not a valid float number.
+     It has been added to allow high speed string decomposition into numbers,
+     especially for mass-data."
+
+    self subclassResponsibility
+
+    "
+     Float fromString:'12345.0'
+     Float fastFromString:'12345.0'
+
+     Integer fromString:'12345'
+     Integer fastFromString:'12345'
+
+     should be roughly 10times faster than the general method:
+
+     Time millisecondsToRun:[
+        100000 timesRepeat:[ Float fromString:'12345.0' ]
+     ].
+     Time millisecondsToRun:[
+        100000 timesRepeat:[ Float fastFromString:'12345.0' ]
+     ].
+
+     Time millisecondsToRun:[
+        100000 timesRepeat:[ Integer fromString:'12345' ]
+     ].
+     Time millisecondsToRun:[
+        100000 timesRepeat:[ Integer fastFromString:'12345' ]
+     ].
+    "
+
+    "Created: / 21-07-2019 / 19:17:17 / Claus Gittinger"
+!
+
 fromNumber:aNumber
     "return aNumber coerced to myself"
 
@@ -520,7 +558,7 @@
 
     ^ [
         |value intValue mantissaAndScale scale decimalMantissa str
-         nextChar radix sign signExp exp numerator denom expChar fragment|
+         nextChar radix sign signExp exp numerator denom expChar fragment mantissa|
 
         str := aStringOrStream readStream.
 
@@ -529,13 +567,11 @@
 
         (nextChar == $-) ifTrue:[
             sign := -1.
-            str next.
-            nextChar := str peekOrNil
+            nextChar := str nextPeekOrNil
         ] ifFalse:[
             sign := 1.
             (nextChar == $+) ifTrue:[
-                str next.
-                nextChar := str peekOrNil
+                nextChar := str nextPeekOrNil
             ]
         ].
         nextChar == $( ifTrue:[
@@ -576,27 +612,16 @@
             intValue := 0.
         ] ifFalse:[
             (allowCStyle and:[nextChar == $0]) ifTrue:[
-                str next.
-                nextChar := str peekOrNil.
+                nextChar := str nextPeekOrNil.
                 nextChar isNil ifTrue:[^ 0].
-                nextChar == $x ifTrue:[
-                    str next.
-                    radix := 16.
-                ] ifFalse:[
-                    nextChar == $b ifTrue:[
-                        str next.
-                        radix := 2.
-                    ] ifFalse:[
-                        nextChar == $o ifTrue:[
-                            str next.
-                            radix := 8.
-                        ] ifFalse:[
-                            nextChar isDigit ifFalse:[
-                                ^ 0
-                            ].        
-                        ].
-                    ].
-                ].
+                nextChar == $x ifTrue:[ str next. radix := 16 ] 
+                ifFalse:[ nextChar == $b ifTrue:[ str next. radix := 2 ] 
+                ifFalse:[ nextChar == $o ifTrue:[ str next. radix := 8 ] 
+                ifFalse:[
+                    nextChar isDigit ifFalse:[
+                        ^ 0
+                    ].        
+                ]]].
                 value := Integer readFrom:str radix:radix.
                 nextChar := str peekOrNil.
             ] ifFalse:[        
@@ -608,7 +633,7 @@
                     (fragment conform:#isDigit) ifFalse:[
                         ^ exceptionBlock value.
                     ].
-                    value := (value * 1000) + (Integer readFrom:fragment).
+                    value := (value * 1000) + (Integer fastFromString:fragment at:1).
                     nextChar := str peekOrNil.
                 ].    
                 ((nextChar == $r) or:[ nextChar == $R]) ifTrue:[
@@ -625,11 +650,9 @@
 
         (self == Integer or:[self inheritsFrom:Integer]) ifFalse:[
             (decimalPointCharacters includes:nextChar) ifTrue:[
-                str next.
-                nextChar := str peekOrNil.
+                nextChar := str nextPeekOrNil.
                 decimalMantissa := 0.
                 (nextChar notNil and:[nextChar isDigitRadix:radix]) ifTrue:[
-                    |mantissa|
                     mantissaAndScale := self readMantissaAndScaleFrom:str radix:radix.
                     mantissa := mantissaAndScale first.
                     value := (mantissa coerce:value) + mantissa.
@@ -639,18 +662,14 @@
 
             ('eEdDqQfF' includes:nextChar) ifTrue:[
                 expChar := nextChar.
-                str next.
-
-                nextChar := str peekOrNil.
+                nextChar := str nextPeekOrNil.
 
                 signExp := 1.
                 (nextChar == $+) ifTrue:[
-                    str next.
-                    nextChar := str peekOrNil.
+                    nextChar := str nextPeekOrNil.
                 ] ifFalse:[
                     (nextChar == $-) ifTrue:[
-                        str next.
-                        nextChar := str peekOrNil.
+                        nextChar := str nextPeekOrNil.
                         signExp := -1
                     ]
                 ].
@@ -689,9 +708,7 @@
                 ]
             ] ifFalse:[
                 ('sS' includes:nextChar) ifTrue:[
-                    str next.
-
-                    nextChar := str peekOrNil.
+                    nextChar := str nextPeekOrNil.
                     (nextChar notNil and:[ nextChar isDigit]) ifTrue:[
                         scale := (Integer readFrom:str).
                     ].
@@ -788,7 +805,7 @@
     "
 
     "Created: / 21-07-2019 / 13:05:04 / Claus Gittinger"
-    "Modified (format): / 21-07-2019 / 17:58:37 / Claus Gittinger"
+    "Modified: / 21-07-2019 / 19:40:34 / Claus Gittinger"
 !
 
 readFrom:aStringOrStream decimalPointCharacters:decimalPointCharacters thousandsSeparator:thousandsSeparator onError:exceptionBlock