LimitedPrecisionReal.st
author claus
Thu, 02 Jun 1994 18:22:49 +0200
changeset 88 81dacba7a63a
parent 85 1343af456e28
child 92 0c73b48551ac
permissions -rw-r--r--
*** empty log message ***

"
 COPYRIGHT (c) 1994 by Claus Gittinger
              All Rights Reserved

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.   This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.
"

Number subclass:#LimitedPrecisionReal
       instanceVariableNames:''
       classVariableNames:''
       poolDictionaries:''
       category:'Magnitude-Numbers'
!

LimitedPrecisionReal comment:'
COPYRIGHT (c) 1994 by Claus Gittinger
              All Rights Reserved
'!

!LimitedPrecisionReal class methodsFor:'documentation'!

copyright
"
 COPYRIGHT (c) 1994 by Claus Gittinger
              All Rights Reserved

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.   This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.
"
!

version
"
$Header: /cvs/stx/stx/libbasic/LimitedPrecisionReal.st,v 1.3 1994-06-02 16:20:39 claus Exp $
"
!

documentation
"
    Abstract superclass for single and double (and maybe more) 
    precision real numbers (i.e. Float and Double).
"
! !

!LimitedPrecisionReal class methodsFor:'instance creation'!

new:aNumber
    "catch this message - not allowed for floats/doubles"

    self error:'Floats/Doubles cannot be created with new:'
! !

!LimitedPrecisionReal methodsFor:'copying'!

shallowCopy
    "return a shallow copy of the receiver"

    ^ self
!

simpleDeepCopy
    "return a deep copy of the receiver
     - because storing into floats is not recommended/allowed, its ok to return the receiver"

    ^ self
!

deepCopyUsing:aDictionary
    "return a deep copy of myself
     - because storing into floats is not recommended/allowed, its ok to return the receiver"

    ^ self
!

deepCopy
    "return a deep copy of myself
     - because storing into floats is not recommended/allowed, its ok to return the receiver"

    ^ self
! !
    
!LimitedPrecisionReal methodsFor:'accessing'!

size
   "redefined since reals are kludgy (ByteArry)"

   ^ 0
!

at:index
    "redefined to prevent access to individual bytes in a real."

    self error:'not allowed for floats/doubles'
!

at:index put:aValue
    "redefined to prevent access to individual bytes in a real"

    self error:'not allowed for floats/doubles'
! !

!LimitedPrecisionReal methodsFor:'arithmetic'!

+ aNumber
    "return the sum of the receiver and the argument, aNumber"

    ^ aNumber sumFromDouble:self asDouble
!

- aNumber
    "return the difference of the receiver and the argument, aNumber"

    ^ aNumber differenceFromDouble:self asDouble
!

* aNumber
    "return the product of the receiver and the argument, aNumber"

    ^ aNumber productFromDouble:self asDouble
!

/ aNumber
    "return the quotient of the receiver and the argument, aNumber"

    ((aNumber == 0) or:[aNumber = 0.0]) ifTrue:[
        DivisionByZeroSignal raise.
        ^ self
    ].
    ^ aNumber quotientFromDouble:self asDouble
!

// aNumber
    "return the integer quotient of dividing the receiver by aNumber with
    truncation towards negative infinity."

    ^ (self / aNumber) floor asInteger
!

\\ aNumber
    "return the integer remainder of dividing the receiver by aNumber with
    truncation towards negative infinity."

    ^ (self - ((self / aNumber) floor * aNumber)) floor asInteger
! !

!LimitedPrecisionReal methodsFor:'testing'!

positive
    "return true if the receiver is greater or equal to zero"

    ^ self asDouble positive
!

negative
    "return true if the receiver is less than zero"

    ^ self asDouble negative
! !

!LimitedPrecisionReal methodsFor:'comparing'!

< aNumber
    "return true, if the argument is greater"

    ^ aNumber lessFromDouble:self asDouble
!

> aNumber
    "return true, if the argument is less"

    ^ self retry:#> coercing:aNumber
!

<= aNumber
    "return true, if the argument is greater or equal"

    ^ self retry:#<= coercing:aNumber
!

>= aNumber
    "return true, if the argument is less or equal"

    ^ self retry:#>= coercing:aNumber
!

= aNumber
    "return true, if the arguments value are equal"

    ^ self retry:#= coercing:aNumber
!

~= aNumber
    "return true, if the arguments value are not equal"

    ^ self retry:#~= coercing:aNumber
! !

!LimitedPrecisionReal methodsFor:'coercion and converting'!

coerce:aNumber
    "return aNumber converted into receivers type"

    ^ aNumber asDouble
!

generality
    "return the generality value - see ArithmeticValue>>retry:coercing:"

    ^ 80
!

asFraction
    "return a corresponding fraction
     - notice, that 'aFract asFloat asFraction' does not always return
     a good fraction ... due to rounding errors when converting to float"

    |fract digits power num denom|

    "we (indirectly) use printf which knows the precision of floats"

    fract := self fractionPart.
    digits := fract printString copyFrom:3.
    power := digits size.
    num := (self - fract) asInteger.
    denom := (10 raisedToInteger:power).
    num := num * denom.
    num := num + (Integer readFromString:digits).
    ^ (Fraction numerator:num denominator:denom) reduced

    "0.3 asFraction"
    "0.5 asFraction"
    "(1/5) asFloat asFraction"
    "(1/8) asFloat asFraction"
    "(1/13) asFloat asFraction -> inexact result due to rounding errors"
!

asInteger
    "return an integer with same value - might truncate"

    |l v sign|

    "this is stupid code - rounding errors accumulate; fix later"

    sign := self sign.
    v := self abs.
    (v >= 10.0) ifTrue:[
        l := (v / 10.0) asInteger * 10
    ] ifFalse:[
        l := 0
    ].
    v := v - ((v / 10.0) floor * 10) floor.
    l := l + v truncated.
    ^ l * sign

    "12345.0 asInteger"
    "1e15 asInteger"
! !

!LimitedPrecisionReal methodsFor:'double dispatching'!

sumFromFraction:aFraction
    "sent when a fraction does not know how to add the recevier, a float"

    |d|

    d := aFraction denominator.
    ^ (self * d + aFraction numerator) / d
!

differenceFromFraction:aFraction
    "sent when a fraction does not know how to subtract the recevier, a float"

    |d|

    d := aFraction denominator.
    ^ (aFraction numerator - (self * d)) / d
!

productFromFraction:aFraction
    "sent when a fraction does not know how to multiply the recevier, a float"

    ^ self * aFraction numerator / aFraction denominator
!

quotientFromFraction:aFraction
    "sent when a fraction does not know how to divide by the recevier, a float"

    ^ aFraction numerator / (self * aFraction denominator)
! !

!LimitedPrecisionReal methodsFor:'truncation and rounding'!

fractionPart
    "return a float with value from digits after the decimal point"

    ^ self - self truncated asFloat

    "1234.56789 fractionPart"
    "1.2345e6 fractionPart"
! !

!LimitedPrecisionReal methodsFor:'printing and storing'!

printOn:aStream
    "append a printed representation of the receiver to
     the argument, aStream"

    aStream nextPutAll:self printString
! !