LargeInteger.st
changeset 701 a309e3ef7faf
parent 530 07d0bce293c9
child 927 8d8edf9df0ae
equal deleted inserted replaced
700:b4ae5ce39bfc 701:a309e3ef7faf
    31  other person.  No title to or ownership of the software is
    31  other person.  No title to or ownership of the software is
    32  hereby transferred.
    32  hereby transferred.
    33 "
    33 "
    34 !
    34 !
    35 
    35 
    36 version
       
    37     ^ '$Header: /cvs/stx/stx/libbasic/LargeInteger.st,v 1.20 1995-11-11 15:23:45 cg Exp $'
       
    38 !
       
    39 
       
    40 documentation
    36 documentation
    41 "
    37 "
    42     This class provides arbitrary precision integers. These are represented as:
    38     This class provides arbitrary precision integers. These are represented as:
    43       sign (-1/0/+1) and, if sign ~~ 0
    39       sign (-1/0/+1) and, if sign ~~ 0
    44       a ByteArray of digits with 8 bits per element; 
    40       a ByteArray of digits with 8 bits per element; 
    63     the sign as an instance variable (ST-80 has LargePositiveInteger and
    59     the sign as an instance variable (ST-80 has LargePositiveInteger and
    64     LargeNegativeInteger). This may change.
    60     LargeNegativeInteger). This may change.
    65 "
    61 "
    66 ! !
    62 ! !
    67 
    63 
    68 !LargeInteger class methodsFor:'queries'!
       
    69 
       
    70 isBuiltInClass
       
    71     "this class is known by the run-time-system"
       
    72 
       
    73     ^ true
       
    74 ! !
       
    75 
       
    76 !LargeInteger class methodsFor:'instance creation'!
    64 !LargeInteger class methodsFor:'instance creation'!
    77 
    65 
    78 value:aSmallInteger
    66 new
    79     "create and return a new LargeInteger with value taken from
    67     "catch creation message"
    80      the argument, aSmallInteger.
    68 
    81      Notice: this should be only used internally, since such small
    69     self error:'LargeIntegers cannot be created with new'
    82      largeIntegers do not normally occur in the system.
       
    83      May change without notice."
       
    84 
       
    85     ^ self basicNew value:aSmallInteger
       
    86 
       
    87     "LargeInteger value:3689"
       
    88 !
    70 !
    89 
    71 
    90 new:numberOfDigits
    72 new:numberOfDigits
    91     "catch creation message"
    73     "catch creation message"
    92 
    74 
    93     self error:'LargeIntegers cannot be created with new'
    75     self error:'LargeIntegers cannot be created with new'
    94 !
       
    95 
       
    96 new
       
    97     "catch creation message"
       
    98 
       
    99     self error:'LargeIntegers cannot be created with new'
       
   100 !
       
   101 
       
   102 valueLow:lowBits hi:hiBits
       
   103     "create and return a new LargeInteger with value taken from
       
   104      the two 16-bit args, where the sign of the high bits determines
       
   105      the sign of the result. 
       
   106      The largeinteger is normalized (but not to a smallInteger).
       
   107      This method is called from the runtime system (+, -),
       
   108      when an integer result has to be converted to a Large.
       
   109      May change without notice."
       
   110 
       
   111     |newLarge|
       
   112 
       
   113     hiBits < 0 ifTrue:[
       
   114 	newLarge := self unsignedValueLow:lowBits hi:(hiBits negated).
       
   115 	newLarge sign:-1.
       
   116 	^ newLarge
       
   117     ].
       
   118     ^ self unsignedValueLow:lowBits hi:hiBits
       
   119 !
       
   120 
       
   121 unsignedValueLow:lowBits hi:hiBits
       
   122     "create and return a new LargeInteger with value taken from
       
   123      the two 16-bit unsigned args. 
       
   124      The largeinteger is normalized (but not to a smallInteger).
       
   125      This method is called from the runtime system (+, -),
       
   126      when an integer result has to be converted to a Large.
       
   127      May change without notice."
       
   128 
       
   129     |bytes b1 b2 b3 b4|
       
   130 
       
   131     b4 := (hiBits bitShift:-8) bitAnd:16rFF.
       
   132     b3 := hiBits bitAnd:16rFF.
       
   133     b2 := (lowBits bitShift:-8) bitAnd:16rFF.
       
   134     b1 := lowBits bitAnd:16rFF.
       
   135 
       
   136     b4 ~~ 0 ifTrue:[
       
   137 	bytes := ByteArray with:b1 with:b2 with:b3 with:b4
       
   138     ] ifFalse:[
       
   139 	b3 ~~ 0 ifTrue:[
       
   140 	    bytes := ByteArray with:b1 with:b2 with:b3
       
   141 	] ifFalse:[
       
   142 	    b2 ~~ 0 ifTrue:[
       
   143 		bytes := ByteArray with:b1 with:b2
       
   144 	    ] ifFalse:[
       
   145 		bytes := ByteArray with:b1
       
   146 	    ]
       
   147 	]
       
   148     ].
       
   149     ^ (self basicNew) setDigits:bytes
       
   150 !
    76 !
   151 
    77 
   152 sign:s value16:ll value16:ml value16:mh value16:hh
    78 sign:s value16:ll value16:ml value16:mh value16:hh
   153     "create and return a new LargeInteger, with value taken from the
    79     "create and return a new LargeInteger, with value taken from the
   154      four 16-bit unsigned value-args.
    80      four 16-bit unsigned value-args.
   248     ].
   174     ].
   249 
   175 
   250     newLarge := self basicNew setDigits:digitBytes.
   176     newLarge := self basicNew setDigits:digitBytes.
   251     s < 0 ifTrue:[newLarge sign:s].
   177     s < 0 ifTrue:[newLarge sign:s].
   252     ^ newLarge
   178     ^ newLarge
       
   179 !
       
   180 
       
   181 unsignedValueLow:lowBits hi:hiBits
       
   182     "create and return a new LargeInteger with value taken from
       
   183      the two 16-bit unsigned args. 
       
   184      The largeinteger is normalized (but not to a smallInteger).
       
   185      This method is called from the runtime system (+, -),
       
   186      when an integer result has to be converted to a Large.
       
   187      May change without notice."
       
   188 
       
   189     |bytes b1 b2 b3 b4|
       
   190 
       
   191     b4 := (hiBits bitShift:-8) bitAnd:16rFF.
       
   192     b3 := hiBits bitAnd:16rFF.
       
   193     b2 := (lowBits bitShift:-8) bitAnd:16rFF.
       
   194     b1 := lowBits bitAnd:16rFF.
       
   195 
       
   196     b4 ~~ 0 ifTrue:[
       
   197 	bytes := ByteArray with:b1 with:b2 with:b3 with:b4
       
   198     ] ifFalse:[
       
   199 	b3 ~~ 0 ifTrue:[
       
   200 	    bytes := ByteArray with:b1 with:b2 with:b3
       
   201 	] ifFalse:[
       
   202 	    b2 ~~ 0 ifTrue:[
       
   203 		bytes := ByteArray with:b1 with:b2
       
   204 	    ] ifFalse:[
       
   205 		bytes := ByteArray with:b1
       
   206 	    ]
       
   207 	]
       
   208     ].
       
   209     ^ (self basicNew) setDigits:bytes
       
   210 !
       
   211 
       
   212 value:aSmallInteger
       
   213     "create and return a new LargeInteger with value taken from
       
   214      the argument, aSmallInteger.
       
   215      Notice: this should be only used internally, since such small
       
   216      largeIntegers do not normally occur in the system.
       
   217      May change without notice."
       
   218 
       
   219     ^ self basicNew value:aSmallInteger
       
   220 
       
   221     "LargeInteger value:3689"
       
   222 !
       
   223 
       
   224 valueLow:lowBits hi:hiBits
       
   225     "create and return a new LargeInteger with value taken from
       
   226      the two 16-bit args, where the sign of the high bits determines
       
   227      the sign of the result. 
       
   228      The largeinteger is normalized (but not to a smallInteger).
       
   229      This method is called from the runtime system (+, -),
       
   230      when an integer result has to be converted to a Large.
       
   231      May change without notice."
       
   232 
       
   233     |newLarge|
       
   234 
       
   235     hiBits < 0 ifTrue:[
       
   236 	newLarge := self unsignedValueLow:lowBits hi:(hiBits negated).
       
   237 	newLarge sign:-1.
       
   238 	^ newLarge
       
   239     ].
       
   240     ^ self unsignedValueLow:lowBits hi:hiBits
   253 ! !
   241 ! !
   254 
   242 
       
   243 !LargeInteger class methodsFor:'queries'!
       
   244 
       
   245 isBuiltInClass
       
   246     "this class is known by the run-time-system"
       
   247 
       
   248     ^ true
       
   249 ! !
       
   250 
   255 !LargeInteger methodsFor:'arithmetic'!
   251 !LargeInteger methodsFor:'arithmetic'!
       
   252 
       
   253 * aNumber
       
   254     "return the product of the receiver and the argument, aNumber"
       
   255 
       
   256     |otherSign|
       
   257 
       
   258     (sign == 0) ifTrue:[^ 0].  "cannot happen if correctly normalized"
       
   259 
       
   260     "
       
   261      this is the common case, multiplying with SmallInteger.
       
   262      Use a special method for this case ...
       
   263     "
       
   264     (aNumber class == SmallInteger) ifTrue:[
       
   265 	^ self productFromInteger:aNumber
       
   266     ].
       
   267 
       
   268     "
       
   269      if the argument is not a largeInteger, coerce
       
   270     "
       
   271     (aNumber class == self class) ifFalse:[
       
   272 	^ self retry:#* coercing:aNumber
       
   273     ].
       
   274 
       
   275     otherSign := aNumber sign.
       
   276     (sign == otherSign) ifTrue:[^ self absMul:aNumber].
       
   277     (otherSign == 0) ifTrue:[^ 0].
       
   278     ^ (self absMul:aNumber) sign:-1
       
   279 !
   256 
   280 
   257 + aNumber
   281 + aNumber
   258     "return the sum of the receiver and the argument, aNumber"
   282     "return the sum of the receiver and the argument, aNumber"
   259 
   283 
   260     |otherSign|
   284     |otherSign|
   358      -12345678901234567890 - -12345678901234567880   
   382      -12345678901234567890 - -12345678901234567880   
   359      -12345678901234567890 - -12345678901234567980   
   383      -12345678901234567890 - -12345678901234567980   
   360     "
   384     "
   361 !
   385 !
   362 
   386 
   363 * aNumber
   387 / aNumber
   364     "return the product of the receiver and the argument, aNumber"
   388     "return the quotient of the receivers and the argument, aNumber"
   365 
   389 
   366     |otherSign|
   390     aNumber isInteger ifTrue:[
   367 
   391 	^ (Fraction numerator:self
   368     (sign == 0) ifTrue:[^ 0].  "cannot happen if correctly normalized"
   392 		  denominator:aNumber) reduced
   369 
   393     ].
   370     "
   394 
   371      this is the common case, multiplying with SmallInteger.
   395     "this is a q&d hack - we loose lots of precision here ..."
   372      Use a special method for this case ...
   396     ^ (self asFloat / aNumber asFloat)
   373     "
       
   374     (aNumber class == SmallInteger) ifTrue:[
       
   375 	^ self productFromInteger:aNumber
       
   376     ].
       
   377 
       
   378     "
       
   379      if the argument is not a largeInteger, coerce
       
   380     "
       
   381     (aNumber class == self class) ifFalse:[
       
   382 	^ self retry:#* coercing:aNumber
       
   383     ].
       
   384 
       
   385     otherSign := aNumber sign.
       
   386     (sign == otherSign) ifTrue:[^ self absMul:aNumber].
       
   387     (otherSign == 0) ifTrue:[^ 0].
       
   388     ^ (self absMul:aNumber) sign:-1
       
   389 !
   397 !
   390 
   398 
   391 // aNumber
   399 // aNumber
   392     "return the quotient of the receiver and the argument, aNumber"
   400     "return the quotient of the receiver and the argument, aNumber"
   393 
   401 
   458 	(sign == otherSign) ifTrue:[^ (self absDiv:aNumber negated) at:2].
   466 	(sign == otherSign) ifTrue:[^ (self absDiv:aNumber negated) at:2].
   459 	^ ((self absDiv:aNumber) at:2) sign:-1
   467 	^ ((self absDiv:aNumber) at:2) sign:-1
   460     ].
   468     ].
   461     (sign == otherSign) ifTrue:[^ (self absDiv:aNumber) at:2].
   469     (sign == otherSign) ifTrue:[^ (self absDiv:aNumber) at:2].
   462     ^ ((self absDiv:aNumber negated) at:2) sign:-1
   470     ^ ((self absDiv:aNumber negated) at:2) sign:-1
   463 !
       
   464 
       
   465 / aNumber
       
   466     "return the quotient of the receivers and the argument, aNumber"
       
   467 
       
   468     aNumber isInteger ifTrue:[
       
   469 	^ (Fraction numerator:self
       
   470 		  denominator:aNumber) reduced
       
   471     ].
       
   472 
       
   473     "this is a q&d hack - we loose lots of precision here ..."
       
   474     ^ (self asFloat / aNumber asFloat)
       
   475 !
   471 !
   476 
   472 
   477 negated
   473 negated
   478     "return an integer with value negated from the receivers value."
   474     "return an integer with value negated from the receivers value."
   479 
   475 
   500     newNumber := self shallowCopy.
   496     newNumber := self shallowCopy.
   501     newNumber sign:(sign negated).
   497     newNumber sign:(sign negated).
   502     ^ newNumber
   498     ^ newNumber
   503 ! !
   499 ! !
   504 
   500 
   505 !LargeInteger methodsFor:'double dispatching'!
   501 !LargeInteger methodsFor:'byte access'!
   506 
   502 
   507 sumFromInteger:anInteger
   503 digitAt:index
   508     "sent, when anInteger does not know how to add the receiver.
   504     "return 8 bits of value, starting at byte index"
   509      Return the sum of the receiver and the argument, (which must be a SmallInteger)"
   505 
   510 
   506     index > digitByteArray size ifTrue:[^ 0].
   511     |result|
   507     ^ digitByteArray at:index
   512 
   508 !
   513     anInteger > 0 ifTrue:[
   509 
   514 	sign < 0 ifTrue:[
   510 digitAt:index put:aByte
   515 	    result := (self absFastMinus:anInteger) sign:-1
   511     "set the 8 bits, index is a byte index"
   516 	] ifFalse:[
   512 
   517 	    result := self absFastPlus:anInteger
   513     digitByteArray at:index put:aByte
   518 	]
   514 !
   519     ] ifFalse:[
   515 
   520 	anInteger == 0 ifTrue:[
   516 digitLength
   521 	    ^ self
   517     "return the number bytes used by this Integer"
       
   518 
       
   519 "/    ^ digitByteArray size
       
   520 
       
   521     "
       
   522      kludge: check if there is a 0-byte ...
       
   523      this allows to ask unnormalized LargeIntegers 
       
   524      to be asked for their digitLength
       
   525     "
       
   526     |l "{ Class: SmallInteger }" |
       
   527 
       
   528     l := digitByteArray size.
       
   529     [(digitByteArray at:l) == 0] whileTrue:[
       
   530 	l := l - 1.
       
   531     ].
       
   532     ^ l
       
   533 !
       
   534 
       
   535 digits
       
   536     "return a byteArray fille with the receivers bits
       
   537      (8 bits of the absolute value per element)"
       
   538 
       
   539     ^ digitByteArray
       
   540 ! !
       
   541 
       
   542 !LargeInteger methodsFor:'coercing & converting'!
       
   543 
       
   544 asFloat
       
   545     "return a Float with same value as myself.
       
   546      Since floats have a limited precision, you usually loose bits when
       
   547      doing this."
       
   548 
       
   549     |newFloat|
       
   550 
       
   551     newFloat := 0.0.
       
   552     (sign == 0) ifFalse:[
       
   553 	digitByteArray reverseDo:[:aDigit |
       
   554 	    newFloat := (newFloat * 256.0) + aDigit asFloat
   522 	].
   555 	].
   523 	sign < 0 ifTrue:[
   556 	(sign < 0) ifTrue:[
   524 	    result := (self absFastPlus:anInteger abs) sign:-1
   557 	    newFloat := newFloat negated
   525 	]  ifFalse:[
   558 	]
   526 	    result := self absFastMinus:anInteger
   559     ].
   527 	]
   560     ^ newFloat
   528     ].
   561 
   529     ^ result normalize
   562     "
   530 
   563      1234567890 asFloat               
   531     "
   564      12345678901234567890 asFloat      
   532      12345678901234567890          
   565      12345678901234567890 asFloat asInteger   
   533      -12345678901234567890         
   566     "
   534      12345678901234567890 sumFromInteger:0       
   567 !
   535      -12345678901234567890 sumFromInteger:0       
   568 
   536      12345678901234567890 sumFromInteger:1       
   569 asLargeInteger
   537      12345678901234567890 sumFromInteger:-1      
   570     "return a LargeInteger with same value as myself - thats me"
   538      -12345678901234567890 sumFromInteger:1     
   571 
   539      -12345678901234567890 sumFromInteger:-1    
   572     ^ self
   540     "
   573 !
   541 !
   574 
   542 
   575 asSmallInteger
   543 differenceFromInteger:anInteger
   576     "return a SmallInteger with same value as myself - 
   544     "sent, when anInteger does not know how to subtract the receiver.
   577      the result is invalid if the receivers value cannot 
   545      Return the result of 'anInteger - self'. The argument must be a SmallInteger."
   578      be represented as a SmallInteger.
   546 
   579      Q: should we raise an exception if this happens ?"
   547     |result|
   580 
   548 
   581     |value|
   549     anInteger > 0 ifTrue:[
   582 
   550 	sign > 0 ifTrue:[
   583     value := 0.
   551 	    result := (self absFastMinus:anInteger) sign:-1
   584     (sign == 0) ifFalse:[
   552 	] ifFalse:[
   585 	digitByteArray reverseDo:[:aDigit |
   553 	    result := self absFastPlus:anInteger
   586 	    value := (value times:256) + aDigit 
   554 	]
       
   555     ] ifFalse:[
       
   556 	anInteger == 0 ifTrue:[
       
   557 	    ^ self negated
       
   558 	].
   587 	].
   559 	sign > 0 ifTrue:[
   588 	(sign < 0) ifTrue:[
   560 	    result := (self absFastPlus:anInteger negated) sign:-1
   589 	    value := value negated
   561 	] ifFalse:[
   590 	]
   562 	    result := (self absFastMinus:anInteger) sign:-1
   591     ].
   563 	]
   592     ^ value
   564     ].
   593 !
   565     ^ result normalize
   594 
   566 
   595 coerce:aNumber
   567     "
   596     "return the argument as a LargeInteger"
   568      12345678901234567890          
   597 
   569      -12345678901234567890         
   598     ^ aNumber asLargeInteger
   570      12345678901234567890 differenceFromInteger:0       
   599 !
   571      12345678901234567890 differenceFromInteger:1       
   600 
   572      12345678901234567890 differenceFromInteger:-1      
   601 normalize
   573      -12345678901234567890 differenceFromInteger:1   
   602     "if the receiver can be represented as a SmallInteger, return
   574      -12345678901234567890 differenceFromInteger:-1   
   603      a SmallInteger with my value; otherwise return self with leading
   575     "
   604      zeros removed"
   576 !
   605 
   577 
   606     |index "{ Class: SmallInteger }" 
   578 productFromInteger:anInteger
   607      val   "{ Class: SmallInteger }" |
   579     "sent, when anInteger does not know how to multiply the receiver.
   608 
   580      Return the product of the receiver and the argument, aSmallInteger"
   609 %{  /* NOCONTEXT */
   581 
   610     OBJ t;
   582     |num result 
   611 
   583      resultDigitByteArray
   612     if (_INST(sign) == _MKSMALLINT(0)) {
   584      val     "{ Class: SmallInteger }"
   613 	RETURN (_MKSMALLINT(0));
   585      len     "{ Class: SmallInteger }"
   614     }
   586      carry   "{ Class: SmallInteger }"
   615 
   587      prod    "{ Class: SmallInteger }" 
   616     t = _INST(digitByteArray);
   588      ok|
   617     if (__isByteArray(t)) {
   589 
   618 	unsigned char *_digitBytes = _ByteArrayInstPtr(t)->ba_element;
   590     "multiplying by a small integer is done here"
   619 	int _idx = _byteArraySize(t);
   591 
   620 	int _val;
   592     "trivial cases"
   621 
   593     anInteger == 0 ifTrue:[^ 0].
   622 	while ((_idx > 0) && (_digitBytes[_idx - 1] == 0)) {
   594     anInteger == 1 ifTrue:[^ self].
   623 	    _idx--;
   595 
       
   596     num := anInteger abs.
       
   597     (num > 16r3FFFFF) ifTrue:[
       
   598 	"if num is too big (so that multiplying by a byte could create a Large)"
       
   599 
       
   600 	^ anInteger retry:#* coercing:self
       
   601     ].
       
   602 
       
   603     len := digitByteArray size.
       
   604 
       
   605     result := self class basicNew numberOfDigits:(len + 4).
       
   606 
       
   607     "used to be the following. replaced, to avoid another multiplication"
       
   608 "
       
   609     result sign:(sign * anInteger sign).
       
   610 "
       
   611     anInteger < 0 ifTrue:[
       
   612 	sign > 0 ifTrue:[
       
   613 	    result sign:-1
       
   614 	].
       
   615     ] ifFalse:[
       
   616 	sign < 0 ifTrue:[
       
   617 	    result sign:sign
       
   618 	]
       
   619     ].
       
   620 
       
   621     resultDigitByteArray := result digits.
       
   622 
       
   623     carry := 0.
       
   624     val := num.
       
   625 
       
   626     ok := false.
       
   627 %{
       
   628     if (__bothSmallInteger(len, val)
       
   629      && __isByteArray(_INST(digitByteArray))
       
   630      && __isByteArray(resultDigitByteArray)) {
       
   631 	int _l = _intVal(len);
       
   632 	int _v = _intVal(val);
       
   633 	unsigned _carry = 0;
       
   634 	unsigned _prod;
       
   635 	unsigned char *digitP = _ByteArrayInstPtr(_INST(digitByteArray))->ba_element;
       
   636 	unsigned char *resultP = _ByteArrayInstPtr(resultDigitByteArray)->ba_element;
       
   637 
       
   638 	while (_l-- > 0) {
       
   639 	    _prod = *digitP++ * _v + _carry;
       
   640 	    *resultP++ = _prod & 0xFF;
       
   641 	    _carry = _prod >> 8;
       
   642 	}
   624 	}
   643 	while (_carry) {
   625 	switch (_idx) {
   644 	    *resultP++ = _carry & 0xFF;
   626 	    case 0:
   645 	    _carry >>= 8;
   627 		RETURN (_MKSMALLINT(0));
       
   628 		break;
       
   629 
       
   630 	    case 1:
       
   631 		_val = _digitBytes[0];
       
   632 		if (_INST(sign) == _MKSMALLINT(-1))
       
   633 		    _val = -_val;
       
   634 		RETURN (_MKSMALLINT(_val));
       
   635                 
       
   636 	    case 2:
       
   637 		_val = (_digitBytes[1]<<8) + _digitBytes[0];
       
   638 		if (_INST(sign) == _MKSMALLINT(-1))
       
   639 		    _val = -_val;
       
   640 		RETURN (_MKSMALLINT(_val));
       
   641 
       
   642 	    case 3:
       
   643 		_val = (((_digitBytes[2]<<8) + _digitBytes[1])<<8) + _digitBytes[0];
       
   644 		if (_INST(sign) == _MKSMALLINT(-1))
       
   645 		    _val = -_val;
       
   646 		RETURN (_MKSMALLINT(_val));
       
   647 
       
   648 	    case 4:
       
   649 		_val = _digitBytes[3];
       
   650 		if (_val <= 0x40) {
       
   651 		    _val = (((((_val<<8) + _digitBytes[2])<<8) + _digitBytes[1])<<8) + _digitBytes[0];
       
   652 		    if (_INST(sign) == _MKSMALLINT(-1))
       
   653 			_val = -_val;
       
   654 		    if ((_val >= _MIN_INT) && (_val <= _MAX_INT)) {
       
   655 			RETURN (_MKSMALLINT(_val));
       
   656 		    }
       
   657 		}
       
   658 		break;
       
   659 
       
   660 	    default:
       
   661 		break;
   646 	}
   662 	}
   647 	ok = true;
       
   648     }
   663     }
   649 %}.
   664 %}.
   650     "
   665     index := digitByteArray size.
   651      fall back - normally not reached
   666     [(index > 0) and:[(digitByteArray at:index) == 0]] whileTrue:[
   652      (could make it a primitive-failure as well)
   667 	index := index - 1
   653     "
   668     ].
   654     ok ifFalse:[
   669 
   655 	1 to:len do:[:i |
   670     (index ~~ digitByteArray size) ifTrue:[
   656 	    prod := (digitByteArray basicAt:i) * val + carry.
   671 	digitByteArray := digitByteArray copyFrom:1 to:index
   657 	    resultDigitByteArray basicAt:i put:(prod bitAnd:16rFF).
   672     ].
   658 	    carry := prod bitShift:-8.
   673     ^ self
   659 	].
       
   660 	[carry ~~ 0] whileTrue:[
       
   661 	    len := len + 1.
       
   662 	    resultDigitByteArray basicAt:len put:(carry bitAnd:16rFF).
       
   663 	    carry := carry bitShift:-8
       
   664 	].
       
   665     ].
       
   666     ^ result normalize
       
   667 ! !
       
   668 
       
   669 !LargeInteger methodsFor:'coercing & converting'!
       
   670 
       
   671 coerce:aNumber
       
   672     "return the argument as a LargeInteger"
       
   673 
       
   674     ^ aNumber asLargeInteger
       
   675 !
   674 !
   676 
   675 
   677 value:aSmallInteger
   676 value:aSmallInteger
   678     "return a new LargeInteger with value taken from a SmallInteger.
   677     "return a new LargeInteger with value taken from a SmallInteger.
   679      This method will fail, if the argument is not a smallInteger."
   678      This method will fail, if the argument is not a smallInteger."
   717 	    ] ifFalse:[
   716 	    ] ifFalse:[
   718 		digitByteArray := ByteArray with:b1 with:b2 with:b3 with:absValue
   717 		digitByteArray := ByteArray with:b1 with:b2 with:b3 with:absValue
   719 	    ]
   718 	    ]
   720 	]
   719 	]
   721     ]
   720     ]
   722 !
   721 ! !
   723 
   722 
   724 asSmallInteger
   723 !LargeInteger methodsFor:'comparing'!
   725     "return a SmallInteger with same value as myself - 
   724 
   726      the result is invalid if the receivers value cannot 
   725 < aNumber
   727      be represented as a SmallInteger.
   726     "return true, if the argument, aNumber is greater than the receiver"
   728      Q: should we raise an exception if this happens ?"
   727 
   729 
   728     |otherSign|
   730     |value|
   729 
   731 
   730     (aNumber class == self class) ifFalse:[
   732     value := 0.
   731 	^ self retry:#< coercing:aNumber
   733     (sign == 0) ifFalse:[
   732     ].
   734 	digitByteArray reverseDo:[:aDigit |
   733     otherSign := aNumber sign.
   735 	    value := (value times:256) + aDigit 
   734 
       
   735     (sign > 0) ifTrue:[
       
   736 	"I am positive"
       
   737 	(otherSign > 0) ifTrue:[^ self absLess:aNumber].
       
   738 	^ false "aNumber is <= 0"
       
   739     ].
       
   740     (sign == 0) ifTrue:[
       
   741 	(otherSign > 0) ifTrue:[^ true].
       
   742 	^ false
       
   743     ].
       
   744     "I am negative"
       
   745     (otherSign > 0) ifTrue:[^ true].
       
   746     (otherSign == 0) ifTrue:[^ true].
       
   747     ^ (self absLess:aNumber) not
       
   748 !
       
   749 
       
   750 = aNumber
       
   751     "return true, if the argument, aNumber has the same value as
       
   752      the receiver"
       
   753 
       
   754     (aNumber class == self class) ifFalse:[
       
   755 	aNumber respondsToArithmetic ifFalse:[ ^ false ].
       
   756 	^ self retry:#= coercing:aNumber
       
   757     ].
       
   758     (aNumber sign == sign) ifFalse:[^ false].
       
   759     ^ self absEq:aNumber
       
   760 !
       
   761 
       
   762 > aNumber
       
   763     "return true, if the argument, aNumber is less than the receiver"
       
   764 
       
   765     |otherSign|
       
   766 
       
   767     (aNumber class == self class) ifFalse:[
       
   768 	^ self retry:#> coercing:aNumber
       
   769     ].
       
   770     otherSign := aNumber sign.
       
   771 
       
   772     (sign > 0) ifTrue:[
       
   773 	"I am positive"
       
   774 	(otherSign > 0) ifTrue:[^ aNumber absLess:self].
       
   775 	^ true "aNumber is <= 0"
       
   776     ].
       
   777     (sign == 0) ifTrue:[
       
   778 	"I am zero"
       
   779 	(otherSign > 0) ifTrue:[^ false].
       
   780 	^ true
       
   781     ].
       
   782     "I am negative"
       
   783     (otherSign > 0) ifTrue:[^ false].
       
   784     (otherSign == 0) ifTrue:[^ false].
       
   785     ^ (self absLess:aNumber) not
       
   786 ! !
       
   787 
       
   788 !LargeInteger methodsFor:'double dispatching'!
       
   789 
       
   790 differenceFromInteger:anInteger
       
   791     "sent, when anInteger does not know how to subtract the receiver.
       
   792      Return the result of 'anInteger - self'. The argument must be a SmallInteger."
       
   793 
       
   794     |result|
       
   795 
       
   796     anInteger > 0 ifTrue:[
       
   797 	sign > 0 ifTrue:[
       
   798 	    result := (self absFastMinus:anInteger) sign:-1
       
   799 	] ifFalse:[
       
   800 	    result := self absFastPlus:anInteger
       
   801 	]
       
   802     ] ifFalse:[
       
   803 	anInteger == 0 ifTrue:[
       
   804 	    ^ self negated
   736 	].
   805 	].
   737 	(sign < 0) ifTrue:[
   806 	sign > 0 ifTrue:[
   738 	    value := value negated
   807 	    result := (self absFastPlus:anInteger negated) sign:-1
   739 	]
   808 	] ifFalse:[
   740     ].
   809 	    result := (self absFastMinus:anInteger) sign:-1
   741     ^ value
   810 	]
   742 !
   811     ].
   743 
   812     ^ result normalize
   744 asLargeInteger
   813 
   745     "return a LargeInteger with same value as myself - thats me"
   814     "
   746 
   815      12345678901234567890          
   747     ^ self
   816      -12345678901234567890         
   748 !
   817      12345678901234567890 differenceFromInteger:0       
   749 
   818      12345678901234567890 differenceFromInteger:1       
   750 asFloat
   819      12345678901234567890 differenceFromInteger:-1      
   751     "return a Float with same value as myself.
   820      -12345678901234567890 differenceFromInteger:1   
   752      Since floats have a limited precision, you usually loose bits when
   821      -12345678901234567890 differenceFromInteger:-1   
   753      doing this."
   822     "
   754 
   823 !
   755     |newFloat|
   824 
   756 
   825 productFromInteger:anInteger
   757     newFloat := 0.0.
   826     "sent, when anInteger does not know how to multiply the receiver.
   758     (sign == 0) ifFalse:[
   827      Return the product of the receiver and the argument, aSmallInteger"
   759 	digitByteArray reverseDo:[:aDigit |
   828 
   760 	    newFloat := (newFloat * 256.0) + aDigit asFloat
   829     |num result 
       
   830      resultDigitByteArray
       
   831      val     "{ Class: SmallInteger }"
       
   832      len     "{ Class: SmallInteger }"
       
   833      carry   "{ Class: SmallInteger }"
       
   834      prod    "{ Class: SmallInteger }" 
       
   835      ok|
       
   836 
       
   837     "multiplying by a small integer is done here"
       
   838 
       
   839     "trivial cases"
       
   840     anInteger == 0 ifTrue:[^ 0].
       
   841     anInteger == 1 ifTrue:[^ self].
       
   842 
       
   843     num := anInteger abs.
       
   844     (num > 16r3FFFFF) ifTrue:[
       
   845 	"if num is too big (so that multiplying by a byte could create a Large)"
       
   846 
       
   847 	^ anInteger retry:#* coercing:self
       
   848     ].
       
   849 
       
   850     len := digitByteArray size.
       
   851 
       
   852     result := self class basicNew numberOfDigits:(len + 4).
       
   853 
       
   854     "used to be the following. replaced, to avoid another multiplication"
       
   855 "
       
   856     result sign:(sign * anInteger sign).
       
   857 "
       
   858     anInteger < 0 ifTrue:[
       
   859 	sign > 0 ifTrue:[
       
   860 	    result sign:-1
   761 	].
   861 	].
   762 	(sign < 0) ifTrue:[
   862     ] ifFalse:[
   763 	    newFloat := newFloat negated
   863 	sign < 0 ifTrue:[
   764 	]
   864 	    result sign:sign
   765     ].
   865 	]
   766     ^ newFloat
   866     ].
   767 
   867 
   768     "
   868     resultDigitByteArray := result digits.
   769      1234567890 asFloat               
   869 
   770      12345678901234567890 asFloat      
   870     carry := 0.
   771      12345678901234567890 asFloat asInteger   
   871     val := num.
   772     "
   872 
   773 !
   873     ok := false.
   774 
   874 %{
   775 normalize
   875     if (__bothSmallInteger(len, val)
   776     "if the receiver can be represented as a SmallInteger, return
   876      && __isByteArray(_INST(digitByteArray))
   777      a SmallInteger with my value; otherwise return self with leading
   877      && __isByteArray(resultDigitByteArray)) {
   778      zeros removed"
   878 	int _l = _intVal(len);
   779 
   879 	int _v = _intVal(val);
   780     |index "{ Class: SmallInteger }" 
   880 	unsigned _carry = 0;
   781      val   "{ Class: SmallInteger }" |
   881 	unsigned _prod;
   782 
   882 	unsigned char *digitP = _ByteArrayInstPtr(_INST(digitByteArray))->ba_element;
   783 %{  /* NOCONTEXT */
   883 	unsigned char *resultP = _ByteArrayInstPtr(resultDigitByteArray)->ba_element;
   784     OBJ t;
   884 
   785 
   885 	while (_l-- > 0) {
   786     if (_INST(sign) == _MKSMALLINT(0)) {
   886 	    _prod = *digitP++ * _v + _carry;
   787 	RETURN (_MKSMALLINT(0));
   887 	    *resultP++ = _prod & 0xFF;
   788     }
   888 	    _carry = _prod >> 8;
   789 
       
   790     t = _INST(digitByteArray);
       
   791     if (__isByteArray(t)) {
       
   792 	unsigned char *_digitBytes = _ByteArrayInstPtr(t)->ba_element;
       
   793 	int _idx = _byteArraySize(t);
       
   794 	int _val;
       
   795 
       
   796 	while ((_idx > 0) && (_digitBytes[_idx - 1] == 0)) {
       
   797 	    _idx--;
       
   798 	}
   889 	}
   799 	switch (_idx) {
   890 	while (_carry) {
   800 	    case 0:
   891 	    *resultP++ = _carry & 0xFF;
   801 		RETURN (_MKSMALLINT(0));
   892 	    _carry >>= 8;
   802 		break;
       
   803 
       
   804 	    case 1:
       
   805 		_val = _digitBytes[0];
       
   806 		if (_INST(sign) == _MKSMALLINT(-1))
       
   807 		    _val = -_val;
       
   808 		RETURN (_MKSMALLINT(_val));
       
   809                 
       
   810 	    case 2:
       
   811 		_val = (_digitBytes[1]<<8) + _digitBytes[0];
       
   812 		if (_INST(sign) == _MKSMALLINT(-1))
       
   813 		    _val = -_val;
       
   814 		RETURN (_MKSMALLINT(_val));
       
   815 
       
   816 	    case 3:
       
   817 		_val = (((_digitBytes[2]<<8) + _digitBytes[1])<<8) + _digitBytes[0];
       
   818 		if (_INST(sign) == _MKSMALLINT(-1))
       
   819 		    _val = -_val;
       
   820 		RETURN (_MKSMALLINT(_val));
       
   821 
       
   822 	    case 4:
       
   823 		_val = _digitBytes[3];
       
   824 		if (_val <= 0x40) {
       
   825 		    _val = (((((_val<<8) + _digitBytes[2])<<8) + _digitBytes[1])<<8) + _digitBytes[0];
       
   826 		    if (_INST(sign) == _MKSMALLINT(-1))
       
   827 			_val = -_val;
       
   828 		    if ((_val >= _MIN_INT) && (_val <= _MAX_INT)) {
       
   829 			RETURN (_MKSMALLINT(_val));
       
   830 		    }
       
   831 		}
       
   832 		break;
       
   833 
       
   834 	    default:
       
   835 		break;
       
   836 	}
   893 	}
       
   894 	ok = true;
   837     }
   895     }
   838 %}.
   896 %}.
   839     index := digitByteArray size.
   897     "
   840     [(index > 0) and:[(digitByteArray at:index) == 0]] whileTrue:[
   898      fall back - normally not reached
   841 	index := index - 1
   899      (could make it a primitive-failure as well)
   842     ].
   900     "
   843 
   901     ok ifFalse:[
   844     (index ~~ digitByteArray size) ifTrue:[
   902 	1 to:len do:[:i |
   845 	digitByteArray := digitByteArray copyFrom:1 to:index
   903 	    prod := (digitByteArray basicAt:i) * val + carry.
   846     ].
   904 	    resultDigitByteArray basicAt:i put:(prod bitAnd:16rFF).
   847     ^ self
   905 	    carry := prod bitShift:-8.
       
   906 	].
       
   907 	[carry ~~ 0] whileTrue:[
       
   908 	    len := len + 1.
       
   909 	    resultDigitByteArray basicAt:len put:(carry bitAnd:16rFF).
       
   910 	    carry := carry bitShift:-8
       
   911 	].
       
   912     ].
       
   913     ^ result normalize
       
   914 !
       
   915 
       
   916 sumFromInteger:anInteger
       
   917     "sent, when anInteger does not know how to add the receiver.
       
   918      Return the sum of the receiver and the argument, (which must be a SmallInteger)"
       
   919 
       
   920     |result|
       
   921 
       
   922     anInteger > 0 ifTrue:[
       
   923 	sign < 0 ifTrue:[
       
   924 	    result := (self absFastMinus:anInteger) sign:-1
       
   925 	] ifFalse:[
       
   926 	    result := self absFastPlus:anInteger
       
   927 	]
       
   928     ] ifFalse:[
       
   929 	anInteger == 0 ifTrue:[
       
   930 	    ^ self
       
   931 	].
       
   932 	sign < 0 ifTrue:[
       
   933 	    result := (self absFastPlus:anInteger abs) sign:-1
       
   934 	]  ifFalse:[
       
   935 	    result := self absFastMinus:anInteger
       
   936 	]
       
   937     ].
       
   938     ^ result normalize
       
   939 
       
   940     "
       
   941      12345678901234567890          
       
   942      -12345678901234567890         
       
   943      12345678901234567890 sumFromInteger:0       
       
   944      -12345678901234567890 sumFromInteger:0       
       
   945      12345678901234567890 sumFromInteger:1       
       
   946      12345678901234567890 sumFromInteger:-1      
       
   947      -12345678901234567890 sumFromInteger:1     
       
   948      -12345678901234567890 sumFromInteger:-1    
       
   949     "
   848 ! !
   950 ! !
   849 
   951 
   850 !LargeInteger methodsFor:'byte access'!
   952 !LargeInteger methodsFor:'printing & storing'!
   851 
   953 
   852 digitLength
   954 storeOn:aStream
   853     "return the number bytes used by this Integer"
   955     "append a representation of the receiver to aStream, which can
   854 
   956      be used to reconstruct the receiver."
   855 "/    ^ digitByteArray size
   957 
   856 
   958     self printOn:aStream.
   857     "
   959     aStream nextPutAll:' asLargeInteger'
   858      kludge: check if there is a 0-byte ...
       
   859      this allows to ask unnormalized LargeIntegers 
       
   860      to be asked for their digitLength
       
   861     "
       
   862     |l "{ Class: SmallInteger }" |
       
   863 
       
   864     l := digitByteArray size.
       
   865     [(digitByteArray at:l) == 0] whileTrue:[
       
   866 	l := l - 1.
       
   867     ].
       
   868     ^ l
       
   869 !
       
   870 
       
   871 digitAt:index
       
   872     "return 8 bits of value, starting at byte index"
       
   873 
       
   874     index > digitByteArray size ifTrue:[^ 0].
       
   875     ^ digitByteArray at:index
       
   876 !
       
   877 
       
   878 digitAt:index put:aByte
       
   879     "set the 8 bits, index is a byte index"
       
   880 
       
   881     digitByteArray at:index put:aByte
       
   882 !
       
   883 
       
   884 digits
       
   885     "return a byteArray fille with the receivers bits
       
   886      (8 bits of the absolute value per element)"
       
   887 
       
   888     ^ digitByteArray
       
   889 ! !
   960 ! !
   890 
   961 
   891 !LargeInteger methodsFor:'private'!
   962 !LargeInteger methodsFor:'private'!
   892 
   963 
   893 sign:aNumber
   964 absDiv:anInteger
   894     sign := aNumber
   965     "return an array with two LargeIntegers representing
   895 !
   966      abs(self) // abs(theArgument) and abs(self) \\ abs(theArgument).
   896 
   967      This needs a rewrite."
   897 numberOfDigits:nDigits
   968 
   898     digitByteArray := ByteArray new:nDigits.
   969     |tmp1 tmp2 
   899     sign := 1.
   970      rem 
   900 !
   971      count "{ Class: SmallInteger }"
   901 
   972      digit "{ Class: SmallInteger }" |
   902 setDigits:digits
   973 
   903     digitByteArray := digits.
   974     anInteger == 0 ifTrue:[
   904     sign := 1.
   975 	^ DivisionByZeroSignal raise
   905 !
   976     ].
   906 
   977 
   907 absFastPlus:aSmallInteger
   978     self < anInteger ifTrue:[
   908     "return a LargeInteger representing abs(self) + abs(theArgument).
   979 	^ Array with:0 with:self
   909      The result is not normalized."
   980     ].
   910 
   981 
   911     |result resultDigitByteArray
   982     tmp1 := self simpleDeepCopy.
   912      len   "{ Class: SmallInteger }"
   983     tmp2 := anInteger simpleDeepCopy.
   913      index "{ Class: SmallInteger }"
   984     count := 0.
   914      carry "{ Class: SmallInteger }" |
   985     [tmp2 < tmp1] whileTrue:[
   915 
   986 	tmp2 mul256.
   916     len := digitByteArray size.
   987 	count := count + 1
   917 
   988     ].
   918     result := self class basicNew numberOfDigits:(len + 1).
   989 
   919     resultDigitByteArray := result digits.
   990     tmp2 div256.
   920 
   991 
   921     index := 1.
   992     rem := 0 asLargeInteger. 
   922     carry := aSmallInteger abs.
   993     [count == 0] whileFalse:[
   923 
   994 	digit := 0.
   924     [carry ~~ 0] whileTrue:[
   995 	[tmp1 >= tmp2] whileTrue:[
   925 	(index <= len) ifTrue:[
   996 	    digit := digit + 1.
   926 	    carry := (digitByteArray basicAt:index) + carry.
   997 	    tmp1 := tmp1 - tmp2
   927 	].
   998 	].
   928 	resultDigitByteArray basicAt:index put:(carry bitAnd:16rFF).
   999 	rem := rem * 256 + digit.
   929 	carry := carry bitShift:-8.
  1000 	tmp2 div256.
   930 	index := index + 1
  1001 	count := count - 1
   931     ].
  1002     ].
   932     [index <= len] whileTrue:[
  1003     ^ Array with:rem with:tmp1 
   933 	resultDigitByteArray basicAt:index put:(digitByteArray basicAt:index).
  1004 !
   934 	index := index + 1
  1005 
   935     ].
  1006 absEq:aLargeInteger
   936 
  1007     "return true, if abs(self) = abs(theArgument)"
   937     ^ result
  1008 
       
  1009     |len1 "{ Class: SmallInteger }"
       
  1010      len2 "{ Class: SmallInteger }"
       
  1011      d1   "{ Class: SmallInteger }"
       
  1012      d2   "{ Class: SmallInteger }"
       
  1013      otherDigitByteArray |
       
  1014 
       
  1015     len1 := digitByteArray size.
       
  1016     otherDigitByteArray := aLargeInteger digits.
       
  1017     len2 := otherDigitByteArray size.
       
  1018 
       
  1019     [(digitByteArray basicAt:len1) == 0] whileTrue:[
       
  1020 	len1 := len1 - 1
       
  1021     ].
       
  1022     [(otherDigitByteArray basicAt:len2) == 0] whileTrue:[
       
  1023 	len2 := len2 - 1
       
  1024     ].
       
  1025     (len1 ~~ len2) ifTrue:[^ false].
       
  1026     [len1 > 0] whileTrue:[
       
  1027 	d1 := digitByteArray basicAt:len1.
       
  1028 	d2 := otherDigitByteArray basicAt:len1.
       
  1029 	(d1 ~~ d2) ifTrue:[^ false].
       
  1030 	len1 := len1 - 1
       
  1031     ].
       
  1032     ^ true
       
  1033 !
       
  1034 
       
  1035 absFastDiv:aSmallInteger
       
  1036     "return an array with two LargeIntegers representing
       
  1037      abs(self) // aSmallInteger and abs(self) \\ aSmallInteger"
       
  1038 
       
  1039     |tmp1     "{ Class: SmallInteger }"
       
  1040      prevRest "{ Class: SmallInteger }"
       
  1041      count    "{ Class: SmallInteger }"
       
  1042      newDigitByteArray result
       
  1043      ok|
       
  1044 
       
  1045     aSmallInteger == 0 ifTrue:[
       
  1046 	^ DivisionByZeroSignal raise
       
  1047     ].
       
  1048 
       
  1049 "This cannot happen (if always normalized)
       
  1050     self < aSmallInteger ifTrue:[
       
  1051 	^ Array with:0 with:self
       
  1052     ].
       
  1053 "
       
  1054     count := digitByteArray size.
       
  1055     result := self class basicNew numberOfDigits:count.
       
  1056     newDigitByteArray := result digits.
       
  1057     ok := false.
       
  1058 %{
       
  1059     if (__isByteArray(_INST(digitByteArray))
       
  1060      && __isByteArray(newDigitByteArray)
       
  1061      && __bothSmallInteger(count, aSmallInteger)) {
       
  1062 	unsigned int rest = 0;
       
  1063 	int index = _intVal(count);
       
  1064 	int divisor = _intVal(aSmallInteger);
       
  1065 	unsigned char *digitBytes = _ByteArrayInstPtr(_INST(digitByteArray))->ba_element;
       
  1066 	unsigned char *resultBytes = _ByteArrayInstPtr(newDigitByteArray)->ba_element;
       
  1067 
       
  1068 	while (index > 0) {
       
  1069 	    unsigned int t;
       
  1070 
       
  1071 	    index--;
       
  1072 	    t = digitBytes[index];
       
  1073 	    t = t | (rest << 8);
       
  1074 	    resultBytes[index] = t / divisor;
       
  1075 	    rest = t % divisor;
       
  1076 	}
       
  1077 	prevRest = _MKSMALLINT(rest);
       
  1078 	ok = true;
       
  1079     }
       
  1080 %}.
       
  1081     "
       
  1082      slow code - not normally reached
       
  1083      (could also do a primitiveFailure here)
       
  1084     "
       
  1085     ok ifFalse:[
       
  1086 	prevRest := 0.
       
  1087 	count to:1 by:-1 do:[:i |
       
  1088 	    tmp1 := digitByteArray at:i.
       
  1089 	    tmp1 := (tmp1 + (prevRest * 256)).
       
  1090 	    newDigitByteArray at:i put:tmp1 // aSmallInteger.
       
  1091 	    prevRest := (tmp1 \\ aSmallInteger).
       
  1092 	]
       
  1093     ].
       
  1094 
       
  1095     ^ Array with:(result normalize) with:prevRest
   938 !
  1096 !
   939 
  1097 
   940 absFastMinus:aSmallInteger
  1098 absFastMinus:aSmallInteger
   941     "return a LargeInteger representing abs(self) - abs(theArgument).
  1099     "return a LargeInteger representing abs(self) - abs(theArgument).
   942      The result is not normalized."
  1100      The result is not normalized."
   984      (SmallInteger maxVal + 1) absFastMinus:1  
  1142      (SmallInteger maxVal + 1) absFastMinus:1  
   985      (SmallInteger minVal - 1) absFastMinus:1  
  1143      (SmallInteger minVal - 1) absFastMinus:1  
   986     "
  1144     "
   987 !
  1145 !
   988 
  1146 
   989 absFastDiv:aSmallInteger
  1147 absFastPlus:aSmallInteger
   990     "return an array with two LargeIntegers representing
  1148     "return a LargeInteger representing abs(self) + abs(theArgument).
   991      abs(self) // aSmallInteger and abs(self) \\ aSmallInteger"
  1149      The result is not normalized."
   992 
  1150 
   993     |tmp1     "{ Class: SmallInteger }"
  1151     |result resultDigitByteArray
   994      prevRest "{ Class: SmallInteger }"
  1152      len   "{ Class: SmallInteger }"
   995      count    "{ Class: SmallInteger }"
  1153      index "{ Class: SmallInteger }"
   996      newDigitByteArray result
  1154      carry "{ Class: SmallInteger }" |
   997      ok|
  1155 
   998 
  1156     len := digitByteArray size.
   999     aSmallInteger == 0 ifTrue:[
  1157 
  1000 	^ DivisionByZeroSignal raise
  1158     result := self class basicNew numberOfDigits:(len + 1).
  1001     ].
  1159     resultDigitByteArray := result digits.
  1002 
  1160 
  1003 "This cannot happen (if always normalized)
  1161     index := 1.
  1004     self < aSmallInteger ifTrue:[
  1162     carry := aSmallInteger abs.
  1005 	^ Array with:0 with:self
  1163 
  1006     ].
  1164     [carry ~~ 0] whileTrue:[
  1007 "
  1165 	(index <= len) ifTrue:[
  1008     count := digitByteArray size.
  1166 	    carry := (digitByteArray basicAt:index) + carry.
  1009     result := self class basicNew numberOfDigits:count.
  1167 	].
  1010     newDigitByteArray := result digits.
  1168 	resultDigitByteArray basicAt:index put:(carry bitAnd:16rFF).
  1011     ok := false.
  1169 	carry := carry bitShift:-8.
  1012 %{
  1170 	index := index + 1
  1013     if (__isByteArray(_INST(digitByteArray))
  1171     ].
  1014      && __isByteArray(newDigitByteArray)
  1172     [index <= len] whileTrue:[
  1015      && __bothSmallInteger(count, aSmallInteger)) {
  1173 	resultDigitByteArray basicAt:index put:(digitByteArray basicAt:index).
  1016 	unsigned int rest = 0;
  1174 	index := index + 1
  1017 	int index = _intVal(count);
  1175     ].
  1018 	int divisor = _intVal(aSmallInteger);
  1176 
  1019 	unsigned char *digitBytes = _ByteArrayInstPtr(_INST(digitByteArray))->ba_element;
  1177     ^ result
  1020 	unsigned char *resultBytes = _ByteArrayInstPtr(newDigitByteArray)->ba_element;
  1178 !
  1021 
  1179 
  1022 	while (index > 0) {
  1180 absLess:aLargeInteger
  1023 	    unsigned int t;
  1181     "return true, if abs(self) < abs(theArgument)"
  1024 
  1182 
  1025 	    index--;
  1183     |len1 "{ Class: SmallInteger }"
  1026 	    t = digitBytes[index];
  1184      len2 "{ Class: SmallInteger }"
  1027 	    t = t | (rest << 8);
  1185      d1   "{ Class: SmallInteger }"
  1028 	    resultBytes[index] = t / divisor;
  1186      d2   "{ Class: SmallInteger }"
  1029 	    rest = t % divisor;
  1187      otherDigitByteArray |
  1030 	}
  1188 
  1031 	prevRest = _MKSMALLINT(rest);
  1189     len1 := digitByteArray size.
  1032 	ok = true;
  1190     otherDigitByteArray := aLargeInteger digits.
  1033     }
  1191     len2 := otherDigitByteArray size.
  1034 %}.
  1192 
  1035     "
  1193     [(digitByteArray basicAt:len1) == 0] whileTrue:[
  1036      slow code - not normally reached
  1194 	len1 := len1 - 1
  1037      (could also do a primitiveFailure here)
  1195     ].
  1038     "
  1196     [(otherDigitByteArray basicAt:len2) == 0] whileTrue:[
  1039     ok ifFalse:[
  1197 	len2 := len2 - 1
  1040 	prevRest := 0.
  1198     ].
  1041 	count to:1 by:-1 do:[:i |
  1199     (len1 < len2) ifTrue:[^ true].
  1042 	    tmp1 := digitByteArray at:i.
  1200     (len1 > len2) ifTrue:[^ false].
  1043 	    tmp1 := (tmp1 + (prevRest * 256)).
  1201 
  1044 	    newDigitByteArray at:i put:tmp1 // aSmallInteger.
  1202     [len1 > 0] whileTrue:[
  1045 	    prevRest := (tmp1 \\ aSmallInteger).
  1203 	d1 := digitByteArray basicAt:len1.
  1046 	]
  1204 	d2 := otherDigitByteArray basicAt:len1.
  1047     ].
  1205 	(d1 < d2) ifTrue:[^ true].
  1048 
  1206 	(d1 > d2) ifTrue:[^ false].
  1049     ^ Array with:(result normalize) with:prevRest
  1207 	len1 := len1 - 1
       
  1208     ].
       
  1209     ^ false
       
  1210 !
       
  1211 
       
  1212 absMinus:aLargeInteger
       
  1213     "return a LargeInteger representing abs(self) - abs(theArgument)"
       
  1214 
       
  1215     |result done
       
  1216      otherDigitByteArray resultDigitByteArray
       
  1217      len1   "{ Class: SmallInteger }"
       
  1218      len2   "{ Class: SmallInteger }"
       
  1219      index  "{ Class: SmallInteger }"
       
  1220      borrow "{ Class: SmallInteger }"
       
  1221      diff   "{ Class: SmallInteger }"
       
  1222      sum    "{ Class: SmallInteger }"
       
  1223      carry  "{ Class: SmallInteger }" |
       
  1224 
       
  1225     len1 := digitByteArray size.
       
  1226     otherDigitByteArray := aLargeInteger digits.
       
  1227     len2 := otherDigitByteArray size.
       
  1228 
       
  1229     result := self class basicNew numberOfDigits:((len1 max: len2) + 1).
       
  1230     resultDigitByteArray := result digits.
       
  1231 
       
  1232     index := 1.
       
  1233     borrow := 0.
       
  1234 
       
  1235     done := false.
       
  1236     [done] whileFalse:[
       
  1237 	diff := borrow.
       
  1238 	(index <= len1) ifTrue:[
       
  1239 	    diff := diff + (digitByteArray basicAt:index).
       
  1240 	    (index <= len2) ifTrue:[
       
  1241 		diff := diff - (otherDigitByteArray basicAt:index)
       
  1242 	    ]
       
  1243 	] ifFalse:[
       
  1244 	    (index <= len2) ifTrue:[
       
  1245 		diff := diff - (otherDigitByteArray basicAt:index)
       
  1246 	    ] ifFalse:[
       
  1247 		"end reached"
       
  1248 		done := true
       
  1249 	    ]
       
  1250 	].
       
  1251 "/ workaround for
       
  1252 "/ gcc code generator bug
       
  1253 "/
       
  1254 
       
  1255 (diff >= 0) ifTrue:[
       
  1256     borrow := 0
       
  1257 ] ifFalse:[
       
  1258     borrow := -1.
       
  1259     diff := diff + 16r100
       
  1260 ].
       
  1261 "/        (diff < 0) ifTrue:[
       
  1262 "/            borrow := -1.
       
  1263 "/            diff := diff + 16r100
       
  1264 "/        ] ifFalse:[
       
  1265 "/            borrow := 0
       
  1266 "/        ].
       
  1267 	resultDigitByteArray basicAt:index put:diff.
       
  1268 	index := index + 1
       
  1269     ].
       
  1270     (borrow ~~ 0) ifTrue:[
       
  1271 	result sign: -1.
       
  1272 	carry := 0.
       
  1273 	1 to:(index - 1) do:[:i |
       
  1274 	    sum := ((resultDigitByteArray at:i) + carry - 16r100) negated.
       
  1275 	    resultDigitByteArray at:i put:sum.
       
  1276 	    carry := 1
       
  1277 	]
       
  1278     ].
       
  1279     ^ result normalize
  1050 !
  1280 !
  1051 
  1281 
  1052 absMul:aLargeInteger
  1282 absMul:aLargeInteger
  1053     "return a LargeInteger representing abs(self) * abs(theArgument)"
  1283     "return a LargeInteger representing abs(self) * abs(theArgument)"
  1054 
  1284 
  1121 	].
  1351 	].
  1122     ].
  1352     ].
  1123     ^ result normalize
  1353     ^ result normalize
  1124 !
  1354 !
  1125 
  1355 
  1126 absLess:aLargeInteger
       
  1127     "return true, if abs(self) < abs(theArgument)"
       
  1128 
       
  1129     |len1 "{ Class: SmallInteger }"
       
  1130      len2 "{ Class: SmallInteger }"
       
  1131      d1   "{ Class: SmallInteger }"
       
  1132      d2   "{ Class: SmallInteger }"
       
  1133      otherDigitByteArray |
       
  1134 
       
  1135     len1 := digitByteArray size.
       
  1136     otherDigitByteArray := aLargeInteger digits.
       
  1137     len2 := otherDigitByteArray size.
       
  1138 
       
  1139     [(digitByteArray basicAt:len1) == 0] whileTrue:[
       
  1140 	len1 := len1 - 1
       
  1141     ].
       
  1142     [(otherDigitByteArray basicAt:len2) == 0] whileTrue:[
       
  1143 	len2 := len2 - 1
       
  1144     ].
       
  1145     (len1 < len2) ifTrue:[^ true].
       
  1146     (len1 > len2) ifTrue:[^ false].
       
  1147 
       
  1148     [len1 > 0] whileTrue:[
       
  1149 	d1 := digitByteArray basicAt:len1.
       
  1150 	d2 := otherDigitByteArray basicAt:len1.
       
  1151 	(d1 < d2) ifTrue:[^ true].
       
  1152 	(d1 > d2) ifTrue:[^ false].
       
  1153 	len1 := len1 - 1
       
  1154     ].
       
  1155     ^ false
       
  1156 !
       
  1157 
       
  1158 absEq:aLargeInteger
       
  1159     "return true, if abs(self) = abs(theArgument)"
       
  1160 
       
  1161     |len1 "{ Class: SmallInteger }"
       
  1162      len2 "{ Class: SmallInteger }"
       
  1163      d1   "{ Class: SmallInteger }"
       
  1164      d2   "{ Class: SmallInteger }"
       
  1165      otherDigitByteArray |
       
  1166 
       
  1167     len1 := digitByteArray size.
       
  1168     otherDigitByteArray := aLargeInteger digits.
       
  1169     len2 := otherDigitByteArray size.
       
  1170 
       
  1171     [(digitByteArray basicAt:len1) == 0] whileTrue:[
       
  1172 	len1 := len1 - 1
       
  1173     ].
       
  1174     [(otherDigitByteArray basicAt:len2) == 0] whileTrue:[
       
  1175 	len2 := len2 - 1
       
  1176     ].
       
  1177     (len1 ~~ len2) ifTrue:[^ false].
       
  1178     [len1 > 0] whileTrue:[
       
  1179 	d1 := digitByteArray basicAt:len1.
       
  1180 	d2 := otherDigitByteArray basicAt:len1.
       
  1181 	(d1 ~~ d2) ifTrue:[^ false].
       
  1182 	len1 := len1 - 1
       
  1183     ].
       
  1184     ^ true
       
  1185 !
       
  1186 
       
  1187 absPlus:aLargeInteger
  1356 absPlus:aLargeInteger
  1188     "return a LargeInteger representing abs(self) + abs(theArgument)"
  1357     "return a LargeInteger representing abs(self) + abs(theArgument)"
  1189 
  1358 
  1190     |result done otherDigitByteArray resultDigitByteArray
  1359     |result done otherDigitByteArray resultDigitByteArray
  1191      len1  "{ Class: SmallInteger }"
  1360      len1  "{ Class: SmallInteger }"
  1230 	index := index + 1
  1399 	index := index + 1
  1231     ].
  1400     ].
  1232     ^ result normalize
  1401     ^ result normalize
  1233 !
  1402 !
  1234 
  1403 
  1235 absMinus:aLargeInteger
       
  1236     "return a LargeInteger representing abs(self) - abs(theArgument)"
       
  1237 
       
  1238     |result done
       
  1239      otherDigitByteArray resultDigitByteArray
       
  1240      len1   "{ Class: SmallInteger }"
       
  1241      len2   "{ Class: SmallInteger }"
       
  1242      index  "{ Class: SmallInteger }"
       
  1243      borrow "{ Class: SmallInteger }"
       
  1244      diff   "{ Class: SmallInteger }"
       
  1245      sum    "{ Class: SmallInteger }"
       
  1246      carry  "{ Class: SmallInteger }" |
       
  1247 
       
  1248     len1 := digitByteArray size.
       
  1249     otherDigitByteArray := aLargeInteger digits.
       
  1250     len2 := otherDigitByteArray size.
       
  1251 
       
  1252     result := self class basicNew numberOfDigits:((len1 max: len2) + 1).
       
  1253     resultDigitByteArray := result digits.
       
  1254 
       
  1255     index := 1.
       
  1256     borrow := 0.
       
  1257 
       
  1258     done := false.
       
  1259     [done] whileFalse:[
       
  1260 	diff := borrow.
       
  1261 	(index <= len1) ifTrue:[
       
  1262 	    diff := diff + (digitByteArray basicAt:index).
       
  1263 	    (index <= len2) ifTrue:[
       
  1264 		diff := diff - (otherDigitByteArray basicAt:index)
       
  1265 	    ]
       
  1266 	] ifFalse:[
       
  1267 	    (index <= len2) ifTrue:[
       
  1268 		diff := diff - (otherDigitByteArray basicAt:index)
       
  1269 	    ] ifFalse:[
       
  1270 		"end reached"
       
  1271 		done := true
       
  1272 	    ]
       
  1273 	].
       
  1274 "/ workaround for
       
  1275 "/ gcc code generator bug
       
  1276 "/
       
  1277 
       
  1278 (diff >= 0) ifTrue:[
       
  1279     borrow := 0
       
  1280 ] ifFalse:[
       
  1281     borrow := -1.
       
  1282     diff := diff + 16r100
       
  1283 ].
       
  1284 "/        (diff < 0) ifTrue:[
       
  1285 "/            borrow := -1.
       
  1286 "/            diff := diff + 16r100
       
  1287 "/        ] ifFalse:[
       
  1288 "/            borrow := 0
       
  1289 "/        ].
       
  1290 	resultDigitByteArray basicAt:index put:diff.
       
  1291 	index := index + 1
       
  1292     ].
       
  1293     (borrow ~~ 0) ifTrue:[
       
  1294 	result sign: -1.
       
  1295 	carry := 0.
       
  1296 	1 to:(index - 1) do:[:i |
       
  1297 	    sum := ((resultDigitByteArray at:i) + carry - 16r100) negated.
       
  1298 	    resultDigitByteArray at:i put:sum.
       
  1299 	    carry := 1
       
  1300 	]
       
  1301     ].
       
  1302     ^ result normalize
       
  1303 !
       
  1304 
       
  1305 absDiv:anInteger
       
  1306     "return an array with two LargeIntegers representing
       
  1307      abs(self) // abs(theArgument) and abs(self) \\ abs(theArgument).
       
  1308      This needs a rewrite."
       
  1309 
       
  1310     |tmp1 tmp2 
       
  1311      rem 
       
  1312      count "{ Class: SmallInteger }"
       
  1313      digit "{ Class: SmallInteger }" |
       
  1314 
       
  1315     anInteger == 0 ifTrue:[
       
  1316 	^ DivisionByZeroSignal raise
       
  1317     ].
       
  1318 
       
  1319     self < anInteger ifTrue:[
       
  1320 	^ Array with:0 with:self
       
  1321     ].
       
  1322 
       
  1323     tmp1 := self simpleDeepCopy.
       
  1324     tmp2 := anInteger simpleDeepCopy.
       
  1325     count := 0.
       
  1326     [tmp2 < tmp1] whileTrue:[
       
  1327 	tmp2 mul256.
       
  1328 	count := count + 1
       
  1329     ].
       
  1330 
       
  1331     tmp2 div256.
       
  1332 
       
  1333     rem := 0 asLargeInteger. 
       
  1334     [count == 0] whileFalse:[
       
  1335 	digit := 0.
       
  1336 	[tmp1 >= tmp2] whileTrue:[
       
  1337 	    digit := digit + 1.
       
  1338 	    tmp1 := tmp1 - tmp2
       
  1339 	].
       
  1340 	rem := rem * 256 + digit.
       
  1341 	tmp2 div256.
       
  1342 	count := count - 1
       
  1343     ].
       
  1344     ^ Array with:rem with:tmp1 
       
  1345 !
       
  1346 
       
  1347 div256
  1404 div256
  1348     "destructively divide the receiver by 256.
  1405     "destructively divide the receiver by 256.
  1349      private - used for division only"
  1406      private - used for division only"
  1350 
  1407 
  1351     digitByteArray replaceFrom:1 with:digitByteArray startingAt:2.
  1408     digitByteArray replaceFrom:1 with:digitByteArray startingAt:2.
  1360 
  1417 
  1361     newDigits := ByteArray uninitializedNew:(digitByteArray size + 1).
  1418     newDigits := ByteArray uninitializedNew:(digitByteArray size + 1).
  1362     newDigits replaceFrom:2 with:digitByteArray startingAt:1.
  1419     newDigits replaceFrom:2 with:digitByteArray startingAt:1.
  1363     newDigits at:1 put:0.
  1420     newDigits at:1 put:0.
  1364     digitByteArray := newDigits
  1421     digitByteArray := newDigits
       
  1422 !
       
  1423 
       
  1424 numberOfDigits:nDigits
       
  1425     digitByteArray := ByteArray new:nDigits.
       
  1426     sign := 1.
       
  1427 !
       
  1428 
       
  1429 setDigits:digits
       
  1430     digitByteArray := digits.
       
  1431     sign := 1.
       
  1432 !
       
  1433 
       
  1434 sign:aNumber
       
  1435     sign := aNumber
  1365 ! !
  1436 ! !
  1366 
  1437 
  1367 !LargeInteger methodsFor:'comparing'!
       
  1368 
       
  1369 = aNumber
       
  1370     "return true, if the argument, aNumber has the same value as
       
  1371      the receiver"
       
  1372 
       
  1373     (aNumber class == self class) ifFalse:[
       
  1374 	aNumber respondsToArithmetic ifFalse:[ ^ false ].
       
  1375 	^ self retry:#= coercing:aNumber
       
  1376     ].
       
  1377     (aNumber sign == sign) ifFalse:[^ false].
       
  1378     ^ self absEq:aNumber
       
  1379 !
       
  1380 
       
  1381 < aNumber
       
  1382     "return true, if the argument, aNumber is greater than the receiver"
       
  1383 
       
  1384     |otherSign|
       
  1385 
       
  1386     (aNumber class == self class) ifFalse:[
       
  1387 	^ self retry:#< coercing:aNumber
       
  1388     ].
       
  1389     otherSign := aNumber sign.
       
  1390 
       
  1391     (sign > 0) ifTrue:[
       
  1392 	"I am positive"
       
  1393 	(otherSign > 0) ifTrue:[^ self absLess:aNumber].
       
  1394 	^ false "aNumber is <= 0"
       
  1395     ].
       
  1396     (sign == 0) ifTrue:[
       
  1397 	(otherSign > 0) ifTrue:[^ true].
       
  1398 	^ false
       
  1399     ].
       
  1400     "I am negative"
       
  1401     (otherSign > 0) ifTrue:[^ true].
       
  1402     (otherSign == 0) ifTrue:[^ true].
       
  1403     ^ (self absLess:aNumber) not
       
  1404 !
       
  1405 
       
  1406 > aNumber
       
  1407     "return true, if the argument, aNumber is less than the receiver"
       
  1408 
       
  1409     |otherSign|
       
  1410 
       
  1411     (aNumber class == self class) ifFalse:[
       
  1412 	^ self retry:#> coercing:aNumber
       
  1413     ].
       
  1414     otherSign := aNumber sign.
       
  1415 
       
  1416     (sign > 0) ifTrue:[
       
  1417 	"I am positive"
       
  1418 	(otherSign > 0) ifTrue:[^ aNumber absLess:self].
       
  1419 	^ true "aNumber is <= 0"
       
  1420     ].
       
  1421     (sign == 0) ifTrue:[
       
  1422 	"I am zero"
       
  1423 	(otherSign > 0) ifTrue:[^ false].
       
  1424 	^ true
       
  1425     ].
       
  1426     "I am negative"
       
  1427     (otherSign > 0) ifTrue:[^ false].
       
  1428     (otherSign == 0) ifTrue:[^ false].
       
  1429     ^ (self absLess:aNumber) not
       
  1430 ! !
       
  1431 
       
  1432 !LargeInteger methodsFor:'testing'!
  1438 !LargeInteger methodsFor:'testing'!
       
  1439 
       
  1440 even
       
  1441     "return true if the receiver is even"
       
  1442 
       
  1443     ^ (digitByteArray at:1) even
       
  1444 !
       
  1445 
       
  1446 negative
       
  1447     "return true, if the receiver is < 0"
       
  1448 
       
  1449     ^ (sign < 0)
       
  1450 !
       
  1451 
       
  1452 odd
       
  1453     "return true if the receiver is odd"
       
  1454 
       
  1455     ^ (digitByteArray at:1) even
       
  1456 !
       
  1457 
       
  1458 positive
       
  1459     "return true, if the receiver is >= 0"
       
  1460 
       
  1461     ^ (sign >= 0)
       
  1462 !
  1433 
  1463 
  1434 sign
  1464 sign
  1435     "return the sign of the receiver"
  1465     "return the sign of the receiver"
  1436 
  1466 
  1437     ^ sign
  1467     ^ sign
  1438 !
  1468 !
  1439 
  1469 
  1440 negative
       
  1441     "return true, if the receiver is < 0"
       
  1442 
       
  1443     ^ (sign < 0)
       
  1444 !
       
  1445 
       
  1446 odd
       
  1447     "return true if the receiver is odd"
       
  1448 
       
  1449     ^ (digitByteArray at:1) even
       
  1450 !
       
  1451 
       
  1452 even
       
  1453     "return true if the receiver is even"
       
  1454 
       
  1455     ^ (digitByteArray at:1) even
       
  1456 !
       
  1457 
       
  1458 positive
       
  1459     "return true, if the receiver is >= 0"
       
  1460 
       
  1461     ^ (sign >= 0)
       
  1462 !
       
  1463 
       
  1464 strictlyPositive
  1470 strictlyPositive
  1465     "return true, if the receiver is > 0"
  1471     "return true, if the receiver is > 0"
  1466 
  1472 
  1467     ^ (sign > 0)
  1473     ^ (sign > 0)
  1468 ! !
  1474 ! !
  1469 
  1475 
  1470 !LargeInteger methodsFor:'printing & storing'!
  1476 !LargeInteger class methodsFor:'documentation'!
  1471 
  1477 
  1472 storeOn:aStream
  1478 version
  1473     "append a representation of the receiver to aStream, which can
  1479     ^ '$Header: /cvs/stx/stx/libbasic/LargeInteger.st,v 1.21 1995-12-07 21:35:26 cg Exp $'
  1474      be used to reconstruct the receiver."
       
  1475 
       
  1476     self printOn:aStream.
       
  1477     aStream nextPutAll:' asLargeInteger'
       
  1478 ! !
  1480 ! !