ArithmeticValue.st
author Claus Gittinger <cg@exept.de>
Tue, 17 Jun 2003 11:12:22 +0200
changeset 7385 852e84340d2b
parent 7384 ae6b11a3b4d5
child 7391 55ca5a24162a
permissions -rw-r--r--
*** empty log message ***

"
 COPYRIGHT (c) 1993 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.
"

"{ Package: 'stx:libbasic' }"

Magnitude subclass:#ArithmeticValue
	instanceVariableNames:''
	classVariableNames:'DivisionByZeroSignal DomainErrorSignal OverflowSignal
		UnderflowSignal ArithmeticSignal UnorderedSignal
		ConversionErrorSignal'
	poolDictionaries:''
	category:'Magnitude-Numbers'
!

!ArithmeticValue class methodsFor:'documentation'!

copyright
"
 COPYRIGHT (c) 1993 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.
"
!

documentation
"
    ArithmeticValue is an abstract superclass for all things responding to
    arithmetic messages. It was inserted into the hierarchy, to allow objects
    like matrices, functions etc. to share the arithmetic methods defined here.

    Notice, that what used to be signals are now exception classes - the class
    variables and signal accessors remain here for backward compatibility.

    [class variables:]
        ArithmeticSignal        <Error>         parent of all arithmetic signals
                                                (never raised itself)
                                                New: now a reference to ArithmeticError

        DomainErrorSignal       <Error>         raised upon float errors
                                                (for example range in trigonometric)
                                                New: now a reference to DomainError

        DivisionByZeroSignal    <Error>         raised when division by 0 is attempted
                                                New: now a reference to ZeroDivide

        OverflowSignal          <Error>         raised on overflow/underflow conditions
        UnderflowSignal                         in float arithmetic. 
                                                Notice: some OperatingSystems do not 
                                                provide enough information for ST/X to 
                                                extract the real reason for the floatException
                                                thus raising DomainErrorSignal in these cases.

    [author:]
        Claus Gittinger

    [See also:]
        Number
"
! !

!ArithmeticValue class methodsFor:'initialization'!

initialize
    "setup the signals"

    "/ notice that we now use class based exceptions;
    "/ however, for backward compatibility, the class variables
    "/ referring to those are kept for a while, for subclass compatibility.
    "/ Please convert your code to access those via the Signal-constants class
    "/ messages (accesors) instead of referring to the class variables.

    ArithmeticSignal := ArithmeticError.
    DomainErrorSignal := DomainError.
    DivisionByZeroSignal := ZeroDivide.
    UnorderedSignal := UnorderedNumbersError.
    ConversionErrorSignal := ConversionError.
    OverflowSignal := OverflowError.
    UnderflowSignal := UnderflowError.
! !

!ArithmeticValue class methodsFor:'Signal constants'!

arithmeticSignal
    "return the parent of all arithmetic signals"

    ^ ArithmeticSignal
!

conversionErrorSignal
    "return the signal which is raised when a conversion fails
     (such as bcd decoding of an invalid BCD number)"

    ^ ConversionErrorSignal

    "Created: / 15.11.1999 / 20:34:18 / cg"
!

divisionByZeroSignal
    "return the signal which is raised on division by zero"

    ^ DivisionByZeroSignal
!

domainErrorSignal
    "return the signal which is raised on math errors
     (such as log of 0 etc.)"

    ^ DomainErrorSignal
!

overflowSignal
    "return the signal which is raised on overflow conditions (in floats)"

    ^ OverflowSignal
!

rangeErrorSignal
    "return the parent of the overflow/underflow signals"

    ^ RangeError
!

underflowSignal
    "return the signal which is raised on underflow conditions (in floats)"

    ^ UnderflowSignal
!

unorderedSignal
    "return the signal which is raised when numbers are compared, 
     for which no ordering is defined (for example: complex numbers)"

    ^ UnorderedSignal
! !

!ArithmeticValue methodsFor:'arithmetic'!

* something
    "return the product of the receiver and the argument"

    ^ self subclassResponsibility
!

+ something
    "return the sum of the receiver and the argument"

    ^ self subclassResponsibility
!

- something
    "return the difference of the receiver and the argument"

    ^ self subclassResponsibility
