53 LargeIntegers are usually not created explicitely, but result from |
53 LargeIntegers are usually not created explicitely, but result from |
54 SmallInteger arithmetic (overflowing the SmallInteger range). |
54 SmallInteger arithmetic (overflowing the SmallInteger range). |
55 Also, results of LargeInteger operations are converted to back to |
55 Also, results of LargeInteger operations are converted to back to |
56 SmallIntegers, when possible (see #compressed). |
56 SmallIntegers, when possible (see #compressed). |
57 |
57 |
58 In contrast to ST-80, there is only one class for LargeIntegers, |
58 In contrast to ST-80, there is only one class for LargeIntegers, |
59 which keeps the sign as an instance variable |
59 which keeps the sign as an instance variable |
60 (ST-80 has LargePositiveInteger and LargeNegativeInteger). |
60 (ST-80 has LargePositiveInteger and LargeNegativeInteger). |
61 Another possible change is to use 2's complement instead of sign-magnitude |
61 Another possible change is to use 2's complement instead of sign-magnitude |
62 representation, and to use the underlying CPU's native byte order (instead of LSB). |
62 representation, and to use the underlying CPU's native byte order (instead of LSB). |
63 This would allow us to use modern CPU vector/longword operations, at least for 64 and |
63 This would allow us to use modern CPU vector/longword operations, at least for 64 and |
64 128 bit numbers (which make up almost all instances in practice). |
64 128 bit numbers (which make up almost all instances in practice). |
65 As all of these are transparent to the outside world, any of it may or may not |
65 As all of these are transparent to the outside world, any of it may or may not |
66 change in the future. |
66 change in the future. |
67 |
67 |
68 [author:] |
68 [author:] |
69 Claus Gittinger |
69 Claus Gittinger |
70 |
70 |
71 [see also:] |
71 [see also:] |
72 Number |
72 Number |
73 Float Fraction FixedPoint |
73 Float Fraction FixedPoint |
74 SmallInteger |
74 SmallInteger |
75 " |
75 " |
76 ! |
76 ! |
77 |
77 |
78 testing |
78 testing |
79 " |
79 " |
477 "Modified: 28.7.1997 / 19:07:55 / cg" |
477 "Modified: 28.7.1997 / 19:07:55 / cg" |
478 ! |
478 ! |
479 |
479 |
480 // aNumber |
480 // aNumber |
481 "return the integer part of the quotient of the receivers value |
481 "return the integer part of the quotient of the receivers value |
482 and the arguments value. |
482 and the arguments value. |
483 The result is truncated toward negative infinity |
483 The result is truncated toward negative infinity |
484 and will be negative, if the operands signs differ. |
484 and will be negative, if the operands signs differ. |
485 The following is always true: |
485 The following is always true: |
486 (receiver // aNumber) * aNumber + (receiver \\ aNumber) = receiver |
486 (receiver // aNumber) * aNumber + (receiver \\ aNumber) = receiver |
487 |
487 |
488 Be careful with negative results: 9 // 4 -> 2, while -9 // 4 -> -3. |
488 Be careful with negative results: 9 // 4 -> 2, while -9 // 4 -> -3. |
489 Especially surprising: |
489 Especially surprising: |
490 -1 // 10 -> -1 (because -(1/10) is truncated towards next smaller integer, which is -1. |
490 -1 // 10 -> -1 (because -(1/10) is truncated towards next smaller integer, which is -1. |
491 -10 // 3 -> -4 (because -(10/3) is truncated towards next smaller integer, which is -4. |
491 -10 // 3 -> -4 (because -(10/3) is truncated towards next smaller integer, which is -4. |
492 |
492 |
493 See #quo: which returns -2 in the above case and #rem: which is the corresponding remainder." |
493 See #quo: which returns -2 in the above case and #rem: which is the corresponding remainder." |
494 |
494 |
495 |cls divMod quo abs "{ Class: SmallInteger }" n| |
495 |cls divMod quo abs "{ Class: SmallInteger }" n| |
496 |
496 |
500 " |
500 " |
501 this is the common case, dividing by a SmallInteger. |
501 this is the common case, dividing by a SmallInteger. |
502 Use a special method for this case ... |
502 Use a special method for this case ... |
503 " |
503 " |
504 (cls == SmallInteger) ifTrue:[ |
504 (cls == SmallInteger) ifTrue:[ |
505 abs := aNumber. |
505 abs := aNumber. |
506 abs := abs abs. |
506 abs := abs abs. |
507 (abs between:1 and:(SmallInteger maxBytes == 8 ifTrue:16r00ffffffffff ifFalse:16r00ffffff)) ifTrue:[ |
507 (abs between:1 and:(SmallInteger maxBytes == 8 ifTrue:16r00ffffffffff ifFalse:16r00ffffff)) ifTrue:[ |
508 divMod := self absFastDivMod:abs. |
508 divMod := self absFastDivMod:abs. |
509 ] ifFalse:[ |
509 ] ifFalse:[ |
510 n := abs asLargeInteger. |
510 n := abs asLargeInteger. |
511 ]. |
511 ]. |
512 ] ifFalse:[ |
512 ] ifFalse:[ |
513 " |
513 " |
514 if the argument is not a largeInteger, coerce |
514 if the argument is not a largeInteger, coerce |
515 " |
515 " |
516 (cls == self class) ifFalse:[ |
516 (cls == self class) ifFalse:[ |
517 ^ self retry:#// coercing:aNumber |
517 ^ self retry:#// coercing:aNumber |
518 ]. |
518 ]. |
519 n := aNumber |
519 n := aNumber |
520 ]. |
520 ]. |
521 |
521 |
522 divMod isNil ifTrue:[ |
522 divMod isNil ifTrue:[ |
523 divMod := self absDivMod:n. |
523 divMod := self absDivMod:n. |
524 ]. |
524 ]. |
525 quo := divMod at:1. |
525 quo := divMod at:1. |
526 (sign == aNumber sign) ifFalse:[ |
526 (sign == aNumber sign) ifFalse:[ |
527 "/ adjust for truncation if negative and there is a remainder ... |
527 "/ adjust for truncation if negative and there is a remainder ... |
528 "/ be careful: there is one special case to care for here: |
528 "/ be careful: there is one special case to care for here: |
529 "/ if quo is maxInt+1, the negation can be represented as a smallInt. |
529 "/ if quo is maxInt+1, the negation can be represented as a smallInt. |
530 quo := quo sign:-1. |
530 quo := quo sign:-1. |
531 (divMod at:2) == 0 ifFalse:[ |
531 (divMod at:2) == 0 ifFalse:[ |
532 ^ quo - 1 |
532 ^ quo - 1 |
533 ]. |
533 ]. |
534 quo digitLength == SmallInteger maxBytes ifTrue:[ |
534 quo digitLength == SmallInteger maxBytes ifTrue:[ |
535 ^ quo compressed |
535 ^ quo compressed |
536 ]. |
536 ]. |
537 ]. |
537 ]. |
538 ^ quo |
538 ^ quo |
539 |
539 |
540 " |
540 " |
541 (9000000000 // 4000000000) = (900 // 400) ifFalse:[self halt]. |
541 (9000000000 // 4000000000) = (900 // 400) ifFalse:[self halt]. |
564 "Modified: / 27.4.1999 / 19:50:26 / stefan" |
564 "Modified: / 27.4.1999 / 19:50:26 / stefan" |
565 ! |
565 ! |
566 |
566 |
567 \\ aNumber |
567 \\ aNumber |
568 "Answer the integer remainder m defined by division with truncation toward |
568 "Answer the integer remainder m defined by division with truncation toward |
569 negative infinity. |
569 negative infinity. |
570 m < |aNumber| AND there is an integer k with (k * aNumber + m) = self |
570 m < |aNumber| AND there is an integer k with (k * aNumber + m) = self |
571 |
571 |
572 The returned remainder has the same sign as aNumber. |
572 The returned remainder has the same sign as aNumber. |
573 The following is always true: |
573 The following is always true: |
574 (receiver // aNumber) * aNumber + (receiver \\ aNumber) = receiver |
574 (receiver // aNumber) * aNumber + (receiver \\ aNumber) = receiver |
575 |
575 |
576 Be careful with negative results: 9 // 4 -> 2, while -9 // 4 -> -3. |
576 Be careful with negative results: 9 // 4 -> 2, while -9 // 4 -> -3. |
577 Especially surprising: |
577 Especially surprising: |
578 -1 \\ 10 -> 9 (because -(1/10) is truncated towards next smaller integer, which is -1, |
578 -1 \\ 10 -> 9 (because -(1/10) is truncated towards next smaller integer, which is -1, |
579 and -1 multiplied by 10 gives -10, so we have to add 9 to get the original -1). |
579 and -1 multiplied by 10 gives -10, so we have to add 9 to get the original -1). |
580 -10 \\ 3 -> 2 (because -(10/3) is truncated towards next smaller integer, which is -4, |
580 -10 \\ 3 -> 2 (because -(10/3) is truncated towards next smaller integer, which is -4, |
581 and -4 * 4 gives -12, so we need to add 2 to get the original -10. |
581 and -4 * 4 gives -12, so we need to add 2 to get the original -10. |
582 |
582 |
583 See #rem: which is the corresponding remainder for division via #quo:. |
583 See #rem: which is the corresponding remainder for division via #quo:. |
584 |
584 |
585 Redefined here for speed." |
585 Redefined here for speed." |
586 |
586 |
587 |abs rem negativeDivisor| |
587 |abs rem negativeDivisor| |
588 |
588 |
589 aNumber negative ifTrue:[ |
589 aNumber negative ifTrue:[ |
590 negativeDivisor := true. |
590 negativeDivisor := true. |
591 abs := aNumber negated. |
591 abs := aNumber negated. |
592 ] ifFalse:[ |
592 ] ifFalse:[ |
593 negativeDivisor := false. |
593 negativeDivisor := false. |
594 abs := aNumber. |
594 abs := aNumber. |
595 ]. |
595 ]. |
596 |
596 |
597 " |
597 " |
598 this is the common case, dividing by a SmallInteger. |
598 this is the common case, dividing by a SmallInteger. |
599 Use a special method for this case ... |
599 Use a special method for this case ... |
600 " |
600 " |
601 (aNumber class == SmallInteger) ifTrue:[ |
601 (aNumber class == SmallInteger) ifTrue:[ |
602 (abs between:1 and:(SmallInteger maxBytes == 8 ifTrue:16r00ffffffffff ifFalse:16r00ffffff)) ifTrue:[ |
602 (abs between:1 and:(SmallInteger maxBytes == 8 ifTrue:16r00ffffffffff ifFalse:16r00ffffff)) ifTrue:[ |
603 rem := (self absFastDivMod:abs) at:2. |
603 rem := (self absFastDivMod:abs) at:2. |
604 ] ifFalse:[ |
604 ] ifFalse:[ |
605 rem := self absMod:abs asLargeInteger |
605 rem := self absMod:abs asLargeInteger |
606 ]. |
606 ]. |
607 ] ifFalse:[ |
607 ] ifFalse:[ |
608 " |
608 " |
609 if the argument is not a largeInteger, coerce |
609 if the argument is not a largeInteger, coerce |
610 " |
610 " |
611 (aNumber class == self class) ifFalse:[ |
611 (aNumber class == self class) ifFalse:[ |
612 ^ self retry:#\\ coercing:aNumber |
612 ^ self retry:#\\ coercing:aNumber |
613 ]. |
613 ]. |
614 |
614 |
615 rem := self absMod:abs. |
615 rem := self absMod:abs. |
616 ]. |
616 ]. |
617 |
617 |
618 rem = 0 ifFalse:[ |
618 rem = 0 ifFalse:[ |
619 negativeDivisor ifTrue:[ |
619 negativeDivisor ifTrue:[ |
620 rem := rem sign:-1 |
620 rem := rem sign:-1 |
621 ]. |
621 ]. |
622 (self negative ~~ negativeDivisor) ifTrue:[ |
622 (self negative ~~ negativeDivisor) ifTrue:[ |
623 "different sign, so remainder would have been negative. |
623 "different sign, so remainder would have been negative. |
624 rem has been rounded toward zero, this code will simulate |
624 rem has been rounded toward zero, this code will simulate |
625 rounding to negative infinity." |
625 rounding to negative infinity." |
626 |
626 |
627 rem := aNumber - rem. |
627 rem := aNumber - rem. |
628 ]. |
628 ]. |
629 ]. |
629 ]. |
630 ^ rem |
630 ^ rem |
631 |
631 |
632 " |
632 " |
633 (9000000000 \\ 4000000000) = (900 \\ 400 * 10000000) ifFalse:[self halt]. |
633 (9000000000 \\ 4000000000) = (900 \\ 400 * 10000000) ifFalse:[self halt]. |
667 |
667 |
668 "Created: / 26.10.1999 / 21:28:06 / stefan" |
668 "Created: / 26.10.1999 / 21:28:06 / stefan" |
669 ! |
669 ! |
670 |
670 |
671 divMod:aNumber |
671 divMod:aNumber |
672 "return an array filled with |
672 "return an array filled with |
673 (self // aNumber) and (self \\ aNumber). |
673 (self // aNumber) and (self \\ aNumber). |
674 The returned remainder has the same sign as aNumber. |
674 The returned remainder has the same sign as aNumber. |
675 The following is always true: |
675 The following is always true: |
676 (receiver // something) * something + (receiver \\ something) = receiver |
676 (receiver // something) * something + (receiver \\ something) = receiver |
677 |
677 |
678 Be careful with negative results: 9 // 4 -> 2, while -9 // 4 -> -3. |
678 Be careful with negative results: 9 // 4 -> 2, while -9 // 4 -> -3. |
679 Especially surprising: |
679 Especially surprising: |
680 -1 \\ 10 -> 9 (because -(1/10) is truncated towards next smaller integer, which is -1, |
680 -1 \\ 10 -> 9 (because -(1/10) is truncated towards next smaller integer, which is -1, |
681 and -1 multiplied by 10 gives -10, so we have to add 9 to get the original -1). |
681 and -1 multiplied by 10 gives -10, so we have to add 9 to get the original -1). |
682 -10 \\ 3 -> 2 (because -(10/3) is truncated towards next smaller integer, which is -4, |
682 -10 \\ 3 -> 2 (because -(10/3) is truncated towards next smaller integer, which is -4, |
683 and -4 * 4 gives -12, so we need to add 2 to get the original -10. |
683 and -4 * 4 gives -12, so we need to add 2 to get the original -10. |
684 |
684 |
685 This is redefined here for more performance |
685 This is redefined here for more performance |
686 (as the remainder is generated as a side effect of division)" |
686 (as the remainder is generated as a side effect of division)" |
687 |
687 |
688 |cls n| |
688 |cls n| |
689 |
689 |
690 ((self < 0) or:[aNumber <= 0]) ifTrue:[ |
690 ((self < 0) or:[aNumber <= 0]) ifTrue:[ |
691 ^ super divMod:aNumber |
691 ^ super divMod:aNumber |
692 ]. |
692 ]. |
693 |
693 |
694 "/ only handle the common case here |
694 "/ only handle the common case here |
695 cls := aNumber class. |
695 cls := aNumber class. |
696 (cls == SmallInteger) ifTrue:[ |
696 (cls == SmallInteger) ifTrue:[ |
697 " |
697 " |
698 this is the common case, dividing by a SmallInteger. |
698 this is the common case, dividing by a SmallInteger. |
699 Use a special method for this case ... |
699 Use a special method for this case ... |
700 " |
700 " |
701 (aNumber between:1 and:(SmallInteger maxBytes == 8 ifTrue:16r00ffffffffff ifFalse:16r00ffffff)) ifTrue:[ |
701 (aNumber between:1 and:(SmallInteger maxBytes == 8 ifTrue:16r00ffffffffff ifFalse:16r00ffffff)) ifTrue:[ |
702 ^ self absFastDivMod:aNumber abs. |
702 ^ self absFastDivMod:aNumber abs. |
703 ]. |
703 ]. |
704 n := aNumber asLargeInteger. |
704 n := aNumber asLargeInteger. |
705 ] ifFalse:[ |
705 ] ifFalse:[ |
706 (cls == self class) ifFalse:[ |
706 (cls == self class) ifFalse:[ |
707 ^ super divMod:aNumber |
707 ^ super divMod:aNumber |
708 ]. |
708 ]. |
709 n := aNumber. |
709 n := aNumber. |
710 ]. |
710 ]. |
711 |
711 |
712 ^ self absDivMod:n abs. |
712 ^ self absDivMod:n abs. |
713 |
713 |
714 " |
714 " |
1550 ! |
1550 ! |
1551 |
1551 |
1552 digitAt:index |
1552 digitAt:index |
1553 "return 8 bits of value, starting at byte index" |
1553 "return 8 bits of value, starting at byte index" |
1554 |
1554 |
|
1555 %{ |
|
1556 #ifdef __JAVA__ |
|
1557 return context._RETURN( ((STLargeInteger)self).digitAt( index.intValue() ) ); |
|
1558 #endif |
|
1559 %}. |
1555 index > digitByteArray size ifTrue:[^ 0]. |
1560 index > digitByteArray size ifTrue:[^ 0]. |
1556 ^ digitByteArray at:index |
1561 ^ digitByteArray at:index |
1557 ! |
1562 ! |
1558 |
1563 |
1559 digitAt:index put:aByte |
1564 digitAt:index put:aByte |
1560 "set the 8 bits, index is a byte index" |
1565 "set the 8 bits, index is a byte index" |
1561 |
1566 |
|
1567 %{ |
|
1568 #ifdef __JAVA__ |
|
1569 ERROR("cannot modify the digits of a LargeInteger"); |
|
1570 #endif |
|
1571 %}. |
1562 digitByteArray at:index put:aByte |
1572 digitByteArray at:index put:aByte |
1563 ! |
1573 ! |
1564 |
1574 |
1565 digitByteAt:index |
1575 digitByteAt:index |
1566 "return 8 bits of my signed value, starting at byte index. |
1576 "return 8 bits of my signed value, starting at byte index. |
1567 For positive receivers, this is the same as #digitAt:; |
1577 For positive receivers, this is the same as #digitAt:; |
1568 for negative ones, the actual bit representation is returned." |
1578 for negative ones, the actual bit representation is returned." |
1569 |
1579 |
1570 |t digits| |
1580 |t digits| |
|
1581 |
|
1582 %{ |
|
1583 #ifdef __JAVA__ |
|
1584 return context._RETURN( ((STLargeInteger)self).digitByteAt( index.intValue() ) ); |
|
1585 #endif |
|
1586 %}. |
1571 sign >= 0 ifTrue:[ |
1587 sign >= 0 ifTrue:[ |
1572 index > digitByteArray size ifTrue:[ |
1588 index > digitByteArray size ifTrue:[ |
1573 ^ 0 |
1589 ^ 0 |
1574 ]. |
1590 ]. |
1575 ^ digitByteArray at:index. |
1591 ^ digitByteArray at:index. |
5375 ! |
5406 ! |
5376 |
5407 |
5377 positive |
5408 positive |
5378 "return true, if the receiver is >= 0" |
5409 "return true, if the receiver is >= 0" |
5379 |
5410 |
|
5411 %{ |
|
5412 #ifdef __JAVA__ |
|
5413 return context._RETURN( ((STLargeInteger)self).largeValue.signum() >= 0 ? STObject.True : STObject.False); |
|
5414 #endif |
|
5415 %}. |
5380 ^ (sign >= 0) |
5416 ^ (sign >= 0) |
5381 ! |
5417 ! |
5382 |
5418 |
5383 sign |
5419 sign |
5384 "return the sign of the receiver (-1, 0 or 1)" |
5420 "return the sign of the receiver (-1, 0 or 1)" |
5385 |
5421 |
|
5422 %{ |
|
5423 #ifdef __JAVA__ |
|
5424 return context._RETURN( STInteger._new( ((STLargeInteger)self).largeValue.signum() )); |
|
5425 #endif |
|
5426 %}. |
5386 ^ sign |
5427 ^ sign |
5387 ! |
5428 ! |
5388 |
5429 |
5389 strictlyPositive |
5430 strictlyPositive |
5390 "return true, if the receiver is > 0" |
5431 "return true, if the receiver is > 0" |
5391 |
5432 |
|
5433 %{ |
|
5434 #ifdef __JAVA__ |
|
5435 return context._RETURN( ((STLargeInteger)self).largeValue.signum() > 0 ? STObject.True : STObject.False); |
|
5436 #endif |
|
5437 %}. |
5392 ^ (sign > 0) |
5438 ^ (sign > 0) |
5393 ! ! |
5439 ! ! |
5394 |
5440 |
5395 !LargeInteger class methodsFor:'documentation'! |
5441 !LargeInteger class methodsFor:'documentation'! |
5396 |
5442 |
5397 version |
5443 version |
5398 ^ '$Header: /cvs/stx/stx/libbasic/LargeInteger.st,v 1.223 2015-03-25 14:12:51 cg Exp $' |
5444 ^ '$Header: /cvs/stx/stx/libbasic/LargeInteger.st,v 1.224 2015-04-19 22:31:45 cg Exp $' |
5399 ! |
5445 ! |
5400 |
5446 |
5401 version_CVS |
5447 version_CVS |
5402 ^ '$Header: /cvs/stx/stx/libbasic/LargeInteger.st,v 1.223 2015-03-25 14:12:51 cg Exp $' |
5448 ^ '$Header: /cvs/stx/stx/libbasic/LargeInteger.st,v 1.224 2015-04-19 22:31:45 cg Exp $' |
5403 ! ! |
5449 ! ! |
5404 |
|