double dispatching fixed;
authorClaus Gittinger <cg@exept.de>
Mon, 16 Jun 2003 11:14:59 +0200
changeset 7355 96f466eeddf5
parent 7354 b22823ab2232
child 7356 fe8fb0a571f2
double dispatching fixed; many refactorings
ArithmeticValue.st
Complex.st
FixedPoint.st
Float.st
Fraction.st
--- 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!