!

/ something
    "return the quotient of the receiver and the argument"

    ^ self subclassResponsibility
!

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

    "/ Note: '^ (self / something) floor' may lead to infinite recursion

    ^ self subclassResponsibility

    "Modified: / 5.11.1996 / 11:46:27 / cg"
    "Modified: / 12.2.1998 / 16:31:36 / stefan"
!

\\ something
    "return the receiver modulo something.
     The remainder has the same sign as something.
     The following is always true:
        (receiver // something) * something + (receiver \\ something) = receiver
    "

    ^ self - ((self // something) * something)

   "
     0.9 \\ 0.4
     0.9 \\ -0.4
    -0.9 \\ 0.4
    -0.9 \\ -0.4
   "

    "Modified: / 12.2.1998 / 19:14:37 / stefan"
!

abs
    "return the absolute value of the receiver"

    (self negative) ifTrue:[^ self negated].
    ^ self
!

negated
    "return the receiver negated"

    ^ self class zero - self
!

quo:something
    "Return the integer quotient of dividing the receiver by the argument
     with truncation towards zero.
     The following is always true:
        (receiver quo: aNumber) * aNumber + (receiver rem: aNumber) = receiver
    "

    ^ (self / something) truncated
!

reciprocal
    "return the receivers reciprocal"

    ^ self class unity / self
!

rem:something
    "Return the integer remainder of dividing the receiver by the argument
     with truncation towards zero.
     The remainder has the same sign as the receiver.
     The following is always true:
        (receiver quo: something) * something + (receiver rem: something) = receiver
    "

    ^ self - ((self quo:something) * something)
! !

!ArithmeticValue methodsFor:'coercing & converting'!

coerce:aNumber
    "convert aNumber into an instance of the receivers class and return it."

    ^ self subclassResponsibility
!

generality
    "return a number giving the receivers generality, that number is
     used to convert one of the arguments in a mixed expression. 
     The generality has to be defined in subclasses,
     such that gen(a) > gen(b) iff, conversion of b into a's class 
     does not cut precision. For example, Integer has 40, Float has 80,
     meaning that if we convert a Float to an Integer, some precision may
     be lost. The generality is used by ArithmeticValue>>retry:coercing:,
     which converts the lower-precision number to the higher precision
     numbers class, when mixed-type arithmetic is performed."
      
    ^ self subclassResponsibility

    "Modified: / 5.11.1996 / 15:05:30 / cg"
    "Modified: / 13.2.1998 / 15:36:01 / stefan"
!

retry:aSymbol coercing:aNumber
    "arithmetic represented by the binary operator, aSymbol,
     could not be performed with the receiver and the argument, aNumber, 
     because of the differences in representation.  
     Coerce either the receiver or the argument, depending on which has higher 
     generality, and try again.  
     If the operation is compare for same value (=), return false if
     the argument is not a Number. 
     If the generalities are the same, create an error message, since this
     means that a subclass has not been fully implemented."

    |hasGenerality myGenerality otherGenerality|

    hasGenerality := aNumber respondsTo:#generality.
    hasGenerality ifFalse:[
        (aSymbol == #=) ifTrue:[
            ^ false
        ].
        (aSymbol == #~=) ifTrue:[
            ^ true
        ].
        ^ self error:'retry:coercing: argument is not a number'.
    ].

    myGenerality := self generality.
    otherGenerality := aNumber generality.
    (myGenerality > otherGenerality) ifTrue:[
        ^ self perform:aSymbol with:(self coerce:aNumber)
    ].
    (myGenerality < otherGenerality) ifTrue:[
        ^ (aNumber coerce:self) perform:aSymbol with:aNumber
    ].
    self error:'retry:coercing: oops - same generality'

    "Modified: 5.11.1996 / 15:03:38 / cg"
! !

!ArithmeticValue methodsFor:'comparing'!

< something
    "return true, if the argument is greater than the receiver"

    ^ self subclassResponsibility
!

<= something
    "return true, if the argument is greater or equal than the receiver"

    ^ (something < self) not
!

> something
    "return true, if the argument is less than the receiver"

    ^ something < self
!

>= something
    "return true, if the argument is less or equal than the receiver"

    ^ (self < something) not
!

compare:arg ifLess:lessBlock ifEqual:equalBlock ifGreater:greaterBlock
    "three-way compare - thanks to Self for this idea.
     Can be redefined in subclasses to do it with a single comparison if
     comparison is expensive."

    self < arg ifTrue:[
	^ lessBlock value
    ].
    self = arg ifTrue:[
	^ equalBlock value
    ].
    ^ greaterBlock value
! !

!ArithmeticValue methodsFor:'converting'!

asDouble
    "ST80 compatibility: return our floats are the identical to ST80 doubles"

   ^ self asFloat

    "Created: / 13.2.1998 / 15:40:14 / stefan"
!

asFloat
    "return a float with same value"

   ^ self subclassResponsibility
!

asFloatD
    "return a double precision float with same value.
     Added for ANSI compatibility"

   ^ self asFloat

    "Created: / 7.9.2001 / 13:36:48 / cg"
    "Modified: / 7.9.2001 / 13:38:10 / cg"
!

asFloatE
    "return a single precision float with same value.
     Added for ANSI compatibility"

   ^ self asShortFloat

    "Created: / 7.9.2001 / 13:37:06 / cg"
    "Modified: / 7.9.2001 / 13:38:15 / cg"
!

asFloatQ
    "return a quad precision float with same value.
     Added for ANSI compatibility"

   ^ self asLongFloat

    "Created: / 7.9.2001 / 13:38:44 / cg"
!

asFraction
    "return a fraction with same value"

   ^ self subclassResponsibility
!

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

    ^ self truncated
!

asLimitedPrecisionReal
    "return a float of any precision with same value"

   ^ self asFloat
!

asLongFloat
    "return a longFloat with same value"

   "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"
!

asScaledDecimal:scale
    "return a fixedPoint approximating the receivers value"

    ^ self asFixedPoint:scale

    "
     1.234 asScaledDecimal:2
    "

    "Created: / 7.9.2001 / 13:46:26 / cg"
    "Modified: / 7.9.2001 / 13:46:44 / cg"
!

asShortFloat
    "return a shortFloat with same value"

   ^ self asFloat asShortFloat

    "Modified: 17.4.1996 / 12:21:35 / cg"
!

degreesToRadians
    "interpreting the receiver as radians, return the degrees"

    ^ self asFloat degreesToRadians
!

radiansToDegrees
    "interpreting the receiver as degrees, return the radians"

    ^ self asFloat radiansToDegrees
! !

!ArithmeticValue methodsFor:'destructive arithmethic'!

*= aNumber
    "Return the product of self multiplied by aNumber. 
     The receiver MAY, but NEED NOT be changed to contain the product.
     So this method must be used as: 'a := a *= 5'.
     This method can be redefined for constructed datatypes to do optimisations"

    ^ self * aNumber

    "Created: / 28.4.1999 / 11:46:11 / stefan"
    "Modified: / 28.4.1999 / 11:53:28 / stefan"
!

+= aNumber
    "Return the sum of self and aNumber. 
     The receiver MAY, but NEED NOT be changed to contain the sum.
     So this method must be used as: 'a := a += 5'.
     This method can be redefined for constructed datatypes to do optimisations"

    ^ self + aNumber

    "Created: / 28.4.1999 / 10:13:41 / stefan"
    "Modified: / 28.4.1999 / 11:54:11 / stefan"
!

-= aNumber
    "Return the difference of self and aNumber. 
     The receiver MAY, but NEED NOT be changed to contain the difference.
     So this method must be used as: 'a := a -= 5'.
     This method can be redefined for constructed datatypes to do optimisations"

    ^ self - aNumber

    "Created: / 28.4.1999 / 10:13:58 / stefan"
    "Modified: / 28.4.1999 / 11:54:37 / stefan"
!

/= aNumber
    "Return the quotient of self and aNumber. 
     The receiver MAY, but NEED NOT be changed to contain the quotient.
     So this method must be used as: 'a := a /= 5'.
     This method can be redefined for constructed datatypes to do optimisations"

    ^ self / aNumber

    "Created: / 28.4.1999 / 11:46:22 / stefan"
    "Modified: / 28.4.1999 / 11:55:06 / stefan"
!

div2
    "Return the quotient of self divided by 2. 
     The receiver MAY, but NEED NOT be changed to contain the result.
     So this method must be used as: 'a := a div2.
     This method can be redefined for constructed datatypes to do optimisations"

    ^ self // 2

    "Created: / 28.4.1999 / 10:12:44 / stefan"
    "Modified: / 28.4.1999 / 11:56:09 / stefan"
!

mul2
    "Return the product of self multiplied by 2. 
     The receiver MAY, but NEED NOT be changed to contain the result.
     So this method must be used as: 'a := a mul2.
     This method can be redefined for constructed datatypes to do optimisations"

    ^ self * 2

    "Created: / 28.4.1999 / 10:12:55 / stefan"
    "Modified: / 28.4.1999 / 11:56:38 / stefan"
! !

!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"

    ^ aFixedPoint retry:#- coercing:self

    "Created: 5.11.1996 / 14:55:51 / cg"
!

differenceFromFloat:aFloat
    "the receiver does not know how to subtract from a float -
     retry the operation by coercing to higher generality"

    ^ aFloat retry:#- coercing:self
!

differenceFromFraction:aFraction
    "the receiver does not know how to subtract from a fraction -
     retry the operation by coercing to higher generality"

    ^ aFraction retry:#- coercing:self
!

differenceFromInteger:anInteger
    "the receiver does not know how to subtract from an integer -
     retry the operation by coercing to higher generality"

    ^ anInteger retry:#- coercing:self
!

differenceFromShortFloat:aShortFloat
    "the receiver does not know how to subtract from a shortFloat -
     retry the operation by coercing to higher generality"

    ^ aShortFloat retry:#- coercing:self

    "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"

    ^ aFixedPoint retry:#< coercing:self

    "Created: 5.11.1996 / 14:56:12 / cg"
!

lessFromFloat:aFloat
    "the receiver does not know how to compare to a float -
     retry the operation by coercing to higher generality"

    ^ aFloat retry:#< coercing:self
!

lessFromFraction:aFraction
    "the receiver does not know how to compare to a fraction -
     retry the operation by coercing to higher generality"

    ^ aFraction retry:#< coercing:self
!

lessFromInteger:anInteger
    "the receiver does not know how to compare to an integer -
     retry the operation by coercing to higher generality"

    ^ anInteger retry:#< coercing:self
!

lessFromShortFloat:aShortFloat
    "the receiver does not know how to compare to a shortFloat -
     retry the operation by coercing to higher generality"

    ^ aShortFloat retry:#< coercing:self

    "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"

    ^ aFixedPoint retry:#* coercing:self

    "Created: 5.11.1996 / 14:56:28 / cg"
!

productFromFloat:aFloat
    "the receiver does not know how to multiply a float -
     retry the operation by coercing to higher generality"

    ^ aFloat retry:#* coercing:self
!

productFromFraction:aFraction
    "the receiver does not know how to multiply a fraction -
     retry the operation by coercing to higher generality"

    ^ aFraction retry:#* coercing:self
!

productFromInteger:anInteger
    "the receiver does not know how to multiply an integer -
     retry the operation by coercing to higher generality"

    ^ anInteger retry:#* coercing:self
!

productFromShortFloat:aShortFloat
    "the receiver does not know how to multiply a shortFloat -
     retry the operation by coercing to higher generality"

    ^ aShortFloat retry:#* coercing:self

    "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"

    ^ aFixedPoint retry:#/ coercing:self

    "Created: 5.11.1996 / 14:56:41 / cg"
!

quotientFromFloat:aFloat
    "the receiver does not know how to divide a float -
     retry the operation by coercing to higher generality"

    ^ aFloat retry:#/ coercing:self
!

quotientFromFraction:aFraction
    "the receiver does not know how to divide a fraction -
     retry the operation by coercing to higher generality"

    ^ aFraction retry:#/ coercing:self
!

quotientFromInteger:anInteger
    "the receiver does not know how to divide an integer -
     retry the operation by coercing to higher generality"

    ^ anInteger retry:#/ coercing:self
!

quotientFromShortFloat:aShortFloat
    "the receiver does not know how to divide a shortFloat -
     retry the operation by coercing to higher generality"

    ^ aShortFloat retry:#/ coercing:self

    "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"

    ^ aFixedPoint retry:#+ coercing:self

    "Created: 5.11.1996 / 14:56:56 / cg"
!

sumFromFloat:aFloat
    "the receiver does not know how to add a float -
     retry the operation by coercing to higher generality"

    ^ aFloat retry:#+ coercing:self
!

sumFromFraction:aFraction
    "the receiver does not know how to add a fraction -
     retry the operation by coercing to higher generality"

    ^ aFraction retry:#+ coercing:self
!

sumFromInteger:anInteger
    "the receiver does not know how to add an integer -
     retry the operation by coercing to higher generality"

    ^ anInteger retry:#+ coercing:self
!

sumFromShortFloat:aShortFloat
    "the receiver does not know how to add a shortFloat -
     retry the operation by coercing to higher generality"

    ^ aShortFloat retry:#+ coercing:self

    "Created: 17.4.1996 / 12:34:10 / cg"
! !

!ArithmeticValue methodsFor:'mathematical functions'!

** aNumber
    "return the receiver raised to aNumber"

    ^ self raisedTo:aNumber

    "
     2 ** 4    
     10 ** 4    
    "
!

exp
    "return e ^ receiver"

    ^ self asFloat exp
!

floorLog:radix
    "return the logarithm truncated as an integer"

    ^ (self log:radix) floor
!

ln
    "return the natural logarithm of the receiver"

    ^ self asFloat ln
!

log
    "return log base 10 of the receiver.
     Alias for log10."

    ^ self log10
!

log10
    "return log base 10 of the receiver"

    ^ self log:10
!

log:aNumber
    "return log base aNumber of the receiver"

    ^ self ln / aNumber ln
!

raisedTo:aNumber
    "return the receiver raised to aNumber"

    aNumber = 0 ifTrue:[^ 1].
    aNumber = 1 ifTrue:[^ self].
    aNumber isInteger ifTrue:[
        ^ self raisedToInteger:aNumber
    ].
    ^ self asFloat raisedTo:aNumber

    "
     2 raisedTo: 4    
     10 raisedTo: 4    
    "
!

raisedToInteger:exp 
    "return the receiver raised to exp"

    |result e t|

    "use the addition chaining algorithm,
     which is much faster for big exp-arguments"

    result := 1.
    t := self.
    exp < 0 ifTrue:[
        e := exp negated.
    ] ifFalse:[
        e := exp.
    ].

    [e ~~ 0] whileTrue:[
        [(e bitAnd:1) == 0] whileTrue:[
            e := e bitShift:-1.
            t := t * t.
        ].
        e := e - 1.
        result := result * t.
    ].

    (exp < 0) ifTrue:[
        ^ 1 / result
    ].

    ^ result


    "
     (2 raisedToInteger:216)
     (2 raisedTo:216) 
-> 105312291668557186697918027683670432318895095400549111254310977536     

     (2 raisedToInteger:216) asFloat     
     (2 raisedTo:216) asFloat     
-> 1.05312E+65

     (2 raisedToInteger:500)
     (2 raisedTo:500) 
-> 3273390607896141870013189696827599152216642046043064789483291368096133796404674554883270092325904157150886684127560071009217256545885393053328527589376
     2 raisedToInteger:10 
-> 1024
    -2 raisedToInteger:10
-> 1024
     -2 raisedToInteger:9
-> -512
     10 raisedToInteger:-10
-> (1/10000000000)
     2 raisedToInteger:0 
-> 1
     2 raisedToInteger:-1 
-> (1/2)

     Time millisecondsToRun:[
        10000 timesRepeat:[
            (2 raisedToInteger:500)
        ]
     ]  

     Time millisecondsToRun:[
        |bigNum|
        bigNum := 2 raisedToInteger:500.
        10 timesRepeat:[
            (bigNum raisedToInteger:500)
        ]
     ]
    "

    "Created: / 27.4.1999 / 15:19:22 / stefan"
    "Modified: / 27.4.1999 / 16:16:11 / stefan"
!

sqrt
    "return the square root of the receiver"

    ^ self asFloat sqrt
!

squared
    "return receiver * receiver"

    ^ self * self
! !

!ArithmeticValue methodsFor:'queries'!

respondsToArithmetic
    "return true, if the receiver responds to arithmetic messages"

    ^ true
! !

!ArithmeticValue methodsFor:'testing'!

denominator
    "return the denominator of the receiver"

    ^ 1
!

even
    "return true if the receiver is divisible by 2"

    ^ self truncated asInteger even
!

isComplex
    "Answer whether the receiver has an imaginary part
     (i.e. if it is a complex number). Always false here."

    ^ false

    "Modified: / 9.7.1998 / 10:19:27 / cg"
!

isReal
    "return true, if the receiver is some kind of real number (as opposed to a complex);
     false is returned here - the method is only redefined in Number (and Complex)."

    ^ false

    "Modified: / 6.11.2001 / 13:20:20 / cg"
    "Created: / 6.11.2001 / 13:26:29 / cg"
!

negative
    "return true, if the receiver is < 0"

    " this would lead to infinite recursion ...
    ^ (self < 0)
    "
    ^ self subclassResponsibility
!

numerator
    "return the numerator of the receiver."

    ^ self
!

odd
    "return true if the receiver is not divisible by 2"

    ^ self even not
!

positive
    "return true, if the receiver is >= 0"

    ^ self negative not
!

sign
    "return the sign of the receiver"

    (self < 0) ifTrue:[^ -1].
    (self > 0) ifTrue:[^ 1].
    ^ 0
!

strictlyPositive
    "return true, if the receiver is > 0"

    ^ (self > 0)
! !

!ArithmeticValue methodsFor:'trigonometric'!

arcCos
    "return the arccosine of the receiver (in radians)"

    ^ self asFloat arcCos
!

arcCosh
    "return the hyperbolic arccosine of the receiver (in radians)"

    ^ self asFloat arcCosh
!

arcSin
    "return the arcsine of the receiver (in radians)"

    ^ self asFloat arcSin
!

arcSinh
    "return the hyperbolic arcsine of the receiver (in radians)"

    ^ self asFloat arcSinh
!

arcTan
    "return the arctangens of the receiver (in radians)"

    ^ self asFloat arcTan
!

arcTanh
    "return the hyperbolic arctangens of the receiver (in radians)"

    ^ self asFloat arcTanh
!

cos
    "return the cosine of the receiver (interpreted as radians)"

    ^ self asFloat cos
!

cosh
    "return the hyperbolic cosine of the receiver (interpreted as radians)"

    ^ self asFloat cosh
!

sin
    "return the sine of the receiver (interpreted as radians)"

    ^ self asFloat sin
!

sinh
    "return the hyperbolic sine of the receiver (interpreted as radians)"

    ^ self asFloat sinh
!

tan
    "return the tangens of the receiver (interpreted as radians)"

    ^ self asFloat tan
!

tanh
    "return the hyperbolic tangens of the receiver (interpreted as radians)"

    ^ self asFloat tanh
! !

!ArithmeticValue methodsFor:'truncation & rounding'!

ceiling
    "return the integer nearest the receiver towards positive infinity."

    |anInteger|

    anInteger := self // 1.       "truncates towards negative infinity"
    anInteger = self ifTrue:[^ anInteger].
    ^ anInteger + 1
!

floor
    "return the receiver truncated towards negative infinity"

    ^ self // 1
!

roundTo:aNumber
    "return the receiver rounded to multiples of aNumber"

    ^ (self / aNumber) rounded * aNumber
!

rounded
    "return the integer nearest the receiver"

    self negative ifTrue:[
        ^ (self - 0.5) ceiling
    ].
    ^ (self + 0.5) floor

    "Modified: 5.11.1996 / 11:31:59 / cg"
!

truncateTo:aNumber
    "return the receiver truncated to multiples of aNumber"

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

truncated
    "return the receiver truncated towards zero"

    self negative ifTrue:[
	^ self ceiling
    ].
    ^ self floor
! !

!ArithmeticValue class methodsFor:'documentation'!

version
    ^ '$Header: /cvs/stx/stx/libbasic/ArithmeticValue.st,v 1.50 2003-06-17 09:11:17 cg Exp $'
! !

ArithmeticValue initialize!