Number.st
changeset 24449 8f3ac8e3b265
parent 24448 466c98f76a4b
child 24462 8018d0dcfa28
equal deleted inserted replaced
24448:466c98f76a4b 24449:8f3ac8e3b265
   110      ].
   110      ].
   111      Time millisecondsToRun:[
   111      Time millisecondsToRun:[
   112 	100000 timesRepeat:[ Integer fastFromString:'12345' ]
   112 	100000 timesRepeat:[ Integer fastFromString:'12345' ]
   113      ].
   113      ].
   114     "
   114     "
       
   115 !
       
   116 
       
   117 fastFromString:aString at:startIndex
       
   118     "return the next Float, Integer or ShortFloat from the string.
       
   119      No spaces are skipped.
       
   120 
       
   121      This is a specially tuned entry (using a low-level C-call), which
       
   122      returns garbage if the argument string is not a valid float number.
       
   123      It has been added to allow high speed string decomposition into numbers,
       
   124      especially for mass-data."
       
   125 
       
   126     self subclassResponsibility
       
   127 
       
   128     "
       
   129      Float fromString:'12345.0'
       
   130      Float fastFromString:'12345.0'
       
   131 
       
   132      Integer fromString:'12345'
       
   133      Integer fastFromString:'12345'
       
   134 
       
   135      should be roughly 10times faster than the general method:
       
   136 
       
   137      Time millisecondsToRun:[
       
   138         100000 timesRepeat:[ Float fromString:'12345.0' ]
       
   139      ].
       
   140      Time millisecondsToRun:[
       
   141         100000 timesRepeat:[ Float fastFromString:'12345.0' ]
       
   142      ].
       
   143 
       
   144      Time millisecondsToRun:[
       
   145         100000 timesRepeat:[ Integer fromString:'12345' ]
       
   146      ].
       
   147      Time millisecondsToRun:[
       
   148         100000 timesRepeat:[ Integer fastFromString:'12345' ]
       
   149      ].
       
   150     "
       
   151 
       
   152     "Created: / 21-07-2019 / 19:17:17 / Claus Gittinger"
   115 !
   153 !
   116 
   154 
   117 fromNumber:aNumber
   155 fromNumber:aNumber
   118     "return aNumber coerced to myself"
   156     "return aNumber coerced to myself"
   119 
   157 
   518         if sent to a concrete number-class, an instance of that class will be returned (independent of the exponent character)
   556         if sent to a concrete number-class, an instance of that class will be returned (independent of the exponent character)
   519     "
   557     "
   520 
   558 
   521     ^ [
   559     ^ [
   522         |value intValue mantissaAndScale scale decimalMantissa str
   560         |value intValue mantissaAndScale scale decimalMantissa str
   523          nextChar radix sign signExp exp numerator denom expChar fragment|
   561          nextChar radix sign signExp exp numerator denom expChar fragment mantissa|
   524 
   562 
   525         str := aStringOrStream readStream.
   563         str := aStringOrStream readStream.
   526 
   564 
   527         nextChar := str skipSeparators.
   565         nextChar := str skipSeparators.
   528         nextChar isNil ifTrue:[^ exceptionBlock value].
   566         nextChar isNil ifTrue:[^ exceptionBlock value].
   529 
   567 
   530         (nextChar == $-) ifTrue:[
   568         (nextChar == $-) ifTrue:[
   531             sign := -1.
   569             sign := -1.
   532             str next.
   570             nextChar := str nextPeekOrNil
   533             nextChar := str peekOrNil
       
   534         ] ifFalse:[
   571         ] ifFalse:[
   535             sign := 1.
   572             sign := 1.
   536             (nextChar == $+) ifTrue:[
   573             (nextChar == $+) ifTrue:[
   537                 str next.
   574                 nextChar := str nextPeekOrNil
   538                 nextChar := str peekOrNil
       
   539             ]
   575             ]
   540         ].
   576         ].
   541         nextChar == $( ifTrue:[
   577         nextChar == $( ifTrue:[
   542             "maybe a Fraction e.g. (1/3)"
   578             "maybe a Fraction e.g. (1/3)"
   543             str next.
   579             str next.
   574                 value := self zero. "/ 0.0.
   610                 value := self zero. "/ 0.0.
   575             ].
   611             ].
   576             intValue := 0.
   612             intValue := 0.
   577         ] ifFalse:[
   613         ] ifFalse:[
   578             (allowCStyle and:[nextChar == $0]) ifTrue:[
   614             (allowCStyle and:[nextChar == $0]) ifTrue:[
   579                 str next.
   615                 nextChar := str nextPeekOrNil.
   580                 nextChar := str peekOrNil.
       
   581                 nextChar isNil ifTrue:[^ 0].
   616                 nextChar isNil ifTrue:[^ 0].
   582                 nextChar == $x ifTrue:[
   617                 nextChar == $x ifTrue:[ str next. radix := 16 ] 
   583                     str next.
   618                 ifFalse:[ nextChar == $b ifTrue:[ str next. radix := 2 ] 
   584                     radix := 16.
   619                 ifFalse:[ nextChar == $o ifTrue:[ str next. radix := 8 ] 
   585                 ] ifFalse:[
   620                 ifFalse:[
   586                     nextChar == $b ifTrue:[
   621                     nextChar isDigit ifFalse:[
   587                         str next.
   622                         ^ 0
   588                         radix := 2.
   623                     ].        
   589                     ] ifFalse:[
   624                 ]]].
   590                         nextChar == $o ifTrue:[
       
   591                             str next.
       
   592                             radix := 8.
       
   593                         ] ifFalse:[
       
   594                             nextChar isDigit ifFalse:[
       
   595                                 ^ 0
       
   596                             ].        
       
   597                         ].
       
   598                     ].
       
   599                 ].
       
   600                 value := Integer readFrom:str radix:radix.
   625                 value := Integer readFrom:str radix:radix.
   601                 nextChar := str peekOrNil.
   626                 nextChar := str peekOrNil.
   602             ] ifFalse:[        
   627             ] ifFalse:[        
   603                 value := Integer readFrom:str radix:10.
   628                 value := Integer readFrom:str radix:10.
   604                 nextChar := str peekOrNil.
   629                 nextChar := str peekOrNil.
   606                     str next.
   631                     str next.
   607                     fragment := str next:3.
   632                     fragment := str next:3.
   608                     (fragment conform:#isDigit) ifFalse:[
   633                     (fragment conform:#isDigit) ifFalse:[
   609                         ^ exceptionBlock value.
   634                         ^ exceptionBlock value.
   610                     ].
   635                     ].
   611                     value := (value * 1000) + (Integer readFrom:fragment).
   636                     value := (value * 1000) + (Integer fastFromString:fragment at:1).
   612                     nextChar := str peekOrNil.
   637                     nextChar := str peekOrNil.
   613                 ].    
   638                 ].    
   614                 ((nextChar == $r) or:[ nextChar == $R]) ifTrue:[
   639                 ((nextChar == $r) or:[ nextChar == $R]) ifTrue:[
   615                     str next.
   640                     str next.
   616                     radix := value.
   641                     radix := value.
   623             intValue := value.
   648             intValue := value.
   624         ].
   649         ].
   625 
   650 
   626         (self == Integer or:[self inheritsFrom:Integer]) ifFalse:[
   651         (self == Integer or:[self inheritsFrom:Integer]) ifFalse:[
   627             (decimalPointCharacters includes:nextChar) ifTrue:[
   652             (decimalPointCharacters includes:nextChar) ifTrue:[
   628                 str next.
   653                 nextChar := str nextPeekOrNil.
   629                 nextChar := str peekOrNil.
       
   630                 decimalMantissa := 0.
   654                 decimalMantissa := 0.
   631                 (nextChar notNil and:[nextChar isDigitRadix:radix]) ifTrue:[
   655                 (nextChar notNil and:[nextChar isDigitRadix:radix]) ifTrue:[
   632                     |mantissa|
       
   633                     mantissaAndScale := self readMantissaAndScaleFrom:str radix:radix.
   656                     mantissaAndScale := self readMantissaAndScaleFrom:str radix:radix.
   634                     mantissa := mantissaAndScale first.
   657                     mantissa := mantissaAndScale first.
   635                     value := (mantissa coerce:value) + mantissa.
   658                     value := (mantissa coerce:value) + mantissa.
   636                     nextChar := str peekOrNil.
   659                     nextChar := str peekOrNil.
   637                 ]
   660                 ]
   638             ].
   661             ].
   639 
   662 
   640             ('eEdDqQfF' includes:nextChar) ifTrue:[
   663             ('eEdDqQfF' includes:nextChar) ifTrue:[
   641                 expChar := nextChar.
   664                 expChar := nextChar.
   642                 str next.
   665                 nextChar := str nextPeekOrNil.
   643 
       
   644                 nextChar := str peekOrNil.
       
   645 
   666 
   646                 signExp := 1.
   667                 signExp := 1.
   647                 (nextChar == $+) ifTrue:[
   668                 (nextChar == $+) ifTrue:[
   648                     str next.
   669                     nextChar := str nextPeekOrNil.
   649                     nextChar := str peekOrNil.
       
   650                 ] ifFalse:[
   670                 ] ifFalse:[
   651                     (nextChar == $-) ifTrue:[
   671                     (nextChar == $-) ifTrue:[
   652                         str next.
   672                         nextChar := str nextPeekOrNil.
   653                         nextChar := str peekOrNil.
       
   654                         signExp := -1
   673                         signExp := -1
   655                     ]
   674                     ]
   656                 ].
   675                 ].
   657 
   676 
   658                 "/ if I am abstract (i.e. I am Number or LPReal),
   677                 "/ if I am abstract (i.e. I am Number or LPReal),
   687                     exp := (Integer readFrom:str radix:radix) * signExp.
   706                     exp := (Integer readFrom:str radix:radix) * signExp.
   688                     value := value * ((value class unity * 10.0) raisedToInteger:exp)
   707                     value := value * ((value class unity * 10.0) raisedToInteger:exp)
   689                 ]
   708                 ]
   690             ] ifFalse:[
   709             ] ifFalse:[
   691                 ('sS' includes:nextChar) ifTrue:[
   710                 ('sS' includes:nextChar) ifTrue:[
   692                     str next.
   711                     nextChar := str nextPeekOrNil.
   693 
       
   694                     nextChar := str peekOrNil.
       
   695                     (nextChar notNil and:[ nextChar isDigit]) ifTrue:[
   712                     (nextChar notNil and:[ nextChar isDigit]) ifTrue:[
   696                         scale := (Integer readFrom:str).
   713                         scale := (Integer readFrom:str).
   697                     ].
   714                     ].
   698 
   715 
   699                     mantissaAndScale isNil ifTrue:[
   716                     mantissaAndScale isNil ifTrue:[
   786      DecimalPointCharactersForReading := #( $. ).
   803      DecimalPointCharactersForReading := #( $. ).
   787      Number readFrom:'99,00'
   804      Number readFrom:'99,00'
   788     "
   805     "
   789 
   806 
   790     "Created: / 21-07-2019 / 13:05:04 / Claus Gittinger"
   807     "Created: / 21-07-2019 / 13:05:04 / Claus Gittinger"
   791     "Modified (format): / 21-07-2019 / 17:58:37 / Claus Gittinger"
   808     "Modified: / 21-07-2019 / 19:40:34 / Claus Gittinger"
   792 !
   809 !
   793 
   810 
   794 readFrom:aStringOrStream decimalPointCharacters:decimalPointCharacters thousandsSeparator:thousandsSeparator onError:exceptionBlock
   811 readFrom:aStringOrStream decimalPointCharacters:decimalPointCharacters thousandsSeparator:thousandsSeparator onError:exceptionBlock
   795     "return the next Number from the (character-)stream aStream;
   812     "return the next Number from the (character-)stream aStream;
   796      skipping all whitespace first.
   813      skipping all whitespace first.