Integer.st
changeset 25149 663805b3e3ef
parent 25146 880c7f41b369
child 25215 9bbaac312afe
equal deleted inserted replaced
25148:03ac6dae4ff8 25149:663805b3e3ef
       
     1 "{ Encoding: utf8 }"
       
     2 
     1 "
     3 "
     2  COPYRIGHT (c) 1988 by Claus Gittinger
     4  COPYRIGHT (c) 1988 by Claus Gittinger
     3               All Rights Reserved
     5               All Rights Reserved
     4 
     6 
     5  This software is furnished under a license and may be used
     7  This software is furnished under a license and may be used
   375     "Created: / 16-11-1995 / 22:48:59 / cg"
   377     "Created: / 16-11-1995 / 22:48:59 / cg"
   376     "Modified (comment): / 09-03-2017 / 16:27:14 / cg"
   378     "Modified (comment): / 09-03-2017 / 16:27:14 / cg"
   377 !
   379 !
   378 
   380 
   379 readFrom:aStringOrStream radix:radix
   381 readFrom:aStringOrStream radix:radix
   380     "return the next UNSIGNED Integer from the (character-)stream aStream in radix; 
   382     "return the next possibly signed Integer from the (character-)stream aStream in radix; 
   381      (assumes that the initial XXr has already been read).
   383      (assumes that any initial XXr has already been read).
   382      No whitespace-skipping is done.
   384      No whitespace-skipping is done.
   383      Returns 0 if no number available.
   385      Returns 0 if no number available.
   384 
   386 
   385      NOTICE:
   387      NOTICE:
   386        This behaves different from the default readFrom:, in returning
   388        This behaves different from the default readFrom:, in returning
   390 
   392 
   391     ^ self readFrom:aStringOrStream radix:radix onError:0
   393     ^ self readFrom:aStringOrStream radix:radix onError:0
   392 !
   394 !
   393 
   395 
   394 readFrom:aStringOrStream radix:radix onError:exceptionBlock
   396 readFrom:aStringOrStream radix:radix onError:exceptionBlock
   395     "return the next UNSIGNED Integer from the (character-)stream aStream in radix; 
   397     "return the next possibly signed Integer from the (character-)stream aStream in radix; 
   396      (assumes that the initial XXr has already been read).
   398      (assumes that any initial XXr has already been read).
   397      No whitespace-skipping is done.
   399      No whitespace-skipping is done.
   398      Returns the value of exceptionBlock, if no number is available."
   400      Returns the value of exceptionBlock, if no number is available."
   399 
   401 
   400     |str nextChar value
   402     |str nextChar|
   401      r     "{ Class: SmallInteger }"
       
   402      r2    "{ Class: SmallInteger }"
       
   403      r3    "{ Class: SmallInteger }"
       
   404      r4    "{ Class: SmallInteger }"
       
   405      digit1 digit2 digit3 digit4 |
       
   406 
   403 
   407     str := aStringOrStream readStream.
   404     str := aStringOrStream readStream.
   408 
   405 
   409     nextChar := str peekOrNil.
   406     nextChar := str peekOrNil.
   410     (nextChar isNil or:[(value := nextChar digitValueRadix:radix) isNil]) ifTrue:[
   407     nextChar == $- ifTrue:[
   411         ^ exceptionBlock value
   408         str next.
   412     ].
   409         ^ self readUnsignedFrom:str radix:radix sign:-1 onError:exceptionBlock
   413 
   410     ].
   414 "/ OLD code
   411     ^ self readUnsignedFrom:str radix:radix sign:1 onError:exceptionBlock
   415 "/    [nextChar notNil and:[nextChar isDigitRadix:radix]] whileTrue:[
       
   416 "/        str next.
       
   417 "/        value := value * radix + nextChar digitValue.
       
   418 "/        nextChar := str peekOrNil.
       
   419 "/    ].
       
   420 "/    ^ value.
       
   421 
       
   422     "/ the code below does the same, but is much faster, if the
       
   423     "/ converted number is large
       
   424     "/ (requires only half as many LargeInt multiplications and additions)
       
   425     "/ It should not be slower for smallIntegers.
       
   426 
       
   427     r := radix.
       
   428     r2 := r * r.
       
   429     r4 := r2 * r2.
       
   430 
       
   431     [
       
   432         nextChar := str nextPeekOrNil.
       
   433         nextChar notNil and:[(digit1 := nextChar digitValueRadix:r) notNil]
       
   434     ] whileTrue:[
       
   435         "/ read 4 chars and pre-compute their value to avoid largeInt operations.
       
   436 
       
   437         nextChar := str nextPeekOrNil.
       
   438         (nextChar isNil or:[(digit2 := nextChar digitValueRadix:r) isNil]) ifTrue:[
       
   439             ^ (value * r) + digit1.
       
   440         ].
       
   441 
       
   442         nextChar := str nextPeekOrNil.
       
   443         (nextChar isNil or:[(digit3 := nextChar digitValueRadix:r) isNil]) ifTrue:[
       
   444             ^ (value * r2) + ((digit1*r) + digit2) .
       
   445         ].
       
   446 
       
   447         nextChar := str nextPeekOrNil.
       
   448         (nextChar isNil or:[ (digit4 := nextChar digitValueRadix:r) isNil]) ifTrue:[
       
   449             r3 := r2 * r.
       
   450             ^ (value * r3) + ((((digit1*r) + digit2)*r) + digit3).
       
   451         ].
       
   452 
       
   453         value := (value * r4) + ((((((digit1*r) + digit2)*r) + digit3)*r) + digit4).
       
   454     ].
       
   455     ^ value
       
   456 
   412 
   457     "
   413     "
   458      Integer readFrom:(ReadStream on:'12345') radix:10
   414      Integer readFrom:(ReadStream on:'12345') radix:10
   459      Integer readFrom:(ReadStream on:'FFFF') radix:16
   415      Integer readFrom:(ReadStream on:'FFFF') radix:16
   460      Integer readFrom:(ReadStream on:'1010') radix:2
   416      Integer readFrom:(ReadStream on:'1010') radix:2
   805      Integer readFromString:'-1234' radix:10 onError:[nil]  - I only read unsigned numbers
   761      Integer readFromString:'-1234' radix:10 onError:[nil]  - I only read unsigned numbers
   806      Integer readFromString:' 1234' radix:10 onError:[nil]  - I do not skip whitespace
   762      Integer readFromString:' 1234' radix:10 onError:[nil]  - I do not skip whitespace
   807      Integer readFromString:'1234 ' radix:10 onError:[nil]  - I do not accept anything after the number
   763      Integer readFromString:'1234 ' radix:10 onError:[nil]  - I do not accept anything after the number
   808 
   764 
   809     "
   765     "
       
   766 !
       
   767 
       
   768 readUnsignedFrom:aStringOrStream radix:radix
       
   769     "return the next UNSIGNED Integer from the (character-)stream aStream in radix; 
       
   770      (assumes that any initial XXr or sign has already been read).
       
   771      No whitespace-skipping is done.
       
   772      Returns 0 if no number available.
       
   773 
       
   774      NOTICE:
       
   775        This behaves different from the default readFrom:, in returning
       
   776        0 (instead of raising an error) in case no number can be read.
       
   777        It is unclear, if this is the correct behavior (ST-80 does this)
       
   778        - depending on the upcoming ANSI standard, this may change."
       
   779 
       
   780     ^ self readUnsignedFrom:aStringOrStream radix:radix sign:1 onError:0
       
   781 !
       
   782 
       
   783 readUnsignedFrom:aStringOrStream radix:radix onError:exceptionBlock
       
   784     "return the next UNSIGNED Integer from the (character-)stream aStream in radix; 
       
   785      (assumes that any initial XXr or sign has already been read).
       
   786      No whitespace-skipping is done.
       
   787      Returns the value of exceptionBlock, if no number is available."
       
   788 
       
   789     ^ self readUnsignedFrom:aStringOrStream radix:radix sign:1 onError:exceptionBlock
       
   790 
       
   791     "
       
   792      Integer readUnsignedFrom:(ReadStream on:'12345') radix:10
       
   793      Integer readUnsignedFrom:(ReadStream on:'FFFF') radix:16
       
   794      Integer readUnsignedFrom:(ReadStream on:'1010') radix:2
       
   795      Integer readUnsignedFrom:(ReadStream on:'foobar') radix:10
       
   796      Integer readUnsignedFrom:(ReadStream on:'foobar') radix:10 onError:nil
       
   797      Integer readUnsignedFrom:'gg' radix:10 onError:0
       
   798      Integer readUnsignedFrom:'' radix:10 onError:'wrong'
       
   799 
       
   800      |s|
       
   801      s := String new:1000 withAll:$1.
       
   802      Time millisecondsToRun:[
       
   803         1000 timesRepeat:[
       
   804             s asInteger
       
   805         ]
       
   806      ]
       
   807     "
       
   808 
       
   809     "Modified: / 14.4.1998 / 19:16:46 / cg"
       
   810 !
       
   811 
       
   812 readUnsignedFrom:aStringOrStream radix:radix sign:sign
       
   813     "return the next UNSIGNED Integer from the (character-)stream aStream in radix; 
       
   814      (assumes that any initial XXr or sign has already been read).
       
   815      No whitespace-skipping is done.
       
   816      Returns 0 if no number available.
       
   817 
       
   818      NOTICE:
       
   819        This behaves different from the default readFrom:, in returning
       
   820        0 (instead of raising an error) in case no number can be read.
       
   821        It is unclear, if this is the correct behavior (ST-80 does this)
       
   822        - depending on the upcoming ANSI standard, this may change."
       
   823 
       
   824     ^ self readUnsignedFrom:aStringOrStream radix:radix sign:sign onError:0
       
   825 !
       
   826 
       
   827 readUnsignedFrom:aStringOrStream radix:radix sign:sign onError:exceptionBlock
       
   828     "return the next UNSIGNED Integer from the (character-)stream aStream in radix; 
       
   829      (assumes that any initial XXr or sign has already been read).
       
   830      No whitespace-skipping is done.
       
   831      Returns the value of exceptionBlock, if no number is available."
       
   832 
       
   833     |str nextChar value ret
       
   834      r     "{ Class: SmallInteger }"
       
   835      r2    "{ Class: SmallInteger }"
       
   836      r3    "{ Class: SmallInteger }"
       
   837      r4    "{ Class: SmallInteger }"
       
   838      digit1 digit2 digit3 digit4 |
       
   839 
       
   840     str := aStringOrStream readStream.
       
   841 
       
   842     nextChar := str peekOrNil.
       
   843     (nextChar isNil or:[(value := nextChar digitValueRadix:radix) isNil]) ifTrue:[
       
   844         ^ exceptionBlock value
       
   845     ].
       
   846 
       
   847 "/ OLD code
       
   848 "/    [nextChar notNil and:[nextChar isDigitRadix:radix]] whileTrue:[
       
   849 "/        str next.
       
   850 "/        value := value * radix + nextChar digitValue.
       
   851 "/        nextChar := str peekOrNil.
       
   852 "/    ].
       
   853 "/    ^ value.
       
   854 
       
   855     "/ the code below does the same, but is much faster, if the
       
   856     "/ converted number is large
       
   857     "/ (requires only half as many LargeInt multiplications and additions)
       
   858     "/ It should not be slower for smallIntegers.
       
   859 
       
   860     r := radix.
       
   861     r2 := r * r.
       
   862     r4 := r2 * r2.
       
   863 
       
   864     [
       
   865         nextChar := str nextPeekOrNil.
       
   866         nextChar notNil and:[(digit1 := nextChar digitValueRadix:r) notNil]
       
   867     ] whileTrue:[
       
   868         "/ read 4 chars and pre-compute their value to avoid largeInt operations.
       
   869 
       
   870         nextChar := str nextPeekOrNil.
       
   871         (nextChar isNil or:[(digit2 := nextChar digitValueRadix:r) isNil]) ifTrue:[
       
   872             ret := (value * r) + digit1.
       
   873             sign == -1 ifTrue:[^ ret negated].
       
   874             ^ ret
       
   875         ].
       
   876 
       
   877         nextChar := str nextPeekOrNil.
       
   878         (nextChar isNil or:[(digit3 := nextChar digitValueRadix:r) isNil]) ifTrue:[
       
   879             ret := (value * r2) + ((digit1*r) + digit2) .
       
   880             sign == -1 ifTrue:[^ ret negated].
       
   881             ^ ret
       
   882         ].
       
   883 
       
   884         nextChar := str nextPeekOrNil.
       
   885         (nextChar isNil or:[ (digit4 := nextChar digitValueRadix:r) isNil]) ifTrue:[
       
   886             r3 := r2 * r.
       
   887             ret := (value * r3) + ((((digit1*r) + digit2)*r) + digit3).
       
   888             sign == -1 ifTrue:[^ ret negated].
       
   889             ^ ret
       
   890         ].
       
   891 
       
   892         value := (value * r4) + ((((((digit1*r) + digit2)*r) + digit3)*r) + digit4).
       
   893     ].
       
   894     sign == -1 ifTrue:[^ value negated].
       
   895     ^ value
       
   896 
       
   897     "
       
   898      Integer readFrom:(ReadStream on:'12345') radix:10
       
   899      Integer readFrom:(ReadStream on:'FFFF') radix:16
       
   900      Integer readFrom:(ReadStream on:'1010') radix:2
       
   901      Integer readFrom:(ReadStream on:'foobar') radix:10
       
   902      Integer readFrom:(ReadStream on:'foobar') radix:10 onError:nil
       
   903      Integer readFrom:'gg' radix:10 onError:0
       
   904      Integer readFrom:'' radix:10 onError:'wrong'
       
   905 
       
   906      |s|
       
   907      s := String new:1000 withAll:$1.
       
   908      Time millisecondsToRun:[
       
   909         1000 timesRepeat:[
       
   910             s asInteger
       
   911         ]
       
   912      ]
       
   913     "
       
   914 
       
   915     "Modified: / 14.4.1998 / 19:16:46 / cg"
   810 ! !
   916 ! !
   811 
   917 
   812 !Integer class methodsFor:'Compatibility-Squeak'!
   918 !Integer class methodsFor:'Compatibility-Squeak'!
   813 
   919 
   814 readFrom:aStringOrStream base:aBase
   920 readFrom:aStringOrStream base:aBase
   825 
   931 
   826     ^ BCDConversionErrorSignal
   932     ^ BCDConversionErrorSignal
   827 
   933 
   828     "Modified: / 15.11.1999 / 20:35:20 / cg"
   934     "Modified: / 15.11.1999 / 20:35:20 / cg"
   829 ! !
   935 ! !
   830 
       
   831 
       
   832 
   936 
   833 !Integer class methodsFor:'class initialization'!
   937 !Integer class methodsFor:'class initialization'!
   834 
   938 
   835 initialize
   939 initialize
   836     BCDConversionErrorSignal isNil ifTrue:[
   940     BCDConversionErrorSignal isNil ifTrue:[
   883 
   987 
   884     ^ 0
   988     ^ 0
   885 
   989 
   886     "Modified: 18.7.1996 / 12:26:38 / cg"
   990     "Modified: 18.7.1996 / 12:26:38 / cg"
   887 ! !
   991 ! !
   888 
       
   889 
   992 
   890 !Integer class methodsFor:'prime numbers'!
   993 !Integer class methodsFor:'prime numbers'!
   891 
   994 
   892 flushPrimeCache
   995 flushPrimeCache
   893     "cleanup after using a primeCache.
   996     "cleanup after using a primeCache.
  1259      True is returned for Integer here; false for subclasses.
  1362      True is returned for Integer here; false for subclasses.
  1260      Abstract subclasses must redefine this again."
  1363      Abstract subclasses must redefine this again."
  1261 
  1364 
  1262     ^ self == Integer
  1365     ^ self == Integer
  1263 ! !
  1366 ! !
  1264 
       
  1265 
  1367 
  1266 !Integer methodsFor:'Compatibility-Dolphin'!
  1368 !Integer methodsFor:'Compatibility-Dolphin'!
  1267 
  1369 
  1268 highWord
  1370 highWord
  1269     "return the high 16 bits of a 32 bit value"
  1371     "return the high 16 bits of a 32 bit value"
  4145     ].
  4247     ].
  4146 
  4248 
  4147     ^ fibUsingDict value:self
  4249     ^ fibUsingDict value:self
  4148 
  4250 
  4149     "the running time is mostly dictated by the LargeInteger multiplication performance...
  4251     "the running time is mostly dictated by the LargeInteger multiplication performance...
  4150      (therefore, we get O(n²) execution times, even for a linear number of multiplications)
  4252      (therefore, we get O(n²) execution times, even for a linear number of multiplications)
  4151 
  4253 
  4152      Time millisecondsToRun:[50000 fib_iterative]  312    (DUO 1.7Ghz CPU)
  4254      Time millisecondsToRun:[50000 fib_iterative]  312    (DUO 1.7Ghz CPU)
  4153      Time millisecondsToRun:[50000 fib_helper]     109
  4255      Time millisecondsToRun:[50000 fib_helper]     109
  4154 
  4256 
  4155      Time millisecondsToRun:[100000 fib_iterative] 1248
  4257      Time millisecondsToRun:[100000 fib_iterative] 1248
  5740     "
  5842     "
  5741 
  5843 
  5742     "Created: / 09-01-2012 / 17:18:06 / cg"
  5844     "Created: / 09-01-2012 / 17:18:06 / cg"
  5743 ! !
  5845 ! !
  5744 
  5846 
  5745 
       
  5746 !Integer methodsFor:'special modulo arithmetic'!
  5847 !Integer methodsFor:'special modulo arithmetic'!
  5747 
  5848 
  5748 add_32:anInteger
  5849 add_32:anInteger
  5749     "return a C-semantic 32bit sum of the receiver and the argument.
  5850     "return a C-semantic 32bit sum of the receiver and the argument.
  5750      Both must be either Small- or LargeIntegers.
  5851      Both must be either Small- or LargeIntegers.