LargeInteger.st
changeset 2001 8c2b957f0cb3
parent 1983 c5a2c4655d10
child 2267 123ec897aca5
equal deleted inserted replaced
2000:2c12eb609e05 2001:8c2b957f0cb3
    58     In contrast to ST-80, there is only one class for LargeIntegers, keeping
    58     In contrast to ST-80, there is only one class for LargeIntegers, keeping
    59     the sign as an instance variable (ST-80 has LargePositiveInteger and
    59     the sign as an instance variable (ST-80 has LargePositiveInteger and
    60     LargeNegativeInteger). This may change.
    60     LargeNegativeInteger). This may change.
    61 
    61 
    62     [author:]
    62     [author:]
    63         Claus Gittinger
    63 	Claus Gittinger
    64 
    64 
    65     [see also:]
    65     [see also:]
    66         Number
    66 	Number
    67         Float Fraction FixedPoint 
    67 	Float Fraction FixedPoint 
    68         SmallInteger
    68 	SmallInteger
    69 "
    69 "
    70 ! !
    70 ! !
    71 
    71 
    72 !LargeInteger class methodsFor:'instance creation'!
    72 !LargeInteger class methodsFor:'instance creation'!
    73 
    73 
   189     "
   189     "
   190      this is the common case, subtracting a SmallInteger.
   190      this is the common case, subtracting a SmallInteger.
   191      Use a special method for this case ...
   191      Use a special method for this case ...
   192     "
   192     "
   193     (aNumber class == SmallInteger) ifTrue:[
   193     (aNumber class == SmallInteger) ifTrue:[
   194         sign < 0 ifTrue:[
   194 	sign < 0 ifTrue:[
   195             aNumber > 0 ifTrue:[
   195 	    aNumber > 0 ifTrue:[
   196                 ^ (self absFastPlus:aNumber) sign:-1
   196 		^ (self absFastPlus:aNumber) sign:-1
   197             ].
   197 	    ].
   198             ^ (self absFastMinus:aNumber) sign:-1
   198 	    ^ (self absFastMinus:aNumber) sign:-1
   199         ].
   199 	].
   200         aNumber > 0 ifTrue:[
   200 	aNumber > 0 ifTrue:[
   201             ^ self absFastMinus:aNumber
   201 	    ^ self absFastMinus:aNumber
   202         ].
   202 	].
   203         ^ self absFastPlus:aNumber
   203 	^ self absFastPlus:aNumber
   204     ].
   204     ].
   205 
   205 
   206     "
   206     "
   207      if the argument is not a largeInteger, coerce
   207      if the argument is not a largeInteger, coerce
   208     "
   208     "
   209     (aNumber class == self class) ifFalse:[
   209     (aNumber class == self class) ifFalse:[
   210         ^ self retry:#- coercing:aNumber
   210 	^ self retry:#- coercing:aNumber
   211     ].
   211     ].
   212 
   212 
   213     otherSign := aNumber sign.
   213     otherSign := aNumber sign.
   214     (sign > 0) ifTrue:[
   214     (sign > 0) ifTrue:[
   215         "I am positive"
   215 	"I am positive"
   216         (otherSign > 0) ifTrue:[^ self absMinus:aNumber].
   216 	(otherSign > 0) ifTrue:[^ self absMinus:aNumber].
   217         (otherSign < 0) ifTrue:[^ self absPlus:aNumber].
   217 	(otherSign < 0) ifTrue:[^ self absPlus:aNumber].
   218         ^ self
   218 	^ self
   219     ].
   219     ].
   220     "I am negative"
   220     "I am negative"
   221     (otherSign > 0) ifTrue:[^ (self absPlus:aNumber) negated].
   221     (otherSign > 0) ifTrue:[^ (self absPlus:aNumber) negated].
   222     (otherSign < 0) ifTrue:[^ (self absMinus:aNumber) negated].
   222     (otherSign < 0) ifTrue:[^ (self absMinus:aNumber) negated].
   223     ^ self
   223     ^ self
   264     "
   264     "
   265      this is the common case, dividing by a SmallInteger.
   265      this is the common case, dividing by a SmallInteger.
   266      Use a special method for this case ...
   266      Use a special method for this case ...
   267     "
   267     "
   268     (aNumber class == SmallInteger) ifTrue:[
   268     (aNumber class == SmallInteger) ifTrue:[
   269         abs := aNumber.
   269 	abs := aNumber.
   270         abs := abs abs.
   270 	abs := abs abs.
   271         (abs between:1 and:16r003fffff) ifTrue:[
   271 	(abs between:1 and:16r003fffff) ifTrue:[
   272             divMod := self absFastDiv:abs.
   272 	    divMod := self absFastDiv:abs.
   273             quo := divMod at:1.
   273 	    quo := divMod at:1.
   274             (sign == otherSign) ifTrue:[^ quo].
   274 	    (sign == otherSign) ifTrue:[^ quo].
   275 
   275 
   276             "/ stupid adjust ...
   276 	    "/ stupid adjust ...
   277             (divMod at:2) == 0 ifFalse:[
   277 	    (divMod at:2) == 0 ifFalse:[
   278                 ^ (quo sign:-1) - 1
   278 		^ (quo sign:-1) - 1
   279             ].
   279 	    ].
   280             ^ quo sign:-1
   280 	    ^ quo sign:-1
   281         ].
   281 	].
   282         n := aNumber asLargeInteger.
   282 	n := aNumber asLargeInteger.
   283     ] ifFalse:[
   283     ] ifFalse:[
   284         n := aNumber
   284 	n := aNumber
   285     ].
   285     ].
   286 
   286 
   287     "
   287     "
   288      if the argument is not a largeInteger, coerce
   288      if the argument is not a largeInteger, coerce
   289     "
   289     "
   290     (n class == self class) ifFalse:[
   290     (n class == self class) ifFalse:[
   291         ^ self retry:#// coercing:aNumber
   291 	^ self retry:#// coercing:aNumber
   292     ].
   292     ].
   293 
   293 
   294     divMod := self absDiv:n.
   294     divMod := self absDiv:n.
   295 
   295 
   296     (sign == otherSign) ifTrue:[^ divMod at:1].
   296     (sign == otherSign) ifTrue:[^ divMod at:1].
   297 
   297 
   298     "/ stupid adjust for truncation ...
   298     "/ stupid adjust for truncation ...
   299     quo := divMod at:1.
   299     quo := divMod at:1.
   300     (divMod at:2) == 0 ifFalse:[
   300     (divMod at:2) == 0 ifFalse:[
   301         ^ (quo sign:-1) - 1
   301 	^ (quo sign:-1) - 1
   302     ].
   302     ].
   303     ^ quo sign:-1
   303     ^ quo sign:-1
   304 
   304 
   305     "
   305     "
   306      900 // 400  
   306      900 // 400  
   338     "
   338     "
   339      this is the common case, dividing by a SmallInteger.
   339      this is the common case, dividing by a SmallInteger.
   340      Use a special method for this case ...
   340      Use a special method for this case ...
   341     "
   341     "
   342     (aNumber class == SmallInteger) ifTrue:[
   342     (aNumber class == SmallInteger) ifTrue:[
   343         (abs between:1 and:16r003fffff) ifTrue:[
   343 	(abs between:1 and:16r003fffff) ifTrue:[
   344             rem := (self absFastDiv:abs) at:2.
   344 	    rem := (self absFastDiv:abs) at:2.
   345         ] ifFalse:[
   345 	] ifFalse:[
   346             rem := (self absDiv:abs asLargeInteger) at:2
   346 	    rem := (self absDiv:abs asLargeInteger) at:2
   347         ].
   347 	].
   348     ] ifFalse:[
   348     ] ifFalse:[
   349         "
   349 	"
   350          if the argument is not a largeInteger, coerce
   350 	 if the argument is not a largeInteger, coerce
   351         "
   351 	"
   352         (aNumber class == self class) ifFalse:[
   352 	(aNumber class == self class) ifFalse:[
   353             ^ self retry:#\\ coercing:aNumber
   353 	    ^ self retry:#\\ coercing:aNumber
   354         ].
   354 	].
   355 
   355 
   356         rem := (self absDiv:abs) at:2.
   356 	rem := (self absDiv:abs) at:2.
   357     ].
   357     ].
   358 
   358 
   359     aNumber negative ifTrue:[
   359     aNumber negative ifTrue:[
   360         ^ rem sign:-1
   360 	^ rem sign:-1
   361     ].
   361     ].
   362     ^ rem
   362     ^ rem
   363 
   363 
   364     "
   364     "
   365      900 \\ 400    
   365      900 \\ 400    
   402     "
   402     "
   403      this is the common case, dividing by a SmallInteger.
   403      this is the common case, dividing by a SmallInteger.
   404      Use a special method for this case ...
   404      Use a special method for this case ...
   405     "
   405     "
   406     (aNumber class == SmallInteger) ifTrue:[
   406     (aNumber class == SmallInteger) ifTrue:[
   407         ^ self absFastDiv:aNumber abs.
   407 	^ self absFastDiv:aNumber abs.
   408     ].
   408     ].
   409 
   409 
   410     "
   410     "
   411      if the argument is not a largeInteger, coerce
   411      if the argument is not a largeInteger, coerce
   412     "
   412     "
   413     (aNumber class == self class) ifTrue:[
   413     (aNumber class == self class) ifTrue:[
   414         ^ self absDiv:aNumber abs
   414 	^ self absDiv:aNumber abs
   415     ].
   415     ].
   416 
   416 
   417     ^ super divMod:aNumber
   417     ^ super divMod:aNumber
   418 
   418 
   419     "
   419     "
   470     "
   470     "
   471      this is the common case, dividing by a SmallInteger.
   471      this is the common case, dividing by a SmallInteger.
   472      Use a special method for this case ...
   472      Use a special method for this case ...
   473     "
   473     "
   474     (aNumber class == SmallInteger) ifTrue:[
   474     (aNumber class == SmallInteger) ifTrue:[
   475         abs := aNumber.
   475 	abs := aNumber.
   476         abs := abs abs.
   476 	abs := abs abs.
   477         (abs between:1 and:16r003fffff) ifTrue:[
   477 	(abs between:1 and:16r003fffff) ifTrue:[
   478             quo := (self absFastDiv:abs) at:1.
   478 	    quo := (self absFastDiv:abs) at:1.
   479             (sign == otherSign) ifTrue:[^ quo].
   479 	    (sign == otherSign) ifTrue:[^ quo].
   480             ^ quo sign:-1
   480 	    ^ quo sign:-1
   481         ]
   481 	]
   482     ].
   482     ].
   483 
   483 
   484     "
   484     "
   485      if the argument is not a largeInteger, coerce
   485      if the argument is not a largeInteger, coerce
   486     "
   486     "
   487     (aNumber class == self class) ifFalse:[
   487     (aNumber class == self class) ifFalse:[
   488         ^ self retry:#quo: coercing:aNumber
   488 	^ self retry:#quo: coercing:aNumber
   489     ].
   489     ].
   490 
   490 
   491     sign < 0 ifTrue:[
   491     sign < 0 ifTrue:[
   492         (sign == otherSign) ifTrue:[^ (self absDiv:aNumber negated) at:1].
   492 	(sign == otherSign) ifTrue:[^ (self absDiv:aNumber negated) at:1].
   493     ] ifFalse:[
   493     ] ifFalse:[
   494         (sign == otherSign) ifTrue:[^ (self absDiv:aNumber) at:1].
   494 	(sign == otherSign) ifTrue:[^ (self absDiv:aNumber) at:1].
   495     ].
   495     ].
   496     ^ ((self absDiv:aNumber) at:1) sign:-1
   496     ^ ((self absDiv:aNumber) at:1) sign:-1
   497 
   497 
   498     "
   498     "
   499      900 // 400  
   499      900 // 400  
   529     "
   529     "
   530      this is the common case, dividing by a SmallInteger.
   530      this is the common case, dividing by a SmallInteger.
   531      Use special code for this case ...
   531      Use special code for this case ...
   532     "
   532     "
   533     (aNumber class == SmallInteger) ifTrue:[
   533     (aNumber class == SmallInteger) ifTrue:[
   534         abs := aNumber.
   534 	abs := aNumber.
   535         abs := abs abs.
   535 	abs := abs abs.
   536         (abs between:1 and:16r003fffff) ifTrue:[
   536 	(abs between:1 and:16r003fffff) ifTrue:[
   537             rem := (self absFastDiv:abs) at:2.
   537 	    rem := (self absFastDiv:abs) at:2.
   538         ] ifFalse:[
   538 	] ifFalse:[
   539             rem := (self absDiv:(abs asLargeInteger)) at:2
   539 	    rem := (self absDiv:(abs asLargeInteger)) at:2
   540         ].
   540 	].
   541     ] ifFalse:[
   541     ] ifFalse:[
   542         "
   542 	"
   543          if the argument is not a largeInteger, coerce
   543 	 if the argument is not a largeInteger, coerce
   544         "
   544 	"
   545         (aNumber class == self class) ifFalse:[
   545 	(aNumber class == self class) ifFalse:[
   546             ^ self retry:#\\ coercing:aNumber
   546 	    ^ self retry:#\\ coercing:aNumber
   547         ].
   547 	].
   548 
   548 
   549         rem := (self absDiv:aNumber) at:2
   549 	rem := (self absDiv:aNumber) at:2
   550     ].
   550     ].
   551 
   551 
   552     sign < 0 ifTrue:[
   552     sign < 0 ifTrue:[
   553         ^ rem sign:-1
   553 	^ rem sign:-1
   554     ].
   554     ].
   555     ^ rem
   555     ^ rem
   556 
   556 
   557     "
   557     "
   558      900 \\ 400    
   558      900 \\ 400    
   689 
   689 
   690 %{  /* NOCONTEXT */
   690 %{  /* NOCONTEXT */
   691     OBJ t;
   691     OBJ t;
   692 
   692 
   693     if (__INST(sign) == __MKSMALLINT(0)) {
   693     if (__INST(sign) == __MKSMALLINT(0)) {
   694         RETURN (__MKSMALLINT(0));
   694 	RETURN (__MKSMALLINT(0));
   695     }
   695     }
   696 
   696 
   697     t = __INST(digitByteArray);
   697     t = __INST(digitByteArray);
   698     if (__isByteArray(t)) {
   698     if (__isByteArray(t)) {
   699         unsigned char *_digitBytes = __ByteArrayInstPtr(t)->ba_element;
   699 	unsigned char *_digitBytes = __ByteArrayInstPtr(t)->ba_element;
   700         int _idx = _byteArraySize(t);
   700 	int _idx = _byteArraySize(t);
   701         int _val;
   701 	int _val;
   702 
   702 
   703         while ((_idx > 0) && (_digitBytes[_idx - 1] == 0)) {
   703 	while ((_idx > 0) && (_digitBytes[_idx - 1] == 0)) {
   704             _idx--;
   704 	    _idx--;
   705         }
   705 	}
   706         switch (_idx) {
   706 	switch (_idx) {
   707             case 0:
   707 	    case 0:
   708                 RETURN (__MKSMALLINT(0));
   708 		RETURN (__MKSMALLINT(0));
   709                 break;
   709 		break;
   710 
   710 
   711             case 1:
   711 	    case 1:
   712                 _val = _digitBytes[0];
   712 		_val = _digitBytes[0];
   713                 if (__INST(sign) == __MKSMALLINT(-1))
   713 		if (__INST(sign) == __MKSMALLINT(-1))
   714                     _val = -_val;
   714 		    _val = -_val;
   715                 RETURN (__MKSMALLINT(_val));
   715 		RETURN (__MKSMALLINT(_val));
   716                 
   716                 
   717             case 2:
   717 	    case 2:
   718                 _val = (_digitBytes[1]<<8) + _digitBytes[0];
   718 		_val = (_digitBytes[1]<<8) + _digitBytes[0];
   719                 if (__INST(sign) == __MKSMALLINT(-1))
   719 		if (__INST(sign) == __MKSMALLINT(-1))
   720                     _val = -_val;
   720 		    _val = -_val;
   721                 RETURN (__MKSMALLINT(_val));
   721 		RETURN (__MKSMALLINT(_val));
   722 
   722 
   723             case 3:
   723 	    case 3:
   724                 _val = (((_digitBytes[2]<<8) + _digitBytes[1])<<8) + _digitBytes[0];
   724 		_val = (((_digitBytes[2]<<8) + _digitBytes[1])<<8) + _digitBytes[0];
   725                 if (__INST(sign) == __MKSMALLINT(-1))
   725 		if (__INST(sign) == __MKSMALLINT(-1))
   726                     _val = -_val;
   726 		    _val = -_val;
   727                 RETURN (__MKSMALLINT(_val));
   727 		RETURN (__MKSMALLINT(_val));
   728 
   728 
   729             case 4:
   729 	    case 4:
   730                 _val = _digitBytes[3];
   730 		_val = _digitBytes[3];
   731                 if (_val <= 0x40) {
   731 		if (_val <= 0x40) {
   732                     _val = (((((_val<<8) + _digitBytes[2])<<8) + _digitBytes[1])<<8) + _digitBytes[0];
   732 		    _val = (((((_val<<8) + _digitBytes[2])<<8) + _digitBytes[1])<<8) + _digitBytes[0];
   733                     if (__INST(sign) == __MKSMALLINT(-1))
   733 		    if (__INST(sign) == __MKSMALLINT(-1))
   734                         _val = -_val;
   734 			_val = -_val;
   735                     if ((_val >= _MIN_INT) && (_val <= _MAX_INT)) {
   735 		    if ((_val >= _MIN_INT) && (_val <= _MAX_INT)) {
   736                         RETURN (__MKSMALLINT(_val));
   736 			RETURN (__MKSMALLINT(_val));
   737                     }
   737 		    }
   738                 }
   738 		}
   739                 break;
   739 		break;
   740 
   740 
   741             default:
   741 	    default:
   742                 break;
   742 		break;
   743         }
   743 	}
   744     }
   744     }
   745 %}.
   745 %}.
   746     index := digitByteArray size.
   746     index := digitByteArray size.
   747     [(index > 0) and:[(digitByteArray at:index) == 0]] whileTrue:[
   747     [(index > 0) and:[(digitByteArray at:index) == 0]] whileTrue:[
   748         index := index - 1
   748 	index := index - 1
   749     ].
   749     ].
   750 
   750 
   751     (index ~~ digitByteArray size) ifTrue:[
   751     (index ~~ digitByteArray size) ifTrue:[
   752         digitByteArray := digitByteArray copyFrom:1 to:index
   752 	digitByteArray := digitByteArray copyFrom:1 to:index
   753     ].
   753     ].
   754     ^ self
   754     ^ self
   755 !
   755 !
   756 
   756 
   757 value:aSmallInteger
   757 value:aSmallInteger
   767      could have simply created a 4-byte largeinteger and normalize
   767      could have simply created a 4-byte largeinteger and normalize
   768      it; the code below does the normalize right away, avoiding the
   768      it; the code below does the normalize right away, avoiding the
   769      overhead of producing any intermediate byte-arrays (and the scanning)
   769      overhead of producing any intermediate byte-arrays (and the scanning)
   770     "
   770     "
   771     (aSmallInteger == 0) ifTrue: [
   771     (aSmallInteger == 0) ifTrue: [
   772         digitByteArray := ByteArray with:0.
   772 	digitByteArray := ByteArray with:0.
   773         sign := 0.
   773 	sign := 0.
   774         ^ self
   774 	^ self
   775     ].
   775     ].
   776     (aSmallInteger < 0) ifTrue: [
   776     (aSmallInteger < 0) ifTrue: [
   777         sign := -1.
   777 	sign := -1.
   778         absValue := aSmallInteger negated
   778 	absValue := aSmallInteger negated
   779     ] ifFalse: [
   779     ] ifFalse: [
   780         sign := 1.
   780 	sign := 1.
   781         absValue := aSmallInteger
   781 	absValue := aSmallInteger
   782     ].
   782     ].
   783     b1 := absValue bitAnd:16rFF.
   783     b1 := absValue bitAnd:16rFF.
   784     absValue := absValue bitShift:-8.
   784     absValue := absValue bitShift:-8.
   785     absValue == 0 ifTrue:[
   785     absValue == 0 ifTrue:[
   786         digitByteArray := ByteArray with:b1
   786 	digitByteArray := ByteArray with:b1
   787     ] ifFalse:[
   787     ] ifFalse:[
   788         b2 := absValue bitAnd:16rFF.
   788 	b2 := absValue bitAnd:16rFF.
   789         absValue := absValue bitShift:-8.
   789 	absValue := absValue bitShift:-8.
   790         absValue == 0 ifTrue:[
   790 	absValue == 0 ifTrue:[
   791             digitByteArray := ByteArray with:b1 with:b2
   791 	    digitByteArray := ByteArray with:b1 with:b2
   792         ] ifFalse:[
   792 	] ifFalse:[
   793             b3 := absValue bitAnd:16rFF.
   793 	    b3 := absValue bitAnd:16rFF.
   794             absValue := absValue bitShift:-8.
   794 	    absValue := absValue bitShift:-8.
   795             absValue == 0 ifTrue:[
   795 	    absValue == 0 ifTrue:[
   796                 digitByteArray := ByteArray with:b1 with:b2 with:b3
   796 		digitByteArray := ByteArray with:b1 with:b2 with:b3
   797             ] ifFalse:[
   797 	    ] ifFalse:[
   798                 digitByteArray := ByteArray with:b1 with:b2 with:b3 with:absValue
   798 		digitByteArray := ByteArray with:b1 with:b2 with:b3 with:absValue
   799             ]
   799 	    ]
   800         ]
   800 	]
   801     ]
   801     ]
   802 
   802 
   803     "Modified: 5.11.1996 / 16:15:39 / cg"
   803     "Modified: 5.11.1996 / 16:15:39 / cg"
   804 ! !
   804 ! !
   805 
   805 
   873 differenceFromInteger:anInteger
   873 differenceFromInteger:anInteger
   874     "sent, when anInteger does not know how to subtract the receiver.
   874     "sent, when anInteger does not know how to subtract the receiver.
   875      Return the result of 'anInteger - self'. The argument must be a SmallInteger."
   875      Return the result of 'anInteger - self'. The argument must be a SmallInteger."
   876 
   876 
   877     anInteger > 0 ifTrue:[
   877     anInteger > 0 ifTrue:[
   878         sign > 0 ifTrue:[
   878 	sign > 0 ifTrue:[
   879             ^ (self absFastMinus:anInteger) sign:-1
   879 	    ^ (self absFastMinus:anInteger) sign:-1
   880         ].
   880 	].
   881         ^ self absFastPlus:anInteger
   881 	^ self absFastPlus:anInteger
   882     ].
   882     ].
   883     anInteger == 0 ifTrue:[
   883     anInteger == 0 ifTrue:[
   884         ^ self negated
   884 	^ self negated
   885     ].
   885     ].
   886     sign > 0 ifTrue:[
   886     sign > 0 ifTrue:[
   887         ^ (self absFastPlus:anInteger negated) sign:-1
   887 	^ (self absFastPlus:anInteger negated) sign:-1
   888     ].
   888     ].
   889     ^ (self absFastMinus:anInteger) sign:-1
   889     ^ (self absFastMinus:anInteger) sign:-1
   890 
   890 
   891     "
   891     "
   892      12345678901234567890          
   892      12345678901234567890          
   919     anInteger == 0 ifTrue:[^ 0].
   919     anInteger == 0 ifTrue:[^ 0].
   920     anInteger == 1 ifTrue:[^ self].
   920     anInteger == 1 ifTrue:[^ self].
   921 
   921 
   922     num := anInteger abs.
   922     num := anInteger abs.
   923     (num > 16r3FFFFF) ifTrue:[
   923     (num > 16r3FFFFF) ifTrue:[
   924         "if num is too big (so that multiplying by a byte could create a Large)"
   924 	"if num is too big (so that multiplying by a byte could create a Large)"
   925 
   925 
   926         ^ anInteger retry:#* coercing:self
   926 	^ anInteger retry:#* coercing:self
   927     ].
   927     ].
   928 
   928 
   929     len := digitByteArray size.
   929     len := digitByteArray size.
   930 
   930 
   931     result := self class basicNew numberOfDigits:(len + 4).
   931     result := self class basicNew numberOfDigits:(len + 4).
   932 
   932 
   933     anInteger < 0 ifTrue:[
   933     anInteger < 0 ifTrue:[
   934         sign > 0 ifTrue:[
   934 	sign > 0 ifTrue:[
   935             result sign:-1
   935 	    result sign:-1
   936         ].
   936 	].
   937     ] ifFalse:[
   937     ] ifFalse:[
   938         sign < 0 ifTrue:[
   938 	sign < 0 ifTrue:[
   939             result sign:sign
   939 	    result sign:sign
   940         ]
   940 	]
   941     ].
   941     ].
   942 
   942 
   943     resultDigitByteArray := result digits.
   943     resultDigitByteArray := result digits.
   944 
   944 
   945     carry := 0.
   945     carry := 0.
   948     ok := false.
   948     ok := false.
   949 %{
   949 %{
   950     if (__bothSmallInteger(len, val)
   950     if (__bothSmallInteger(len, val)
   951      && __isByteArray(__INST(digitByteArray))
   951      && __isByteArray(__INST(digitByteArray))
   952      && __isByteArray(resultDigitByteArray)) {
   952      && __isByteArray(resultDigitByteArray)) {
   953         int _l = __intVal(len);
   953 	int _l = __intVal(len);
   954         int _v = __intVal(val);
   954 	int _v = __intVal(val);
   955         unsigned _carry = 0;
   955 	unsigned _carry = 0;
   956         unsigned _prod;
   956 	unsigned _prod;
   957         unsigned char *digitP = __ByteArrayInstPtr(__INST(digitByteArray))->ba_element;
   957 	unsigned char *digitP = __ByteArrayInstPtr(__INST(digitByteArray))->ba_element;
   958         unsigned char *resultP = __ByteArrayInstPtr(resultDigitByteArray)->ba_element;
   958 	unsigned char *resultP = __ByteArrayInstPtr(resultDigitByteArray)->ba_element;
   959 
   959 
   960 #if defined(i386) /* XXX actually: LSB_FIRST */
   960 #if defined(i386) /* XXX actually: LSB_FIRST */
   961         /* max: 0xFFFF * 0xFFFF -> 0xrFFFE0001
   961 	/* max: 0xFFFF * 0xFFFF -> 0xrFFFE0001
   962          * + maxCarry (0xFFFF)  -> 0xFFFF0000
   962 	 * + maxCarry (0xFFFF)  -> 0xFFFF0000
   963          */
   963 	 */
   964 
   964 
   965         if (_v <= 0xFFFF) {
   965 	if (_v <= 0xFFFF) {
   966             /* can do it short-wise */
   966 	    /* can do it short-wise */
   967             while (_l > 1) {
   967 	    while (_l > 1) {
   968                 _prod = ((unsigned short *)digitP)[0] * _v + _carry;
   968 		_prod = ((unsigned short *)digitP)[0] * _v + _carry;
   969                 ((unsigned short *)resultP)[0] = _prod & 0xFFFF;
   969 		((unsigned short *)resultP)[0] = _prod & 0xFFFF;
   970                 _carry = _prod >> 16;
   970 		_carry = _prod >> 16;
   971                 digitP += 2;
   971 		digitP += 2;
   972                 resultP += 2;
   972 		resultP += 2;
   973                 _l -= 2;
   973 		_l -= 2;
   974             }
   974 	    }
   975         }
   975 	}
   976 #endif
   976 #endif
   977         {
   977 	{
   978             while (_l-- > 0) {
   978 	    while (_l-- > 0) {
   979                 _prod = *digitP++ * _v + _carry;
   979 		_prod = *digitP++ * _v + _carry;
   980                 *resultP++ = _prod & 0xFF;
   980 		*resultP++ = _prod & 0xFF;
   981                 _carry = _prod >> 8;
   981 		_carry = _prod >> 8;
   982             }
   982 	    }
   983 
   983 
   984             while (_carry) {
   984 	    while (_carry) {
   985                 *resultP++ = _carry & 0xFF;
   985 		*resultP++ = _carry & 0xFF;
   986                 _carry >>= 8;
   986 		_carry >>= 8;
   987             }
   987 	    }
   988         }
   988 	}
   989         ok = true;
   989 	ok = true;
   990     }
   990     }
   991 %}.
   991 %}.
   992     "
   992     "
   993      fall back - normally not reached
   993      fall back - normally not reached
   994      (could make it a primitive-failure as well)
   994      (could make it a primitive-failure as well)
   995     "
   995     "
   996     ok ifFalse:[
   996     ok ifFalse:[
   997         1 to:len do:[:i |
   997 	1 to:len do:[:i |
   998             prod := (digitByteArray basicAt:i) * val + carry.
   998 	    prod := (digitByteArray basicAt:i) * val + carry.
   999             resultDigitByteArray basicAt:i put:(prod bitAnd:16rFF).
   999 	    resultDigitByteArray basicAt:i put:(prod bitAnd:16rFF).
  1000             carry := prod bitShift:-8.
  1000 	    carry := prod bitShift:-8.
  1001         ].
  1001 	].
  1002         [carry ~~ 0] whileTrue:[
  1002 	[carry ~~ 0] whileTrue:[
  1003             len := len + 1.
  1003 	    len := len + 1.
  1004             resultDigitByteArray basicAt:len put:(carry bitAnd:16rFF).
  1004 	    resultDigitByteArray basicAt:len put:(carry bitAnd:16rFF).
  1005             carry := carry bitShift:-8
  1005 	    carry := carry bitShift:-8
  1006         ].
  1006 	].
  1007     ].
  1007     ].
  1008     ^ result compressed
  1008     ^ result compressed
  1009 !
  1009 !
  1010 
  1010 
  1011 sumFromInteger:anInteger
  1011 sumFromInteger:anInteger
  1012     "sent, when anInteger does not know how to add the receiver.
  1012     "sent, when anInteger does not know how to add the receiver.
  1013      Return the sum of the receiver and the argument, (which must be a SmallInteger)"
  1013      Return the sum of the receiver and the argument, (which must be a SmallInteger)"
  1014 
  1014 
  1015     anInteger > 0 ifTrue:[
  1015     anInteger > 0 ifTrue:[
  1016         sign < 0 ifTrue:[
  1016 	sign < 0 ifTrue:[
  1017             ^ (self absFastMinus:anInteger) sign:-1
  1017 	    ^ (self absFastMinus:anInteger) sign:-1
  1018         ].
  1018 	].
  1019         ^ self absFastPlus:anInteger
  1019 	^ self absFastPlus:anInteger
  1020     ].
  1020     ].
  1021     anInteger == 0 ifTrue:[
  1021     anInteger == 0 ifTrue:[
  1022         ^ self
  1022 	^ self
  1023     ].
  1023     ].
  1024     sign < 0 ifTrue:[
  1024     sign < 0 ifTrue:[
  1025         ^ (self absFastPlus:anInteger abs) sign:-1
  1025 	^ (self absFastPlus:anInteger abs) sign:-1
  1026     ].
  1026     ].
  1027     ^ self absFastMinus:anInteger
  1027     ^ self absFastMinus:anInteger
  1028 
  1028 
  1029     "
  1029     "
  1030      12345678901234567890          
  1030      12345678901234567890          
  1062      quo
  1062      quo
  1063      count "{ Class: SmallInteger }"
  1063      count "{ Class: SmallInteger }"
  1064      digit "{ Class: SmallInteger }" |
  1064      digit "{ Class: SmallInteger }" |
  1065 
  1065 
  1066     anInteger == 0 ifTrue:[
  1066     anInteger == 0 ifTrue:[
  1067         ^ DivisionByZeroSignal raise
  1067 	^ DivisionByZeroSignal raise
  1068     ].
  1068     ].
  1069 
  1069 
  1070     self = anInteger ifTrue:[
  1070     self = anInteger ifTrue:[
  1071         ^ Array with:1 with:0
  1071 	^ Array with:1 with:0
  1072     ].
  1072     ].
  1073 
  1073 
  1074     tmp1 := self simpleDeepCopy.
  1074     tmp1 := self simpleDeepCopy.
  1075     tmp1 sign:1.
  1075     tmp1 sign:1.
  1076     tmp2 := anInteger simpleDeepCopy.
  1076     tmp2 := anInteger simpleDeepCopy.
  1077     tmp2 sign:1.
  1077     tmp2 sign:1.
  1078 
  1078 
  1079     (tmp1 < tmp2) ifTrue:[
  1079     (tmp1 < tmp2) ifTrue:[
  1080         ^ Array with:0 with:tmp1 
  1080 	^ Array with:0 with:tmp1 
  1081     ].
  1081     ].
  1082 
  1082 
  1083     count := 0.
  1083     count := 0.
  1084     [tmp2 absLess: tmp1] whileTrue:[
  1084     [tmp2 absLess: tmp1] whileTrue:[
  1085         tmp2 mul2.
  1085 	tmp2 mul2.
  1086         count := count + 1
  1086 	count := count + 1
  1087     ].
  1087     ].
  1088 
  1088 
  1089     tmp2 div2.
  1089     tmp2 div2.
  1090 
  1090 
  1091     quo := 0 asLargeInteger. 
  1091     quo := 0 asLargeInteger. 
  1092     quo sign:1.
  1092     quo sign:1.
  1093 
  1093 
  1094     [count == 0] whileFalse:[
  1094     [count == 0] whileFalse:[
  1095         quo mul2.
  1095 	quo mul2.
  1096         (tmp1 absLess:tmp2) ifFalse:[
  1096 	(tmp1 absLess:tmp2) ifFalse:[
  1097             quo digits at:1 put:((quo digits at:1) bitOr:1).
  1097 	    quo digits at:1 put:((quo digits at:1) bitOr:1).
  1098             (tmp1 absSubtract: tmp2) ifFalse:[
  1098 	    (tmp1 absSubtract: tmp2) ifFalse:[
  1099                 "/ difference is zero; continue shifting
  1099 		"/ difference is zero; continue shifting
  1100                 count := count - 1.
  1100 		count := count - 1.
  1101                 [count >= 8] whileTrue:[
  1101 		[count >= 8] whileTrue:[
  1102                     quo mul256.
  1102 		    quo mul256.
  1103                     count := count - 8
  1103 		    count := count - 8
  1104                 ].
  1104 		].
  1105                 [count == 0] whileFalse:[
  1105 		[count == 0] whileFalse:[
  1106                     quo mul2.
  1106 		    quo mul2.
  1107                     count := count - 1.
  1107 		    count := count - 1.
  1108                 ].
  1108 		].
  1109                 ^ Array with:quo compressed with:tmp1 compressed
  1109 		^ Array with:quo compressed with:tmp1 compressed
  1110             ].
  1110 	    ].
  1111         ].
  1111 	].
  1112         tmp2 div2.
  1112 	tmp2 div2.
  1113         count := count - 1
  1113 	count := count - 1
  1114     ].
  1114     ].
  1115     ^ Array with:quo compressed with:tmp1 compressed
  1115     ^ Array with:quo compressed with:tmp1 compressed
  1116 
  1116 
  1117     "Modified: 5.11.1996 / 18:40:24 / cg"
  1117     "Modified: 5.11.1996 / 18:40:24 / cg"
  1118 !
  1118 !
  1155      count    "{ Class: SmallInteger }"
  1155      count    "{ Class: SmallInteger }"
  1156      newDigitByteArray result
  1156      newDigitByteArray result
  1157      ok|
  1157      ok|
  1158 
  1158 
  1159     aPositiveSmallInteger == 0 ifTrue:[
  1159     aPositiveSmallInteger == 0 ifTrue:[
  1160         ^ DivisionByZeroSignal raise
  1160 	^ DivisionByZeroSignal raise
  1161     ].
  1161     ].
  1162 
  1162 
  1163 "This cannot happen (if always normalized)
  1163 "This cannot happen (if always normalized)
  1164     self < aPositiveSmallInteger ifTrue:[
  1164     self < aPositiveSmallInteger ifTrue:[
  1165         ^ Array with:0 with:self
  1165 	^ Array with:0 with:self
  1166     ].
  1166     ].
  1167 "
  1167 "
  1168     count := digitByteArray size.
  1168     count := digitByteArray size.
  1169     result := self class basicNew numberOfDigits:count.
  1169     result := self class basicNew numberOfDigits:count.
  1170     newDigitByteArray := result digits.
  1170     newDigitByteArray := result digits.
  1175     __digits = __INST(digitByteArray);
  1175     __digits = __INST(digitByteArray);
  1176 
  1176 
  1177     if (__isByteArray(__digits)
  1177     if (__isByteArray(__digits)
  1178      && __isByteArray(newDigitByteArray)
  1178      && __isByteArray(newDigitByteArray)
  1179      && __bothSmallInteger(count, aPositiveSmallInteger)) {
  1179      && __bothSmallInteger(count, aPositiveSmallInteger)) {
  1180         unsigned int rest = 0;
  1180 	unsigned int rest = 0;
  1181         int index = __intVal(count);
  1181 	int index = __intVal(count);
  1182         int index0;
  1182 	int index0;
  1183         unsigned divisor = __intVal(aPositiveSmallInteger);
  1183 	unsigned divisor = __intVal(aPositiveSmallInteger);
  1184         unsigned char *digitBytes = __ByteArrayInstPtr(__digits)->ba_element;
  1184 	unsigned char *digitBytes = __ByteArrayInstPtr(__digits)->ba_element;
  1185         unsigned char *resultBytes = __ByteArrayInstPtr(newDigitByteArray)->ba_element;
  1185 	unsigned char *resultBytes = __ByteArrayInstPtr(newDigitByteArray)->ba_element;
  1186 
  1186 
  1187         index0 = index;
  1187 	index0 = index;
  1188 
  1188 
  1189 /*
  1189 /*
  1190         if (divisor < 0xFFFF) {
  1190 	if (divisor < 0xFFFF) {
  1191             while (index > 1) {
  1191 	    while (index > 1) {
  1192                 unsigned int t;
  1192 		unsigned int t;
  1193                 unsigned div;
  1193 		unsigned div;
  1194 
  1194 
  1195                 index--;
  1195 		index--;
  1196                 t = digitBytes[index];
  1196 		t = digitBytes[index];
  1197                 index--;
  1197 		index--;
  1198                 t = (t << 8) | digitBytes[index];
  1198 		t = (t << 8) | digitBytes[index];
  1199                 t = t | (rest << 16);
  1199 		t = t | (rest << 16);
  1200                 div = t / divisor;
  1200 		div = t / divisor;
  1201                 rest = t % divisor;
  1201 		rest = t % divisor;
  1202                 resultBytes[index+1] = (div >> 8);
  1202 		resultBytes[index+1] = (div >> 8);
  1203                 resultBytes[index] = (div & 0xFF);
  1203 		resultBytes[index] = (div & 0xFF);
  1204             }
  1204 	    }
  1205         }
  1205 	}
  1206 */
  1206 */
  1207         while (index > 0) {
  1207 	while (index > 0) {
  1208             unsigned int t;
  1208 	    unsigned int t;
  1209 
  1209 
  1210             index--;
  1210 	    index--;
  1211             t = digitBytes[index];
  1211 	    t = digitBytes[index];
  1212             t = t | (rest << 8);
  1212 	    t = t | (rest << 8);
  1213             resultBytes[index] = t / divisor;
  1213 	    resultBytes[index] = t / divisor;
  1214             rest = t % divisor;
  1214 	    rest = t % divisor;
  1215         }
  1215 	}
  1216         prevRest = __MKSMALLINT(rest);
  1216 	prevRest = __MKSMALLINT(rest);
  1217         ok = true;
  1217 	ok = true;
  1218 
  1218 
  1219         /*
  1219 	/*
  1220          * no need to normalize ?
  1220 	 * no need to normalize ?
  1221          */
  1221 	 */
  1222         if ((index0 > 4)
  1222 	if ((index0 > 4)
  1223          && (resultBytes[index0-1])) {
  1223 	 && (resultBytes[index0-1])) {
  1224             RETURN ( __ARRAY_WITH2(result, prevRest));
  1224 	    RETURN ( __ARRAY_WITH2(result, prevRest));
  1225         }
  1225 	}
  1226     }
  1226     }
  1227 %}.
  1227 %}.
  1228     "
  1228     "
  1229      slow code - not normally reached
  1229      slow code - not normally reached
  1230      (could also do a primitiveFailure here)
  1230      (could also do a primitiveFailure here)
  1231     "
  1231     "
  1232     ok ifFalse:[
  1232     ok ifFalse:[
  1233         self primitiveFailed
  1233 	self primitiveFailed
  1234     ].
  1234     ].
  1235 
  1235 
  1236     ^ Array with:result compressed with:prevRest
  1236     ^ Array with:result compressed with:prevRest
  1237 !
  1237 !
  1238 
  1238 
  1253 
  1253 
  1254     index := 1.
  1254     index := 1.
  1255     borrow := aSmallInteger abs.
  1255     borrow := aSmallInteger abs.
  1256 
  1256 
  1257     [borrow ~~ 0] whileTrue:[
  1257     [borrow ~~ 0] whileTrue:[
  1258         (index <= len) ifTrue:[
  1258 	(index <= len) ifTrue:[
  1259             diff := (digitByteArray basicAt:index) - (borrow bitAnd:16rFF).
  1259 	    diff := (digitByteArray basicAt:index) - (borrow bitAnd:16rFF).
  1260             borrow := borrow bitShift:-8.
  1260 	    borrow := borrow bitShift:-8.
  1261             diff < 0 ifTrue:[
  1261 	    diff < 0 ifTrue:[
  1262                 diff := diff + 256.
  1262 		diff := diff + 256.
  1263                 borrow := borrow + 1.
  1263 		borrow := borrow + 1.
  1264             ]
  1264 	    ]
  1265         ] ifFalse:[
  1265 	] ifFalse:[
  1266             diff := borrow bitAnd:255.
  1266 	    diff := borrow bitAnd:255.
  1267             borrow := borrow bitShift:-8.
  1267 	    borrow := borrow bitShift:-8.
  1268         ].
  1268 	].
  1269         resultDigitByteArray basicAt:index put:(lastDigit := diff).
  1269 	resultDigitByteArray basicAt:index put:(lastDigit := diff).
  1270         index := index + 1
  1270 	index := index + 1
  1271     ].
  1271     ].
  1272     [index <= len] whileTrue:[
  1272     [index <= len] whileTrue:[
  1273         resultDigitByteArray basicAt:index put:(lastDigit := digitByteArray basicAt:index).
  1273 	resultDigitByteArray basicAt:index put:(lastDigit := digitByteArray basicAt:index).
  1274         index := index + 1
  1274 	index := index + 1
  1275     ].
  1275     ].
  1276 
  1276 
  1277     lastDigit == 0 ifTrue:[
  1277     lastDigit == 0 ifTrue:[
  1278         ^ result compressed
  1278 	^ result compressed
  1279     ].
  1279     ].
  1280     ^ result
  1280     ^ result
  1281 
  1281 
  1282     "                                                          
  1282     "                                                          
  1283      12345678900000000000 absFastMinus:1       
  1283      12345678900000000000 absFastMinus:1       
  1306 
  1306 
  1307     index := 1.
  1307     index := 1.
  1308     carry := aSmallInteger abs.
  1308     carry := aSmallInteger abs.
  1309 
  1309 
  1310     [carry ~~ 0] whileTrue:[
  1310     [carry ~~ 0] whileTrue:[
  1311         (index <= len) ifTrue:[
  1311 	(index <= len) ifTrue:[
  1312             carry := (digitByteArray basicAt:index) + carry.
  1312 	    carry := (digitByteArray basicAt:index) + carry.
  1313         ].
  1313 	].
  1314         resultDigitByteArray basicAt:index put:(lastDigit := carry bitAnd:16rFF).
  1314 	resultDigitByteArray basicAt:index put:(lastDigit := carry bitAnd:16rFF).
  1315         carry := carry bitShift:-8.
  1315 	carry := carry bitShift:-8.
  1316         index := index + 1
  1316 	index := index + 1
  1317     ].
  1317     ].
  1318     [index <= len] whileTrue:[
  1318     [index <= len] whileTrue:[
  1319         resultDigitByteArray basicAt:index put:(lastDigit := digitByteArray basicAt:index).
  1319 	resultDigitByteArray basicAt:index put:(lastDigit := digitByteArray basicAt:index).
  1320         index := index + 1
  1320 	index := index + 1
  1321     ].
  1321     ].
  1322 
  1322 
  1323     lastDigit == 0 ifTrue:[
  1323     lastDigit == 0 ifTrue:[
  1324         ^ result compressed
  1324 	^ result compressed
  1325     ].
  1325     ].
  1326     ^ result
  1326     ^ result
  1327 
  1327 
  1328     "Modified: 5.11.1996 / 14:09:19 / cg"
  1328     "Modified: 5.11.1996 / 14:09:19 / cg"
  1329 !
  1329 !
  1341     myLen := digitByteArray size.
  1341     myLen := digitByteArray size.
  1342     otherDigitByteArray := aLargeInteger digits.
  1342     otherDigitByteArray := aLargeInteger digits.
  1343     otherLen := otherDigitByteArray size.
  1343     otherLen := otherDigitByteArray size.
  1344 
  1344 
  1345     [(digitByteArray basicAt:myLen) == 0] whileTrue:[
  1345     [(digitByteArray basicAt:myLen) == 0] whileTrue:[
  1346         myLen := myLen - 1
  1346 	myLen := myLen - 1
  1347     ].
  1347     ].
  1348     [(otherDigitByteArray basicAt:otherLen) == 0] whileTrue:[
  1348     [(otherDigitByteArray basicAt:otherLen) == 0] whileTrue:[
  1349         otherLen := otherLen - 1
  1349 	otherLen := otherLen - 1
  1350     ].
  1350     ].
  1351     (myLen < otherLen) ifTrue:[^ true].
  1351     (myLen < otherLen) ifTrue:[^ true].
  1352     (myLen > otherLen) ifTrue:[^ false].
  1352     (myLen > otherLen) ifTrue:[^ false].
  1353 
  1353 
  1354     [myLen > 0] whileTrue:[
  1354     [myLen > 0] whileTrue:[
  1355         d1 := digitByteArray basicAt:myLen.
  1355 	d1 := digitByteArray basicAt:myLen.
  1356         d2 := otherDigitByteArray basicAt:myLen.
  1356 	d2 := otherDigitByteArray basicAt:myLen.
  1357         d1 == d2 ifFalse:[
  1357 	d1 == d2 ifFalse:[
  1358             (d1 < d2) ifTrue:[^ true].
  1358 	    (d1 < d2) ifTrue:[^ true].
  1359             ^ false
  1359 	    ^ false
  1360         ].
  1360 	].
  1361         myLen := myLen - 1
  1361 	myLen := myLen - 1
  1362     ].
  1362     ].
  1363     ^ false
  1363     ^ false
  1364 
  1364 
  1365     "Modified: 5.11.1996 / 18:37:27 / cg"
  1365     "Modified: 5.11.1996 / 18:37:27 / cg"
  1366 !
  1366 !
  1389     index := 1.
  1389     index := 1.
  1390     borrow := 0.
  1390     borrow := 0.
  1391 
  1391 
  1392     done := false.
  1392     done := false.
  1393     [done] whileFalse:[
  1393     [done] whileFalse:[
  1394         diff := borrow.
  1394 	diff := borrow.
  1395         (index <= len1) ifTrue:[
  1395 	(index <= len1) ifTrue:[
  1396             diff := diff + (digitByteArray basicAt:index).
  1396 	    diff := diff + (digitByteArray basicAt:index).
  1397             (index <= len2) ifTrue:[
  1397 	    (index <= len2) ifTrue:[
  1398                 diff := diff - (otherDigitByteArray basicAt:index)
  1398 		diff := diff - (otherDigitByteArray basicAt:index)
  1399             ]
  1399 	    ]
  1400         ] ifFalse:[
  1400 	] ifFalse:[
  1401             (index <= len2) ifTrue:[
  1401 	    (index <= len2) ifTrue:[
  1402                 diff := diff - (otherDigitByteArray basicAt:index)
  1402 		diff := diff - (otherDigitByteArray basicAt:index)
  1403             ] ifFalse:[
  1403 	    ] ifFalse:[
  1404                 "end reached"
  1404 		"end reached"
  1405                 done := true
  1405 		done := true
  1406             ]
  1406 	    ]
  1407         ].
  1407 	].
  1408 
  1408 
  1409         "/ workaround for
  1409 	"/ workaround for
  1410         "/ gcc code generator bug
  1410 	"/ gcc code generator bug
  1411 
  1411 
  1412         (diff >= 0) ifTrue:[
  1412 	(diff >= 0) ifTrue:[
  1413             borrow := 0
  1413 	    borrow := 0
  1414         ] ifFalse:[
  1414 	] ifFalse:[
  1415             borrow := -1.
  1415 	    borrow := -1.
  1416             diff := diff + 16r100
  1416 	    diff := diff + 16r100
  1417         ].
  1417 	].
  1418 
  1418 
  1419 "/        (diff < 0) ifTrue:[
  1419 "/        (diff < 0) ifTrue:[
  1420 "/            borrow := -1.
  1420 "/            borrow := -1.
  1421 "/            diff := diff + 16r100
  1421 "/            diff := diff + 16r100
  1422 "/        ] ifFalse:[
  1422 "/        ] ifFalse:[
  1423 "/            borrow := 0
  1423 "/            borrow := 0
  1424 "/        ].
  1424 "/        ].
  1425 
  1425 
  1426         resultDigitByteArray basicAt:index put:diff.
  1426 	resultDigitByteArray basicAt:index put:diff.
  1427         index := index + 1
  1427 	index := index + 1
  1428     ].
  1428     ].
  1429 
  1429 
  1430     (borrow ~~ 0) ifTrue:[
  1430     (borrow ~~ 0) ifTrue:[
  1431         "/ must generate 255's complement
  1431 	"/ must generate 255's complement
  1432 
  1432 
  1433         result sign:-1.
  1433 	result sign:-1.
  1434         [index <= lResult] whileTrue:[
  1434 	[index <= lResult] whileTrue:[
  1435             resultDigitByteArray basicAt:index put:16rFF.
  1435 	    resultDigitByteArray basicAt:index put:16rFF.
  1436             index := index + 1.
  1436 	    index := index + 1.
  1437         ].
  1437 	].
  1438         index := resultDigitByteArray size.
  1438 	index := resultDigitByteArray size.
  1439         [index > 0] whileTrue:[
  1439 	[index > 0] whileTrue:[
  1440             resultDigitByteArray basicAt:index put:(255 - (resultDigitByteArray at:index)).
  1440 	    resultDigitByteArray basicAt:index put:(255 - (resultDigitByteArray at:index)).
  1441             index := index -1.
  1441 	    index := index -1.
  1442         ].
  1442 	].
  1443 
  1443 
  1444         index := 1.
  1444 	index := 1.
  1445         carry := 1.
  1445 	carry := 1.
  1446         [carry ~~ 0] whileTrue:[
  1446 	[carry ~~ 0] whileTrue:[
  1447             (index <= lResult) ifTrue:[
  1447 	    (index <= lResult) ifTrue:[
  1448                 carry := (resultDigitByteArray basicAt:index) + carry.
  1448 		carry := (resultDigitByteArray basicAt:index) + carry.
  1449             ].
  1449 	    ].
  1450             resultDigitByteArray basicAt:index put:(carry bitAnd:16rFF).
  1450 	    resultDigitByteArray basicAt:index put:(carry bitAnd:16rFF).
  1451             carry := carry bitShift:-8.
  1451 	    carry := carry bitShift:-8.
  1452             index := index + 1
  1452 	    index := index + 1
  1453         ].
  1453 	].
  1454     ].
  1454     ].
  1455     ^ result compressed
  1455     ^ result compressed
  1456 
  1456 
  1457     "Modified: 5.11.1996 / 14:09:25 / cg"
  1457     "Modified: 5.11.1996 / 14:09:25 / cg"
  1458 !
  1458 !
  1479 %{
  1479 %{
  1480     if (__isByteArray(__INST(digitByteArray))
  1480     if (__isByteArray(__INST(digitByteArray))
  1481      && __isByteArray(otherDigitByteArray)
  1481      && __isByteArray(otherDigitByteArray)
  1482      && __isByteArray(resultDigitByteArray)
  1482      && __isByteArray(resultDigitByteArray)
  1483      && __bothSmallInteger(len1, len2)) {
  1483      && __bothSmallInteger(len1, len2)) {
  1484         unsigned char *myBytes = __ByteArrayInstPtr(__INST(digitByteArray))->ba_element;
  1484 	unsigned char *myBytes = __ByteArrayInstPtr(__INST(digitByteArray))->ba_element;
  1485         unsigned char *otherBytes = __ByteArrayInstPtr(otherDigitByteArray)->ba_element;
  1485 	unsigned char *otherBytes = __ByteArrayInstPtr(otherDigitByteArray)->ba_element;
  1486         unsigned char *resultBytes = __ByteArrayInstPtr(resultDigitByteArray)->ba_element;
  1486 	unsigned char *resultBytes = __ByteArrayInstPtr(resultDigitByteArray)->ba_element;
  1487         int _index1, _index2, _dstIndex, _idx;
  1487 	int _index1, _index2, _dstIndex, _idx;
  1488         unsigned _prod, _carry, _v;
  1488 	unsigned _prod, _carry, _v;
  1489 
  1489 
  1490         for (_index1 = 0; _index1 < __intVal(len1); _index1++) {
  1490 	for (_index1 = 0; _index1 < __intVal(len1); _index1++) {
  1491             for (_index2 = 0; _index2 < __intVal(len2); _index2++) {
  1491 	    for (_index2 = 0; _index2 < __intVal(len2); _index2++) {
  1492                 _dstIndex = _index1 + _index2;
  1492 		_dstIndex = _index1 + _index2;
  1493                 _prod = myBytes[_index1] * otherBytes[_index2];
  1493 		_prod = myBytes[_index1] * otherBytes[_index2];
  1494                 _prod += resultBytes[_dstIndex];
  1494 		_prod += resultBytes[_dstIndex];
  1495                 resultBytes[_dstIndex] = _prod & 0xFF;
  1495 		resultBytes[_dstIndex] = _prod & 0xFF;
  1496                 _carry = _prod >> 8;
  1496 		_carry = _prod >> 8;
  1497                 if (_carry) {
  1497 		if (_carry) {
  1498                     _idx = _dstIndex + 1;
  1498 		    _idx = _dstIndex + 1;
  1499                     while (_carry) {
  1499 		    while (_carry) {
  1500                         _v = resultBytes[_idx] + _carry;
  1500 			_v = resultBytes[_idx] + _carry;
  1501                         resultBytes[_idx] = _v & 0xFF;
  1501 			resultBytes[_idx] = _v & 0xFF;
  1502                         _carry = _v >> 8;
  1502 			_carry = _v >> 8;
  1503                         _idx = _idx + 1;
  1503 			_idx = _idx + 1;
  1504                     }
  1504 		    }
  1505                 }
  1505 		}
  1506             }
  1506 	    }
  1507         }
  1507 	}
  1508         ok = true;
  1508 	ok = true;
  1509     }
  1509     }
  1510 %}.
  1510 %}.
  1511     ok ifFalse:[
  1511     ok ifFalse:[
  1512         1 to:len1 do:[:index1 |
  1512 	1 to:len1 do:[:index1 |
  1513             1 to:len2 do:[:index2 |
  1513 	    1 to:len2 do:[:index2 |
  1514                 dstIndex := index1 + index2 - 1.
  1514 		dstIndex := index1 + index2 - 1.
  1515                 prod := (digitByteArray basicAt:index1) * (otherDigitByteArray basicAt:index2).
  1515 		prod := (digitByteArray basicAt:index1) * (otherDigitByteArray basicAt:index2).
  1516                 prod := prod + (resultDigitByteArray basicAt:dstIndex).
  1516 		prod := prod + (resultDigitByteArray basicAt:dstIndex).
  1517                 resultDigitByteArray basicAt:dstIndex put:(prod bitAnd:16rFF).
  1517 		resultDigitByteArray basicAt:dstIndex put:(prod bitAnd:16rFF).
  1518                 carry := prod bitShift:-8.
  1518 		carry := prod bitShift:-8.
  1519                 carry ~~ 0 ifTrue:[
  1519 		carry ~~ 0 ifTrue:[
  1520                     idx := dstIndex + 1.
  1520 		    idx := dstIndex + 1.
  1521                     [carry ~~ 0] whileTrue:[
  1521 		    [carry ~~ 0] whileTrue:[
  1522                         v := (resultDigitByteArray basicAt:idx) + carry.
  1522 			v := (resultDigitByteArray basicAt:idx) + carry.
  1523                         resultDigitByteArray basicAt:idx put:(v bitAnd:255).
  1523 			resultDigitByteArray basicAt:idx put:(v bitAnd:255).
  1524                         carry := v bitShift:-8.
  1524 			carry := v bitShift:-8.
  1525                         idx := idx + 1
  1525 			idx := idx + 1
  1526                     ]
  1526 		    ]
  1527                 ]
  1527 		]
  1528             ]
  1528 	    ]
  1529         ].
  1529 	].
  1530     ].
  1530     ].
  1531     ^ result compressed
  1531     ^ result compressed
  1532 !
  1532 !
  1533 
  1533 
  1534 absPlus:aLargeInteger
  1534 absPlus:aLargeInteger
  1551     index := 1.
  1551     index := 1.
  1552     carry := 0.
  1552     carry := 0.
  1553 
  1553 
  1554     done := false.
  1554     done := false.
  1555     [done] whileFalse:[
  1555     [done] whileFalse:[
  1556         sum := carry.
  1556 	sum := carry.
  1557         (index <= len1) ifTrue:[
  1557 	(index <= len1) ifTrue:[
  1558             sum := sum + (digitByteArray basicAt:index).
  1558 	    sum := sum + (digitByteArray basicAt:index).
  1559             (index <= len2) ifTrue:[
  1559 	    (index <= len2) ifTrue:[
  1560                 sum := sum + (otherDigitByteArray basicAt:index)
  1560 		sum := sum + (otherDigitByteArray basicAt:index)
  1561             ]
  1561 	    ]
  1562         ] ifFalse:[
  1562 	] ifFalse:[
  1563             (index <= len2) ifTrue:[
  1563 	    (index <= len2) ifTrue:[
  1564                 sum := sum + (otherDigitByteArray basicAt:index)
  1564 		sum := sum + (otherDigitByteArray basicAt:index)
  1565             ] ifFalse:[
  1565 	    ] ifFalse:[
  1566                 "end reached"
  1566 		"end reached"
  1567                 done := true
  1567 		done := true
  1568             ]
  1568 	    ]
  1569         ].
  1569 	].
  1570         (sum >= 16r100) ifTrue:[
  1570 	(sum >= 16r100) ifTrue:[
  1571             carry := 1.
  1571 	    carry := 1.
  1572             sum := sum - 16r100
  1572 	    sum := sum - 16r100
  1573         ] ifFalse:[
  1573 	] ifFalse:[
  1574             carry := 0
  1574 	    carry := 0
  1575         ].
  1575 	].
  1576         resultDigitByteArray basicAt:index put:sum.
  1576 	resultDigitByteArray basicAt:index put:sum.
  1577         index := index + 1
  1577 	index := index + 1
  1578     ].
  1578     ].
  1579     ^ result compressed
  1579     ^ result compressed
  1580 
  1580 
  1581     "Modified: 5.11.1996 / 14:09:34 / cg"
  1581     "Modified: 5.11.1996 / 14:09:34 / cg"
  1582 !
  1582 !
  1599 
  1599 
  1600     len1 := digitByteArray size.
  1600     len1 := digitByteArray size.
  1601     otherDigitByteArray := aLargeInteger digits.
  1601     otherDigitByteArray := aLargeInteger digits.
  1602     len2 := otherDigitByteArray size.
  1602     len2 := otherDigitByteArray size.
  1603     len2 > len1 ifTrue:[
  1603     len2 > len1 ifTrue:[
  1604         [(otherDigitByteArray at:len2) == 0] whileTrue:[
  1604 	[(otherDigitByteArray at:len2) == 0] whileTrue:[
  1605             len2 := len2 - 1
  1605 	    len2 := len2 - 1
  1606         ].
  1606 	].
  1607         len2 > len1 ifTrue:[
  1607 	len2 > len1 ifTrue:[
  1608             self halt "/ may not be called that way
  1608 	    self halt "/ may not be called that way
  1609         ].
  1609 	].
  1610     ].
  1610     ].
  1611 
  1611 
  1612     nonZero := false.
  1612     nonZero := false.
  1613     index := 1.
  1613     index := 1.
  1614     borrow := 0.
  1614     borrow := 0.
  1615 
  1615 
  1616     done := false.
  1616     done := false.
  1617     [index <= len1] whileTrue:[
  1617     [index <= len1] whileTrue:[
  1618         diff := borrow.
  1618 	diff := borrow.
  1619         diff := diff + (digitByteArray basicAt:index).
  1619 	diff := diff + (digitByteArray basicAt:index).
  1620         index <= len2 ifTrue:[
  1620 	index <= len2 ifTrue:[
  1621             diff := diff - (otherDigitByteArray basicAt:index).
  1621 	    diff := diff - (otherDigitByteArray basicAt:index).
  1622         ].
  1622 	].
  1623 
  1623 
  1624         "/ workaround for
  1624 	"/ workaround for
  1625         "/ gcc code generator bug
  1625 	"/ gcc code generator bug
  1626 
  1626 
  1627         (diff >= 0) ifTrue:[
  1627 	(diff >= 0) ifTrue:[
  1628             borrow := 0
  1628 	    borrow := 0
  1629         ] ifFalse:[
  1629 	] ifFalse:[
  1630             borrow := -1.
  1630 	    borrow := -1.
  1631             diff := diff + 16r100
  1631 	    diff := diff + 16r100
  1632         ].
  1632 	].
  1633         diff ~~ 0 ifTrue:[
  1633 	diff ~~ 0 ifTrue:[
  1634             nonZero := true
  1634 	    nonZero := true
  1635         ].
  1635 	].
  1636         digitByteArray basicAt:index put:diff.
  1636 	digitByteArray basicAt:index put:diff.
  1637         index := index + 1
  1637 	index := index + 1
  1638     ].
  1638     ].
  1639     ^ nonZero
  1639     ^ nonZero
  1640 
  1640 
  1641     "Created: 5.11.1996 / 16:23:47 / cg"
  1641     "Created: 5.11.1996 / 16:23:47 / cg"
  1642     "Modified: 5.11.1996 / 18:56:50 / cg"
  1642     "Modified: 5.11.1996 / 18:56:50 / cg"
  1649 
  1649 
  1650 %{  /* NOCONTEXT */
  1650 %{  /* NOCONTEXT */
  1651     OBJ __digits = __INST(digitByteArray);
  1651     OBJ __digits = __INST(digitByteArray);
  1652 
  1652 
  1653     if (__isByteArray(__digits)) {
  1653     if (__isByteArray(__digits)) {
  1654         int __nBytes = __byteArraySize(__digits);
  1654 	int __nBytes = __byteArraySize(__digits);
  1655         unsigned char *__bp = __ByteArrayInstPtr(__digits)->ba_element;
  1655 	unsigned char *__bp = __ByteArrayInstPtr(__digits)->ba_element;
  1656         unsigned __this, __next;
  1656 	unsigned __this, __next;
  1657         int __idx;
  1657 	int __idx;
  1658 
  1658 
  1659         if (__nBytes == 1) {
  1659 	if (__nBytes == 1) {
  1660             __bp[0] >>= 1;
  1660 	    __bp[0] >>= 1;
  1661             RETURN (self);
  1661 	    RETURN (self);
  1662         }
  1662 	}
  1663 
  1663 
  1664         __idx = 1;
  1664 	__idx = 1;
  1665 
  1665 
  1666         if ((__idx+4) < __nBytes) {
  1666 	if ((__idx+4) < __nBytes) {
  1667             __this = ((unsigned long *)__bp)[0];
  1667 	    __this = ((unsigned long *)__bp)[0];
  1668 
  1668 
  1669             while ((__idx+4) < __nBytes) {
  1669 	    while ((__idx+4) < __nBytes) {
  1670                 __next = ((unsigned long *)__bp)[1];
  1670 		__next = ((unsigned long *)__bp)[1];
  1671                 __this >>= 1;
  1671 		__this >>= 1;
  1672                 __this |= __next << 31;
  1672 		__this |= __next << 31;
  1673                 ((unsigned long *)__bp)[0] = __this;
  1673 		((unsigned long *)__bp)[0] = __this;
  1674                 __this = __next;
  1674 		__this = __next;
  1675                 __bp += 4;
  1675 		__bp += 4;
  1676                 __idx += 4;
  1676 		__idx += 4;
  1677             }
  1677 	    }
  1678         }
  1678 	}
  1679 
  1679 
  1680         __this = __bp[0];
  1680 	__this = __bp[0];
  1681         while (__idx < __nBytes) {
  1681 	while (__idx < __nBytes) {
  1682             __next = __bp[1];
  1682 	    __next = __bp[1];
  1683             __this >>= 1;
  1683 	    __this >>= 1;
  1684             __this |= __next << 7;
  1684 	    __this |= __next << 7;
  1685             __bp[0] = __this;
  1685 	    __bp[0] = __this;
  1686             __this = __next;
  1686 	    __this = __next;
  1687             __bp++;
  1687 	    __bp++;
  1688             __idx++;
  1688 	    __idx++;
  1689         }
  1689 	}
  1690         __bp[0] = __this >> 1;
  1690 	__bp[0] = __this >> 1;
  1691         RETURN (self);
  1691 	RETURN (self);
  1692     }
  1692     }
  1693 %}.
  1693 %}.
  1694     self primitiveFailed
  1694     self primitiveFailed
  1695 
  1695 
  1696     "
  1696     "
  1711 
  1711 
  1712     nBytes := digitByteArray size.
  1712     nBytes := digitByteArray size.
  1713 
  1713 
  1714     b := digitByteArray at:nBytes.
  1714     b := digitByteArray at:nBytes.
  1715     (b bitAnd:16r80) ~~ 0 ifTrue:[
  1715     (b bitAnd:16r80) ~~ 0 ifTrue:[
  1716         "/ need another byte
  1716 	"/ need another byte
  1717         nBytes := nBytes + 1.
  1717 	nBytes := nBytes + 1.
  1718         t := ByteArray uninitializedNew:nBytes.
  1718 	t := ByteArray uninitializedNew:nBytes.
  1719         t replaceFrom:1 with:digitByteArray.
  1719 	t replaceFrom:1 with:digitByteArray startingAt:1.
  1720         t at:nBytes put:0.
  1720 	t at:nBytes put:0.
  1721         digitByteArray := t.
  1721 	digitByteArray := t.
  1722     ].
  1722     ].
  1723 
  1723 
  1724 %{
  1724 %{
  1725     OBJ __digits = __INST(digitByteArray);
  1725     OBJ __digits = __INST(digitByteArray);
  1726 
  1726 
  1727     if (__isByteArray(__digits)) {
  1727     if (__isByteArray(__digits)) {
  1728         int __nBytes = __intVal(nBytes);
  1728 	int __nBytes = __intVal(nBytes);
  1729         unsigned char *__bp = __ByteArrayInstPtr(__digits)->ba_element;
  1729 	unsigned char *__bp = __ByteArrayInstPtr(__digits)->ba_element;
  1730         unsigned __carry = 0, __newCarry,  __this;
  1730 	unsigned __carry = 0, __newCarry,  __this;
  1731         int __idx;
  1731 	int __idx;
  1732 
  1732 
  1733         while (__nBytes >= 4) {
  1733 	while (__nBytes >= 4) {
  1734             __this = ((unsigned long *)__bp)[0];
  1734 	    __this = ((unsigned long *)__bp)[0];
  1735             __newCarry = __this >> 31;
  1735 	    __newCarry = __this >> 31;
  1736             ((unsigned long *)__bp)[0] = (__this << 1) | __carry;
  1736 	    ((unsigned long *)__bp)[0] = (__this << 1) | __carry;
  1737             __carry = __newCarry;
  1737 	    __carry = __newCarry;
  1738             __bp += 4;
  1738 	    __bp += 4;
  1739             __nBytes -= 4;
  1739 	    __nBytes -= 4;
  1740         }
  1740 	}
  1741         while (__nBytes) {
  1741 	while (__nBytes) {
  1742             __this = __bp[0];
  1742 	    __this = __bp[0];
  1743             __newCarry = __this >> 7;
  1743 	    __newCarry = __this >> 7;
  1744             __bp[0] = (__this << 1) | __carry;
  1744 	    __bp[0] = (__this << 1) | __carry;
  1745             __carry = __newCarry;
  1745 	    __carry = __newCarry;
  1746             __bp ++;
  1746 	    __bp ++;
  1747             __nBytes--;
  1747 	    __nBytes--;
  1748         }
  1748 	}
  1749         RETURN (self);
  1749 	RETURN (self);
  1750     }
  1750     }
  1751 %}.
  1751 %}.
  1752     self primitiveFailed
  1752     self primitiveFailed
  1753 
  1753 
  1754     "
  1754     "
  1769     newDigits at:1 put:0.
  1769     newDigits at:1 put:0.
  1770     digitByteArray := newDigits
  1770     digitByteArray := newDigits
  1771 !
  1771 !
  1772 
  1772 
  1773 numberOfDigits:nDigits
  1773 numberOfDigits:nDigits
       
  1774 "/    digitByteArray := ByteArray uninitializedNew:nDigits.
  1774     digitByteArray := ByteArray new:nDigits.
  1775     digitByteArray := ByteArray new:nDigits.
  1775     sign := 1.
  1776     sign := 1.
  1776 !
  1777 !
  1777 
  1778 
  1778 setDigits:digits
  1779 setDigits:digits
  1825 ! !
  1826 ! !
  1826 
  1827 
  1827 !LargeInteger class methodsFor:'documentation'!
  1828 !LargeInteger class methodsFor:'documentation'!
  1828 
  1829 
  1829 version
  1830 version
  1830     ^ '$Header: /cvs/stx/stx/libbasic/LargeInteger.st,v 1.39 1996-11-18 21:19:39 cg Exp $'
  1831     ^ '$Header: /cvs/stx/stx/libbasic/LargeInteger.st,v 1.40 1996-12-19 16:26:17 cg Exp $'
  1831 ! !
  1832 ! !