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| |
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 |
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 ! ! |