--- a/ArithmeticValue.st Fri Oct 16 07:01:59 2015 +0200
+++ b/ArithmeticValue.st Wed Oct 28 07:44:54 2015 +0000
@@ -157,6 +157,14 @@
UnderflowSignal := UnderflowError.
! !
+!ArithmeticValue class methodsFor:'coercing & converting'!
+
+coerce:aNumber
+ "convert the argument aNumber into an instance of the receiver (class) and return it."
+
+ ^ self subclassResponsibility
+! !
+
!ArithmeticValue class methodsFor:'constants'!
NaN
@@ -346,7 +354,7 @@
!
reciprocal
- "return the receivers reciprocal"
+ "return the receiver's reciprocal"
^ self class unity / self
!
@@ -367,12 +375,12 @@
Do not check for divide by zero (return NaN or Infinity).
This operation is provided for emulators of other languages/semantics,
where no exception is raised for these results (i.e. Java).
- Its only defined if the arguments type is the same as the receivers."
+ It is only defined if the argument's type is the same as the receiver's."
aNumber isZero ifTrue:[
- self isZero ifTrue:[^ self class NaN].
- self negative ifTrue:[^ self class negativeInfinity].
- ^ self class infinity.
+ self isZero ifTrue:[^ self class NaN].
+ self negative ifTrue:[^ self class negativeInfinity].
+ ^ self class infinity.
].
^ self / aNumber
! !
@@ -454,21 +462,22 @@
!ArithmeticValue methodsFor:'coercing & converting'!
coerce:aNumber
- "convert the argument aNumber into an instance of the receivers class and return it."
+ "convert the argument aNumber into an instance of the receiver's class and return it."
^ self subclassResponsibility
!
generality
- "return a number giving the receivers generality, that number is
- used to convert one of the arguments in a mixed expression.
+ "return a number giving the receiver's generality.
+ That number is used to convert one of the arguments in a mixed expression.
The generality has to be defined in subclasses,
such that gen(a) > gen(b) iff, conversion of b into a's class
- does not cut precision. For example, Integer has 40, Float has 80,
- meaning that if we convert a Float to an Integer, some precision may
- be lost. The generality is used by ArithmeticValue>>retry:coercing:,
+ does not cut precision.
+ For example, Integer has 40, Float has 80, meaning that if we convert a Float to an Integer,
+ some precision may be lost.
+ The generality is used by ArithmeticValue>>retry:coercing:,
which converts the lower-precision number to the higher precision
- numbers class, when mixed-type arithmetic is performed."
+ number's class, when mixed-type arithmetic is performed."
^ self subclassResponsibility
@@ -565,8 +574,8 @@
!
asDouble
- "ST80 compatibility: return a double with receivers value.
- our floats are the identical to ST80 doubles"
+ "ST80 compatibility: return a double with receiver's value.
+ Attention: our floats are the identical to ST80's doubles"
^ self asFloat
@@ -721,7 +730,7 @@
!
asScaledDecimal:scale
- "return a fixedPoint approximating the receivers value"
+ "return a fixedPoint approximating the receiver's value"
^ self asFixedPoint:scale
@@ -1186,12 +1195,67 @@
!
raisedToInteger:exp
- "return the receiver raised to exp"
+ "return the receiver raised to exp.
+ Warning: if the receiver is a float/double, currently INF
+ may be returned. This may be changed silently to raise an error
+ in future versions."
+
+ ^ self raisedToIntegerAsInteger:exp
+
+ "
+ (2.0 raisedToInteger:10000)
+
+ (2.0 raisedToInteger:216)
+ (2 raisedToInteger:216)
+ (2 raisedTo:216)
+ -> 105312291668557186697918027683670432318895095400549111254310977536
+
+ (2 raisedToInteger:216) asFloat
+ (2 raisedTo:216) asFloat
+ -> 1.05312E+65
+
+ (2 raisedToInteger:500)
+ (2 raisedTo:500)
+ -> 3273390607896141870013189696827599152216642046043064789483291368096133796404674554883270092325904157150886684127560071009217256545885393053328527589376
+ 2 raisedToInteger:10
+ -> 1024
+ -2 raisedToInteger:10
+ -> 1024
+ -2 raisedToInteger:9
+ -> -512
+ 10 raisedToInteger:-10
+ -> (1/10000000000)
+ 2 raisedToInteger:0
+ -> 1
+ 2 raisedToInteger:-1
+ -> (1/2)
+
+ Time millisecondsToRun:[
+ 10000 timesRepeat:[
+ (2 raisedToInteger:500)
+ ]
+ ]
+
+ Time millisecondsToRun:[
+ |bigNum|
+ bigNum := 2 raisedToInteger:500.
+ 10 timesRepeat:[
+ (bigNum raisedToInteger:500)
+ ]
+ ]
+ "
+
+ "Created: / 27.4.1999 / 15:19:22 / stefan"
+ "Modified: / 27.4.1999 / 16:16:11 / stefan"
+!
+
+raisedToIntegerAsInteger:exp
+ "return the receiver raised to exp as a (large-) integer"
|result e t|
"use the addition chaining algorithm,
- which is much faster for big exp-arguments"
+ which is much faster for big exponents"
result := 1.
t := self.
@@ -1487,11 +1551,11 @@
!ArithmeticValue class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/ArithmeticValue.st,v 1.100 2015-03-25 17:54:48 cg Exp $'
+ ^ '$Header$'
!
version_CVS
- ^ '$Header: /cvs/stx/stx/libbasic/ArithmeticValue.st,v 1.100 2015-03-25 17:54:48 cg Exp $'
+ ^ '$Header$'
! !
--- a/Complex.st Fri Oct 16 07:01:59 2015 +0200
+++ b/Complex.st Wed Oct 28 07:44:54 2015 +0000
@@ -1,3 +1,5 @@
+"{ Encoding: utf8 }"
+
"
This is a Manchester Goodie. It is distributed freely on condition
that you observe these conditions in respect of the whole Goodie, and on
@@ -19,6 +21,8 @@
"
"{ Package: 'stx:libbasic' }"
+"{ NameSpace: Smalltalk }"
+
ArithmeticValue subclass:#Complex
instanceVariableNames:'real imaginary'
classVariableNames:'ComplexOne ComplexZero'
@@ -345,6 +349,8 @@
!Complex methodsFor:'coercing'!
coerce: aNumber
+ "convert the argument aNumber into an instance of the receiver's class and return it."
+
^ aNumber asComplex
!
@@ -768,6 +774,6 @@
!Complex class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/Complex.st,v 1.16 2014-07-10 12:23:25 cg Exp $'
+ ^ '$Header$'
! !
--- a/FixedPoint.st Fri Oct 16 07:01:59 2015 +0200
+++ b/FixedPoint.st Wed Oct 28 07:44:54 2015 +0000
@@ -1,3 +1,5 @@
+"{ Encoding: utf8 }"
+
"
This is public domain code, not covered by the ST/X copyright.
Code is provided 'as is', as a goody, without any warranty.
@@ -336,7 +338,7 @@
* aNumber
"return the product of the receiver and the argument.
Redefined to care for the scale if the argument is another fixPoint number.
- The results scale is the maximum of the receivers scale and the arguments scale."
+ The result's scale is the maximum of the receiver's scale and the argument's scale."
"/ notice:
"/ the following code handles some common cases,
@@ -427,7 +429,7 @@
+ aNumber
"return the sum of the receiver and the argument, aNumber.
Redefined to care for the scale if the argument is another fixPoint number.
- The results scale will be the maximum of the receivers and the arguments scale."
+ The result's scale will be the maximum of the receiver's and the argument's scale."
|n|
@@ -507,7 +509,7 @@
- aNumber
"return the difference of the receiver and the argument, aNumber.
Redefined to care for the scale if the argument is another fixPoint number.
- The results scale is the maximum of the receivers scale and the arguments scale."
+ The result's scale is the maximum of the receiver's scale and the argument's scale."
|n|
@@ -592,7 +594,7 @@
/ aNumber
"return the quotient of the receiver and the argument, aNumber.
Redefined to care for the scale if the argument is another fixPoint number.
- The results scale is the maximum of the receivers scale and the arguments scale."
+ The result's scale is the maximum of the receiver's scale and the argument's scale."
"/ notice:
"/ the following code handles some common cases,
@@ -743,7 +745,7 @@
!
coerce:aNumber
- "convert the argument aNumber into an instance of the receivers class and return it."
+ "convert the argument aNumber into an instance of the receiver's class and return it."
^ aNumber asFixedPoint
!
@@ -1007,10 +1009,10 @@
sqrt
"compute the square root, using the Newton method.
The approximated return value has an error less than
- the receivers last digit, as specified in the scale."
+ the receiver's last digit, as specified in the scale."
^ self
- sqrtWithErrorLessThan:(1 / (10 raisedTo:scale+1)) asFixedPoint
+ sqrtWithErrorLessThan:(1 / (10 raisedTo:scale+1)) asFixedPoint
"
(2 asFixedPoint:4) sqrt
@@ -1356,10 +1358,10 @@
!FixedPoint class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/FixedPoint.st,v 1.48 2015-02-07 16:16:28 cg Exp $'
+ ^ '$Header$'
!
version_CVS
- ^ '$Header: /cvs/stx/stx/libbasic/FixedPoint.st,v 1.48 2015-02-07 16:16:28 cg Exp $'
+ ^ '$Header$'
! !
--- a/Float.st Fri Oct 16 07:01:59 2015 +0200
+++ b/Float.st Wed Oct 28 07:44:54 2015 +0000
@@ -302,6 +302,8 @@
!
coerce:aNumber
+ "convert the argument aNumber into an instance of the receiver (class) and return it."
+
^ aNumber asFloat.
!
@@ -466,7 +468,6 @@
^ Epsilon
! !
-
!Float class methodsFor:'binary storage'!
readBinaryIEEEDoubleFrom:aStream
@@ -744,7 +745,6 @@
"
! !
-
!Float class methodsFor:'queries'!
exponentCharacter
@@ -805,7 +805,6 @@
^ 2 "must be careful here, whenever ST/X is used on VAX or a 370"
! !
-
!Float methodsFor:'arithmetic'!
* aNumber
@@ -1104,7 +1103,7 @@
Do not check for divide by zero (return NaN or Infinity).
This operation is provided for emulators of other languages/semantics,
where no exception is raised for these results (i.e. Java).
- Its only defined if the arguments type is the same as the receivers."
+ It is only defined if the argument's type is the same as the receiver's."
%{ /* NOCONTEXT */
@@ -1112,20 +1111,20 @@
double result, val;
if (__isSmallInteger(aNumber)) {
- result = __floatVal(self) / ( (double)__intVal(aNumber)) ;
+ result = __floatVal(self) / ( (double)__intVal(aNumber)) ;
retResult:
- __qMKFLOAT(newFloat, result);
- RETURN ( newFloat );
+ __qMKFLOAT(newFloat, result);
+ RETURN ( newFloat );
}
if (__isFloatLike(aNumber)) {
- val = __floatVal(aNumber);
- result = __floatVal(self) / val;
- goto retResult;
+ val = __floatVal(aNumber);
+ result = __floatVal(self) / val;
+ goto retResult;
}
if (__isShortFloat(aNumber)) {
- val = (double)(__shortFloatVal(aNumber));
- result = __floatVal(self) / val;
- goto retResult;
+ val = (double)(__shortFloatVal(aNumber));
+ result = __floatVal(self) / val;
+ goto retResult;
}
%}.
^ aNumber quotientFromFloat:self
@@ -1287,7 +1286,7 @@
!
coerce:aNumber
- "convert the argument aNumber into an instance of the receivers class and return it."
+ "convert the argument aNumber into an instance of the receiver's class and return it."
^ aNumber asFloat
!
@@ -2314,7 +2313,6 @@
"
! !
-
!Float methodsFor:'testing'!
isFinite
@@ -2458,7 +2456,7 @@
!
positive
- "return true if the receiver is greater or equal to zero.
+ "return true if the receiver is greater or equal to zero (not negative).
0.0 and -0.0 are positive for now."
%{ /* NOCONTEXT */
@@ -2468,12 +2466,12 @@
%}.
"
- 0.0 positive
- -0.0 positive
- 1.0 positive
- -1.0 positive
- (1.0 uncheckedDivide: 0.0) positive
- (-1.0 uncheckedDivide: 0.0) positive
+ 0.0 positive
+ -0.0 positive
+ 1.0 positive
+ -1.0 positive
+ (1.0 uncheckedDivide: 0.0) positive
+ (-1.0 uncheckedDivide: 0.0) positive
"
!
--- a/Fraction.st Fri Oct 16 07:01:59 2015 +0200
+++ b/Fraction.st Wed Oct 28 07:44:54 2015 +0000
@@ -1,3 +1,5 @@
+"{ Encoding: utf8 }"
+
"
COPYRIGHT (c) 1989 by Claus Gittinger
All Rights Reserved
@@ -11,6 +13,8 @@
"
"{ Package: 'stx:libbasic' }"
+"{ NameSpace: Smalltalk }"
+
Number subclass:#Fraction
instanceVariableNames:'numerator denominator'
classVariableNames:'FractionOne FractionZero PrintWholeNumbers'
@@ -634,7 +638,7 @@
!
coerce:aNumber
- "convert the argument aNumber into an instance of the receivers class and return it."
+ "convert the argument aNumber into an instance of the receiver's class and return it."
^ aNumber asFraction
!
@@ -1191,11 +1195,11 @@
!Fraction class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/Fraction.st,v 1.86 2015-04-20 10:48:54 cg Exp $'
+ ^ '$Header$'
!
version_CVS
- ^ '$Header: /cvs/stx/stx/libbasic/Fraction.st,v 1.86 2015-04-20 10:48:54 cg Exp $'
+ ^ '$Header$'
! !
--- a/Infinity.st Fri Oct 16 07:01:59 2015 +0200
+++ b/Infinity.st Wed Oct 28 07:44:54 2015 +0000
@@ -1,3 +1,5 @@
+"{ Encoding: utf8 }"
+
"
This is a Manchester Goodie. It is distributed freely on condition
that you observe these conditions in respect of the whole Goodie, and on
@@ -19,6 +21,8 @@
"
"{ Package: 'stx:libbasic' }"
+"{ NameSpace: Smalltalk }"
+
MetaNumber subclass:#Infinity
instanceVariableNames:''
classVariableNames:'InfNeg InfPos'
@@ -309,7 +313,8 @@
!
lessFromSomeNumber:aNumber
- "Sent from aNumber < self, if aNumber does not know how to handle this"
+ "Sent from aNumber < self, if aNumber does not know how to handle this.
+ Return true if aNumber < self."
aNumber isFinite ifTrue:[
^ self positive.
@@ -437,11 +442,11 @@
!Infinity class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/Infinity.st,v 1.15 2014-02-14 14:20:03 cg Exp $'
+ ^ '$Header$'
!
version_CVS
- ^ '$Header: /cvs/stx/stx/libbasic/Infinity.st,v 1.15 2014-02-14 14:20:03 cg Exp $'
+ ^ '$Header$'
! !
--- a/Integer.st Fri Oct 16 07:01:59 2015 +0200
+++ b/Integer.st Wed Oct 28 07:44:54 2015 +0000
@@ -763,8 +763,6 @@
"Modified: / 15.11.1999 / 20:35:20 / cg"
! !
-
-
!Integer class methodsFor:'class initialization'!
initialize
@@ -825,7 +823,6 @@
"
! !
-
!Integer class methodsFor:'prime numbers'!
flushPrimeCache
@@ -1148,7 +1145,6 @@
^ self == Integer
! !
-
!Integer methodsFor:'*Roe'!
acceptRoeVisitor: aVisitor
@@ -1417,7 +1413,6 @@
"
! !
-
!Integer methodsFor:'bcd conversion'!
decodeFromBCD
@@ -2289,22 +2284,17 @@
digitByteLength
"return the number bytes required for a 2's complement
binary representation of this Integer.
- For positive receivers, thats the same as the digitLength."
-
- "
- check if there is a 0-byte ...
- this allows to ask unnormalized LargeIntegers
- for their digitLength
- "
- |l "{ Class: SmallInteger }" |
+ For positive receivers, that's the same as the digitLength."
+
+ |absLen "{ Class: SmallInteger }" |
self >= 0 ifTrue:[^ self digitLength].
- l := self negated digitLength.
- (self digitByteAt:l) == 16rFF ifTrue:[
- ^ (l - 1) max:1
+ absLen := self negated digitLength.
+ (self digitByteAt:absLen) == 16rFF ifTrue:[
+ ^ (absLen - 1) max:1
].
- ^ l
+ ^ absLen
"
-129 digitByteLength
@@ -2315,7 +2305,7 @@
!
digitBytes
- "return a byteArray filled with the receivers bits
+ "return a byteArray filled with the receiver's bits
(8 bits of the absolute value per element),
least significant byte is first"
@@ -2323,7 +2313,7 @@
!
digitBytesMSB
- "return a byteArray filled with the receivers bits
+ "return a byteArray filled with the receiver's bits
(8 bits of the absolute value per element),
most significant byte is first"
@@ -2331,7 +2321,7 @@
!
digitBytesMSB:msbFlag
- "return a byteArray filled with the receivers bits
+ "return a byteArray filled with the receiver's bits
(8 bits of the absolute value per element),
if msbflag = true, most significant byte is first,
otherwise least significant byte is first"
@@ -2688,7 +2678,7 @@
acker:n
"return the value of acker(self, n).
- ;-) Do not try with receivers > 3"
+ ;-) Do not try with receivers > 3"
(self == 0) ifTrue:[^ n + 1].
(n == 0) ifTrue:[^ (self - 1) acker: 1].
@@ -3163,10 +3153,19 @@
"newton's method to get the largest integer which is less or equal to the
receiver's square root.
This might be needed for some number theoretic problems with large numbers
- (ans also in cryptography)"
+ (and also in cryptography)"
|guess prevGuess guessSquared|
+ self negative ifTrue:[
+ ^ self class
+ raise:#imaginaryResultSignal
+ receiver:self
+ selector:#integerSqrt
+ arguments:#()
+ errorString:'bad (negative) receiver in sqrt'
+ ].
+
guess := (1 bitShift:(self highBit // 2)).
[
@@ -3184,7 +3183,6 @@
^ guess.
-
"
333 integerSqrt
325 integerSqrt
@@ -3192,7 +3190,10 @@
323 integerSqrt
10239552311579 integerSqrt
5397346292805549782720214077673687806275517530364350655459511599582614290 integerSqrt
- 1000 factorial integerSqrt
+ 1000 factorial integerSqrt
+
+ 1000 factorial - 1000 factorial integerSqrt squared
+ 1000 factorial - (1000 factorial integerSqrt + 1) squared
"
!
@@ -3563,6 +3564,19 @@
"Created: / 30.4.1999 / 15:53:15 / stefan"
"Modified: / 5.5.1999 / 11:01:15 / stefan"
+!
+
+raisedToInteger:exp
+ "return the receiver raised to exp"
+
+ exp > 1000 ifTrue:[
+ "LargeInteger req's more than 1000 bits"
+ (self < 0) ifTrue:[
+ ^ PowerInteger new base:(self negated) exponent:exp negative:(exp odd).
+ ].
+ ^ PowerInteger new base:self exponent:exp
+ ].
+ ^ self raisedToIntegerAsInteger:exp
! !
!Integer methodsFor:'printing & storing'!
@@ -3756,8 +3770,7 @@
"
claus: changed it from a recursive algorithm;
- (it used to trigger stack-overflow exceptions when printing
- 3000 factorial ...)
+ (it used to trigger stack-overflow exceptions when printing 3000 factorial ...)
"
"/ leftPart := num // base.
"/ (leftPart ~= 0) ifTrue:[
@@ -3774,20 +3787,24 @@
"/ within that junk) and speeds up the conversions noticably.
r2 := base*base. "/ radix^2
- r4 := r2*r2. "/ radix^4
+ r4 := r2*r2. "/ radix^4
base <= 10 ifTrue:[
- r := r4*r2. "/ radix^6
+ r := r4*r2. "/ radix^6 (chunks of 6 digits)
nD := 6.
] ifFalse:[
- r := r4*base. "/ radix^5
+ r := r4*base. "/ radix^5 (chunks of 5 digits)
nD := 5.
].
-
+ SmallInteger maxBits >= 63 ifTrue:[
+ r := r*r. "/ radix^10 / radix^12 (chunks of 10/12 digits)
+ nD := nD * 2.
+ ].
+
"get a Stream with space for the digits we are going to print.
We need ((num log:base) ceiling) digits, which is equivalent
to ((num log:2)/(base log:2) ceiling)
"
- s := WriteStream on:(String new:((num highBit // base highBit - 1) + 1)).
+ s := WriteStream on:(String new:10).
[num >= r] whileTrue:[
"/
@@ -3819,9 +3836,11 @@
3000 factorial printOn:Transcript base:10
10 printOn:Transcript base:3
31 printOn:Transcript base:3
+ 10 printOn:Transcript base:2
+ 31 printOn:Transcript base:2
-20 printOn:Transcript base:16
-20 printOn:Transcript base:10
- Time millisecondsToRun:[10000 factorial printString] 7650
+ Time millisecondsToRun:[10000 factorial printString] 610 7650
"
"Modified: / 20-01-1998 / 18:05:02 / stefan"
@@ -4393,7 +4412,6 @@
"Created: / 09-01-2012 / 17:18:06 / cg"
! !
-
!Integer methodsFor:'special modulo arithmetic'!
add_32:anInteger
@@ -4909,7 +4927,7 @@
integerPart
"return a number with value from digits before the decimal point.
- (i.e. the receivers truncated value)
+ (i.e. the receiver's truncated value)
Since integers have no fraction, return the receiver here."
^ self
--- a/LargeInteger.st Fri Oct 16 07:01:59 2015 +0200
+++ b/LargeInteger.st Wed Oct 28 07:44:54 2015 +0000
@@ -17,7 +17,7 @@
Integer subclass:#LargeInteger
instanceVariableNames:'sign digitByteArray'
- classVariableNames:''
+ classVariableNames:'UseKarazuba'
poolDictionaries:''
category:'Magnitude-Numbers'
!
@@ -493,17 +493,17 @@
!
// aNumber
- "return the integer part of the quotient of the receivers value
- and the arguments value.
+ "return the integer part of the quotient of the receiver's value
+ and the argument's value.
The result is truncated toward negative infinity
and will be negative, if the operands signs differ.
The following is always true:
- (receiver // aNumber) * aNumber + (receiver \\ aNumber) = receiver
+ (receiver // aNumber) * aNumber + (receiver \\ aNumber) = receiver
Be careful with negative results: 9 // 4 -> 2, while -9 // 4 -> -3.
Especially surprising:
- -1 // 10 -> -1 (because -(1/10) is truncated towards next smaller integer, which is -1.
- -10 // 3 -> -4 (because -(10/3) is truncated towards next smaller integer, which is -4.
+ -1 // 10 -> -1 (because -(1/10) is truncated towards next smaller integer, which is -1.
+ -10 // 3 -> -4 (because -(10/3) is truncated towards next smaller integer, which is -4.
See #quo: which returns -2 in the above case and #rem: which is the corresponding remainder."
@@ -517,38 +517,38 @@
Use a special method for this case ...
"
(cls == SmallInteger) ifTrue:[
- abs := aNumber.
- abs := abs abs.
- (abs between:1 and:(SmallInteger maxBytes == 8 ifTrue:16r00ffffffffff ifFalse:16r00ffffff)) ifTrue:[
- divMod := self absFastDivMod:abs.
- ] ifFalse:[
- n := abs asLargeInteger.
- ].
+ abs := aNumber.
+ abs := abs abs.
+ (abs between:1 and:(SmallInteger maxBytes == 8 ifTrue:16r00ffffffffff ifFalse:16r00ffffff)) ifTrue:[
+ divMod := self absFastDivMod:abs.
+ ] ifFalse:[
+ n := abs asLargeInteger.
+ ].
] ifFalse:[
- "
- if the argument is not a largeInteger, coerce
- "
- (cls == self class) ifFalse:[
- ^ self retry:#// coercing:aNumber
- ].
- n := aNumber
+ "
+ if the argument is not a largeInteger, coerce
+ "
+ (cls == self class) ifFalse:[
+ ^ self retry:#// coercing:aNumber
+ ].
+ n := aNumber
].
divMod isNil ifTrue:[
- divMod := self absDivMod:n.
+ divMod := self absDivMod:n.
].
quo := divMod at:1.
(sign == aNumber sign) ifFalse:[
- "/ adjust for truncation if negative and there is a remainder ...
- "/ be careful: there is one special case to care for here:
- "/ if quo is maxInt+1, the negation can be represented as a smallInt.
- quo := quo setSign:-1.
- (divMod at:2) == 0 ifFalse:[
- ^ quo - 1
- ].
- quo digitLength == SmallInteger maxBytes ifTrue:[
- ^ quo compressed
- ].
+ "/ adjust for truncation if negative and there is a remainder ...
+ "/ be careful: there is one special case to care for here:
+ "/ if quo is maxInt+1, the negation can be represented as a smallInt.
+ quo := quo setSign:-1.
+ (divMod at:2) == 0 ifFalse:[
+ ^ quo - 1
+ ].
+ quo digitLength == SmallInteger maxBytes ifTrue:[
+ ^ quo compressed
+ ].
].
^ quo
@@ -737,7 +737,7 @@
!
negated
- "return an integer with value negated from the receivers value."
+ "return an integer with value negated from the receiver's value."
|newNumber sz|
@@ -747,73 +747,73 @@
special case for SmallInteger minVal
"
sign == 1 ifTrue:[
- sz := digitByteArray size.
+ sz := digitByteArray size.
%{
#ifdef __SCHTEAM__
#else /* not SCHTEAM */
- int idx;
- unsigned char *bp;
-
- bp = (unsigned char *)(__ByteArrayInstPtr(__INST(digitByteArray))->ba_element);
- idx = __intVal(sz);
-
- while ((idx > 1) && (bp[idx-1] == 0)) idx--;
-
- if (idx == sizeof(INT)) {
+ int idx;
+ unsigned char *bp;
+
+ bp = (unsigned char *)(__ByteArrayInstPtr(__INST(digitByteArray))->ba_element);
+ idx = __intVal(sz);
+
+ while ((idx > 1) && (bp[idx-1] == 0)) idx--;
+
+ if (idx == sizeof(INT)) {
# if defined(__LSBFIRST__)
# if __POINTER_SIZE__ == 8
- if ( ((unsigned INT *)bp)[0] == 0x4000000000000000L)
+ if ( ((unsigned INT *)bp)[0] == 0x4000000000000000L)
# else
- if ( ((unsigned INT *)bp)[0] == 0x40000000)
+ if ( ((unsigned INT *)bp)[0] == 0x40000000)
# endif
# else
- /*
- * generic code
- */
- if ((bp[idx-1] == 0x40)
- && (bp[idx-2] == 0)
- && (bp[idx-3] == 0)
- && (bp[idx-4] == 0)
+ /*
+ * generic code
+ */
+ if ((bp[idx-1] == 0x40)
+ && (bp[idx-2] == 0)
+ && (bp[idx-3] == 0)
+ && (bp[idx-4] == 0)
# if __POINTER_SIZE__ == 8
- && (bp[idx-5] == 0)
- && (bp[idx-6] == 0)
- && (bp[idx-7] == 0)
- && (bp[idx-8] == 0)
+ && (bp[idx-5] == 0)
+ && (bp[idx-6] == 0)
+ && (bp[idx-7] == 0)
+ && (bp[idx-8] == 0)
# endif
- )
+ )
# endif
- {
- RETURN (__mkSmallInteger(_MIN_INT));
- }
- }
+ {
+ RETURN (__mkSmallInteger(_MIN_INT));
+ }
+ }
#endif
%}.
- sz == SmallInteger maxBytes ifTrue:[
- (digitByteArray at:1) == 0 ifTrue:[
- (digitByteArray at:2) == 0 ifTrue:[
- (digitByteArray at:3) == 0 ifTrue:[
- SmallInteger maxBytes == 8 ifTrue:[
- (digitByteArray at:4) == 0 ifTrue:[
- (digitByteArray at:5) == 0 ifTrue:[
- (digitByteArray at:6) == 0 ifTrue:[
- (digitByteArray at:7) == 0 ifTrue:[
- (digitByteArray at:8) == 16r40 ifTrue:[
- ^ SmallInteger minVal
- ].
- ]
- ]
- ]
- ]
- ] ifFalse:[
- (digitByteArray at:4) == 16r40 ifTrue:[
- ^ SmallInteger minVal
- ].
- ]
- ]
- ]
- ]
- ].
+ sz == SmallInteger maxBytes ifTrue:[
+ (digitByteArray at:1) == 0 ifTrue:[
+ (digitByteArray at:2) == 0 ifTrue:[
+ (digitByteArray at:3) == 0 ifTrue:[
+ SmallInteger maxBytes == 8 ifTrue:[
+ (digitByteArray at:4) == 0 ifTrue:[
+ (digitByteArray at:5) == 0 ifTrue:[
+ (digitByteArray at:6) == 0 ifTrue:[
+ (digitByteArray at:7) == 0 ifTrue:[
+ (digitByteArray at:8) == 16r40 ifTrue:[
+ ^ SmallInteger minVal
+ ].
+ ]
+ ]
+ ]
+ ]
+ ] ifFalse:[
+ (digitByteArray at:4) == 16r40 ifTrue:[
+ ^ SmallInteger minVal
+ ].
+ ]
+ ]
+ ]
+ ]
+ ].
].
"/ cg - can share the digits ...
newNumber := self class digitBytes:digitByteArray sign:(sign negated).
@@ -1642,7 +1642,7 @@
!
digitBytes
- "return a byteArray filled with the receivers bits
+ "return a byteArray filled with the receiver's bits
(8 bits of the absolute value per element).
Least significant byte is first!!"
@@ -1657,7 +1657,7 @@
!
digitBytesMSB
- "return a byteArray filled with the receivers bits
+ "return a byteArray filled with the receiver's bits
(8 bits of the absolute value per element),
most significant byte first"
@@ -1665,13 +1665,13 @@
!
digitBytesMSB:msbFlag
- "return a byteArray filled with the receivers bits
+ "return a byteArray filled with the receiver's bits
(8 bits of the absolute value per element),
if msbflag = true, most significant byte is first,
otherwise least significant byte is first"
msbFlag ifTrue:[
- ^ digitByteArray copyReverse.
+ ^ digitByteArray copyReverse.
].
^ digitByteArray
@@ -1741,7 +1741,7 @@
asSmallInteger
"return a SmallInteger with same value as myself -
- the result is invalid if the receivers value cannot
+ the result is invalid if the receiver's value cannot
be represented as a SmallInteger.
Q: should we raise an exception if this happens ?"
@@ -1749,12 +1749,12 @@
value := 0.
(sign == 0) ifFalse:[
- digitByteArray reverseDo:[:aDigit |
- value := (value times:256) + aDigit
- ].
- (sign < 0) ifTrue:[
- value := value negated
- ]
+ digitByteArray reverseDo:[:aDigit |
+ value := (value times:256) + aDigit
+ ].
+ (sign < 0) ifTrue:[
+ value := value negated
+ ]
].
^ value
!
@@ -1779,7 +1779,7 @@
!
coerce:aNumber
- "convert the argument aNumber into an instance of the receivers class and return it."
+ "convert the argument aNumber into an instance of the receiver's class and return it."
^ aNumber asLargeInteger
!
@@ -2336,9 +2336,8 @@
!
lessFromInteger:anInteger
- "sent when an integer does not know how to compare to the receiver, a largeInt"
-
- |otherSign|
+ "sent when an integer does not know how to compare to the receiver, a largeInt.
+ Return true if anInteger < self"
"/
"/ here, we depend on the fact, that largeinteger
@@ -2346,14 +2345,12 @@
"/ therefore, a largeInt in the smallInt range is not allowed (possible)
"/
(anInteger class == SmallInteger) ifTrue:[
- otherSign := anInteger sign.
-
- (sign > 0) ifTrue:[
- "I am positive"
- ^ true "aNumber is <= 0"
- ].
- "I am negative"
- ^ false
+ (sign > 0) ifTrue:[
+ "I am positive - any largeInteger is larger than any smallInteger"
+ ^ true "anInteger is <= 0"
+ ].
+ "I am negative - any negative largeInteger is smaller than any smallInteger"
+ ^ false
].
^ super lessFromInteger:anInteger
!
@@ -3798,7 +3795,7 @@
"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.
+ with a byteSize smaller than the receiver's byteSize.
This is a helper for addition and subtraction - not for public use."
|result done
@@ -3817,9 +3814,9 @@
len2 := otherDigitByteArray size.
len1 > len2 ifTrue:[
- lResult := len1
+ lResult := len1
] ifFalse:[
- lResult := (len1 max: len2) + 1.
+ lResult := (len1 max: len2) + 1.
].
result := self class basicNew numberOfDigits:lResult sign:newSign.
resultDigitByteArray := result digitBytes.
@@ -3832,202 +3829,202 @@
if (__isByteArray(_digitByteArray)
&& __isByteArray(otherDigitByteArray)
&& __isByteArray(resultDigitByteArray)) {
- int __len1 = __intVal(len1);
- int __len2 = __intVal(len2);
- int __minLen = __len1 < __len2 ? __len1 : __len2;
- int __index, __borrow = 0;
- INT __diff;
- unsigned char *__myDigits, *__otherDigits, *__resultDigits;
-
- ok = true;
-
- __resultDigits = __ByteArrayInstPtr(resultDigitByteArray)->ba_element;
- __otherDigits = __ByteArrayInstPtr(otherDigitByteArray)->ba_element;
- __myDigits = __ByteArrayInstPtr(_digitByteArray)->ba_element;
-
- __index = 1;
+ int __len1 = __intVal(len1);
+ int __len2 = __intVal(len2);
+ int __minLen = __len1 < __len2 ? __len1 : __len2;
+ int __index, __borrow = 0;
+ INT __diff;
+ unsigned char *__myDigits, *__otherDigits, *__resultDigits;
+
+ ok = true;
+
+ __resultDigits = __ByteArrayInstPtr(resultDigitByteArray)->ba_element;
+ __otherDigits = __ByteArrayInstPtr(otherDigitByteArray)->ba_element;
+ __myDigits = __ByteArrayInstPtr(_digitByteArray)->ba_element;
+
+ __index = 1;
#if defined(__LSBFIRST__)
# if __POINTER_SIZE__ == 8
- /*
- * subtract int-wise
- */
- while ((__index+3) <= __minLen) {
- /* do not make this into one expression - ask cg why */
- __diff = ((unsigned int *)(__myDigits+__index-1))[0];
- __diff -= ((unsigned int *)(__otherDigits+__index-1))[0];
- __diff -= __borrow;
-
- if (__diff >= 0) {
- __borrow = 0;
- } else {
- __borrow = 1;
- /* __diff += 0x10000; */
- }
- ((unsigned int *)(__resultDigits+__index-1))[0] = __diff;
- __index += 4;
- }
+ /*
+ * subtract int-wise
+ */
+ while ((__index+3) <= __minLen) {
+ /* do not make this into one expression - ask cg why */
+ __diff = ((unsigned int *)(__myDigits+__index-1))[0];
+ __diff -= ((unsigned int *)(__otherDigits+__index-1))[0];
+ __diff -= __borrow;
+
+ if (__diff >= 0) {
+ __borrow = 0;
+ } else {
+ __borrow = 1;
+ /* __diff += 0x10000; */
+ }
+ ((unsigned int *)(__resultDigits+__index-1))[0] = __diff;
+ __index += 4;
+ }
# endif /* 64bit */
- /*
- * subtract short-wise
- */
- while (__index < __minLen) { /* i.e. index+1 <= minLen */
- /* do not make this into one expression - ask cg why */
- __diff = ((unsigned short *)(__myDigits+__index-1))[0];
- __diff -= ((unsigned short *)(__otherDigits+__index-1))[0];
- __diff -= __borrow;
- if (__diff >= 0) {
- __borrow = 0;
- } else {
- __borrow = 1;
- /* __diff += 0x10000; */
- }
- ((unsigned short *)(__resultDigits+__index-1))[0] = __diff;
- __index += 2;
- }
-
- if (__index == __minLen) {
- /* one of the operands has odd length - cannot continue short-wise */
- } else {
- if (__len1 > __len2) {
- while (__index < __len1) {
- /* do not make this into one expression - ask cg why */
- __diff = ((unsigned short *)(__myDigits+__index-1))[0];
- __diff -= __borrow;
- if (__diff >= 0) {
- __borrow = 0;
- ((unsigned short *)(__resultDigits+__index-1))[0] = __diff;
- __index += 2;
-
- /* copy over rest */
- while (__index < __len1) {
- ((unsigned short *)(__resultDigits+__index-1))[0] = ((unsigned short *)(__myDigits+__index-1))[0];
- __index+=2;
- }
- if (__index <= __len1) {
- __resultDigits[__index-1] = __myDigits[__index-1];
- __index++;
- }
- break;
- }
- __borrow = 1;
- /* __diff += 0x10000; */
- ((unsigned short *)(__resultDigits+__index-1))[0] = __diff;
- __index += 2;
- }
- } else {
- if (__len2 > __len1) {
- while (__index < __len2) {
- /* do not make this into one expression - ask cg why */
- __diff = 0;
- __diff -= ((unsigned short *)(__otherDigits+__index-1))[0];
- __diff -= __borrow;
- if (__diff >= 0) {
- __borrow = 0;
- } else {
- __borrow = 1;
- /* __diff += 0x10000; */
- }
- ((unsigned short *)(__resultDigits+__index-1))[0] = __diff;
- __index += 2;
- }
- }
- }
- }
+ /*
+ * subtract short-wise
+ */
+ while (__index < __minLen) { /* i.e. index+1 <= minLen */
+ /* do not make this into one expression - ask cg why */
+ __diff = ((unsigned short *)(__myDigits+__index-1))[0];
+ __diff -= ((unsigned short *)(__otherDigits+__index-1))[0];
+ __diff -= __borrow;
+ if (__diff >= 0) {
+ __borrow = 0;
+ } else {
+ __borrow = 1;
+ /* __diff += 0x10000; */
+ }
+ ((unsigned short *)(__resultDigits+__index-1))[0] = __diff;
+ __index += 2;
+ }
+
+ if (__index == __minLen) {
+ /* one of the operands has odd length - cannot continue short-wise */
+ } else {
+ if (__len1 > __len2) {
+ while (__index < __len1) {
+ /* do not make this into one expression - ask cg why */
+ __diff = ((unsigned short *)(__myDigits+__index-1))[0];
+ __diff -= __borrow;
+ if (__diff >= 0) {
+ __borrow = 0;
+ ((unsigned short *)(__resultDigits+__index-1))[0] = __diff;
+ __index += 2;
+
+ /* copy over rest */
+ while (__index < __len1) {
+ ((unsigned short *)(__resultDigits+__index-1))[0] = ((unsigned short *)(__myDigits+__index-1))[0];
+ __index+=2;
+ }
+ if (__index <= __len1) {
+ __resultDigits[__index-1] = __myDigits[__index-1];
+ __index++;
+ }
+ break;
+ }
+ __borrow = 1;
+ /* __diff += 0x10000; */
+ ((unsigned short *)(__resultDigits+__index-1))[0] = __diff;
+ __index += 2;
+ }
+ } else {
+ if (__len2 > __len1) {
+ while (__index < __len2) {
+ /* do not make this into one expression - ask cg why */
+ __diff = 0;
+ __diff -= ((unsigned short *)(__otherDigits+__index-1))[0];
+ __diff -= __borrow;
+ if (__diff >= 0) {
+ __borrow = 0;
+ } else {
+ __borrow = 1;
+ /* __diff += 0x10000; */
+ }
+ ((unsigned short *)(__resultDigits+__index-1))[0] = __diff;
+ __index += 2;
+ }
+ }
+ }
+ }
#endif
- /*
- * subtract byte-wise
- */
- while (__index <= __minLen) {
- /* do not make this into one expression - ask cg why */
- __diff = __myDigits[__index-1];
- __diff -= __otherDigits[__index-1];
- __diff -= __borrow;
- if (__diff >= 0) {
- __borrow = 0;
- } else {
- __borrow = 1;
- /* __diff += 0x100; */
- }
- __resultDigits[__index-1] = __diff;
- __index++;
- }
-
- if (__len1 > __len2) {
- while (__index <= __len1) {
- /* do not make this into one expression - ask cg why */
- __diff = __myDigits[__index-1];
- __diff -= __borrow;
- if (__diff >= 0) {
- __borrow = 0;
- /* copy over rest */
- __resultDigits[__index-1] = __diff;
- __index++;
- while (__index <= __len1) {
- __resultDigits[__index-1] = __myDigits[__index-1];
- __index++;
- }
- break;
- }
- __borrow = 1;
- /* __diff += 0x100; */
- __resultDigits[__index-1] = __diff;
- __index++;
- }
- } else {
- if (__len2 > __len1) {
- while (__index <= __len2) {
- /* do not make this into one expression - ask cg why */
- __diff = 0;
- __diff -= __otherDigits[__index-1];
- __diff -= __borrow;
- if (__diff >= 0) {
- __borrow = 0;
- } else {
- __borrow = 1;
- /* __diff += 0x100; */
- }
- __resultDigits[__index-1] = __diff;
- __index++;
- }
- }
- }
- borrow = __mkSmallInteger(__borrow);
- index = __mkSmallInteger(__index);
- lastDigit = __mkSmallInteger(__resultDigits[__intVal(lResult)-1]);
+ /*
+ * subtract byte-wise
+ */
+ while (__index <= __minLen) {
+ /* do not make this into one expression - ask cg why */
+ __diff = __myDigits[__index-1];
+ __diff -= __otherDigits[__index-1];
+ __diff -= __borrow;
+ if (__diff >= 0) {
+ __borrow = 0;
+ } else {
+ __borrow = 1;
+ /* __diff += 0x100; */
+ }
+ __resultDigits[__index-1] = __diff;
+ __index++;
+ }
+
+ if (__len1 > __len2) {
+ while (__index <= __len1) {
+ /* do not make this into one expression - ask cg why */
+ __diff = __myDigits[__index-1];
+ __diff -= __borrow;
+ if (__diff >= 0) {
+ __borrow = 0;
+ /* copy over rest */
+ __resultDigits[__index-1] = __diff;
+ __index++;
+ while (__index <= __len1) {
+ __resultDigits[__index-1] = __myDigits[__index-1];
+ __index++;
+ }
+ break;
+ }
+ __borrow = 1;
+ /* __diff += 0x100; */
+ __resultDigits[__index-1] = __diff;
+ __index++;
+ }
+ } else {
+ if (__len2 > __len1) {
+ while (__index <= __len2) {
+ /* do not make this into one expression - ask cg why */
+ __diff = 0;
+ __diff -= __otherDigits[__index-1];
+ __diff -= __borrow;
+ if (__diff >= 0) {
+ __borrow = 0;
+ } else {
+ __borrow = 1;
+ /* __diff += 0x100; */
+ }
+ __resultDigits[__index-1] = __diff;
+ __index++;
+ }
+ }
+ }
+ borrow = __mkSmallInteger(__borrow);
+ index = __mkSmallInteger(__index);
+ lastDigit = __mkSmallInteger(__resultDigits[__intVal(lResult)-1]);
}
%}.
ok == true ifFalse:[
- index := 1.
- borrow := 0.
-
- done := false.
- [done] whileFalse:[
- diff := borrow.
- (index <= len1) ifTrue:[
- diff := diff + (digitByteArray basicAt:index).
- (index <= len2) ifTrue:[
- diff := diff - (otherDigitByteArray basicAt:index)
- ]
- ] ifFalse:[
- (index <= len2) ifTrue:[
- diff := diff - (otherDigitByteArray basicAt:index)
- ] ifFalse:[
- "end reached"
- done := true
- ]
- ].
-
- "/ workaround for
- "/ gcc code generator bug
-
- (diff >= 0) ifTrue:[
- borrow := 0
- ] ifFalse:[
- borrow := -1.
- diff := diff + 16r100
- ].
+ index := 1.
+ borrow := 0.
+
+ done := false.
+ [done] whileFalse:[
+ diff := borrow.
+ (index <= len1) ifTrue:[
+ diff := diff + (digitByteArray basicAt:index).
+ (index <= len2) ifTrue:[
+ diff := diff - (otherDigitByteArray basicAt:index)
+ ]
+ ] ifFalse:[
+ (index <= len2) ifTrue:[
+ diff := diff - (otherDigitByteArray basicAt:index)
+ ] ifFalse:[
+ "end reached"
+ done := true
+ ]
+ ].
+
+ "/ workaround for
+ "/ gcc code generator bug
+
+ (diff >= 0) ifTrue:[
+ borrow := 0
+ ] ifFalse:[
+ borrow := -1.
+ diff := diff + 16r100
+ ].
"/ (diff < 0) ifTrue:[
"/ borrow := -1.
@@ -4036,40 +4033,40 @@
"/ borrow := 0
"/ ].
- resultDigitByteArray basicAt:index put:diff.
- index := index + 1
- ].
- lastDigit := resultDigitByteArray basicAt:lResult.
+ resultDigitByteArray basicAt:index put:diff.
+ index := index + 1
+ ].
+ lastDigit := resultDigitByteArray basicAt:lResult.
].
(borrow ~~ 0) ifTrue:[
- "/ must generate 255's complement
-
- result sign:newSign negated.
- [index <= lResult] whileTrue:[
- resultDigitByteArray basicAt:index put:16rFF.
- index := index + 1.
- ].
- index := lResult.
- [index > 0] whileTrue:[
- resultDigitByteArray basicAt:index put:(255 - (resultDigitByteArray at:index)).
- index := index - 1.
- ].
-
- index := 1.
- carry := 1.
- [carry ~~ 0] whileTrue:[
- (index <= lResult) ifTrue:[
- carry := (resultDigitByteArray basicAt:index) + carry.
- ].
- resultDigitByteArray basicAt:index put:(carry bitAnd:16rFF).
- carry := carry bitShift:-8.
- index := index + 1
- ].
- lastDigit := resultDigitByteArray basicAt:lResult.
+ "/ must generate 255's complement
+
+ result sign:newSign negated.
+ [index <= lResult] whileTrue:[
+ resultDigitByteArray basicAt:index put:16rFF.
+ index := index + 1.
+ ].
+ index := lResult.
+ [index > 0] whileTrue:[
+ resultDigitByteArray basicAt:index put:(255 - (resultDigitByteArray at:index)).
+ index := index - 1.
+ ].
+
+ index := 1.
+ carry := 1.
+ [carry ~~ 0] whileTrue:[
+ (index <= lResult) ifTrue:[
+ carry := (resultDigitByteArray basicAt:index) + carry.
+ ].
+ resultDigitByteArray basicAt:index put:(carry bitAnd:16rFF).
+ carry := carry bitShift:-8.
+ index := index + 1
+ ].
+ lastDigit := resultDigitByteArray basicAt:lResult.
].
(lastDigit == 0 or:[lResult <= SmallInteger maxBytes]) ifTrue:[
- ^ result compressed.
+ ^ result compressed.
].
^ result
@@ -4138,6 +4135,7 @@
carry "{ Class: SmallInteger }"
len1 "{ Class: SmallInteger }"
len2 "{ Class: SmallInteger }"
+ lenRslt "{ Class: SmallInteger }"
dstIndex "{ Class: SmallInteger }"
prod "{ Class: SmallInteger }"
v "{ Class: SmallInteger }"|
@@ -4145,8 +4143,12 @@
len1 := digitByteArray size.
otherDigitByteArray := aLargeInteger digitBytes.
len2 := otherDigitByteArray size.
-
- result := self class basicNew numberOfDigits:(len1 + len2).
+ lenRslt := len1 + len2.
+ UseKarazuba ~~ false ifTrue:[
+ lenRslt > 400 ifTrue:[ ^ self absMulKarazuba:aLargeInteger ].
+ ].
+
+ result := self class basicNew numberOfDigits:lenRslt.
resultDigitByteArray := result digitBytes.
ok := false.
%{
@@ -4154,277 +4156,337 @@
&& __isByteArray(otherDigitByteArray)
&& __isByteArray(resultDigitByteArray)
&& __bothSmallInteger(len1, len2)) {
- unsigned char *myBytes = __ByteArrayInstPtr(__INST(digitByteArray))->ba_element;
- unsigned char *otherBytes = __ByteArrayInstPtr(otherDigitByteArray)->ba_element;
- unsigned char *resultBytes = __ByteArrayInstPtr(resultDigitByteArray)->ba_element;
- unsigned char *_p1, *_pResult0, *_p1Last, *_p2Last, *_pResultLast;
- unsigned char *_pResultLastShort, *_pResultLastInt;
- unsigned INT _v;
- int _len1 = __intVal(len1);
- int _len2 = __intVal(len2);
-
- _p1Last = myBytes + _len1 - 1; /* the last byte */
- _p2Last = otherBytes + _len2 - 1; /* the last byte */
- _pResult0 = resultBytes;
- _pResultLast = resultBytes + _len1 + _len2 - 1; /* the last byte */
-
- /*
- * aaa...aaa f1[0] * f2
- * bbb...bbb f1[1] * f2
- * ccc...ccc f1[2] * f2
- * ...
- * xxx...xxx f1[high] * f2
- *
- * start short-wise
- * bounds: (16rFFFF * 16rFFFF) + 16rFFFF -> FFFF0000
- */
- _p1 = myBytes;
+ unsigned char *myBytes = __ByteArrayInstPtr(__INST(digitByteArray))->ba_element;
+ unsigned char *otherBytes = __ByteArrayInstPtr(otherDigitByteArray)->ba_element;
+ unsigned char *resultBytes = __ByteArrayInstPtr(resultDigitByteArray)->ba_element;
+ unsigned char *_p1, *_pResult0, *_p1Last, *_p2Last, *_pResultLast;
+ unsigned char *_pResultLastShort, *_pResultLastInt;
+ unsigned INT _v;
+ int _len1 = __intVal(len1);
+ int _len2 = __intVal(len2);
+
+ _p1Last = myBytes + _len1 - 1; /* the last byte */
+ _p2Last = otherBytes + _len2 - 1; /* the last byte */
+ _pResult0 = resultBytes;
+ _pResultLast = resultBytes + _len1 + _len2 - 1; /* the last byte */
+
+ /*
+ * aaa...aaa f1[0] * f2
+ * bbb...bbb f1[1] * f2
+ * ccc...ccc f1[2] * f2
+ * ...
+ * xxx...xxx f1[high] * f2
+ *
+ * start short-wise
+ * bounds: (16rFFFF * 16rFFFF) + 16rFFFF -> FFFF0000
+ */
+ _p1 = myBytes;
#if defined(__LSBFIRST__) && (__POINTER_SIZE__ == 8)
- _pResultLastInt = _pResultLast - 3; /* the last int */
-
- /* loop over ints of f1 */
- for (; _p1 <= (_p1Last-3); _p1 += 4, _pResult0 += 4) {
- unsigned char *_pResult, *_p2;
- unsigned INT word1 = ((unsigned int *)_p1)[0];
-
- _pResult = _pResult0;
- _p2 = otherBytes;
-
- /* loop over ints of f2 */
- while (_p2 <= (_p2Last-3)) {
- _v = (word1 * (unsigned INT)(((unsigned int *)_p2)[0])) + ((unsigned INT)((unsigned int *)_pResult)[0]);
- ((unsigned int *)_pResult)[0] = _v /* & 0xFFFFFFFF */;
- _v >>= 32; /* now _v contains the carry*/
- _pResult += 4;
- if (_v) {
- unsigned char *_pResult1;
-
- /* distribute carry - int-wise, then byte-wise */
- for (_pResult1 = _pResult; _v; _pResult1 += 4) {
- if (_pResult1 > _pResultLastInt) break;
- _v += (unsigned INT)(((unsigned int *)_pResult1)[0]);
- ((unsigned int *)_pResult1)[0] = _v /* & 0xFFFFFFFF */;
- _v >>= 32;
- }
- for (; _v; _pResult1++) {
- _v += _pResult1[0];
- _pResult1[0] = _v /* & 0xFF */;
- _v >>= 8;
- }
- }
- _p2 += 4;
- }
-
- /* possible odd highByte of f2 */
- while (_p2 <= _p2Last) {
- _v = (word1 * (unsigned INT)((unsigned char *)_p2[0])) + (unsigned INT)((unsigned char *)_pResult[0]);
-
- ((unsigned char *)_pResult)[0] = _v /* & 0xFFFFFFFF */;
- _v >>= 8; /* now _v contains the carry*/
- _pResult++;
- if (_v) {
- unsigned char *_pResult1 = _pResult;
-
- /* distribute carry byte-wise */
- for (; _v; _pResult1++) {
- _v += _pResult1[0];
- _pResult1[0] = _v /* & 0xFF */;
- _v >>= 8;
- }
- }
- _p2++;
- }
- }
+ _pResultLastInt = _pResultLast - 3; /* the last int */
+
+ /* loop over ints of f1 */
+ for (; _p1 <= (_p1Last-3); _p1 += 4, _pResult0 += 4) {
+ unsigned char *_pResult, *_p2;
+ unsigned INT word1 = ((unsigned int *)_p1)[0];
+
+ _pResult = _pResult0;
+ _p2 = otherBytes;
+
+ /* loop over ints of f2 */
+ while (_p2 <= (_p2Last-3)) {
+ _v = (word1 * (unsigned INT)(((unsigned int *)_p2)[0])) + ((unsigned INT)((unsigned int *)_pResult)[0]);
+ ((unsigned int *)_pResult)[0] = _v /* & 0xFFFFFFFF */;
+ _v >>= 32; /* now _v contains the carry*/
+ _pResult += 4;
+ if (_v) {
+ unsigned char *_pResult1;
+
+ /* distribute carry - int-wise, then byte-wise */
+ for (_pResult1 = _pResult; _v; _pResult1 += 4) {
+ if (_pResult1 > _pResultLastInt) break;
+ _v += (unsigned INT)(((unsigned int *)_pResult1)[0]);
+ ((unsigned int *)_pResult1)[0] = _v /* & 0xFFFFFFFF */;
+ _v >>= 32;
+ }
+ for (; _v; _pResult1++) {
+ _v += _pResult1[0];
+ _pResult1[0] = _v /* & 0xFF */;
+ _v >>= 8;
+ }
+ }
+ _p2 += 4;
+ }
+
+ /* possible odd highByte of f2 */
+ while (_p2 <= _p2Last) {
+ _v = (word1 * (unsigned INT)((unsigned char *)_p2[0])) + (unsigned INT)((unsigned char *)_pResult[0]);
+
+ ((unsigned char *)_pResult)[0] = _v /* & 0xFFFFFFFF */;
+ _v >>= 8; /* now _v contains the carry*/
+ _pResult++;
+ if (_v) {
+ unsigned char *_pResult1 = _pResult;
+
+ /* distribute carry byte-wise */
+ for (; _v; _pResult1++) {
+ _v += _pResult1[0];
+ _pResult1[0] = _v /* & 0xFF */;
+ _v >>= 8;
+ }
+ }
+ _p2++;
+ }
+ }
#endif /* 64bit */
- /* possible odd high short of f1 (or shortLoop, if not 64bit) */
- _pResultLastShort = _pResultLast - 1; /* the last short */
-
- for (; _p1 < _p1Last; _p1 += 2, _pResult0 += 2) {
- unsigned char *_pResult, *_p2;
- unsigned int short1 = ((unsigned short *)_p1)[0];
+ /* possible odd high short of f1 (or shortLoop, if not 64bit) */
+ _pResultLastShort = _pResultLast - 1; /* the last short */
+
+ for (; _p1 < _p1Last; _p1 += 2, _pResult0 += 2) {
+ unsigned char *_pResult, *_p2;
+ unsigned int short1 = ((unsigned short *)_p1)[0];
#if !defined(__LSBFIRST__)
- short1 = ((short1 >> 8) & 0xFF) | ((short1 & 0xFF) << 8);
+ short1 = ((short1 >> 8) & 0xFF) | ((short1 & 0xFF) << 8);
#endif
- _pResult = _pResult0;
- _p2 = otherBytes;
-
- /* loop over shorts of f2 */
- while (_p2 < _p2Last) {
+ _pResult = _pResult0;
+ _p2 = otherBytes;
+
+ /* loop over shorts of f2 */
+ while (_p2 < _p2Last) {
#if !defined(__LSBFIRST__)
- unsigned int _short2;
- unsigned int _short3;
-
- _short2 = ((unsigned short *)_p2)[0];
- _short2 = ((_short2 >> 8) /* & 0xFF */) | ((_short2 & 0xFF) << 8);
- _short3 = ((unsigned short *)_pResult)[0];
- _short3 = ((_short3 >> 8) /* & 0xFF */) | ((_short3 & 0xFF) << 8);
- _v = (short1 * _short2) + _short3;
- _pResult[0] = _v;
- _pResult[1] = _v >> 8;
+ unsigned int _short2;
+ unsigned int _short3;
+
+ _short2 = ((unsigned short *)_p2)[0];
+ _short2 = ((_short2 >> 8) /* & 0xFF */) | ((_short2 & 0xFF) << 8);
+ _short3 = ((unsigned short *)_pResult)[0];
+ _short3 = ((_short3 >> 8) /* & 0xFF */) | ((_short3 & 0xFF) << 8);
+ _v = (short1 * _short2) + _short3;
+ _pResult[0] = _v;
+ _pResult[1] = _v >> 8;
#else /* __LSBFIRST__ */
- _v = (short1 * ((unsigned short *)_p2)[0]) + ((unsigned short *)_pResult)[0];
- ((unsigned short *)_pResult)[0] = _v /* & 0xFFFF */;
+ _v = (short1 * ((unsigned short *)_p2)[0]) + ((unsigned short *)_pResult)[0];
+ ((unsigned short *)_pResult)[0] = _v /* & 0xFFFF */;
#endif
- _v >>= 16; /* now _v contains the carry*/
- _pResult += 2;
- if (_v) {
- unsigned char *_pResult1;
-
- /* distribute carry - short-wise, then byte-wise */
- _pResult1 = _pResult;
+ _v >>= 16; /* now _v contains the carry*/
+ _pResult += 2;
+ if (_v) {
+ unsigned char *_pResult1;
+
+ /* distribute carry - short-wise, then byte-wise */
+ _pResult1 = _pResult;
#if defined(__LSBFIRST__)
- for (; _v; _pResult1 += 2) {
- if (_pResult1 > _pResultLastShort) break;
- _v += ((unsigned short *)_pResult1)[0];
- ((unsigned short *)_pResult1)[0] = _v /* & 0xFFFF */;
- _v >>= 16;
- }
+ for (; _v; _pResult1 += 2) {
+ if (_pResult1 > _pResultLastShort) break;
+ _v += ((unsigned short *)_pResult1)[0];
+ ((unsigned short *)_pResult1)[0] = _v /* & 0xFFFF */;
+ _v >>= 16;
+ }
#endif
- for (; _v; _pResult1++) {
- _v += _pResult1[0];
- _pResult1[0] = _v /* & 0xFF */;
- _v >>= 8;
- }
- }
- _p2 += 2;
- }
-
- /* possible odd highByte of f2 */
- if (_p2 <= _p2Last) {
+ for (; _v; _pResult1++) {
+ _v += _pResult1[0];
+ _pResult1[0] = _v /* & 0xFF */;
+ _v >>= 8;
+ }
+ }
+ _p2 += 2;
+ }
+
+ /* possible odd highByte of f2 */
+ if (_p2 <= _p2Last) {
#if !defined(__LSBFIRST__)
- unsigned int _short3;
-
- _short3 = ((unsigned short *)_pResult)[0];
- _short3 = ((_short3 >> 8) /* & 0xFF */) | ((_short3 & 0xFF) << 8);
- _v = (short1 * _p2[0]) + _short3;
- _pResult[0] = _v;
- _pResult[1] = _v >> 8;
+ unsigned int _short3;
+
+ _short3 = ((unsigned short *)_pResult)[0];
+ _short3 = ((_short3 >> 8) /* & 0xFF */) | ((_short3 & 0xFF) << 8);
+ _v = (short1 * _p2[0]) + _short3;
+ _pResult[0] = _v;
+ _pResult[1] = _v >> 8;
#else /* __LSBFIRST__ */
- _v = (short1 * _p2[0]) + ((unsigned short *)_pResult)[0];
- ((unsigned short *)_pResult)[0] = _v /* & 0xFFFF */;
+ _v = (short1 * _p2[0]) + ((unsigned short *)_pResult)[0];
+ ((unsigned short *)_pResult)[0] = _v /* & 0xFFFF */;
#endif
- _v >>= 16; /* now _v contains the carry*/
- _pResult += 2;
- if (_v) {
- unsigned char *_pResult1;
-
- /* distribute carry - short-wise, then byte-wise */
- _pResult1 = _pResult;
+ _v >>= 16; /* now _v contains the carry*/
+ _pResult += 2;
+ if (_v) {
+ unsigned char *_pResult1;
+
+ /* distribute carry - short-wise, then byte-wise */
+ _pResult1 = _pResult;
#if defined(__LSBFIRST__)
- for (; _v; _pResult1 += 2) {
- if (_pResult1 > _pResultLastShort) break;
- _v += ((unsigned short *)_pResult1)[0];
- ((unsigned short *)_pResult1)[0] = _v /* & 0xFFFF */;
- _v >>= 16;
- }
+ for (; _v; _pResult1 += 2) {
+ if (_pResult1 > _pResultLastShort) break;
+ _v += ((unsigned short *)_pResult1)[0];
+ ((unsigned short *)_pResult1)[0] = _v /* & 0xFFFF */;
+ _v >>= 16;
+ }
#endif
- for (; _v; _pResult1++) {
- _v += _pResult1[0];
- _pResult1[0] = _v /* & 0xFF */;
- _v >>= 8;
- }
- }
- _p2++;
- }
- }
-
- /* possible odd highByte of f1 (or byteLoop, if above is ever disabled) */
- for (; _p1 <= _p1Last; _p1++, _pResult0++) {
- unsigned char *_pResult, *_p2;
- unsigned int byte1 = _p1[0];
-
- _pResult = _pResult0;
- _p2 = otherBytes;
-
- /* loop over shorts of f2 */
- while (_p2 < _p2Last) {
+ for (; _v; _pResult1++) {
+ _v += _pResult1[0];
+ _pResult1[0] = _v /* & 0xFF */;
+ _v >>= 8;
+ }
+ }
+ _p2++;
+ }
+ }
+
+ /* possible odd highByte of f1 (or byteLoop, if above is ever disabled) */
+ for (; _p1 <= _p1Last; _p1++, _pResult0++) {
+ unsigned char *_pResult, *_p2;
+ unsigned int byte1 = _p1[0];
+
+ _pResult = _pResult0;
+ _p2 = otherBytes;
+
+ /* loop over shorts of f2 */
+ while (_p2 < _p2Last) {
#if !defined(__LSBFIRST__)
- unsigned int _short2;
- unsigned int _short3;
-
- _short2 = ((unsigned short *)_p2)[0];
- _short2 = ((_short2 >> 8) /* & 0xFF */) | ((_short2 & 0xFF) << 8);
- _short3 = ((unsigned short *)_pResult)[0];
- _short3 = ((_short3 >> 8) /* & 0xFF */) | ((_short3 & 0xFF) << 8);
- _v = (byte1 * _short2) + _short3;
- _pResult[0] = _v;
- _pResult[1] = _v >> 8;
+ unsigned int _short2;
+ unsigned int _short3;
+
+ _short2 = ((unsigned short *)_p2)[0];
+ _short2 = ((_short2 >> 8) /* & 0xFF */) | ((_short2 & 0xFF) << 8);
+ _short3 = ((unsigned short *)_pResult)[0];
+ _short3 = ((_short3 >> 8) /* & 0xFF */) | ((_short3 & 0xFF) << 8);
+ _v = (byte1 * _short2) + _short3;
+ _pResult[0] = _v;
+ _pResult[1] = _v >> 8;
#else /* __LSBFIRST__ */
- _v = (byte1 * ((unsigned short *)_p2)[0]) + ((unsigned short *)_pResult)[0];
- ((unsigned short *)_pResult)[0] = _v /* & 0xFFFF */;
+ _v = (byte1 * ((unsigned short *)_p2)[0]) + ((unsigned short *)_pResult)[0];
+ ((unsigned short *)_pResult)[0] = _v /* & 0xFFFF */;
#endif
- _v >>= 16; /* now _v contains the carry*/
- _pResult += 2;
- if (_v) {
- unsigned char *_pResult1;
-
- /* distribute carry - short-wise, then byte-wise */
- _pResult1 = _pResult;
+ _v >>= 16; /* now _v contains the carry*/
+ _pResult += 2;
+ if (_v) {
+ unsigned char *_pResult1;
+
+ /* distribute carry - short-wise, then byte-wise */
+ _pResult1 = _pResult;
#if defined(__LSBFIRST__)
- for (_pResult1 = _pResult; _v; _pResult1 += 2) {
- if (_pResult1 > _pResultLastShort) break;
- _v += ((unsigned short *)_pResult1)[0];
- ((unsigned short *)_pResult1)[0] = _v /* & 0xFFFF */;
- _v >>= 16;
- }
+ for (_pResult1 = _pResult; _v; _pResult1 += 2) {
+ if (_pResult1 > _pResultLastShort) break;
+ _v += ((unsigned short *)_pResult1)[0];
+ ((unsigned short *)_pResult1)[0] = _v /* & 0xFFFF */;
+ _v >>= 16;
+ }
#endif /* __LSBFIRST__ */
- for (; _v; _pResult1++) {
- _v += _pResult1[0];
- _pResult1[0] = _v /* & 0xFF */;
- _v >>= 8;
- }
- }
- _p2 += 2;
- }
-
- /* possible odd highByte of f2 (or byteLoop, if not __LSBFIRST__) */
- while (_p2 <= _p2Last) {
- _v = (byte1 * _p2[0]) + _pResult[0];
- _pResult[0] = _v /* & 0xFF */;
- _v >>= 8; /* now _v contains the carry*/
- _pResult++;
- if (_v) {
- unsigned char *_pResult1;
-
- /* distribute carry */
- for (_pResult1 = _pResult; _v; _pResult1++) {
- _v += _pResult1[0];
- _pResult1[0] = _v /* & 0xFF */;
- _v >>= 8;
- }
- }
- _p2++;
- }
- }
- ok = true;
+ for (; _v; _pResult1++) {
+ _v += _pResult1[0];
+ _pResult1[0] = _v /* & 0xFF */;
+ _v >>= 8;
+ }
+ }
+ _p2 += 2;
+ }
+
+ /* possible odd highByte of f2 (or byteLoop, if not __LSBFIRST__) */
+ while (_p2 <= _p2Last) {
+ _v = (byte1 * _p2[0]) + _pResult[0];
+ _pResult[0] = _v /* & 0xFF */;
+ _v >>= 8; /* now _v contains the carry*/
+ _pResult++;
+ if (_v) {
+ unsigned char *_pResult1;
+
+ /* distribute carry */
+ for (_pResult1 = _pResult; _v; _pResult1++) {
+ _v += _pResult1[0];
+ _pResult1[0] = _v /* & 0xFF */;
+ _v >>= 8;
+ }
+ }
+ _p2++;
+ }
+ }
+ ok = true;
}
%}.
ok ifFalse:[
- 1 to:len1 do:[:index1 |
- 1 to:len2 do:[:index2 |
- dstIndex := index1 + index2 - 1.
- prod := (digitByteArray basicAt:index1) * (otherDigitByteArray basicAt:index2).
- prod := prod + (resultDigitByteArray basicAt:dstIndex).
- resultDigitByteArray basicAt:dstIndex put:(prod bitAnd:16rFF).
- carry := prod bitShift:-8.
- carry ~~ 0 ifTrue:[
- idx := dstIndex + 1.
- [carry ~~ 0] whileTrue:[
- v := (resultDigitByteArray basicAt:idx) + carry.
- resultDigitByteArray basicAt:idx put:(v bitAnd:255).
- carry := v bitShift:-8.
- idx := idx + 1
- ]
- ]
- ]
- ].
+ 1 to:len1 do:[:index1 |
+ 1 to:len2 do:[:index2 |
+ dstIndex := index1 + index2 - 1.
+ prod := (digitByteArray basicAt:index1) * (otherDigitByteArray basicAt:index2).
+ prod := prod + (resultDigitByteArray basicAt:dstIndex).
+ resultDigitByteArray basicAt:dstIndex put:(prod bitAnd:16rFF).
+ carry := prod bitShift:-8.
+ carry ~~ 0 ifTrue:[
+ idx := dstIndex + 1.
+ [carry ~~ 0] whileTrue:[
+ v := (resultDigitByteArray basicAt:idx) + carry.
+ resultDigitByteArray basicAt:idx put:(v bitAnd:255).
+ carry := v bitShift:-8.
+ idx := idx + 1
+ ]
+ ]
+ ]
+ ].
].
^ result compressed
!
+absMulKarazuba:aLargeInteger
+ "return a LargeInteger representing abs(self) * abs(theArgument) using the karazuba algorithm.
+ a = (2^n * p) + q
+ b = (2^n * r) + s
+ a * b = ((2^n * p) + q) * ((2^n * r) + s)
+ = 2^(n+n)*p*r + 2^n*p*s + 2^n*q*r + q*s
+ = 2^(n+n)*p*r + (p*r + q*s - (q-p)*(s-r))*2^n + q*s
+
+ this is faster for sufficient large n1,n2
+ because regular multiplication is O(n1*n2) and karazuma multiplies much smaller numbers
+ (half number of bits) but does more multiplations (on smaller numbers) and req's more
+ additions and subtractions (on smaller numbers).
+ The break-even for when to use regular multiplication has been determined heuristically
+ and is somewhere around 1600 bits (digitLength of 200).
+ (see test in absMul:)
+
+ To disable karazuba, set UseKarazuba to false.
+ "
+
+ "/ compute half-sized pi and qi...
+ |l1 l2 n nh p q r s pr qs q_p s_r q_ps_r pr_raisedTo_n mdl_raisedTo_nh|
+
+ l1 := self digitLength.
+ l2 := aLargeInteger digitLength.
+
+ n := l1 max:l2.
+
+ nh := (n / 2) ceiling. n := nh * 2.
+ p := LargeInteger digitBytes:(digitByteArray copyFrom:nh+1) sign:1. "/ high bits of nr1
+ q := LargeInteger digitBytes:(digitByteArray copyToMax:nh) sign:1. "/ low bits of nr1
+ r := LargeInteger digitBytes:(aLargeInteger digitBytes copyFrom:nh+1) sign:1. "/ high bits of nr2
+ s := LargeInteger digitBytes:(aLargeInteger digitBytes copyToMax:nh). "/ low bits of nr2
+
+ p := p compressed.
+ q := q compressed.
+ r := r compressed.
+ s := s compressed.
+
+ pr := p * r.
+ qs := q * s.
+ q_p := q - p.
+ s_r := s - r.
+ q_ps_r := q_p * s_r.
+
+ pr_raisedTo_n := (pr bitShift:(n*8)).
+ mdl_raisedTo_nh := ((pr + qs - q_ps_r) bitShift:(nh*8)).
+ ^ pr_raisedTo_n + mdl_raisedTo_nh + qs
+
+ "
+ #(100 500 1000 2500 5000 10000 25000 50000 100000 250000 500000 1000000) do:[:exp |
+ |nr r1 r2|
+ nr := (3 raisedTo:exp) asInteger.
+ Transcript show:exp; show:' nbytes: '; showCR:nr digitLength;
+ show:' normal: '; showCR:(Time microsecondsToRun:[ UseKarazuba := false. r1 := nr * nr ]);
+ show:' karazuba: '; showCR:(Time microsecondsToRun:[ UseKarazuba := true. r2 := nr absMulKarazuba: nr ]).
+ self assert:(r1 = r2).
+ ]
+ "
+!
+
absPlus:aLargeInteger sign:newSign
"return a LargeInteger representing abs(self) + abs(theArgument)
with sign: newSign.
@@ -5436,7 +5498,7 @@
!
negative
- "return true, if the receiver is < 0"
+ "return true, if the receiver is less than zero"
%{
#ifdef __SCHTEAM__
@@ -5455,7 +5517,7 @@
!
positive
- "return true, if the receiver is >= 0"
+ "return true, if the receiver is greater or equal to zero (not negative)"
%{
#ifdef __SCHTEAM__
@@ -5477,7 +5539,7 @@
!
strictlyPositive
- "return true, if the receiver is > 0"
+ "return true, if the receiver is greater than zero"
%{
#ifdef __SCHTEAM__
@@ -5496,3 +5558,4 @@
version_CVS
^ '$Header$'
! !
+
--- a/LimitedPrecisionReal.st Fri Oct 16 07:01:59 2015 +0200
+++ b/LimitedPrecisionReal.st Wed Oct 28 07:44:54 2015 +0000
@@ -126,10 +126,6 @@
!LimitedPrecisionReal class methodsFor:'instance creation'!
-coerce:aNumber
- ^ self subclassResponsibility.
-!
-
fromInteger:anInteger
"return a float with anInteger's value.
Since floats have a limited precision, you usually loose bits when doing this
@@ -1171,7 +1167,6 @@
! !
-
!LimitedPrecisionReal methodsFor:'printing & storing'!
printOn:aStream
@@ -1242,7 +1237,6 @@
^ 0
! !
-
!LimitedPrecisionReal methodsFor:'testing'!
isFinite
@@ -1322,7 +1316,7 @@
!
positive
- "return true if the receiver is greater or equal to zero"
+ "return true if the receiver is greater or equal to zero (not negative)"
^ self sign >= 0
@@ -1386,11 +1380,11 @@
!LimitedPrecisionReal class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/LimitedPrecisionReal.st,v 1.85 2015-04-24 12:10:09 stefan Exp $'
+ ^ '$Header$'
!
version_CVS
- ^ '$Header: /cvs/stx/stx/libbasic/LimitedPrecisionReal.st,v 1.85 2015-04-24 12:10:09 stefan Exp $'
+ ^ '$Header$'
! !
--- a/LongFloat.st Fri Oct 16 07:01:59 2015 +0200
+++ b/LongFloat.st Wed Oct 28 07:44:54 2015 +0000
@@ -1,3 +1,5 @@
+"{ Encoding: utf8 }"
+
"
COPYRIGHT (c) 1999 by eXept Software AG
All Rights Reserved
@@ -319,6 +321,8 @@
!
coerce:aNumber
+ "convert the argument aNumber into an instance of the receiver's class and return it."
+
^ aNumber asLongFloat.
!
@@ -927,7 +931,7 @@
Do not check for divide by zero (return NaN or Infinity).
This operation is provided for emulators of other languages/semantics,
where no exception is raised for these results (i.e. Java).
- Its only defined if the arguments type is the same as the receivers."
+ It is only defined if the argument's type is the same as the receiver's."
%{ /* NOCONTEXT */
@@ -935,25 +939,25 @@
LONGFLOAT result, val;
if (__isSmallInteger(aNumber)) {
- val = (LONGFLOAT)(__intVal(aNumber));
+ val = (LONGFLOAT)(__intVal(aNumber));
doDiv:
- result = __longFloatVal(self) / val;
- __qMKLFLOAT(newFloat, result);
- RETURN ( newFloat );
+ result = __longFloatVal(self) / val;
+ __qMKLFLOAT(newFloat, result);
+ RETURN ( newFloat );
}
if (aNumber != nil) {
- if (__qIsLongFloat(aNumber)) {
- val = __longFloatVal(aNumber);
- goto doDiv;
- }
- if (__qIsShortFloat(aNumber)) {
- val = (LONGFLOAT)(__shortFloatVal(aNumber));
- goto doDiv;
- }
- if (__qIsFloatLike(aNumber)) {
- val = (LONGFLOAT)(__floatVal(aNumber));
- goto doDiv;
- }
+ if (__qIsLongFloat(aNumber)) {
+ val = __longFloatVal(aNumber);
+ goto doDiv;
+ }
+ if (__qIsShortFloat(aNumber)) {
+ val = (LONGFLOAT)(__shortFloatVal(aNumber));
+ goto doDiv;
+ }
+ if (__qIsFloatLike(aNumber)) {
+ val = (LONGFLOAT)(__floatVal(aNumber));
+ goto doDiv;
+ }
}
%}.
^ aNumber quotientFromLongFloat:self
@@ -1029,7 +1033,7 @@
!
coerce:aNumber
- "convert the argument aNumber into an instance of the receivers class and return it."
+ "convert the argument aNumber into an instance of the receiver's class and return it."
^ aNumber asLongFloat
!
@@ -2046,7 +2050,7 @@
!
positive
- "return true if the receiver is greater or equal to zero
+ "return true if the receiver is greater or equal to zero (not negative)
0.0 and -0.0 are positive for now."
%{ /* NOCONTEXT */
@@ -2056,12 +2060,12 @@
%}.
"
- 0.0 asLongFloat positive
- -0.0 asLongFloat positive
- 1.0 asLongFloat positive
- -1.0 asLongFloat positive
- (1.0 uncheckedDivide: 0.0) asLongFloat positive
- (-1.0 uncheckedDivide: 0.0) asLongFloat positive
+ 0.0 asLongFloat positive
+ -0.0 asLongFloat positive
+ 1.0 asLongFloat positive
+ -1.0 asLongFloat positive
+ (1.0 uncheckedDivide: 0.0) asLongFloat positive
+ (-1.0 uncheckedDivide: 0.0) asLongFloat positive
"
!
@@ -2844,11 +2848,11 @@
!LongFloat class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/LongFloat.st,v 1.98 2015-05-18 00:08:20 cg Exp $'
+ ^ '$Header$'
!
version_CVS
- ^ '$Header: /cvs/stx/stx/libbasic/LongFloat.st,v 1.98 2015-05-18 00:08:20 cg Exp $'
+ ^ '$Header$'
! !
--- a/MeasurementValue.st Fri Oct 16 07:01:59 2015 +0200
+++ b/MeasurementValue.st Wed Oct 28 07:44:54 2015 +0000
@@ -1,3 +1,5 @@
+"{ Encoding: utf8 }"
+
"
COPYRIGHT (c) 2007 by eXept Software AG
All Rights Reserved
@@ -11,6 +13,8 @@
"
"{ Package: 'stx:libbasic' }"
+"{ NameSpace: Smalltalk }"
+
Number subclass:#MeasurementValue
instanceVariableNames:'value minValue maxValue'
classVariableNames:'MeasurementValueZero'
@@ -238,7 +242,7 @@
!
coerce:aNumber
- "convert the argument aNumber into an instance of the receivers class and return it."
+ "convert the argument aNumber into an instance of the receiver's class and return it."
^ MeasurementValue value:aNumber minValue:aNumber maxValue:aNumber
!
@@ -246,7 +250,7 @@
generality
"return the generality value - see ArithmeticValue>>retry:coercing:"
- "/ adding 1 to the values generality has the subtle side effect of enforcing
+ "/ adding 1 to the value's generality has the subtle side effect of enforcing
"/ a call to coerce: for mixed type operations (i.e. Int * MeasurementValue).
"/ try it.
@@ -384,6 +388,6 @@
!MeasurementValue class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/MeasurementValue.st,v 1.13 2014-03-24 11:14:37 stefan Exp $'
+ ^ '$Header$'
! !
--- a/MetaNumber.st Fri Oct 16 07:01:59 2015 +0200
+++ b/MetaNumber.st Wed Oct 28 07:44:54 2015 +0000
@@ -1,3 +1,5 @@
+"{ Encoding: utf8 }"
+
"
COPYRIGHT (c) 2003 by eXept Software AG
All Rights Reserved
@@ -11,6 +13,8 @@
"
"{ Package: 'stx:libbasic' }"
+"{ NameSpace: Smalltalk }"
+
Number subclass:#MetaNumber
instanceVariableNames:''
classVariableNames:''
@@ -105,6 +109,8 @@
!
coerce:aNumber
+ "convert the argument aNumber into an instance of the receiver's class and return it."
+
^ aNumber asMetaNumber
!
@@ -118,7 +124,7 @@
!MetaNumber class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/MetaNumber.st,v 1.1 2003/06/21 10:12:21 cg Exp $'
+ ^ '$Header$'
!
version_SVN
--- a/Number.st Fri Oct 16 07:01:59 2015 +0200
+++ b/Number.st Wed Oct 28 07:44:54 2015 +0000
@@ -1,3 +1,5 @@
+"{ Encoding: utf8 }"
+
"
COPYRIGHT (c) 1988 by Claus Gittinger
All Rights Reserved
@@ -14,10 +16,10 @@
"{ NameSpace: Smalltalk }"
ArithmeticValue subclass:#Number
- instanceVariableNames:''
- classVariableNames:'DecimalPointCharacterForPrinting DecimalPointCharactersForReading'
- poolDictionaries:''
- category:'Magnitude-Numbers'
+ instanceVariableNames:''
+ classVariableNames:'DecimalPointCharacterForPrinting DecimalPointCharactersForReading'
+ poolDictionaries:''
+ category:'Magnitude-Numbers'
!
!Number class methodsFor:'documentation'!
@@ -1344,7 +1346,8 @@
!
log:aNumber
- "return log base aNumber of the receiver"
+ "return log base aNumber of the receiver.
+ This will usually return a float value"
^ self ln / aNumber ln
@@ -2513,10 +2516,10 @@
!Number class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/Number.st,v 1.162 2015-05-07 13:57:44 stefan Exp $'
+ ^ '$Header$'
!
version_CVS
- ^ '$Header: /cvs/stx/stx/libbasic/Number.st,v 1.162 2015-05-07 13:57:44 stefan Exp $'
+ ^ '$Header$'
! !
--- a/Point.st Fri Oct 16 07:01:59 2015 +0200
+++ b/Point.st Wed Oct 28 07:44:54 2015 +0000
@@ -11,6 +11,8 @@
"
"{ Package: 'stx:libbasic' }"
+"{ NameSpace: Smalltalk }"
+
ArithmeticValue subclass:#Point
instanceVariableNames:'x y'
classVariableNames:'PointZero PointOne'
@@ -313,7 +315,7 @@
!Point methodsFor:'coercing & converting'!
coerce:anObject
- "convert the argument aNumber into an instance of the receivers class and return it."
+ "convert the argument aNumber into an instance of the receiver's class and return it."
^ anObject asPoint
!
@@ -639,6 +641,7 @@
y := y + anOffset y
! !
+
!Point methodsFor:'interpolating'!
interpolateTo: end at: amountDone
@@ -1184,13 +1187,14 @@
!Point class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/Point.st,v 1.73 2009/05/26 06:31:07 cg Exp $'
+ ^ '$Header$'
!
version_SVN
^ '$Id: Point.st 10761 2012-01-19 11:46:00Z vranyj1 $'
! !
+
Point initialize!
--- a/ShortFloat.st Fri Oct 16 07:01:59 2015 +0200
+++ b/ShortFloat.st Wed Oct 28 07:44:54 2015 +0000
@@ -1,3 +1,5 @@
+"{ Encoding: utf8 }"
+
"
COPYRIGHT (c) 1996 by Claus Gittinger
All Rights Reserved
@@ -247,6 +249,8 @@
!
coerce:aNumber
+ "convert the argument aNumber into an instance of the receiver's class and return it."
+
^ aNumber asShortFloat.
!
@@ -792,7 +796,7 @@
Do not check for divide by zero (return NaN or Infinity).
This operation is provided for emulators of other languages/semantics,
where no exception is raised for these results (i.e. Java).
- Its only defined if the arguments type is the same as the receivers."
+ It is only defined if the argument's type is the same as the receiver's."
%{ /* NOCONTEXT */
@@ -801,21 +805,21 @@
double dResult, dVal;
if (__isSmallInteger(aNumber)) {
- result = __shortFloatVal(self) / (float)(__intVal(aNumber));
+ result = __shortFloatVal(self) / (float)(__intVal(aNumber));
retResult:
- __qMKSFLOAT(newFloat, result);
- RETURN ( newFloat );
+ __qMKSFLOAT(newFloat, result);
+ RETURN ( newFloat );
}
if (__isShortFloat(aNumber)) {
- val = __shortFloatVal(aNumber);
- result = __shortFloatVal(self) / val;
- goto retResult;
+ val = __shortFloatVal(aNumber);
+ result = __shortFloatVal(self) / val;
+ goto retResult;
}
if (__isFloatLike(aNumber)) {
- dVal = __floatVal(aNumber);
- dResult = (double) __shortFloatVal(self) / dVal;
- __qMKFLOAT(newFloat, dResult);
- RETURN ( newFloat );
+ dVal = __floatVal(aNumber);
+ dResult = (double) __shortFloatVal(self) / dVal;
+ __qMKFLOAT(newFloat, dResult);
+ RETURN ( newFloat );
}
%}.
^ aNumber quotientFromShortFloat:self
@@ -881,7 +885,7 @@
!
coerce:aNumber
- "convert the argument aNumber into an instance of the receivers class and return it."
+ "convert the argument aNumber into an instance of the receiver's class and return it."
^ aNumber asShortFloat
!
@@ -1746,7 +1750,7 @@
!
positive
- "return true if the receiver is greater or equal to zero
+ "return true if the receiver is greater or equal to zero (not negative)
0.0 and -0.0 are positive for now."
%{ /* NOCONTEXT */
@@ -2098,11 +2102,11 @@
!ShortFloat class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/ShortFloat.st,v 1.140 2015-03-25 19:18:18 cg Exp $'
+ ^ '$Header$'
!
version_CVS
- ^ '$Header: /cvs/stx/stx/libbasic/ShortFloat.st,v 1.140 2015-03-25 19:18:18 cg Exp $'
+ ^ '$Header$'
! !
--- a/SmallInteger.st Fri Oct 16 07:01:59 2015 +0200
+++ b/SmallInteger.st Wed Oct 28 07:44:54 2015 +0000
@@ -1,5 +1,3 @@
-"{ Encoding: utf8 }"
-
"
COPYRIGHT (c) 1988 by Claus Gittinger
All Rights Reserved
@@ -441,7 +439,7 @@
!
+ aNumber
- "return the sum of the receivers value and the arguments value"
+ "return the sum of the receiver's value and the argument's value"
%{ /* NOCONTEXT */
#ifdef __SCHTEAM__
@@ -459,30 +457,30 @@
if (__isSmallInteger(aNumber)) {
# ifdef _ADD_IO_IO
- RETURN ( _ADD_IO_IO(self, aNumber) );
+ RETURN ( _ADD_IO_IO(self, aNumber) );
# else
- REGISTER INT sum;
-
- sum = __intVal(self) + __intVal(aNumber);
- if (__ISVALIDINTEGER(sum)) {
- RETURN ( __mkSmallInteger(sum) );
- }
- RETURN ( __MKLARGEINT(sum) );
+ REGISTER INT sum;
+
+ sum = __intVal(self) + __intVal(aNumber);
+ if (__ISVALIDINTEGER(sum)) {
+ RETURN ( __mkSmallInteger(sum) );
+ }
+ RETURN ( __MKLARGEINT(sum) );
# endif
}
if (__isFloatLike(aNumber)) {
- OBJ newFloat;
- double val = (double)__intVal(self) + __floatVal(aNumber);
-
- __qMKFLOAT(newFloat, val);
- RETURN ( newFloat );
+ OBJ newFloat;
+ double val = (double)__intVal(self) + __floatVal(aNumber);
+
+ __qMKFLOAT(newFloat, val);
+ RETURN ( newFloat );
}
if (__isShortFloat(aNumber)) {
- OBJ newFloat;
- float val = (float)__intVal(self) + __shortFloatVal(aNumber);
-
- __qMKSFLOAT(newFloat, val);
- RETURN ( newFloat );
+ OBJ newFloat;
+ float val = (float)__intVal(self) + __shortFloatVal(aNumber);
+
+ __qMKSFLOAT(newFloat, val);
+ RETURN ( newFloat );
}
#endif /* not __SCHTEAM__ */
%}.
@@ -490,7 +488,7 @@
!
- aNumber
- "return the difference of the receivers value and the arguments value"
+ "return the difference of the receiver's value and the argument's value"
%{ /* NOCONTEXT */
#ifdef __SCHTEAM__
@@ -508,30 +506,30 @@
if (__isSmallInteger(aNumber)) {
# ifdef _SUB_IO_IO
- RETURN ( _SUB_IO_IO(self, aNumber) );
+ RETURN ( _SUB_IO_IO(self, aNumber) );
# else
- REGISTER INT diff;
-
- diff = __intVal(self) - __intVal(aNumber);
- if (__ISVALIDINTEGER(diff)) {
- RETURN ( __mkSmallInteger(diff) );
- }
- RETURN ( __MKLARGEINT(diff) );
+ REGISTER INT diff;
+
+ diff = __intVal(self) - __intVal(aNumber);
+ if (__ISVALIDINTEGER(diff)) {
+ RETURN ( __mkSmallInteger(diff) );
+ }
+ RETURN ( __MKLARGEINT(diff) );
# endif
}
if (__isFloatLike(aNumber)) {
- OBJ newFloat;
- double val = (double)__intVal(self) - __floatVal(aNumber);
-
- __qMKFLOAT(newFloat, val);
- RETURN ( newFloat );
+ OBJ newFloat;
+ double val = (double)__intVal(self) - __floatVal(aNumber);
+
+ __qMKFLOAT(newFloat, val);
+ RETURN ( newFloat );
}
if (__isShortFloat(aNumber)) {
- OBJ newFloat;
- float val = (float)__intVal(self) - __shortFloatVal(aNumber);
-
- __qMKSFLOAT(newFloat, val);
- RETURN ( newFloat );
+ OBJ newFloat;
+ float val = (float)__intVal(self) - __shortFloatVal(aNumber);
+
+ __qMKSFLOAT(newFloat, val);
+ RETURN ( newFloat );
}
#endif /* not __SCHTEAM__ */
%}.
@@ -539,7 +537,7 @@
!
/ aNumber
- "return the quotient of the receivers value and the arguments value"
+ "return the quotient of the receiver's value and the argument's value"
%{ /* NOCONTEXT */
#ifdef __SCHTEAM__
@@ -560,45 +558,45 @@
double dval;
if (__isSmallInteger(aNumber)) {
- val = __intVal(aNumber);
- if (val != 0) {
- me = __intVal(self);
- t = me / val;
+ val = __intVal(aNumber);
+ if (val != 0) {
+ me = __intVal(self);
+ t = me / val;
# ifdef GOOD_OPTIMIZER
- if (me % val == 0) {
+ if (me % val == 0) {
# else
- /* this is stupid - all I want is to look for a remainder ...
- but most compilers are too stupid and generate an extra modulus
- instruction for "if (me % val)".
- Even if most divide instructions already leave the remainder in
- some register.
- Therefore I use a multiplication which is faster than a modulo
- on most machines. Hint to GNU people :-)
- */
- if ((t * val) == me) {
+ /* this is stupid - all I want is to look for a remainder ...
+ but most compilers are too stupid and generate an extra modulus
+ instruction for "if (me % val)".
+ Even if most divide instructions already leave the remainder in
+ some register.
+ Therefore I use a multiplication which is faster than a modulo
+ on most machines. Hint to GNU people :-)
+ */
+ if ((t * val) == me) {
# endif
- RETURN ( __mkSmallInteger(t) );
- }
- }
+ RETURN ( __mkSmallInteger(t) );
+ }
+ }
} else {
- if (__isFloatLike(aNumber)) {
- dval = __floatVal(aNumber);
- if (dval != 0.0) {
- OBJ newFloat;
- double val = (double)__intVal(self) / dval;
-
- __qMKFLOAT(newFloat, val);
- RETURN ( newFloat );
- }
- }
+ if (__isFloatLike(aNumber)) {
+ dval = __floatVal(aNumber);
+ if (dval != 0.0) {
+ OBJ newFloat;
+ double val = (double)__intVal(self) / dval;
+
+ __qMKFLOAT(newFloat, val);
+ RETURN ( newFloat );
+ }
+ }
}
#endif /* not __SCHTEAM__ */
%}.
aNumber isInteger ifTrue:[
- aNumber == 0 ifTrue:[
- ^ ZeroDivide raiseRequestWith:thisContext.
- ].
- ^ Fraction numerator:self denominator:aNumber
+ aNumber == 0 ifTrue:[
+ ^ ZeroDivide raiseRequestWith:thisContext.
+ ].
+ ^ Fraction numerator:self denominator:aNumber
].
^ aNumber quotientFromInteger:self
@@ -616,8 +614,8 @@
!
// aNumber
- "return the integer part of the quotient of the receivers value
- and the arguments value.
+ "return the integer part of the quotient of the receiver's value
+ and the argument's value.
The result is truncated toward negative infinity
and will be negative, if the operands signs differ.
The following is always true:
@@ -897,8 +895,8 @@
!
quo:aNumber
- "return the integer part of the quotient of the receivers value
- and the arguments value. The result is truncated towards zero
+ "return the integer part of the quotient of the receiver's value
+ and the argument's value. The result is truncated towards zero
and negative, if the operands signs differ..
The following is always true:
(receiver quo: aNumber) * aNumber + (receiver rem: aNumber) = receiver
@@ -963,7 +961,6 @@
! !
-
!SmallInteger methodsFor:'bit operators'!
bitAnd:anInteger
@@ -2562,7 +2559,7 @@
!
coerce:aNumber
- "convert the argument aNumber into an instance of the receivers class and return it."
+ "convert the argument aNumber into an instance of the receiver's class and return it."
^ aNumber asInteger
!