--- a/ArithmeticValue.st Fri Jun 13 20:52:21 2003 +0200
+++ b/ArithmeticValue.st Mon Jun 16 11:14:59 2003 +0200
@@ -407,7 +407,10 @@
asLongFloat
"return a longFloat with same value"
- ^ self subclassResponsibility
+ "WARNING: could loose precision here, if not redefined in concrete classes which
+ have more than float precision (i.e. LargeIntegers and Fractions)"
+
+ ^ self asFloat asLongFloat "/ subclassResponsibility
"Modified: / 17.4.1996 / 12:21:35 / cg"
"Created: / 7.9.2001 / 13:39:31 / cg"
@@ -522,6 +525,13 @@
!ArithmeticValue methodsFor:'double dispatching'!
+differenceFromComplex:aComplex
+ "the receiver does not know how to subtract from a complex -
+ retry the operation by coercing to higher generality"
+
+ ^ aComplex retry:#- coercing:self
+!
+
differenceFromFixedPoint:aFixedPoint
"the receiver does not know how to subtract from a fixedPoint number -
retry the operation by coercing to higher generality"
@@ -561,6 +571,55 @@
"Created: 17.4.1996 / 12:33:16 / cg"
!
+equalFromComplex:aComplex
+ "the receiver does not know how to compare to a complex number -
+ retry the operation by coercing to higher generality"
+
+ ^ aComplex retry:#= coercing:self
+!
+
+equalFromFixedPoint:aFixedPoint
+ "the receiver does not know how to compare to a fixed point -
+ retry the operation by coercing to higher generality"
+
+ ^ aFixedPoint retry:#= coercing:self
+!
+
+equalFromFloat:aFloat
+ "the receiver does not know how to compare to a float -
+ retry the operation by coercing to higher generality"
+
+ ^ aFloat retry:#= coercing:self
+!
+
+equalFromFraction:aFraction
+ "the receiver does not know how to compare to a fraction -
+ retry the operation by coercing to higher generality"
+
+ ^ aFraction retry:#= coercing:self
+!
+
+equalFromInteger:anInteger
+ "the receiver does not know how to compare to an integer -
+ retry the operation by coercing to higher generality"
+
+ ^ anInteger retry:#= coercing:self
+!
+
+equalFromLongFloat:aLongFloat
+ "the receiver does not know how to compare to a long float -
+ retry the operation by coercing to higher generality"
+
+ ^ aLongFloat retry:#= coercing:self
+!
+
+equalFromShortFloat:aShortFloat
+ "the receiver does not know how to compare to a short float -
+ retry the operation by coercing to higher generality"
+
+ ^ aShortFloat retry:#= coercing:self
+!
+
lessFromFixedPoint:aFixedPoint
"the receiver does not know how to compare to a fixedPoint number -
retry the operation by coercing to higher generality"
@@ -600,6 +659,13 @@
"Modified: 17.4.1996 / 12:33:33 / cg"
!
+productFromComplex:aComplex
+ "the receiver does not know how to multiply a complex -
+ retry the operation by coercing to higher generality"
+
+ ^ aComplex retry:#* coercing:self
+!
+
productFromFixedPoint:aFixedPoint
"the receiver does not know how to multiply a fixed point number -
retry the operation by coercing to higher generality"
@@ -639,6 +705,13 @@
"Created: 17.4.1996 / 12:33:48 / cg"
!
+quotientFromComplex:aComplex
+ "the receiver does not know how to divide a complex -
+ retry the operation by coercing to higher generality"
+
+ ^ aComplex retry:#/ coercing:self
+!
+
quotientFromFixedPoint:aFixedPoint
"the receiver does not know how to divide a fixed point number -
retry the operation by coercing to higher generality"
@@ -678,6 +751,13 @@
"Created: 17.4.1996 / 12:34:00 / cg"
!
+sumFromComplex:aComplex
+ "the receiver does not know how to add a complex -
+ retry the operation by coercing to higher generality"
+
+ ^ aComplex retry:#+ coercing:self
+!
+
sumFromFixedPoint:aFixedPoint
"the receiver does not know how to add a fixed point number -
retry the operation by coercing to higher generality"
@@ -887,7 +967,8 @@
!
isComplex
- "Answer whether the receiver has an imaginary part"
+ "Answer whether the receiver has an imaginary part
+ (i.e. if it is a complex number). Always false here."
^ false
@@ -1036,7 +1117,7 @@
!ArithmeticValue class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/ArithmeticValue.st,v 1.46 2003-04-23 17:09:32 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/ArithmeticValue.st,v 1.47 2003-06-16 09:14:02 cg Exp $'
! !
ArithmeticValue initialize!
--- a/Complex.st Fri Jun 13 20:52:21 2003 +0200
+++ b/Complex.st Mon Jun 16 11:14:59 2003 +0200
@@ -22,7 +22,7 @@
ArithmeticValue subclass:#Complex
instanceVariableNames:'real imaginary'
- classVariableNames:''
+ classVariableNames:'ComplexOne ComplexZero'
poolDictionaries:''
category:'Magnitude-Numbers'
!
@@ -53,23 +53,26 @@
documentation
"
- This is an implementation of complex numbers. A complex number has real and
- imaginary parts which must be manipulated simultaneously in any numeric processing.
- Complex numbers can be used in many of the same places that regular numbers
- can be used with one major exception of comparisons, since complex numbers cannot
- be directly compared for size (except through lengths of vectors (see absolute
- value)).
+ This class implements complex numbers.
+ A complex number has real and imaginary parts which must be manipulated simultaneously
+ in any numeric processing.
+ Complex numbers can be used in many of the same places that regular numbers
+ can be used with one major exception of comparisons, since complex numbers cannot
+ be directly compared for size
+ (except through lengths of vectors (see absolute value)).
-Instance variables:
- real <Number> the part of the number which can be expressed as a Real number
- imaginary <Number> the part of the number which, in terms of how the number behaves,
- has been multiplied by 'i' (-1 sqrt)
+ [Instance variables:]
+ real <Number> the part of the number which can be expressed as a Real number
+ imaginary <Number> the part of the number which, in terms of how the number behaves,
+ has been multiplied by 'i' (-1 sqrt)
-Author: Kurt Hebel (hebel@uinova.cerl.uiuc.edu)
+ [Author:]
+ Kurt Hebel (hebel@uinova.cerl.uiuc.edu)
+ minor changes and double dispatching code by cg.
"
!
-example
+examples
"
(5 % 7) real
(5 % 7) imaginary
@@ -84,43 +87,67 @@
(1 % 0) * (2 % 0)
(1 % 0) * (0 % 2)
(1 % 0) * (2 % 3)
+
+ (1 % 2) + 2
+ (1 % 2) * 2
+ 2 + (1 % 2)
+ 2 * (1 % 2)
+
"
! !
!Complex class methodsFor:'instance creation'!
fromReal: aNumber
- "Create a new complex number from the given real number."
- ^ self basicNew setReal: aNumber setImaginary: 0
+ "Create a new complex number from the given real number."
+
+ ^ self basicNew setReal: aNumber setImaginary: 0
+!
+
+imaginary: v
+ "Create a new complex number with 0 as real and given imaginary parts.
+ If the imaginary part is zero, return the real part of the number."
+
+ v = 0 ifTrue: [^ 0].
+ ^ self basicNew setReal: 0 setImaginary: v
+!
+
+real: aNumber
+ "Create a new complex number from the given real number."
+
+ ^ self basicNew setReal: aNumber setImaginary: 0
!
real: u imaginary: v
- "Create a new complex number with the given real and imaginary parts. If the
- imaginary part is zero, return the real part of the number."
- ^v = 0 ifTrue: [u]
- ifFalse: [self basicNew setReal: u setImaginary: v]
+ "Create a new complex number with the given real and imaginary parts. If the
+ imaginary part is zero, return the real part of the number."
+
+ v = 0 ifTrue: [^ u].
+ ^ self basicNew setReal: u setImaginary: v
! !
!Complex class methodsFor:'constants access'!
unity
- "Answer the value which allows, for any given arithmetic value, the following to be true
-
- aNumber * aNumber class unity = aNumber
+ "Answer the value which allows, for any given arithmetic value, the following to be true:
+ aNumber * aNumber class unity = aNumber
+ This must be true regardless of how a given subclass chooses to define #*"
- This must be true regardless of how a given subclass chooses to define #*"
-
- ^self fromReal: 1
+ ComplexOne isNil ifTrue:[
+ ComplexOne := self fromReal: 1
+ ].
+ ^ ComplexOne
!
zero
- "Answer the value which allows, for any given arithmetic value, the following to be true
-
- aNumber + aNumber class zero = aNumber
+ "Answer the value which allows, for any given arithmetic value, the following to be true:
+ aNumber + aNumber class zero = aNumber
+ This must be true regardless of how a given subclass chooses to define #+"
- This must be true regardless of how a given subclass chooses to define #+"
-
- ^self fromReal: 0
+ ComplexZero isNil ifTrue:[
+ ComplexZero := self fromReal: 0
+ ].
+ ^ ComplexZero
! !
!Complex class methodsFor:'exception handling'!
@@ -144,311 +171,554 @@
!Complex methodsFor:'accessing'!
imaginary
- "Return the imaginary part of the complex number."
- ^ imaginary
+ "Return the imaginary part of the complex number."
+
+ ^ imaginary
+!
+
+imaginaryPart
+ "Return the imaginary part of the complex number.
+ An alias for imaginary (for compatibility with other complex implementations)"
+
+ ^ imaginary
!
real
- "Return the real part of the complex number."
- ^ real
+ "Return the real part of the complex number."
+
+ ^ real
+!
+
+realPart
+ "Return the real part of the complex number.
+ An alias for real (for compatibility with other complex implementations)"
+
+ ^ real
! !
!Complex methodsFor:'arithmetic'!
* aNumber
- "Return the product of the receiver and the argument."
-
- | u v r i |
+ "Return the product of the receiver and the argument."
- aNumber isComplex ifTrue:[
- u := aNumber real.
- v := aNumber imaginary.
- r := (real * u) - (imaginary * v).
- i := (real * v) + (imaginary * u).
- i = 0 ifTrue:[ ^ r ].
- ^ Complex real:r imaginary:i
- ].
- ^ self retry: #* coercing: aNumber
+"/ | u v r i |
+"/
+"/ aNumber isComplex ifTrue:[
+"/ u := aNumber real.
+"/ v := aNumber imaginary.
+"/ r := (real * u) - (imaginary * v).
+"/ i := (real * v) + (imaginary * u).
+"/ i = 0 ifTrue:[ ^ r ].
+"/ ^ Complex real:r imaginary:i
+"/ ].
+ ^ aNumber productFromComplex:self.
"Modified: / 8.7.1998 / 12:12:37 / cg"
!
+ aNumber
- "Return the sum of the receiver and the argument."
-
- | r i |
+ "Return the sum of the receiver and the argument."
- aNumber isComplex ifTrue: [
- r := aNumber real + real.
- i := aNumber imaginary + imaginary.
- i = 0 ifTrue:[ ^ r ].
- ^ Complex real:r imaginary:i
- ].
- ^ self retry: #+ coercing: aNumber
+"/ | r i |
+"/
+"/ aNumber isComplex ifTrue: [
+"/ r := aNumber real + real.
+"/ i := aNumber imaginary + imaginary.
+"/ i = 0 ifTrue:[ ^ r ].
+"/ ^ Complex real:r imaginary:i
+"/ ].
+ ^ aNumber sumFromComplex:self.
"Modified: / 8.7.1998 / 12:15:42 / cg"
!
- aNumber
- "Return the difference of the receiver and the argument."
-
- | r i |
+ "Return the difference of the receiver and the argument."
- aNumber isComplex ifTrue: [
- r := real - aNumber real.
- i := imaginary - aNumber imaginary.
- i = 0 ifTrue:[ ^ r ].
- ^ Complex real:r imaginary:i.
- ].
- ^ self retry: #- coercing: aNumber
+"/ | r i |
+"/
+"/ aNumber isComplex ifTrue: [
+"/ r := real - aNumber real.
+"/ i := imaginary - aNumber imaginary.
+"/ i = 0 ifTrue:[ ^ r ].
+"/ ^ Complex real:r imaginary:i.
+"/ ].
+ ^ aNumber differenceFromComplex:self.
"Modified: / 8.7.1998 / 12:15:38 / cg"
!
/ aNumber
- "Return the quotient of the receiver and the argument."
-
- | denom u v r i |
+ "Return the quotient of the receiver and the argument."
- aNumber isComplex ifTrue:[
- u := aNumber real.
- v := aNumber imaginary.
- denom := u * u + (v * v).
- r := u * real + (v * imaginary) / denom.
- i := u * imaginary - (v * real) / denom.
- i = 0 ifTrue:[ ^ r ].
- ^ Complex real:r imaginary:i
- ].
- ^ self retry: #/ coercing: aNumber
+"/ | denom u v r i |
+"/
+"/ aNumber isComplex ifTrue:[
+"/ u := aNumber real.
+"/ v := aNumber imaginary.
+"/ denom := u * u + (v * v).
+"/ r := u * real + (v * imaginary) / denom.
+"/ i := u * imaginary - (v * real) / denom.
+"/ i = 0 ifTrue:[ ^ r ].
+"/ ^ Complex real:r imaginary:i
+"/ ].
+ ^ aNumber quotientFromComplex:self.
"Modified: / 8.7.1998 / 12:15:34 / cg"
!
abs
- "Return the magnitude (or absolute value) of the complex number."
+ "Return the magnitude (or absolute value) of the complex number
+ (thats the distance from the origin in the complex plane)."
- ^ (real * real + (imaginary * imaginary)) sqrt
+ ^ (real * real + (imaginary * imaginary)) sqrt
+
+ "
+ (1 % 1) abs
+ "
!
conjugated
- "Return the complex conjugate of this complex number."
+ "Return the complex conjugate of this complex number
+ (i.e. with imaginary part negated)."
+
+ ^ Complex
+ real: real
+ imaginary: imaginary negated
+!
+
+differenceFromComplex:aComplex
+ "Return the difference of the argument, aComplex and the receiver."
+
+ | r i |
+
+ r := aComplex real - real.
+ i := aComplex imaginary - imaginary.
+ i = 0 ifTrue:[ ^ r ].
+ ^ Complex real:r imaginary:i.
+!
+
+modulus
+ | absReal absImag multiplicand quotient |
+
+ absReal := real abs.
+ absImag := imaginary abs.
+
+ absReal >= absImag ifTrue: [
+ multiplicand := absReal.
+ quotient := imaginary / real
+ ] ifFalse: [
+ multiplicand := absImag.
+ quotient := real / imaginary
+ ].
+ ^ multiplicand * ((1 + (quotient * quotient)) sqrt)
+!
+
+negated
+ "return a new complex with both real and imaginary parts negated"
+
+ ^ Complex
+ real: real negated
+ imaginary: imaginary negated
+!
+
+productFromComplex:aComplex
+ "Return the product of the receiver and the argument, aComplex."
+
+ | u v r i |
- ^ Complex real: real imaginary: imaginary negated
+ u := aComplex real.
+ v := aComplex imaginary.
+ r := (real * u) - (imaginary * v).
+ i := (real * v) + (imaginary * u).
+ i = 0 ifTrue:[ ^ r ].
+ ^ Complex real:r imaginary:i
+!
+
+quotientFromComplex:aComplex
+ "Return the quotient of the argument, aComplex and the receiver."
+
+ | denom nr ni r i |
+
+ nr := aComplex real.
+ ni := aComplex imaginary.
+ denom := real * real + (imaginary * imaginary).
+ r := real * nr + (imaginary * ni) / denom.
+ i := real * ni - (imaginary * nr) / denom.
+ i = 0 ifTrue:[ ^ r ].
+ ^ Complex real:r imaginary:i
+
+"/ is the stuff below better ?
+"/ "Implement complex division (a + ib) / (c + id).
+"/ Due to double dispatch, in this routine
+"/ self = (c + id) and aComplex = (a + ib)."
+"/
+"/ | quotient denominator |
+"/
+"/ self realPart abs >= (self imaginaryPart abs)
+"/ ifTrue: [
+"/ quotient := self imaginaryPart / self realPart.
+"/ denominator := self realPart + (self imaginaryPart * quotient).
+"/ ^ Complex
+"/ real: (aComplex realPart + (aComplex imaginaryPart * quotient)) / denominator
+"/ imaginary: (aComplex imaginaryPart - (aComplex realPart * quotient)) / denominator ]
+"/ ifFalse: [
+"/ quotient := self realPart / self imaginaryPart.
+"/ denominator := (self realPart * quotient) + self imaginaryPart.
+"/ ^ Complex
+"/ real: ((aComplex realPart * quotient) + aComplex imaginaryPart) / denominator
+"/ imaginary: ((aComplex imaginaryPart * quotient) - aComplex realPart) / denominator ]
+!
+
+sumFromComplex:aComplex
+ "Return the sum of the receiver and the argument, aComplex."
+
+ | r i |
+
+ r := aComplex real + real.
+ i := aComplex imaginary + imaginary.
+ i = 0 ifTrue:[ ^ r ].
+ ^ Complex real:r imaginary:i
! !
!Complex methodsFor:'coercing'!
coerce: aNumber
-
- ^aNumber asComplex
+ ^ aNumber asComplex
!
generality
-
- ^150
+ ^ 150
! !
!Complex methodsFor:'comparing'!
< aNumber
- ^Number
- raise: #unorderedSignal
- receiver: self
- selector: #<
- arg: aNumber
- errorString: 'Complex numbers are not well ordered'
+ "raises an error - complex numbers are not well ordered"
+
+ ^ Number
+ raise: #unorderedSignal
+ receiver: self
+ selector: #<
+ arg: aNumber
+ errorString: 'Complex numbers are not well ordered'
+
+ "
+ 1 < (2 % 2)
+ (2 % 2) < 1
+ "
!
= aNumber
- ^ (aNumber real = real) and:[aNumber imaginary = imaginary]
+ "return true, if the argument represents the same numeric value
+ as the receiver, false otherwise"
+
+ ^ aNumber equalFromComplex:self
!
hash
- "Hash is implemented because equals is implemented."
+ "Hash is implemented because equals is implemented."
- ^ real hash
+ ^ real hash
! !
!Complex methodsFor:'converting'!
asComplex
+ "I am a complex - so return the receiver"
- ^self
+ ^ self
!
asFloat
-
- imaginary = 0 ifTrue: [^real asFloat].
- ^Number
- raise: #coercionErrorSignal
- receiver: self
- selector: #asFloat
- errorString: 'Can''t coerce an instance of Complex to a Float'
+ imaginary = 0 ifTrue: [^ real asFloat].
+ ^ Number
+ raise: #coercionErrorSignal
+ receiver: self
+ selector: #asFloat
+ errorString: 'Can''t coerce an instance of Complex to a Float'
!
asInteger
-
- imaginary = 0 ifTrue: [^real asInteger].
- ^Number
- raise: #coercionErrorSignal
- receiver: self
- selector: #asInteger
- errorString: 'Can''t coerce an instance of Complex to an Integer'
+ imaginary = 0 ifTrue: [^real asInteger].
+ ^ Number
+ raise: #coercionErrorSignal
+ receiver: self
+ selector: #asInteger
+ errorString: 'Can''t coerce an instance of Complex to an Integer'
!
asPoint
- "Return the complex number as a point."
- ^ real @ imaginary
+ "Return the complex number as a point."
+
+ ^ real @ imaginary
!
reduceGeneralityIfPossible
- "Answer the receiver transformed to a lower generality, if such a
- transformation is possible without losing information. If not, answer
- the receiver"
+ "Answer the receiver transformed to a lower generality, if such a
+ transformation is possible without losing information.
+ If not, answer the receiver"
- imaginary isZero
- ifTrue: [^real]
- ifFalse: [^self]
+ imaginary isZero
+ ifTrue: [^ real]
+ ifFalse: [^ self]
! !
!Complex methodsFor:'double dispatching'!
-differenceFromFloat: argument
- ^ argument asComplex - self
-!
+differenceFromFloat:aFloat
+ "Return the difference of the argument, aFloat and the receiver."
+
+ "/ ^ aFloat asComplex - self
+
+ | r |
-differenceFromFraction: argument
- ^ argument asComplex - self
+ r := aFloat - real.
+ imaginary = 0 ifTrue:[ ^ r ].
+ ^ Complex real:r imaginary:imaginary
+
+ "
+ (1 % 1) - 1.0
+ 1.0 - (1 % 1)
+ "
!
-differenceFromInteger: argument
- ^ argument asComplex - self
+differenceFromFraction: aFraction
+ ^ aFraction asComplex - self
+!
+
+differenceFromInteger: anInteger
+ ^ anInteger asComplex - self
!
-productFromFloat: argument
- ^ argument asComplex * self
+equalFromComplex:aComplex
+ ^ (aComplex real = real) and:[aComplex imaginary = imaginary]
!
-productFromFraction: argument
- ^ argument asComplex * self
+equalFromFloat:aFloat
+ imaginary = 0 ifFalse:[^ false].
+ ^ real = aFloat
!
-productFromInteger: argument
- ^ argument asComplex * self
+productFromFloat: aFloat
+ "Return the product of the receiver and the argument, aFloat."
+
+ "/ ^ aFloat asComplex * self
+
+ | u r i |
+
+ u := aFloat.
+ r := (real * aFloat).
+ i := (imaginary * aFloat).
+ i = 0 ifTrue:[ ^ r ].
+ ^ Complex real:r imaginary:i
+
+ "
+ (1 % 1) * 2.0
+ (1 % 1) * 0.0
+ 2.0 * (1 % 1)
+ "
!
-quotientFromFloat: argument
- ^ argument asComplex / self
+productFromFraction: aFraction
+ ^ aFraction asComplex * self
!
-quotientFromFraction: argument
- ^ argument asComplex / self
+productFromInteger: anInteger
+ ^ anInteger asComplex * self
+!
+
+quotientFromFloat: aFloat
+ ^ aFloat asComplex / self
!
-quotientFromInteger: argument
- ^ argument asComplex / self
+quotientFromFraction: aFraction
+ ^ aFraction asComplex / self
+!
+
+quotientFromInteger: anInteger
+ ^ anInteger asComplex / self
!
-sumFromFloat: argument
- ^ argument asComplex + self
+sumFromFloat: aFloat
+ "Return the sum of the receiver and the argument, aFloat."
+
+ "/ ^ aFloat asComplex + self
+
+ | r |
+
+ r := aFloat + real.
+ imaginary = 0 ifTrue:[ ^ r ].
+ ^ Complex real:r imaginary:imaginary
+
+ "
+ (1 % 1) + 1.0
+ 1.0 + (1 % 1)
+ "
!
-sumFromFraction: argument
- ^ argument asComplex + self
+sumFromFraction: aFraction
+ ^ aFraction asComplex + self
!
-sumFromInteger: argument
- ^ argument asComplex + self
+sumFromInteger: anInteger
+ ^ anInteger asComplex + self
! !
!Complex methodsFor:'mathematical functions'!
angle
- "Return the radian angle for this Complex number."
+ "Return the radian angle for this Complex number."
- real < 0 ifTrue: [
- imaginary < 0 ifTrue: [
- ^ (imaginary / real) arcTan - Float pi
- ].
- ^ Float pi + (imaginary / real) arcTan
- ].
- ^ (imaginary / real) arcTan
+ real < 0 ifTrue: [
+ imaginary < 0 ifTrue: [
+ ^ (imaginary / real) arcTan - Float pi
+ ].
+ ^ Float pi + (imaginary / real) arcTan
+ ].
+ ^ (imaginary / real) arcTan
+
+ "
+ (1 % 1) angle radiansToDegrees
+ "
!
exp
- "Return the complex exponential of the receiver."
+ "Return the complex exponential of the receiver."
- ^ imaginary cos % imaginary sin * real exp
+ ^ (imaginary cos % imaginary sin) * real exp
!
sqrt
- "Return the square root of the receiver"
+ "Return the square root of the receiver"
+
+ | w quotient absReal absImag |
+
+ ((real = 0) and: [ imaginary = 0 ]) ifTrue: [
+ ^ Complex zero
+ ].
+ absReal := real abs.
+ absImag := imaginary abs.
+
+ absReal >= absImag ifTrue:[
+ quotient := imaginary / real.
+ w := (absReal sqrt) * (((1 + (1 + (quotient * quotient)) sqrt) / 2) sqrt)
+ ] ifFalse: [
+ quotient := real / imaginary.
+ w := (absImag sqrt) * (((quotient abs + (1 + (quotient * quotient)) sqrt) / 2) sqrt)
+ ].
- | u v |
- (imaginary = 0 and: [real >= 0]) ifTrue: [^real sqrt].
- v := (self abs - real / 2) sqrt.
- u := imaginary / 2 / v.
- ^Complex real: u imaginary: v
+ real >= 0 ifTrue:[
+ ^ Complex real: w imaginary: (imaginary / (2 * w))
+ ].
+ imaginary >= 0 ifTrue: [
+ ^ Complex real: absImag / (2 * w) imaginary: w
+ ].
+ ^ Complex real: absImag / (2 * w) imaginary: -1 * w
+!
+
+sqrt_bad
+ "Return the square root of the receiver"
- "-4 asComplex sqrt"
- "-4 asComplex sqrt squared"
+ | u v |
+
+ (imaginary = 0 and: [real >= 0]) ifTrue: [^ real sqrt].
+ v := (self abs - real / 2) sqrt.
+ u := imaginary / 2 / v.
+ ^ Complex real: u imaginary: v
+
+ "
+ -4 asComplex sqrt
+ 4 asComplex sqrt
+ "
+ "
+ -4 asComplex sqrt squared
+ "
! !
!Complex methodsFor:'printing'!
+displayOn: aStream
+ aStream nextPut: $(.
+ self realPart printOn: aStream.
+ self imaginaryPart >= 0
+ ifTrue: [ aStream nextPut: $+ ]
+ ifFalse: [ aStream nextPut: $- ].
+ self imaginaryPart abs printOn: aStream.
+ aStream nextPutAll: 'i)'
+
+ "
+ Complex real:1 imaginary:1
+ "
+!
+
printOn: aStream
- aStream nextPut: $(.
- real storeOn: aStream.
- aStream nextPutAll: '%'.
- imaginary storeOn: aStream.
- aStream nextPut: $).
+ aStream nextPut: $(.
+ real storeOn: aStream.
+ aStream nextPutAll: '%'.
+ imaginary storeOn: aStream.
+ aStream nextPut: $).
!
printString
- ^ '(' , real printString, '%', imaginary printString, ')'
+ ^ '(' , real printString, '%', imaginary printString, ')'
!
storeOn: aStream
- aStream nextPut: $(.
- real storeOn: aStream.
- aStream nextPutAll: '%'.
- imaginary storeOn: aStream.
- aStream nextPut: $).
+ self printOn:aStream
! !
!Complex methodsFor:'private'!
setReal: u setImaginary: v
- real := u.
- imaginary := v.
+ real := u.
+ imaginary := v.
! !
!Complex methodsFor:'testing'!
isComplex
+ "Answer whether the receiver has an imaginary part
+ (i.e. if it is a complex number). Always true here."
- ^true
+ ^ true
!
isReal
- "Return true if this Complex number has a zero imaginary part."
- ^ imaginary = 0
+ "Return true if this Complex number has a zero imaginary part."
+
+ ^ imaginary = 0
!
isZero
- "Answer whether 'self = self class zero'. We can't use #= because
- #= is defined in terms of #isZero"
+ "Answer whether 'self = self class zero'.
+ We can't use #= because #= is defined in terms of #isZero"
- ^real isZero and: [imaginary isZero]
+ ^real isZero and: [imaginary isZero]
!
sign
+ "return a new complex, consisting of the signs of the real and imaginary parts"
- ^Complex real: real sign imaginary: imaginary sign
+ ^ Complex real: real sign imaginary: imaginary sign
+! !
+
+!Complex methodsFor:'truncation & rounding'!
+
+ceiling
+ "blocked: complex numbers have no ceiling"
+
+ ^ self shouldNotImplement
+!
+
+floor
+ "blocked: complex numbers have no floor"
+
+ ^ self shouldNotImplement
! !
!Complex class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/Complex.st,v 1.7 2003-04-22 09:44:13 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/Complex.st,v 1.8 2003-06-16 09:13:42 cg Exp $'
! !
--- a/FixedPoint.st Fri Jun 13 20:52:21 2003 +0200
+++ b/FixedPoint.st Mon Jun 16 11:14:59 2003 +0200
@@ -286,21 +286,20 @@
* aNumber
"return the product 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 results scale is the maximum of the receivers scale and the arguments scale."
- aNumber isInteger ifTrue:[
+ "/ notice:
+ "/ the following code handles some common cases,
+ "/ and exists as an optimization, to speed up those cases.
+ "/ also notice, that checks for those cases must be inlinable without
+ "/ a message send; otherwise double-dispatch is just as fast.
+
+ (aNumber isMemberOf:SmallInteger) ifTrue:[
^ self class
numerator:(numerator * aNumber)
denominator:denominator
scale:scale
].
- aNumber isFraction ifTrue:[
- ^ self class
- numerator:(numerator * aNumber numerator)
- denominator:(denominator * aNumber denominator)
- scale:(scale max:aNumber scale)
- ].
^ aNumber productFromFixedPoint:self
"
@@ -378,54 +377,41 @@
+ 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 results scale will be the maximum of the receivers and the arguments scale."
- |n d|
+ |n|
- (aNumber isInteger or:[aNumber isFraction]) ifTrue:[
- n := aNumber numerator.
- d := aNumber denominator.
+ "/ notice:
+ "/ the following code handles some common cases,
+ "/ and exists as an optimization, to speed up those cases.
+ "/ also notice, that checks for those cases must be inlinable without
+ "/ a message send; otherwise double-dispatch is just as fast.
+ (aNumber isMemberOf:SmallInteger) ifTrue:[
"save a multiplication if possible"
- denominator == d ifTrue:[
- ^ self class
- numerator:(numerator + n)
- denominator:d
- scale:scale
- ].
-
- ^ self class
- numerator:((numerator * d) + (n * denominator))
- denominator:(denominator * d)
- scale:scale
- ].
- aNumber isFixedPoint ifTrue:[
- n := aNumber numerator.
- d := aNumber denominator.
-
- "save a multiplication if possible"
- denominator == d ifTrue:[
- n := numerator + n
+ denominator == 1 ifTrue:[
+ n := numerator + aNumber.
] ifFalse:[
- n := (numerator * d) + (n * denominator).
- d := denominator * d.
+ n := numerator + (aNumber * denominator).
].
^ self class
- numerator:n
- denominator:d
- scale:(scale max:aNumber scale)
+ numerator:n
+ denominator:denominator
+ scale:scale
].
^ aNumber sumFromFixedPoint:self
"
+ ((1/3) asFixedPoint:2) + 1
+ ((1/3) asFixedPoint:2) + (1/3)
+ "
+ "
|a b|
a := (FixedPoint fromString:'123.456').
b := (FixedPoint fromString:'1.10').
a + b
"
-
"
|a b|
@@ -471,43 +457,27 @@
- 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 results scale is the maximum of the receivers scale and the arguments scale."
- |n d|
+ |n|
- (aNumber isInteger or:[aNumber isFraction]) ifTrue:[
- n := aNumber numerator.
- d := aNumber denominator.
+ "/ notice:
+ "/ the following code handles some common cases,
+ "/ and exists as an optimization, to speed up those cases.
+ "/ also notice, that checks for those cases must be inlinable without
+ "/ a message send; otherwise double-dispatch is just as fast.
+ (aNumber isMemberOf:SmallInteger) ifTrue:[
"save a multiplication if possible"
- denominator == d ifTrue:[
- ^ self class
- numerator:(numerator - n)
- denominator:d
- scale:scale
- ].
-
- ^ self class
- numerator:((numerator * d) - (n * denominator))
- denominator:(denominator * d)
- scale:scale
- ].
- aNumber isFixedPoint ifTrue:[
- n := aNumber numerator.
- d := aNumber denominator.
-
- "save a multiplication if possible"
- denominator == d ifTrue:[
- n := numerator - n
+ denominator == 1 ifTrue:[
+ n := numerator - aNumber.
] ifFalse:[
- n := (numerator * d) - (n * denominator).
- d := denominator * d
+ n := numerator - (aNumber * denominator).
].
^ self class
- numerator:n
- denominator:d
- scale:(scale max:aNumber scale)
+ numerator:n
+ denominator:denominator
+ scale:scale
].
^ aNumber differenceFromFixedPoint:self
@@ -516,7 +486,7 @@
a := (FixedPoint fromString:'123.456').
b := (FixedPoint fromString:'1.10').
- a - b
+ a - b
"
"
@@ -572,22 +542,21 @@
/ 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 results scale is the maximum of the receivers scale and the arguments scale."
- aNumber isInteger ifTrue:[
+ "/ notice:
+ "/ the following code handles some common cases,
+ "/ and exists as an optimization, to speed up those cases.
+ "/ also notice, that checks for those cases must be inlinable without
+ "/ a message send; otherwise double-dispatch is just as fast.
+
+ (aNumber isMemberOf:SmallInteger) ifTrue:[
^ self class
numerator:numerator
denominator:(denominator * aNumber)
scale:scale
].
- aNumber isFraction ifTrue:[
- ^ self class
- numerator:(numerator * aNumber denominator)
- denominator:(denominator * aNumber numerator)
- scale:(scale max:aNumber scale)
- ].
^ aNumber quotientFromFixedPoint:self
"
@@ -673,8 +642,10 @@
!
asFixedPoint:newScale
- "return a copy of the receiver, with newScale number of post-decimal
- digits"
+ "return a fixedPoint with the same value as the receiver,
+ and newScale number of post-decimal digits"
+
+ newScale == scale ifTrue:[^ self].
^ self class
numerator:numerator
@@ -697,9 +668,9 @@
asFraction
"return the receiver as a fraction"
- ^ (Fraction
+ ^ Fraction
numerator:numerator
- denominator:denominator)
+ denominator:denominator
"
(FixedPoint fromString:'0.2')
@@ -739,48 +710,199 @@
!FixedPoint methodsFor:'double dispatching'!
+differenceFromFixedPoint:aFixedPoint
+ |n d otherNumerator otherDenominator|
+
+ otherNumerator := aFixedPoint numerator.
+ otherDenominator := aFixedPoint denominator.
+
+ "save a multiplication if possible"
+ denominator = otherDenominator ifTrue:[
+ n := otherNumerator - numerator.
+ d := otherDenominator.
+ ] ifFalse:[
+ n := (otherNumerator * denominator) - (numerator * otherDenominator).
+ d := denominator * otherDenominator.
+ ].
+ ^ self class
+ numerator:n
+ denominator:d
+ scale:(scale max:aFixedPoint scale)
+
+ "
+ ((1/3) asFixedPoint:2) - ((1/3) asFixedPoint:2)
+ ((1/3) asFixedPoint:2) - ((2/3) asFixedPoint:2)
+ (1/3) - ((2/3) asFixedPoint:2)
+
+ ((1/3) asFixedPoint:2) - ((1/3) asFixedPoint:4)
+ ((1/3) asFixedPoint:2) - ((2/3) asFixedPoint:4)
+ "
+!
+
+differenceFromFraction:aFraction
+ |n d otherNumerator otherDenominator|
+
+ otherNumerator := aFraction numerator.
+ otherDenominator := aFraction denominator.
+
+ "save a multiplication if possible"
+ denominator = otherDenominator ifTrue:[
+ n := otherNumerator - numerator.
+ d := otherDenominator.
+ ] ifFalse:[
+ n := (otherNumerator * denominator) - (numerator * otherDenominator).
+ d := denominator * otherDenominator.
+ ].
+ ^ self class
+ numerator:n
+ denominator:d
+ scale:scale
+
+ "
+ (1/3) - ((2/3) asFixedPoint:2)
+ "
+!
+
differenceFromInteger:anInteger
"sent when an integer does not know how to subtract the receiver.
Redefined here to preserve the scale."
- ^ (self class
+ ^ self class
numerator:((anInteger * denominator) - numerator)
denominator:denominator
- scale:scale)
+ scale:scale
+!
+
+productFromFixedPoint:aFixedPoint
+ ^ aFixedPoint class
+ numerator:(aFixedPoint numerator * numerator)
+ denominator:(aFixedPoint denominator * denominator)
+ scale:(scale max:aFixedPoint scale)
+
+ "
+ ((1/3) asFixedPoint:2) * ((1/3) asFixedPoint:4)
+ (1/3) * ((1/3) asFixedPoint:4)
+ "
+!
+
+productFromFraction:aFraction
+ ^ self class
+ numerator:(aFraction numerator * numerator)
+ denominator:(aFraction denominator * denominator)
+ scale:scale
+
+ "
+ (1/3) * ((1/3) asFixedPoint:4)
+ "
!
productFromInteger:anInteger
"sent when an integer does not know how to multiply the receiver.
Redefined here to preserve the scale."
- ^ (self class
+ ^ self class
numerator:(anInteger * numerator)
denominator:denominator
- scale:scale)
+ scale:scale
"Modified: 5.11.1996 / 10:32:28 / cg"
!
+quotientFromFixedPoint:aFixedPoint
+ ^ aFixedPoint class
+ numerator:(aFixedPoint numerator * denominator)
+ denominator:(aFixedPoint denominator * numerator)
+ scale:(scale max:aFixedPoint scale)
+
+ "
+ ((1/3) asFixedPoint:2) / ((1/3) asFixedPoint:2)
+ ((1/3) asFixedPoint:2) / ((1/3) asFixedPoint:4)
+ "
+!
+
+quotientFromFraction:aFraction
+ ^ aFraction class
+ numerator:(aFraction numerator * denominator)
+ denominator:(aFraction denominator * numerator)
+ scale:scale
+
+ "
+ ((1/3) asFixedPoint:2) / ((1/3) asFixedPoint:2)
+ ((1/3) asFixedPoint:2) / ((1/3) asFixedPoint:4)
+ "
+!
+
quotientFromInteger:anInteger
"sent when an integer does not know how to divide by the receiver.
Redefined here to preserve the scale."
- ^ (self class
+ ^ self class
numerator:(anInteger * denominator)
denominator:numerator
- scale:scale)
+ scale:scale
"Modified: 5.11.1996 / 10:32:35 / cg"
!
+sumFromFixedPoint:aFixedPoint
+ |n d otherNumerator otherDenominator|
+
+ otherNumerator := aFixedPoint numerator.
+ otherDenominator := aFixedPoint denominator.
+
+ "save a multiplication if possible"
+ denominator = otherDenominator ifTrue:[
+ n := numerator + otherNumerator.
+ d := otherDenominator.
+ ] ifFalse:[
+ n := (numerator * otherDenominator) + (otherNumerator * denominator).
+ d := denominator * otherDenominator.
+ ].
+ ^ self class
+ numerator:n
+ denominator:d
+ scale:(scale max:aFixedPoint scale)
+
+ "
+ ((1/3) asFixedPoint:2) + ((1/3) asFixedPoint:2)
+ ((1/3) asFixedPoint:2) + ((2/3) asFixedPoint:2)
+
+ ((1/3) asFixedPoint:2) + ((1/3) asFixedPoint:4)
+ "
+!
+
+sumFromFraction:aFraction
+ |n d otherNumerator otherDenominator|
+
+ otherNumerator := aFraction numerator.
+ otherDenominator := aFraction denominator.
+
+ "save a multiplication if possible"
+ denominator = otherDenominator ifTrue:[
+ n := numerator + otherNumerator.
+ d := otherDenominator.
+ ] ifFalse:[
+ n := (numerator * otherDenominator) + (otherNumerator * denominator).
+ d := denominator * otherDenominator.
+ ].
+ ^ self class
+ numerator:n
+ denominator:d
+ scale:scale
+
+ "
+ (1/3) + ((1/3) asFixedPoint:2)
+ "
+!
+
sumFromInteger:anInteger
"sent when an integer does not know how to add the receiver.
Redefined here to preserve the scale."
- ^ (self class
+ ^ self class
numerator:(numerator + (anInteger * denominator))
denominator:denominator
- scale:scale)
+ scale:scale
"Modified: 5.11.1996 / 10:32:43 / cg"
! !
@@ -970,5 +1092,5 @@
!FixedPoint class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/FixedPoint.st,v 1.26 2003-02-25 10:17:54 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/FixedPoint.st,v 1.27 2003-06-16 09:14:24 cg Exp $'
! !
--- a/Float.st Fri Jun 13 20:52:21 2003 +0200
+++ b/Float.st Mon Jun 16 11:14:59 2003 +0200
@@ -406,42 +406,6 @@
]
!
-readBinaryIEEESingleFrom:aStream
- "read a float value from the binary stream, aStream,
- interpreting the next bytes as an IEEE formatted 4-byte float"
-
- |f|
-
- f := self basicNew.
- self readBinaryIEEESingleFrom:aStream into:f.
- ^ f
-
- "Created: 16.4.1996 / 21:00:35 / cg"
-!
-
-readBinaryIEEESingleFrom:aStream into:aFloat
- "read a float value from the binary stream, aStream,
- interpreting the next bytes as an IEEE formatted 4-byte float"
-
- "
- this implementation is wrong: does not work on non-IEEE machines
- (to date all machines where ST/X is running on use
- IEEE float format. Need more here, when porting ST/X to 370's)
- "
- self isIEEEFormat ifFalse:[self error:'unsupported operation'].
-
- UninterpretedBytes isBigEndian ifFalse:[
- "swap the bytes"
- 8 to:4 by:-1 do:[:i |
- aFloat basicAt:i put:(aStream next)
- ].
- ^ self
- ].
- 1 to:4 do:[:i |
- aFloat basicAt:i put:aStream next
- ]
-!
-
storeBinaryIEEEDouble:aFloat on:aStream
"store aFloat as an IEEE formatted 8-byte float
onto the binary stream, aStream"
@@ -463,29 +427,6 @@
1 to:8 do:[:i |
aStream nextPut:(aFloat basicAt:i).
].
-!
-
-storeBinaryIEEESingle:aFloat on:aStream
- "store aFloat as an IEEE formatted 4-byte float
- onto the binary stream, aStream"
-
- "
- this implementation is wrong: does not work on non-IEEE machines
- (to date all machines where ST/X is running on use
- IEEE float format. Need more here, when porting ST/X to 370's)
- "
- self isIEEEFormat ifFalse:[self error:'unsupported operation'].
-
- UninterpretedBytes isBigEndian ifFalse:[
- "swap the bytes"
- 8 to:4 by:-1 do:[:i |
- aStream nextPut:(aFloat basicAt:i).
- ].
- ^ self
- ].
- 1 to:4 do:[:i |
- aStream nextPut:(aFloat basicAt:i).
- ]
! !
!Float class methodsFor:'constants'!
@@ -504,7 +445,7 @@
# endif
#endif
%}.
- ^ nil
+ ^ 0.0 uncheckedDivide:0.0
"
Float NaN
@@ -515,9 +456,9 @@
!
infinity
- "return a float representing infinity"
+ "return a float representing infinity"
- ^ 1.0 uncheckedDivide:0.0
+ ^ 1.0 uncheckedDivide:0.0
!
pi
@@ -531,22 +472,6 @@
"Modified: 23.4.1996 / 09:27:02 / cg"
!
-precision
- "answer the precision of a Float
- This is an IEEE float, only the fraction from the normalized mantissa is stored
- and so there is a hidden bit and the mantissa is actually represented
- by 53 binary digits"
-
- ^ 53
-!
-
-radix
- "answer the radix of a Float
- This is an IEEE float, which is represented as binary"
-
- ^ 2
-!
-
unity
"return the neutral element for multiplication (1.0) as Float"
@@ -599,6 +524,40 @@
(among others). Today, most systems use IEEE format floats."
^ true "/ this may be a lie
+!
+
+numBitsInExponent
+ "answer the number of bits in the exponent
+ This is an IEEE float, where 11 bits are available:
+ seeeeeee eeeemmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm
+ "
+
+ ^ 11
+!
+
+numBitsInMantissa
+ "answer the number of bits in the mantissa.
+ This is an IEEE double, where 52 bits (the hidden one is not counted here) are available:
+ seeeeeee eeeemmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm
+ "
+
+ ^ 52
+!
+
+precision
+ "answer the precision of a Float (in bits)
+ This is an IEEE double, only the fraction from the normalized mantissa is stored
+ and so there is a hidden bit and the mantissa is actually represented
+ by 53 binary digits"
+
+ ^ 53
+!
+
+radix
+ "answer the radix of a Floats exponent
+ This is an IEEE float, which is represented as binary"
+
+ ^ 2 "must be careful here, whenever ST/X is used on VAX or a 370"
! !
!Float methodsFor:'arithmetic'!
@@ -766,13 +725,12 @@
double rslt;
if (val < 0.0) {
- rslt = -val;
- __qMKFLOAT(newFloat, rslt);
- RETURN ( newFloat );
+ rslt = -val;
+ __qMKFLOAT(newFloat, rslt);
+ RETURN ( newFloat );
}
RETURN (self);
%}.
- ^ super abs
"
3.0 abs
@@ -784,19 +742,20 @@
"return myself negated"
%{ /* NOCONTEXT */
-
OBJ newFloat;
double rslt = - __floatVal(self);
__qMKFLOAT(newFloat, rslt);
RETURN ( newFloat );
%}.
- ^ 0.0 - self
!
uncheckedDivide:aNumber
"return the quotient of the receiver and the argument, aNumber.
- Do not check for divide by zero (return NaN or infinity)"
+ 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."
%{ /* NOCONTEXT */
@@ -804,23 +763,28 @@
double result, val;
if (__isSmallInteger(aNumber)) {
- result = __floatVal(self) / ( (double)__intVal(aNumber)) ;
+ result = __floatVal(self) / ( (double)__intVal(aNumber)) ;
retResult:
- __qMKFLOAT(newFloat, result);
- RETURN ( newFloat );
- } else if (__isFloatLike(aNumber)) {
- val = __floatVal(aNumber);
- result = __floatVal(self) / val;
- goto retResult;
+ __qMKFLOAT(newFloat, result);
+ RETURN ( newFloat );
}
-%}
-.
+ if (__isFloatLike(aNumber)) {
+ val = __floatVal(aNumber);
+ result = __floatVal(self) / val;
+ goto retResult;
+ }
+ if (__isShortFloat(aNumber)) {
+ val = (double)(__shortFloatVal(aNumber));
+ result = __floatVal(self) / val;
+ goto retResult;
+ }
+%}.
^ aNumber quotientFromFloat:self
-
"
- 0.0 uncheckedDivide:0.0
- 1.0 uncheckedDivide:0.0
+ 0.0 uncheckedDivide:0.0
+ 1.0 uncheckedDivide:0.0
+ -1.0 uncheckedDivide:0.0
"
! !
@@ -871,17 +835,7 @@
asLongFloat
"return a longFloat with same value as receiver"
-%{ /* NOCONTEXT */
-#ifdef LONGFLOAT
- OBJ dummy = @global(LongFloat);
- OBJ newFloat;
- LONGFLOAT fVal = (LONGFLOAT)__floatVal(self);
-
- __qMKLFLOAT(newFloat, fVal);
- RETURN ( newFloat );
-#endif
-%}.
- ^ self
+ ^ LongFloat fromFloat:self
"
123 asFloat asLongFloat
@@ -892,7 +846,8 @@
!
asShortFloat
- "return a shortFloat with same value as receiver"
+ "return a shortFloat with same value as receiver.
+ CAVEAT: should raise an error if the receiver exceeds the float range."
%{ /* NOCONTEXT */
@@ -906,7 +861,7 @@
!
asTrueFraction
- "Answer a fraction that EXACTLY represents self,
+ "Answer a fraction or integer that EXACTLY represents self,
a double precision IEEE floating point number.
Floats are stored in the same form on all platforms.
(Does not handle gradual underflow or NANs.)
@@ -928,7 +883,7 @@
"Extract the bits of an IEEE double float "
shifty := LargeInteger basicNew numberOfDigits:8.
UninterpretedBytes isBigEndian ifTrue:[
-"/ shifty := ((self basicAt: 1) bitShift: 32) + (self basicAt: 2).
+"/ shifty := ((self longWordAt: 1) bitShift: 32) + (self longWordAt: 2).
1 to:8 do:[:i | shifty digitAt:(9-i) put:(self basicAt:i)].
] ifFalse:[
1 to:8 do:[:i | shifty digitAt:i put:(self basicAt:i)].
@@ -1002,13 +957,16 @@
%{ /* NOCONTEXT */
+ if (__isSmallInteger(aNumber)) {
+ RETURN ( (__floatVal(self) < (double)(__intVal(aNumber))) ? true : false );
+ }
if (aNumber != nil) {
- if (__isSmallInteger(aNumber)) {
- RETURN ( (__floatVal(self) < (double)(__intVal(aNumber))) ? true : false );
- }
- if (__qIsFloatLike(aNumber)) {
- RETURN ( (__floatVal(self) < __floatVal(aNumber)) ? true : false );
- }
+ if (__qIsFloatLike(aNumber)) {
+ RETURN ( (__floatVal(self) < __floatVal(aNumber)) ? true : false );
+ }
+ if (__qIsShortFloat(aNumber)) {
+ RETURN ( (__floatVal(self) < (double)(__shortFloatVal(aNumber))) ? true : false );
+ }
}
%}.
^ aNumber lessFromFloat:self
@@ -1019,38 +977,42 @@
%{ /* NOCONTEXT */
+ if (__isSmallInteger(aNumber)) {
+ RETURN ( (__floatVal(self) <= (double)(__intVal(aNumber))) ? true : false );
+ }
if (aNumber != nil) {
- if (__isSmallInteger(aNumber)) {
- RETURN ( (__floatVal(self) <= (double)(__intVal(aNumber))) ? true : false );
- }
- if (__qIsFloatLike(aNumber)) {
- RETURN ( (__floatVal(self) <= __floatVal(aNumber)) ? true : false );
- }
+ if (__qIsFloatLike(aNumber)) {
+ RETURN ( (__floatVal(self) <= __floatVal(aNumber)) ? true : false );
+ }
+ if (__qIsShortFloat(aNumber)) {
+ RETURN ( (__floatVal(self) <= (double)(__shortFloatVal(aNumber))) ? true : false );
+ }
}
%}.
^ self retry:#<= coercing:aNumber
!
= aNumber
- "return true, if the arguments value are equal by value"
+ "return true, if the argument represents the same numeric value
+ as the receiver, false otherwise"
%{ /* NOCONTEXT */
+ if (__isSmallInteger(aNumber)) {
+ RETURN ( (__floatVal(self) == (double)(__intVal(aNumber))) ? true : false );
+ }
if (aNumber != nil) {
- if (__isSmallInteger(aNumber)) {
- RETURN ( (__floatVal(self) == (double)(__intVal(aNumber))) ? true : false );
- }
- if (__qIsFloatLike(aNumber)) {
- RETURN ( (__floatVal(self) == __floatVal(aNumber)) ? true : false );
- }
- if (__qClass(aNumber)==ShortFloat) {
- RETURN ( (__floatVal(self) == (double)(__shortFloatVal(aNumber))) ? true : false );
- }
+ if (__qIsFloatLike(aNumber)) {
+ RETURN ( (__floatVal(self) == __floatVal(aNumber)) ? true : false );
+ }
+ if (__qIsShortFloat(aNumber)) {
+ RETURN ( (__floatVal(self) == (double)(__shortFloatVal(aNumber))) ? true : false );
+ }
} else {
- RETURN (false);
+ RETURN (false);
}
%}.
- ^ self retry:#= coercing:aNumber
+ ^ aNumber equalFromFloat:self
!
> aNumber
@@ -1058,13 +1020,16 @@
%{ /* NOCONTEXT */
+ if (__isSmallInteger(aNumber)) {
+ RETURN ( (__floatVal(self) > (double)(__intVal(aNumber))) ? true : false );
+ }
if (aNumber != nil) {
- if (__isSmallInteger(aNumber)) {
- RETURN ( (__floatVal(self) > (double)(__intVal(aNumber))) ? true : false );
- }
- if (__qIsFloatLike(aNumber)) {
- RETURN ( (__floatVal(self) > __floatVal(aNumber)) ? true : false );
- }
+ if (__qIsFloatLike(aNumber)) {
+ RETURN ( (__floatVal(self) > __floatVal(aNumber)) ? true : false );
+ }
+ if (__qIsShortFloat(aNumber)) {
+ RETURN ( (__floatVal(self) > (double)(__shortFloatVal(aNumber))) ? true : false );
+ }
}
%}.
^ self retry:#> coercing:aNumber
@@ -1075,13 +1040,16 @@
%{ /* NOCONTEXT */
+ if (__isSmallInteger(aNumber)) {
+ RETURN ( (__floatVal(self) >= (double)(__intVal(aNumber))) ? true : false );
+ }
if (aNumber != nil) {
- if (__isSmallInteger(aNumber)) {
- RETURN ( (__floatVal(self) >= (double)(__intVal(aNumber))) ? true : false );
- }
- if (__qIsFloatLike(aNumber)) {
- RETURN ( (__floatVal(self) >= __floatVal(aNumber)) ? true : false );
- }
+ if (__qIsFloatLike(aNumber)) {
+ RETURN ( (__floatVal(self) >= __floatVal(aNumber)) ? true : false );
+ }
+ if (__qIsShortFloat(aNumber)) {
+ RETURN ( (__floatVal(self) >= (double)(__shortFloatVal(aNumber))) ? true : false );
+ }
}
%}.
^ self retry:#>= coercing:aNumber
@@ -1127,18 +1095,21 @@
%{ /* NOCONTEXT */
+ if (__isSmallInteger(aNumber)) {
+ RETURN ( (__floatVal(self) != (double)(__intVal(aNumber))) ? true : false );
+ }
if (aNumber != nil) {
- if (__isSmallInteger(aNumber)) {
- RETURN ( (__floatVal(self) != (double)(__intVal(aNumber))) ? true : false );
- }
- if (__qIsFloatLike(aNumber)) {
- RETURN ( (__floatVal(self) != __floatVal(aNumber)) ? true : false );
- }
+ if (__qIsFloatLike(aNumber)) {
+ RETURN ( (__floatVal(self) != __floatVal(aNumber)) ? true : false );
+ }
+ if (__qIsShortFloat(aNumber)) {
+ RETURN ( (__floatVal(self) != (double)(__shortFloatVal(aNumber))) ? true : false );
+ }
} else {
- RETURN (true);
+ RETURN ( true );
}
%}.
- ^ self retry:#~= coercing:aNumber
+ ^ super ~= aNumber
! !
!Float methodsFor:'mathematical functions'!
@@ -1581,24 +1552,26 @@
OBJ s;
if (__isString(formatString)) {
- sprintf(buffer, __stringVal(formatString), __floatVal(self));
+ sprintf(buffer, __stringVal(formatString), __floatVal(self));
- s = __MKSTRING(buffer COMMA_SND);
- if (s != nil) {
- RETURN (s);
- }
+ s = __MKSTRING(buffer COMMA_SND);
+ if (s != nil) {
+ RETURN (s);
+ }
}
%}.
self primitiveFailed
- "Float pi printfPrintString:'%%lg -> %lg'"
- "Float pi printfPrintString:'%%lf -> %lf'"
- "Float pi printfPrintString:'%%7.5lg -> %7.5lg'"
- "Float pi printfPrintString:'%%7.5lf -> %7.5lf'"
- "Float pi printfPrintString:'%%G -> %G'"
- "Float pi printfPrintString:'%%F -> %F'"
- "Float pi printfPrintString:'%%7.5G -> %7.5G'"
- "Float pi printfPrintString:'%%7.5F -> %7.5F'"
+ "
+ Float pi printfPrintString:'%%lg -> %lg'
+ Float pi printfPrintString:'%%lf -> %lf'
+ Float pi printfPrintString:'%%7.5lg -> %7.5lg'
+ Float pi printfPrintString:'%%7.5lf -> %7.5lf'
+ Float pi printfPrintString:'%%G -> %G'
+ Float pi printfPrintString:'%%F -> %F'
+ Float pi printfPrintString:'%%7.5G -> %7.5G'
+ Float pi printfPrintString:'%%7.5F -> %7.5F'
+ "
! !
!Float methodsFor:'private-accessing'!
@@ -1703,12 +1676,6 @@
RETURN (__MKSMALLINT(sizeof(double)));
%}.
-!
-
-defaultNumberOfDigits
- "Answer how many digits of accuracy this class supports"
-
- ^ 14
! !
!Float methodsFor:'special access'!
@@ -1952,7 +1919,6 @@
RETURN ( (__floatVal(self) < 0.0) ? true : false );
%}.
- ^ self < 0.0
!
numberOfBits
@@ -2009,12 +1975,12 @@
%{
double dVal;
+ dVal = ceil(__floatVal(self));
/*
* ST-80 (and X3J20) returns integer.
*/
- dVal = ceil(__floatVal(self));
if ((dVal >= (double)_MIN_INT) && (dVal <= (double)_MAX_INT)) {
- RETURN ( __MKSMALLINT( (INT) dVal ) );
+ RETURN ( __MKSMALLINT( (INT) dVal ) );
}
__qMKFLOAT(val, dVal);
%}.
@@ -2025,20 +1991,21 @@
"return the smallest integer-valued float greater or equal to the receiver.
This is much like #ceiling, but avoids a (possibly expensive) conversion
of the result to an integer.
- It may be useful, if the result is to be further used in another
- float-operation."
+ It may be useful, if the result is to be further used in another float-operation."
%{ /* NOCONTEXT */
double dVal;
- OBJ val;
+ OBJ v;
- /*
- * ST-80 (and X3J20) returns integer.
- */
dVal = ceil(__floatVal(self));
- __qMKFLOAT(val, dVal);
- RETURN (val);
+ __qMKFLOAT(v, dVal);
+ RETURN (v);
%}
+ "
+ 0.5 ceilingAsFloat
+ -0.5 ceilingAsFloat
+ -1.5 ceilingAsFloat
+ "
!
floor
@@ -2049,12 +2016,12 @@
%{
double dVal;
+ dVal = floor(__floatVal(self));
/*
* ST-80 (and X3J20) returns integer.
*/
- dVal = floor(__floatVal(self));
if ((dVal >= (double)_MIN_INT) && (dVal <= (double)_MAX_INT)) {
- RETURN ( __MKSMALLINT( (INT) dVal ) );
+ RETURN ( __MKSMALLINT( (INT) dVal ) );
}
__qMKFLOAT(val, dVal);
%}.
@@ -2066,16 +2033,13 @@
-0.5 floor
-0.5 floorAsFloat
"
-
!
floorAsFloat
- "return the integer nearest the receiver towards negative infinity
- as a float.
+ "return the integer nearest the receiver towards negative infinity as a float.
This is much like #floor, but avoids a (possibly expensive) conversion
of the result to an integer.
- It may be useful, if the result is to be further used in another
- float-operation."
+ It may be useful, if the result is to be further used in another float-operation."
%{ /* NOCONTEXT */
double dVal;
@@ -2092,13 +2056,11 @@
-0.5 floor
-0.5 floorAsFloat
"
-
!
fractionPart
"extract the after-decimal fraction part.
- the floats value is
- float truncated + float fractionalPart"
+ such that (self truncated + self fractionPart) = self"
%{ /* NOCONTEXT */
@@ -2108,12 +2070,15 @@
__threadErrno = 0;
frac = modf(__floatVal(self), &trunc);
if (__threadErrno == 0) {
- RETURN (__MKFLOAT(frac));
+ RETURN (__MKFLOAT(frac));
}
%}.
^ self primitiveFailed
"
+ 1.6 fractionPart + 1.6 truncated
+ -1.6 fractionPart + -1.6 truncated
+
1.0 fractionPart
2.0 fractionPart
3.0 fractionPart
@@ -2142,25 +2107,19 @@
dVal = __floatVal(self);
if (dVal < 0.0) {
- dVal = ceil(dVal - 0.5);
+ dVal = ceil(dVal - 0.5);
} else {
- dVal = floor(dVal + 0.5);
+ dVal = floor(dVal + 0.5);
}
/*
* ST-80 (and X3J20) returns integer.
*/
if ((dVal >= (double)_MIN_INT) && (dVal <= (double)_MAX_INT)) {
- RETURN ( __MKSMALLINT( (INT) dVal ) );
+ RETURN ( __MKSMALLINT( (INT) dVal ) );
}
__qMKFLOAT(val, dVal);
%}.
- val notNil ifTrue:[
- ^ val asInteger
- ].
- self < 0.0 ifTrue:[
- ^ (self - 0.5) ceiling asInteger
- ].
- ^ (self + 0.5) floor asInteger
+ ^ val asInteger
"
0.4 rounded
@@ -2270,7 +2229,7 @@
!Float class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/Float.st,v 1.132 2003-05-07 14:10:38 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/Float.st,v 1.133 2003-06-16 09:14:45 cg Exp $'
! !
Float initialize!
--- a/Fraction.st Fri Jun 13 20:52:21 2003 +0200
+++ b/Fraction.st Mon Jun 16 11:14:59 2003 +0200
@@ -207,32 +207,21 @@
* aNumber
"return the product of the receiver and the argument, aNumber"
- |n d|
-
- "/
"/ notice:
"/ the following code handles some common cases,
"/ and exists as an optimization, to speed up those cases.
+ "/ also notice, that checks for those cases must be inlinable without
+ "/ a message send; otherwise double-dispatch is just as fast.
"/
"/ Conceptionally, (and for most other argument types),
"/ mixed arithmetic is implemented by double dispatching
"/ (see the message send at the bottom)
- "/
- aNumber isInteger ifTrue:[
+ (aNumber isMemberOf:SmallInteger) ifTrue:[
^ self class
numerator:(numerator * aNumber)
denominator:denominator
].
- aNumber isFraction ifTrue:[
- aNumber isFixedPoint ifFalse:[ "/ the value was corrent, but the scale is lost
- n := numerator * aNumber numerator.
- d := denominator * aNumber denominator.
- ^ self class
- numerator:n
- denominator:d
- ]
- ].
(aNumber isMemberOf:Float) ifTrue:[
^ (numerator * aNumber) / denominator
].
@@ -245,42 +234,23 @@
+ aNumber
"return the sum of the receiver and the argument, aNumber"
- |n d|
-
- "/
"/ notice:
"/ the following code handles some common cases,
"/ and exists as an optimization, to speed up those cases.
+ "/ also notice, that checks for those cases must be inlinable without
+ "/ a message send; otherwise double-dispatch is just as fast.
"/
"/ Conceptionally, (and for most other argument types),
"/ mixed arithmetic is implemented by double dispatching
"/ (see the message send at the bottom)
- "/
- aNumber isInteger ifTrue:[
+ (aNumber isMemberOf:SmallInteger) ifTrue:[
^ self class
- numerator:(numerator + (denominator * aNumber))
- denominator:denominator
- ].
- aNumber isFraction ifTrue:[
- aNumber isFixedPoint ifFalse:[ "/ the value was correct, but the scale is lost
- n := aNumber numerator.
- d := aNumber denominator.
-
- "save a multiplication if possible"
- denominator == d ifTrue:[
- n := numerator + n
- ] ifFalse:[
- n := (numerator * d) + (n * denominator).
- d := denominator * d.
- ].
- ^ self class
- numerator:n
- denominator:d
- ]
+ numerator:(numerator + (denominator * aNumber))
+ denominator:denominator
].
(aNumber isMemberOf:Float) ifTrue:[
- ^ aNumber + self asFloat
+ ^ (numerator asFloat / denominator asFloat) + aNumber
].
^ aNumber sumFromFraction:self
@@ -291,40 +261,21 @@
- aNumber
"return the difference of the receiver and the argument, aNumber"
- |n d|
-
- "/
"/ notice:
"/ the following code handles some common cases,
"/ and exists as an optimization, to speed up those cases.
+ "/ also notice, that checks for those cases must be inlinable without
+ "/ a message send; otherwise double-dispatch is just as fast.
"/
"/ Conceptionally, (and for most other argument types),
"/ mixed arithmetic is implemented by double dispatching
"/ (see the message send at the bottom)
- "/
- aNumber isInteger ifTrue:[
+ (aNumber isMemberOf:SmallInteger) ifTrue:[
^ self class
numerator:(numerator - (denominator * aNumber))
denominator:denominator
].
- aNumber isFraction ifTrue:[
- aNumber isFixedPoint ifFalse:[ "/ the value was corrent, but the scale is lost
- n := aNumber numerator.
- d := aNumber denominator.
-
- "save a multiplication if possible"
- denominator == d ifTrue:[
- n := numerator - n
- ] ifFalse:[
- n := (numerator * d) - (n * denominator).
- d := denominator * d
- ].
- ^ self class
- numerator:n
- denominator:d
- ]
- ].
(aNumber isMemberOf:Float) ifTrue:[
^ (numerator asFloat / denominator asFloat) - aNumber
].
@@ -345,32 +296,21 @@
/ aNumber
"return the quotient of the receiver and the argument, aNumber"
- |n d|
-
- "/
"/ notice:
"/ the following code handles some common cases,
"/ and exists as an optimization, to speed up those cases.
+ "/ also notice, that checks for those cases must be inlinable without
+ "/ a message send; otherwise double-dispatch is just as fast.
"/
"/ Conceptionally, (and for most other argument types),
"/ mixed arithmetic is implemented by double dispatching
"/ (see the message send at the bottom)
- "/
- aNumber isInteger ifTrue:[
+ (aNumber isMemberOf:SmallInteger) ifTrue:[
^ self class
numerator:numerator
denominator:(denominator * aNumber)
].
- aNumber isFraction ifTrue:[
- aNumber isFixedPoint ifFalse:[ "/ the value was corrent, but the scale is lost
- n := numerator * aNumber denominator.
- d := denominator * aNumber numerator.
- ^ self class
- numerator:n
- denominator:d
- ]
- ].
(aNumber isMemberOf:Float) ifTrue:[
^ numerator / (denominator * aNumber)
].
@@ -514,6 +454,51 @@
^ self asInteger asLargeInteger
!
+asLongFloat
+ "return a long float with (approximately) my value"
+
+ |num den numShift denShift bits|
+
+ (numerator class == SmallInteger and:[denominator class == SmallInteger]) ifTrue:[
+ ^ (numerator asLongFloat) / (denominator asLongFloat)
+ ].
+
+ "Do it the hard way: reduce magnitude and undo reduction on the quotient"
+
+ bits := LongFloat precision * 2. "number of bits to preserve (conservative)"
+ num := numerator abs.
+ numShift := bits - num highBit. "(num highBit - bits) negated"
+ numShift < 0 ifTrue:[num := num bitShift:numShift] ifFalse:[numShift := 0].
+
+ den := denominator.
+ denShift := bits - den highBit. "(den highBit - bits) negated"
+ denShift < 0 ifTrue:[den := den bitShift:denShift] ifFalse:[denShift := 0].
+
+ ^ (num asLongFloat / den asLongFloat) * (2.0 raisedToInteger:denShift-numShift) * (num sign)
+
+ "
+ (5/9) asLongFloat
+ (-5/9) asLongFloat
+ (500000000000/900000000000) asLongFloat
+ (-500000000000/900000000000) asLongFloat
+ (500000000000/9) asLongFloat
+ (5/900000000000) asLongFloat
+ 89012345678901234567 asFloat / 123456789123456789 asLongFloat
+ (89012345678901234567 / 123456789123456789) asLongFloat
+
+ (
+ 180338700661043257034670206806167960222709397862806840937993331366591676308781197477183367018067356365812757479444845320188679437752013593674158587947149815441890236037219685250845721864713487208757788709113534916165172927384095182655935222723385253851776639985379367854545495930551624041981995105743408203125
+ /
+ 180331613628627651967947866455016278082980736719853750685591387625058011528928110602436691256100991596843001549483950600930062886280582766771424470965440873615557144641435276844465734361353086032476712374317224249252177316815544331763696909434844464464323192083930469387098582956241443753242492675781250
+ ) asLongFloat
+
+ 180338700661043257034670206806167960222709397862806840937993331366591676308781197477183367018067356365812757479444845320188679437752013593674158587947149815441890236037219685250845721864713487208757788709113534916165172927384095182655935222723385253851776639985379367854545495930551624041981995105743408203125
+ asLongFloat /
+ 180331613628627651967947866455016278082980736719853750685591387625058011528928110602436691256100991596843001549483950600930062886280582766771424470965440873615557144641435276844465734361353086032476712374317224249252177316815544331763696909434844464464323192083930469387098582956241443753242492675781250
+ asLongFloat
+ "
+!
+
asShortFloat
"return a short float with (approximately) my value"
@@ -548,21 +533,9 @@
"return true if the receiver is less
than aNumber, false otherwise."
- |d n|
-
(aNumber isMemberOf:SmallInteger) ifTrue:[
^ numerator < (denominator * aNumber)
].
- aNumber isFraction ifTrue:[
- d := aNumber denominator.
- n := aNumber numerator.
-
- "/ save a multiplication if possible
- d == denominator ifTrue:[
- ^ numerator < n
- ].
- ^ (numerator * d) < (denominator * n)
- ].
^ aNumber lessFromFraction:self
"Modified: 5.11.1996 / 10:30:52 / cg"
@@ -578,19 +551,7 @@
].
^ numerator = aNumber
].
- aNumber isFraction ifTrue:[
- denominator = aNumber denominator ifTrue:[
- ^ numerator = aNumber numerator
- ].
- ^ self sameFractionValueAs:aNumber
- ].
- (aNumber isInteger) ifTrue:[
- (denominator == 1) ifFalse:[
- ^ numerator = (aNumber * denominator)
- ].
- ^ numerator = aNumber
- ].
- ^ self retry:#= coercing:aNumber
+ ^ aNumber equalFromFraction:self
"Modified: / 7.7.1998 / 17:17:07 / cg"
!
@@ -600,24 +561,10 @@
than aNumber, false otherwise."
"optional - could use inherited method ..."
- |d n|
-
(aNumber isMemberOf:SmallInteger) ifTrue:[
^ numerator > (denominator * aNumber)
].
- aNumber isFraction ifTrue:[
- d := aNumber denominator.
- n := aNumber numerator.
-
- "/ save a multiplication if possible
- d == denominator ifTrue:[
- ^ numerator > n
- ].
- ^ (numerator * d) > (denominator * n)
- ].
- ^ self retry:#> coercing:aNumber
-
- "Modified: 5.11.1996 / 10:31:28 / cg"
+ ^ aNumber < self
!
hash
@@ -658,72 +605,249 @@
!Fraction methodsFor:'double dispatching'!
+differenceFromFixedPoint:aFixedPoint
+ |n d otherDenominator otherNumerator|
+
+ otherDenominator := aFixedPoint denominator.
+ otherNumerator := aFixedPoint numerator.
+
+ "save a multiplication if possible"
+ otherDenominator == denominator ifTrue:[
+ n := otherNumerator - numerator.
+ d := otherDenominator.
+ ] ifFalse:[
+ n := (otherNumerator * denominator) - (numerator * otherDenominator).
+ d := otherDenominator * denominator.
+ ].
+ ^ aFixedPoint class
+ numerator:n
+ denominator:d
+ scale:(aFixedPoint scale)
+
+ "
+ ((1/3) asFixedPoint:2) - (1/3)
+ ((1/3) asFixedPoint:2) - (2/3)
+ "
+!
+
differenceFromFloat:aFloat
"sent when a float does not know how to subtract the receiver, a fraction"
^ (aFloat * denominator - numerator) / denominator
!
+differenceFromFraction:aFraction
+ |n d otherDenominator otherNumerator|
+
+ otherDenominator := aFraction denominator.
+ otherNumerator := aFraction numerator.
+
+ "save a multiplication if possible"
+ otherDenominator == denominator ifTrue:[
+ n := otherNumerator - numerator.
+ d := otherDenominator.
+ ] ifFalse:[
+ n := (otherNumerator * denominator) - (numerator * otherDenominator).
+ d := otherDenominator * denominator.
+ ].
+ ^ aFraction class
+ numerator:n
+ denominator:d
+
+ "
+ ((1/3) asFixedPoint:2) - (1/3)
+ ((1/3) asFixedPoint:2) - (2/3)
+ "
+!
+
differenceFromInteger:anInteger
"sent when an integer does not know how to subtract the receiver, a fraction"
- ^ (self class
+ ^ self class
numerator:((anInteger * denominator) - numerator)
- denominator:denominator)
+ denominator:denominator
"Modified: 28.7.1997 / 19:08:53 / cg"
!
+equalFromFraction:aFraction
+ denominator = aFraction denominator ifFalse:[^ false].
+ ^ numerator = aFraction numerator
+!
+
+equalFromInteger:anInteger
+ "sent when an integer does not know how to compare to the receiver, a fraction"
+
+ "as I am always reduced, this test should not be required.
+ However, it is here for subclasses and to allow comparing unnormalized fractions,
+ which might be encountered internally"
+
+ denominator = 1 ifFalse:[^ false].
+ ^ numerator = anInteger
+!
+
+lessFromFraction:aFraction
+ "sent when a fraction does not know how to compare to the receiver"
+
+ |n d|
+
+ d := aFraction denominator.
+ n := aFraction numerator.
+
+ "/ save a multiplication if possible
+ d == denominator ifTrue:[
+ ^ n < numerator
+ ].
+ ^ (denominator * n) < (numerator * d)
+!
+
lessFromInteger:anInteger
"sent when an integer does not know how to compare to the receiver, a fraction"
^ (denominator * anInteger) < numerator
!
+productFromFixedPoint:aFixedPoint
+ ^ aFixedPoint class
+ numerator:(aFixedPoint numerator * numerator)
+ denominator:(aFixedPoint denominator * denominator)
+ scale:(aFixedPoint scale)
+
+ "
+ ((1/3) asFixedPoint:2) * 2
+ ((1/3) asFixedPoint:2) * (1/2)
+ ((1/3) asFixedPoint:2) * (3/2)
+ "
+!
+
productFromFloat:aFloat
"sent when a float does not know how to multiply the receiver, a fraction"
^ aFloat * numerator / denominator
!
+productFromFraction:aFraction
+ ^ aFraction class
+ numerator:(aFraction numerator * numerator)
+ denominator:(aFraction denominator * denominator)
+
+ "
+ ((1/3) asFixedPoint:2) * 2
+ ((1/3) asFixedPoint:2) * (1/2)
+ ((1/3) asFixedPoint:2) * (3/2)
+ "
+!
+
productFromInteger:anInteger
"sent when an integer does not know how to multiply the receiver, a fraction"
- ^ (self class
+ ^ self class
numerator:(anInteger * numerator)
- denominator:denominator)
+ denominator:denominator
"Modified: 28.7.1997 / 19:06:22 / cg"
!
+quotientFromFixedPoint:aFixedPoint
+ ^ aFixedPoint class
+ numerator:(aFixedPoint numerator * denominator)
+ denominator:(aFixedPoint denominator * numerator)
+ scale:(aFixedPoint scale)
+
+ "
+ ((1/3) asFixedPoint:2) / 2
+ ((1/3) asFixedPoint:2) / (1/2)
+ "
+!
+
quotientFromFloat:aFloat
"sent when a float does not know how to divide by the receiver, a fraction"
^ (aFloat * denominator) / numerator
!
+quotientFromFraction:aFraction
+ ^ aFraction class
+ numerator:(aFraction numerator * denominator)
+ denominator:(aFraction denominator * numerator)
+
+ "
+ (1/3) / (1/2)
+ (1/3) / (3/2)
+ "
+!
+
quotientFromInteger:anInteger
"sent when an integer does not know how to divide by the receiver, a fraction"
- ^ (self class
+ ^ self class
numerator:(anInteger * denominator)
- denominator:numerator)
+ denominator:numerator
"Modified: 28.7.1997 / 19:08:46 / cg"
!
+sumFromFixedPoint:aFixedPoint
+ |n d otherDenominator otherNumerator|
+
+ otherDenominator := aFixedPoint denominator.
+ otherNumerator := aFixedPoint numerator.
+
+ "save a multiplication if possible"
+ otherDenominator == denominator ifTrue:[
+ n := otherNumerator + numerator.
+ d := otherDenominator.
+ ] ifFalse:[
+ n := (otherNumerator * denominator) + (numerator * otherDenominator).
+ d := otherDenominator * denominator.
+ ].
+ ^ aFixedPoint class
+ numerator:n
+ denominator:d
+ scale:(aFixedPoint scale)
+
+ "
+ ((1/3) asFixedPoint:2) + (1/3)
+ ((1/3) asFixedPoint:2) + (2/3)
+ "
+!
+
sumFromFloat:aFloat
"sent when a float does not know how to add the receiver, a fraction"
^ (aFloat * denominator + numerator) / denominator
!
+sumFromFraction:aFraction
+ |n d otherDenominator otherNumerator|
+
+ otherDenominator := aFraction denominator.
+ otherNumerator := aFraction numerator.
+
+ "save a multiplication if possible"
+ otherDenominator == denominator ifTrue:[
+ n := otherNumerator + numerator.
+ d := otherDenominator.
+ ] ifFalse:[
+ n := (otherNumerator * denominator) + (numerator * otherDenominator).
+ d := otherDenominator * denominator.
+ ].
+ ^ aFraction class
+ numerator:n
+ denominator:d
+
+ "
+ (1/3) + (1/3)
+ (1/3) + (2/3)
+ "
+!
+
sumFromInteger:anInteger
"sent when an integer does not know how to add the receiver, a fraction"
- ^ (self class
+ ^ self class
numerator:(numerator + (anInteger * denominator))
- denominator:denominator)
+ denominator:denominator
"Modified: 28.7.1997 / 19:08:40 / cg"
! !
@@ -836,17 +960,24 @@
!Fraction methodsFor:'truncation & rounding'!
fractionPart
- "extract the after-decimal fraction part."
+ "extract the after-decimal fraction part,
+ such that (self truncated + self fractionPart) = self"
numerator abs < denominator abs ifTrue:[
^ self
].
- ^ super fractionPart
+ ^ (numerator rem: denominator) / denominator
+ "/ ^ super fractionPart
"
- (3/2) fractionPart
+ (3/2) fractionPart + (3/2) truncated
+ (-3/2) fractionPart + (-3/2) truncated
+
+ (3/2) fractionPart
(-3/2) fractionPart
- (2/3) fractionPart
+ (3/2) asFloat fractionPart
+ (-3/2) asFloat fractionPart
+ (2/3) fractionPart
((3/2)*(15/4)) fractionPart
((2/3)*(4/15)) fractionPart
"
@@ -917,7 +1048,7 @@
!Fraction class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/Fraction.st,v 1.62 2003-03-31 09:12:58 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/Fraction.st,v 1.63 2003-06-16 09:14:59 cg Exp $'
! !
Fraction initialize!