|
|
Class: LargeInteger
Object
|
+--Magnitude
|
+--ArithmeticValue
|
+--Number
|
+--Integer
|
+--LargeInteger
- Package:
- stx:libbasic
- Category:
- Magnitude-Numbers
- Version:
- rev:
1.201
date: 2010/04/14 08:00:14
- user: stefan
- file: LargeInteger.st directory: libbasic
- module: stx stc-classLibrary: libbasic
- Author:
- Claus Gittinger
This class provides arbitrary precision integers. These are represented as:
sign (-1/0/+1) and, if sign ~~ 0
a ByteArray of digits with 8 bits per element;
least significant 8 bits at index 1 ...
The implementation is not completely tuned for high performance
(more key-methods should be rewritten as primitives), although the
common operations have been pretty tuned for some architectures.
LargeIntegers are usually not created explicitely, but result from
SmallInteger arithmetic (overflowing the SmallInteger range).
Also, results of LargeInteger operations are converted to back to
SmallIntegers, when possible (see #compressed).
In contrast to ST-80, there is only one class for LargeIntegers, keeping
the sign as an instance variable (ST-80 has LargePositiveInteger and
LargeNegativeInteger). This may change.
Number
Float
Fraction
FixedPoint
SmallInteger
instance creation
-
digitBytes: aByteArrayOfDigits
-
create and return a new LargeInteger with digits (lsb-first)
from the argument, aByteArray.
Experimental interface - May change/be removed without notice.
-
digitBytes: aByteArrayOfDigits MSB: msb
-
create and return a new LargeInteger with digits (which may be in either msb/lsb order)
from the argument, aByteArray.
-
new
-
catch creation message.
LargeIntegers are only created by system code, which
uses basicNew and cares for correct initialization.
-
new: numberOfDigits
-
catch creation message
-
value: aSmallInteger
-
create and return a new LargeInteger with value taken from
the argument, aSmallInteger.
Notice:
this should be only used internally, since such small
largeIntegers do not normally occur in the system.
(They are used by myself)
May change/be removed without notice.
queries
-
isBuiltInClass
-
return true if this class is known by the run-time-system.
Here, true is returned.
arithmetic
-
* aNumber
-
return the product of the receiver and the argument.
-
+ aNumber
-
return the sum of the receiver and the argument, aNumber
-
- aNumber
-
return the difference of the receiver and the argument, aNumber
-
/ aNumber
-
return the quotient of the receiver and the argument, aNumber
-
// aNumber
-
return the quotient of the receiver and the argument, aNumber.
The result is truncated toward negative infinity and negative,
if the operands signs differ.
The following is always true:
(receiver // aNumber) * aNumber + (receiver \\ aNUmber) = receiver
-
\\ aNumber
-
Answer the integer remainder m defined by division with truncation toward
negative infinity. The remainder has the same sign as aNumber.
m < |aNumber| AND there is an integer k with (k * aNumber + m) = self
The following is always true:
(receiver // aNumber) * aNumber + (receiver \\ aNumber) = receiver
Compare with #rem:
-
abs
-
return my absolute value. redefined for speed.
-
divMod: aNumber
-
return an array filled with self // aNumber and
self \\ aNumber.
The result is only defined for positive receiver and
argument.
-
negated
-
return an integer with value negated from the receivers value.
-
quo: aNumber
-
return the quotient of the receiver and the argument, aNumber.
The result is truncated toward zero (which is different from //, which
truncates toward negative infinity).
The results sign is negative if the receiver has a sign
different from the args sign.
The following is always true:
(receiver quo: aNumber) * aNumber + (receiver rem: aNumber) = receiver
-
rem: aNumber
-
return the remainder of division of the receiver by the argument, aNumber.
The returned remainder has the same sign as the receiver.
The following is always true:
(receiver quo: aNumber) * aNumber + (receiver rem: aNumber) = receiver
bit operators
-
bitAnd: anInteger
-
return the bitwise-and of the receiver and the argument, anInteger
-
bitAt: anIntegerIndex
-
return the value of the index's bit (index starts at 1) as 0 or 1.
Notice: the result of bitAt: on negative receivers is not
defined in the language standard (since the implementation
is free to choose any internal representation for integers)
-
bitXor: anInteger
-
return the bitwise-or of the receiver and the argument, anInteger.
Here, a specially tuned version for largeInteger arguments
(to speed up some cryptographic code)
-
lowBit
-
return the bitIndex of the lowest bit set. The returned bitIndex
starts at 1 for the least significant bit.
Returns 0 if no bit is set.
For negative numbers, the low bit of my absolute value is returned.
Redefined here for more performance of the gcd: algorithm, which
is used when big fractions are reduced (should we write a primitive for this ?).
-
setBit: index
-
return a new integer, where the specified bit is on.
Bits are counted from 1 starting with the least significant.
The methods name may be missleading: the receiver is not changed,
but a new number is returned. Should be named #withBitSet:
bit operators-32bit
-
bitInvert32
-
return the value of the receiver with all bits inverted in 32bit signed int space
(changes the sign)
-
bitRotate32: shiftCount
-
return the value of the receiver rotated by shiftCount bits,
but only within 32 bits, rotating left for positive, right for negative counts.
Rotates through the sign bit.
Useful for crypt algorithms, or to emulate C/Java semantics.
-
bitShift32: shiftCount
-
return the value of the receiver shifted by shiftCount bits,
but only within 32 bits, shifting into/out-of the sign bit.
May be useful for communication interfaces, to create ST-numbers
from a signed 32bit int value given as individual bytes,
or to emulate C/Java semantics.
The shift is unsigned
-
bitXor32: aNumber
-
return the xor of the receiver and the argument.
The argument must be a SmallInteger or a 4-byte LargeInteger.
If the result overflows the 32 bit range, the value modulo 16rFFFFFFFF is returned.
This is of course not always correct, but allows for C/Java behavior to be emulated.
byte access
-
digitAt: index
-
return 8 bits of value, starting at byte index
-
digitAt: index put: aByte
-
set the 8 bits, index is a byte index
-
digitByteAt: index
-
return 8 bits of my signed value, starting at byte index.
For positive receivers, this is the same as #digitAt:;
for negative ones, the actual bit representation is returned.
-
digitBytes
-
return a byteArray filled with the receivers bits
(8 bits of the absolute value per element).
Least significant byte is first!
-
digitBytesMSB: msbFlag
-
return a byteArray filled with the receivers bits
(8 bits of the absolute value per element),
if msbflag = true, most significant byte is first,
otherwise least significant byte is first
-
digitLength
-
return the number bytes used by this Integer.
For negative receivers, the digitLength of its absolute value
is returned.
-
digits
-
obsolete, use #digitBytes
** This is an obsolete interface - do not use it (it may vanish in future versions) **
coercing & converting
-
asLargeInteger
-
return a LargeInteger with same value as myself - thats me
-
asSigned32
-
return a 32-bit integer with my bit-pattern. Receiver must be unsigned (i.e. positive).
May be required for bit operations on the sign-bit and/or to
convert C/Java numbers.
-
asSmallInteger
-
return a SmallInteger with same value as myself -
the result is invalid if the receivers value cannot
be represented as a SmallInteger.
Q: should we raise an exception if this happens ?
-
asUnsigned32
-
return a 32-bit integer with my bit-pattern. Receiver must be unsigned (i.e. positive).
May be required for bit operations on the sign-bit and/or to
convert C/Java numbers.
-
coerce: aNumber
-
convert the argument aNumber into an instance of the receivers class and return it.
-
compressed
-
if the receiver can be represented as a SmallInteger, return
a SmallInteger with my value;
otherwise remove leading zero bytes in the digitByte array
and return the receiver
-
generality
-
return the generality value - see ArithmeticValue>>retry:coercing:
-
value: aSmallInteger
-
setup my contents to represent the same value as aSmallInteger.
This method will fail, if the argument is not a smallInteger.
This should only be used internally,
since it will create an unnormalized LargeInt (by purpose) if asked for.
comparing
-
< aNumber
-
return true, if the argument, aNumber is greater than the receiver
-
= aNumber
-
return true, if the argument represents the same numeric value
as the receiver, false otherwise
-
> aNumber
-
return true, if the argument, aNumber is less than the receiver
-
hash
-
return an integer useful for hashing on large numbers
double dispatching
-
differenceFromInteger: anInteger
-
sent, when anInteger does not know how to subtract the receiver.
Return the result of 'anInteger - self'. The argument must be a SmallInteger.
-
equalFromInteger: anInteger
-
sent when an integer does not know how to compare to the receiver, a largeInt
-
lessFromInteger: anInteger
-
sent when an integer does not know how to compare to the receiver, a largeInt
-
productFromInteger: anInteger
-
sent, when anInteger does not know how to multiply the receiver.
Return the product of the receiver and the argument, aSmallInteger
-
sumFromInteger: anInteger
-
sent, when anInteger does not know how to add the receiver.
Return the sum of the receiver and the argument, (which must be a SmallInteger)
modulu arithmetic
-
plus32: aNumber
-
return the sum of the receiver and the argument, as SmallInteger.
The argument must be another SmallInteger.
If the result overflows the 32 bit range, the value modulo 16rFFFFFFFF is returned.
This is of course not always correct, but allows for C/Java behavior to be emulated.
printing & storing
-
xxxstoreOn: aStream
-
append a representation of the receiver to aStream, which can
be used to reconstruct the receiver.
private
-
absDivMod: anInteger
-
return an array with two LargeIntegers representing
abs(self) // abs(theArgument) and abs(self) \\ abs(theArgument).
Used as a helper for \\, //, rem: and quo:.
This method needs a rewrite.
-
absEq: aLargeInteger
-
return true, if abs(self) = abs(theArgument)
-
absFastDivMod: aPositiveSmallInteger
-
return an array with two LargeIntegers representing
abs(self) // aPositiveSmallInteger and
abs(self) \\ aPositiveSmallInteger.
-
absFastMinus: aSmallInteger sign: newSign
-
return a LargeInteger representing abs(self) - abs(theArgument)
with sign: newSign.
The result is normalized.
This is a helper for addition and subtraction - not for public use.
-
absFastPlus: aSmallInteger sign: newSign
-
return a LargeInteger representing abs(self) + abs(theArgument).
with sign: newSign.
The result is normalized. The argument must be a smallInteger
with byteSize one less than the integer byteSize.
This is a helper for addition and subtraction - not for public use.
-
absLess: aLargeInteger
-
return true, if abs(self) < abs(theArgument).
This handles unnormalized largeIntegers.
-
absLessEq: aLargeInteger
-
return true, if abs(self) <= abs(theArgument).
This handles unnormalized largeIntegers.
-
absMinus: aLargeInteger sign: newSign
-
return a LargeInteger representing abs(self) - abs(theArgument)
with sign: newSign.
The result is normalized. The argument must be a largeInteger
with a byteSize smaller than the receivers byteSize.
This is a helper for addition and subtraction - not for public use.
-
absMod: anInteger
-
return a LargeIntegers representing
abs(self) \\ abs(theArgument).
Used as a helper for \\ and rem:
-
absMul: aLargeInteger
-
return a LargeInteger representing abs(self) * abs(theArgument)
-
absPlus: aLargeInteger sign: newSign
-
return a LargeInteger representing abs(self) + abs(theArgument)
with sign: newSign.
The result is normalized. The argument must be a smallInteger
with byteSize one less than the integer byteSize.
This is a helper for addition and subtraction - not for public use.
-
absSubtract: aLargeInteger
-
private helper for division:
destructively subtract aLargeInteger from myself
AND return true, if the result is non-zero, false otherwise.
(i.e. this method has both a return value and a side-effect
on the receiver)
Only allowed for positive receiver and argument
The receiver must be >= the argument.
The receiver must be a temporary scratch-number
-
div2
-
private helper for division:
destructively divide the receiver by 2.
-
mul2
-
private helper for division:
destructively multiply the receiver by 2.
-
mul256
-
private helper for division:
destructively multiply the receiver by 256.
-
numberOfDigits: nDigits
-
digitByteArray := ByteArray uninitializedNew:nDigits.
-
setDigits: digits
-
-
sign: aNumber
-
testing
-
even
-
return true if the receiver is even
-
negative
-
return true, if the receiver is < 0
-
odd
-
return true if the receiver is odd
-
positive
-
return true, if the receiver is >= 0
-
sign
-
return the sign of the receiver (-1, 0 or 1)
-
strictlyPositive
-
return true, if the receiver is > 0
|