QuadFloat.st
author Claus Gittinger <cg@exept.de>
Fri, 22 Nov 2019 00:48:55 +0100
changeset 5266 ee57fea3ec72
parent 5264 e01656e04937
child 5267 a9529d2468bb
permissions -rw-r--r--
#FEATURE by exept class: QuadFloat added: #isQuadFloat

"{ Encoding: utf8 }"

"{ Package: 'stx:libbasic2' }"

"{ NameSpace: Smalltalk }"

LimitedPrecisionReal variableByteSubclass:#QuadFloat
	instanceVariableNames:''
	classVariableNames:'QuadFloatZero QuadFloatOne Pi E Epsilon NaN PositiveInfinity
		NegativeInfinity Halfpi HalfpiNegative Phi'
	poolDictionaries:''
	category:'Magnitude-Numbers'
!

!QuadFloat primitiveDefinitions!
%{
#define SUPPORT_QUADFLOAT

#include <math.h>

extern int STX_qisNan(float128_t* pq);
extern int STX_qprcmp(float128_t* a, float128_t* b);
extern float128_t STX_qadd(float128_t, float128_t, int);
extern float128_t STX_qneg(float128_t n);
extern float128_t STX_qabs(float128_t n);
extern float128_t STX_qfloor(float128_t n);
extern float128_t STX_qceil(float128_t n);
extern float128_t STX_qZero;
extern float128_t STX_dbltoq(double);
extern float128_t STX_inttoq(long);
extern double STX_qtodbl(float128_t);

#define STX_qisfinite(q)    (!STX_qisNan(&(q)) && !STX_qisInf(&(q)))
#define STX_qeq(x1, x2)     (STX_qprcmp (&(x1), &(x2)) == 0)
#define STX_qneq(x1, x2)    (STX_qprcmp (&(x1), &(x2)) != 0)
#define STX_qgt(x1, x2)     (STX_qprcmp (&(x1), &(x2)) > 0)
#define STX_qge(x1, x2)     (STX_qprcmp (&(x1), &(x2)) >= 0)
#define STX_qlt(x1, x2)     (STX_qprcmp (&(x1), &(x2)) < 0)
#define STX_qle(x1, x2)     (STX_qprcmp (&(x1), &(x2)) <= 0)

#ifdef __win32__
/*
 * no finite(x) ?
 * no isnan(x) ?
 */
# ifndef isnan
#  define isnan(x)      \
	((((unsigned int *)(&x))[0] == 0x00000000) && \
	 (((unsigned int *)(&x))[1] == 0xFFF80000))
# endif

# ifndef isPositiveInfinity
#  define isPositiveInfinity(x) \
	((((unsigned int *)(&x))[0] == 0x00000000) && \
	 (((unsigned int *)(&x))[1] == 0x7FF00000))
# endif

# ifndef isNegativeInfinity
#  define isNegativeInfinity(x) \
	((((unsigned int *)(&x))[0] == 0x00000000) && \
	 (((unsigned int *)(&x))[1] == 0xFFF00000))
# endif

# ifndef isinf
#  define isinf(x) \
	((((unsigned int *)(&x))[0] == 0x00000000) && \
	 ((((unsigned int *)(&x))[1] & 0x7FF00000) == 0x7FF00000))
# endif

# ifndef isfinite
#  define isfinite(x) (!isinf(x) && !isnan(x))
# endif

#else // not win32
#endif

%}
! !

!QuadFloat primitiveVariables!
ded float format (amd64, x86_64)
	    u.qf = extF80_to_f128( u.ef);
	    __qMKQFLOAT(newFloat, u.qf);   /* OBJECT ALLOCATION */
	    RETURN (newFloat);
	}
	// fall into error case
    }
#endif /* SUPPORT_QUADFLOAT */
%}.
    aFloat isLongFloat ifTrue:[
	self errorUnsupported
    ].
    ArgumentError raise

    "
     QuadFloat fromLongFloat:123.0 asLongFloat
    "
! !

!QuadFloat primitiveFunctions!
f);   /* OBJECT ALLOCATION */
	    nan = newFloat;
	}
#endif /* SUPPORT_QUADFLOAT */
%}.
	NaN := nan
    ].
    ^ NaN
! !

!QuadFloat class methodsFor:'documentation'!

documentation
"
    QuadFloats represent rational numbers with limited precision
    and are mapped to IEEE quadruple precision format (128bit),
    also called binary128.

    If the underlying cpu supports them natively, the machine format (long double) is
    used. Otherwise, a software emulation is done, which is much slower.
    Thus only use them, if you really need the additional precision;
    if not, use Float (which are doubles) or LongFloats which usually have IEEE extended precision (80bit).

    QuadFloats give you definite 128 bit quadruple floats,
    thus, code using quadFloats is guaranteed to be portable from one architecture to another.

    Representation:
	    128bit quadruple IEEE floats (16bytes);
	    112 bit mantissa,
	    16 bit exponent,
	    34 decimal digits (approx.)

    On Sparc CPUs, this is a native supported type (long double) and fast;
    on x86 CPUs, this is emulated and slow.

    Mixed mode arithmetic:
	quadFloat op anyFloat    -> quadFloat
	anyFloat op quadFloat    -> quadFloat

    Range and precision of storage formats: see LimitedPrecisionReal >> documentation

    [author:]
	Claus Gittinger

    [see also:]
	Number
	Float ShortFloat LongFloat Fraction FixedPoint Integer Complex
	FloatArray DoubleArray
	https://en.wikipedia.org/wiki/Extended_precision
"
! !

!QuadFloat class methodsFor:'instance creation'!

basicNew
    "return a new quadFloat - here we return 0.0
     - QuadFloats are usually NOT created this way ...
     Its implemented here to allow things like binary store & load
     of quadFloats.
     (but it is not a good idea to store the bits of a float - the reader might have a
      totally different representation - so floats should be
      binary stored in a device independent format)."

%{  /* NOCONTEXT */
#ifdef SUPPORT_QUADFLOAT
    OBJ newFloat;

    if (sizeof(long double) == sizeof(float128_t)) {
	__qMKLFLOAT(newFloat, 0.0);   /* OBJECT ALLOCATION */
    } else {
	float128_t qf;
	f64_to_f128M(0.0, &qf);
	__qMKQFLOAT(newFloat, qf);   /* OBJECT ALLOCATION */
    }
    RETURN (newFloat);
#endif /* SUPPORT_QUADFLOAT */
%}.
    self error:'QuadFloats not supported on this patform'

    "Created: / 06-06-2019 / 17:18:58 / Claus Gittinger"
!

fromFloat:aFloat
    "return a new quadFloat, given a float value"

%{  /* NOCONTEXT */
#ifdef SUPPORT_QUADFLOAT
    OBJ newFloat;

    if (__isFloatLike(aFloat)) {
	float64_t f = __floatVal(aFloat);
	float128_t qf;

	f64_to_f128M(f, &qf);
	__qMKQFLOAT(newFloat, qf);   /* OBJECT ALLOCATION */
	RETURN (newFloat);
    }
#endif /* SUPPORT_QUADFLOAT */
%}.
    aFloat isFloat ifTrue:[
	self errorUnsupported
    ].
    ArgumentError raise

    "
     QuadFloat fromFloat:123.0
     123.0 asQuadFloat
     123 asQuadFloat
    "

    "Created: / 06-06-2019 / 18:01:03 / Claus Gittinger"
!

fromInteger:anInteger
    "return a new quadFloat, given an integer value"

%{  /* NOCONTEXT */
#ifdef SUPPORT_QUADFLOAT
    OBJ newFloat;

    if (__isSmallInteger(anInteger)) {
	INT iVal = __intVal(anInteger);
	float128_t qf;

#if __POINTER_SIZE__ == 4
	i32_to_f128M( iVal, &qf );
else
	i64_to_f128M( iVal, &qf );
#endif
	__qMKQFLOAT(newFloat, qf);   /* OBJECT ALLOCATION */
	RETURN (newFloat);
    }
#endif /* SUPPORT_QUADFLOAT */
%}.
    ^ super fromInteger:anInteger

    "
     QuadFloat fromInteger:123
     123 asQuadFloat
    "
!

fromLongFloat:aFloat
    "return a new quadFloat, given a long float value"

%{  /* NOCONTEXT */
#ifdef SUPPORT_QUADFLOAT
    OBJ newFloat;
    union {
	LONGFLOAT_t lf;         // is long double
	extFloat80_t ef;        // is 80bit ext
	float128_t qf;          // is 128bit quad
    } u;

    if (__isLongFloat(aFloat)) {
	u.lf = __longFloatVal(aFloat);

	if (sizeof(LONGFLOAT_t) == 16) {
	    // longFloat is already 128 bits in size (sparc)
	    __qMKQFLOAT(newFloat, u.qf);   /* OBJECT ALLOCATION */
	    RETURN (newFloat);
	}
	if (sizeof(LONGFLOAT_t) < 16) {
	    // assume 80bit extended float format (amd64, x86_64)
	    u.qf = extF80_to_f128( u.ef);
	    __qMKQFLOAT(newFloat, u.qf);   /* OBJECT ALLOCATION */
	    RETURN (newFloat);
	}
	// fall into error case
    }
#endif /* SUPPORT_QUADFLOAT */
%}.
    aFloat isLongFloat ifTrue:[
	self errorUnsupported
    ].
    ArgumentError raise

    "
     QuadFloat fromLongFloat:123.0 asLongFloat
    "
!

fromShortFloat:aShortFloat
    "return a new quadFloat, given a float value"

    ^ self fromFloat:(aShortFloat asFloat)

    "
     QuadFloat fromShortFloat:123.0 asShortFloat
    "

    "Created: / 08-06-2019 / 03:28:37 / Claus Gittinger"
! !

!QuadFloat class methodsFor:'coercing & converting'!

coerce:aNumber
    "convert the argument aNumber into an instance of the receiver's class and return it."

    ^ aNumber asQuadFloat.

    "Created: / 06-06-2019 / 16:51:01 / Claus Gittinger"
! !

!QuadFloat class methodsFor:'constants'!

NaN
    "return a quadFloat which represents not-a-Number (i.e. an invalid number)"

    |nan|

    NaN isNil ifTrue:[
%{  /* NOCONTEXT */
#ifdef SUPPORT_QUADFLOAT
	{
	    OBJ newFloat;
	    float128_t qf;

	    softfloat_commonNaNToF128M( (uint32_t*)(&qf) );
	    __qMKQFLOAT(newFloat, qf);   /* OBJECT ALLOCATION */
	    nan = newFloat;
	}
#endif /* SUPPORT_QUADFLOAT */
%}.
	NaN := nan
    ].
    ^ NaN
!

e
    "return the constant e as quadFloat"

    E isNil ifTrue:[
	"/ eDigits has enough digits for 128bit IEEE quads
	"/ do not use as a literal constant here - we cannot depend on the underlying C-compiler here...
	E  := self readFrom:(Number eDigits)
    ].
    ^ E

    "Created: / 06-06-2019 / 17:01:54 / Claus Gittinger"
!

infinity
    "return a quadFloat which represents +INF"

    |inf|

    PositiveInfinity isNil ifTrue:[
%{  /* NOCONTEXT */
#ifdef SUPPORT_QUADFLOAT
	{
	    OBJ newFloat;
	    struct uint128 uiZ;
	    union ui128_f128 uZ;
	    float128_t qf;

	    uiZ.v64 = packToF128UI64( 0, 0x7FFF, 0 );
	    uiZ.v0 = 0;
	    uZ.ui = uiZ;
	    qf = uZ.f;
	    __qMKQFLOAT(newFloat, qf);   /* OBJECT ALLOCATION */
	    inf = newFloat;
	}
#endif /* SUPPORT_QUADFLOAT */
%}.
	PositiveInfinity := inf
    ].
    ^ PositiveInfinity

    "Created: / 08-06-2019 / 14:05:26 / Claus Gittinger"
!

negativeInfinity
    "return a quadFloat which represents -INF"

    |inf|

    NegativeInfinity isNil ifTrue:[
%{  /* NOCONTEXT */
#ifdef SUPPORT_QUADFLOAT
	{
	    OBJ newFloat;
	    struct uint128 uiZ;
	    union ui128_f128 uZ;
	    float128_t qf;

	    uiZ.v64 = packToF128UI64( 1, 0x7FFF, 0 );
	    uiZ.v0 = 0;
	    uZ.ui = uiZ;
	    qf = uZ.f;
	    __qMKQFLOAT(newFloat, qf);   /* OBJECT ALLOCATION */
	    inf = newFloat;
	}
#endif /* SUPPORT_QUADFLOAT */
%}.
	NegativeInfinity := inf
    ].
    ^ NegativeInfinity

    "Created: / 08-06-2019 / 14:05:50 / Claus Gittinger"
!

phi
    "return the constant phi as quadFloat"

    Phi isNil ifTrue:[
        "/ phiDigits has enough digits for 128bit IEEE quads
        "/ do not use as a literal constant here - we cannot depend on the underlying C-compiler here...
        Phi  := self readFrom:(Number phiDigits)
    ].
    ^ Phi


!

pi
    "return the constant pi as quadFloat"

    Pi isNil ifTrue:[
	"/ piDigits has enough digits for 128bit IEEE quads
	"/ do not use as a literal constant here - we cannot depend on the underlying C-compiler here...
	Pi  := self readFrom:(Number piDigits)
    ].
    ^ Pi

    "Created: / 06-06-2019 / 17:09:51 / Claus Gittinger"
!

unity
    "return the neutral element for multiplication (1.0) as QuadFloat"

    QuadFloatOne isNil ifTrue:[
	QuadFloatOne := 1.0 asQuadFloat.
    ].
    ^ QuadFloatOne

    "Created: / 07-06-2019 / 03:26:38 / Claus Gittinger"
!

zero
    "return the neutral element for addition (0.0) as QuadFloat"

    QuadFloatZero isNil ifTrue:[
	QuadFloatZero := 0.0 asQuadFloat
    ].
    ^ QuadFloatZero

    "Created: / 07-06-2019 / 09:22:56 / Claus Gittinger"
! !

!QuadFloat class methodsFor:'error reportng'!

errorUnsupported
    self error:'QuadFloats not supported on this patform'

    "Created: / 07-06-2019 / 02:44:39 / Claus Gittinger"
! !

!QuadFloat class methodsFor:'queries'!

epsilon
    "return the maximum relative spacing of instances of mySelf
     (i.e. the value-delta of the least significant bit)"

    Epsilon isNil ifTrue:[
	Epsilon := self computeEpsilon.
    ].
    ^ Epsilon

    "
     self epsilon
    "

    "Created: / 10-06-2019 / 21:21:18 / Claus Gittinger"
!

exponentCharacter
    "return the character used to print between mantissa an exponent.
     Also used by the scanner when reading numbers."

    ^ $Q

    "Created: / 10-06-2019 / 21:28:04 / Claus Gittinger"
!

numBitsInExponent
    "answer the number of bits in the exponent
     the hidden bit is not counted here:

     This is an 128bit quadfloat,
	   where 15 bits are available in the exponent:
	seeeeeee eeeeeeee mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm...
    "

    ^ 15

    "
     1.0 class numBitsInExponent -> 11
     1.0 asShortFloat class numBitsInExponent -> 8
     1.0 asLongFloat class numBitsInExponent -> 15
     1.0 asQuadFloat class numBitsInExponent -> 15
    "

    "Created: / 11-06-2019 / 00:14:55 / Claus Gittinger"
!

numBitsInMantissa
    "answer the number of bits in the mantissa
     the hidden bit is not counted here:

     This is an 128bit quadfloat,
	   where 112 bits are available in the mantissa:
	seeeeeee eeeeeeee mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm...
    "

    ^ 112

    "
     1.0 class numBitsInMantissa
     1.0 asShortFloat class numBitsInMantissa
     1.0 asLongFloat class numBitsInMantissa
     1.0 asQuadFloat class numBitsInMantissa
    "

    "Created: / 07-06-2019 / 03:24:20 / Claus Gittinger"
!

radix
    "answer the radix of a QuadFloat's 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"

    "Created: / 19-07-2019 / 17:28:00 / Claus Gittinger"
! !

!QuadFloat methodsFor:'arithmetic'!

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

    aNumber class == QuadFloat ifTrue:[
        ^ aNumber productFromQuadFloat:self
    ].

    thisContext isReallyRecursive ifTrue:[self error].
    ^ aNumber productFromQuadFloat:self
!

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

    ^ aNumber sumFromQuadFloat:self
!

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

    ^ aNumber differenceFromQuadFloat:self
!

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

    aNumber isZero ifTrue:[
	"
	 No, you shalt not divide by zero
	"
	^ ZeroDivide raiseRequestWith:thisContext.
    ].
    ^ aNumber quotientFromQuadFloat:self
!

negated
    "return the receiver negated"

%{  /* NOCONTEXT */
#ifdef SUPPORT_QUADFLOAT
    OBJ newFloat;
    float128_t result, myVal;

    myVal = __quadFloatVal(self);
    f128M_negate( &myVal, &result );
    __qMKQFLOAT(newFloat, result);
    RETURN ( newFloat );
#endif
%}.
!

rem: aNumber
    "return the floating point remainder of the receiver and the argument, aNumber"

    aNumber isZero ifTrue:[
	"
	 No, you shalt not divide by zero
	"
	^ ZeroDivide raiseRequestWith:thisContext.
    ].
    ^ aNumber remainderFromLongFloat:self
! !

!QuadFloat methodsFor:'coercing & converting'!

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

    ^ 93

    "Created: / 07-06-2019 / 09:30:58 / Claus Gittinger"
! !

!QuadFloat methodsFor:'comparing'!

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

    ^ aNumber lessFromQuadFloat:self

    "Created: / 07-06-2019 / 09:25:47 / Claus Gittinger"
!

= aNumber
    "return true, if the argument represents the same numeric value
     as the receiver, false otherwise"

    ^ aNumber equalFromQuadFloat:self

    "Created: / 07-06-2019 / 09:25:27 / Claus Gittinger"
!

hash
    "return a number for hashing; redefined, since floats compare
     by numeric value (i.e. 3.0 = 3), therefore 3.0 hash must be the same
     as 3 hash."

    |i|

    (self >= SmallInteger minVal and:[self <= SmallInteger maxVal]) ifTrue:[
	i := self asInteger.
	self = i ifTrue:[
	    ^ i hash
	].
    ].

    ^ self asFloat hash

    "
     1.2345 hash
     1.2345 asShortFloat hash
     1.2345 asLongFloat hash
     1.2345 asQuadFloat hash

     1.0 hash
     1.0 asShortFloat hash
     1.0 asLongFloat hash
     1.0 asQuadFloat hash

     0.5 asShortFloat hash
     0.5 asShortFloat hash
     0.5 asLongFloat hash
     0.5 asQuadFloat hash

     0.25 asShortFloat hash
     0.25 asShortFloat hash
     0.25 asLongFloat hash
     0.25 asQuadFloat hash
    "

    "Created: / 07-06-2019 / 09:28:07 / Claus Gittinger"
! !

!QuadFloat methodsFor:'double dispatching'!

differenceFromQuadFloat:aQuadFloat
%{
#ifdef SUPPORT_QUADFLOAT
    OBJ newFloat;
    float128_t result, myVal, argVal;

    myVal = __quadFloatVal(self);
    argVal = __quadFloatVal(aQuadFloat);
    f128M_sub( &myVal, &argVal, &result );
    __qMKQFLOAT(newFloat, result);
    RETURN ( newFloat );
#endif // SUPPORT_QUADFLOAT
%}.
    self errorUnsupported
!

equalFromQuadFloat:aQuadFloat
    "sent when aQuadFloat does not know how to compare agaist the receiver, self"

%{
#ifdef SUPPORT_QUADFLOAT
    OBJ newFloat;
    float128_t result, myVal, argVal;

    myVal = __quadFloatVal(self);
    argVal = __quadFloatVal(aQuadFloat);
    RETURN (f128M_eq( &argVal, &myVal ) ? true : false);
#endif // SUPPORT_QUADFLOAT
%}.
    self errorUnsupported

    "Modified: / 08-06-2019 / 13:31:48 / Claus Gittinger"
!

lessFromQuadFloat:aQuadFloat
    "sent when aQuadFloat does not know how to compare agaist the receiver, self"

%{
#ifdef SUPPORT_QUADFLOAT
    OBJ newFloat;
    float128_t result, myVal, argVal;

    myVal = __quadFloatVal(self);
    argVal = __quadFloatVal(aQuadFloat);
    RETURN (f128M_lt( &argVal, &myVal ) ? true : false);
#endif // SUPPORT_QUADFLOAT
%}.
    self errorUnsupported
!

productFromQuadFloat:aQuadFloat
    "sent when aQuadFloat does not know how to multiply the receiver, self"

%{
#ifdef SUPPORT_QUADFLOAT
    OBJ newFloat;
    float128_t result, myVal, argVal;

    myVal = __quadFloatVal(self);
    argVal = __quadFloatVal(aQuadFloat);
    f128M_mul( &myVal, &argVal, &result );
    __qMKQFLOAT(newFloat, result);
    RETURN ( newFloat );
#endif // SUPPORT_QUADFLOAT
%}.
    self errorUnsupported
!

quotientFromQuadFloat:aQuadFloat
    "sent when aQuadFloat does not know how to multiply the receiver, self"

%{
#ifdef SUPPORT_QUADFLOAT
    OBJ newFloat;
    float128_t result, myVal, argVal;

    myVal = __quadFloatVal(self);
    argVal = __quadFloatVal(aQuadFloat);
    f128M_div( &myVal, &argVal, &result );
    __qMKQFLOAT(newFloat, result);
    RETURN ( newFloat );
#endif // SUPPORT_QUADFLOAT
%}.
    self errorUnsupported
!

sumFromQuadFloat:aQuadFloat
    "sent when aQuadFloat does not know how to add the receiver, self"

%{
#ifdef SUPPORT_QUADFLOAT
    OBJ newFloat;
    float128_t result, myVal, argVal;

    myVal = __quadFloatVal(self);
    argVal = __quadFloatVal(aQuadFloat);
    f128M_add( &myVal, &argVal, &result );
    __qMKQFLOAT(newFloat, result);
    RETURN ( newFloat );
#endif // SUPPORT_QUADFLOAT
%}.
    self errorUnsupported
! !

!QuadFloat methodsFor:'error reportng'!

errorUnsupported
    self class errorUnsupported

    "Modified: / 07-06-2019 / 02:44:51 / Claus Gittinger"
! !

!QuadFloat methodsFor:'printing'!

printOn:aStream
    |mantissa exponent|

    mantissa := self mantissa.
    exponent := self exponent.

    self exponent == 0 ifTrue:[
	mantissa printOn:aStream.
	aStream nextPutAll:'.0'.
	^ self
    ].
    mantissa == 0 ifTrue:[
	"/ a zero mantissa is impossible - except for zero and a few others
	exponent == 0 ifTrue:[ aStream nextPutAll:'0.0'. ^ self].
	self == NaN ifTrue:[ aStream nextPutAll:'NAN'. ^ self ].
	self == NegativeInfinity ifTrue:[ aStream nextPutAll:'-INF'. ^ self].
	self == PositiveInfinity ifTrue:[ aStream nextPutAll:'INF'. ^ self].

	self error:'invalid largeFloat' mayProceed:true.
	aStream nextPutAll:'Invalid'. ^ self.
    ].

    exponent >= 0 ifTrue:[
	(mantissa bitShift:exponent) printOn:aStream.
	aStream nextPutAll:'.0'.
	^ self
    ].
    ((mantissa / (1 bitShift:exponent negated)) asFixedPoint:6) printOn:aStream.

    "Created: / 11-06-2019 / 00:13:00 / Claus Gittinger"
! !

!QuadFloat methodsFor:'queries'!

isFinite
    "return true, if the receiver is a finite float (not NaN and not +/-INF)"

%{  /* NOCONTEXT */
#ifdef SUPPORT_QUADFLOAT
    float128_t myVal;

    myVal = __quadFloatVal(self);
    RETURN ((f128_isInf(myVal) || f128_isNan(myVal)) ? false : true);
#endif // SUPPORT_QUADFLOAT
%}.

    "
        1.0 isFinite
        self NaN isFinite
        self infinity isFinite
        self negativeInfinity isFinite
        (0.0 uncheckedDivide: 0.0) isFinite
        (1.0 uncheckedDivide: 0.0) isFinite
    "
!

isInfinite
    "return true, if the receiver is an infinite float (+Inf or -Inf)."

%{  /* NOCONTEXT */
#ifdef SUPPORT_QUADFLOAT
    float128_t myVal;

    myVal = __quadFloatVal(self);
    RETURN (f128_isInf(myVal) ? true : false);
#endif // SUPPORT_QUADFLOAT
%}.

    "
        1.0 isFinite
        1.0 isInfinite
        self NaN isFinite
        self NaN isInfinite
        self infinity isFinite
        self infinity isInfinite
        self negativeInfinity isFinite
        self negativeInfinity isInfinite
        (0.0 uncheckedDivide: 0.0) isFinite
        (1.0 uncheckedDivide: 0.0) isFinite
    "
!

isNaN
    "return true, if the receiver is an invalid float (NaN - not a number).
     These are not created by ST/X float operations (they raise an exception);
     however, inline C-code could produce them."

%{  /* NOCONTEXT */
#ifdef SUPPORT_QUADFLOAT
    float128_t myVal;

    myVal = __quadFloatVal(self);
    RETURN (f128_isNan(myVal) ? true : false);
#endif // SUPPORT_QUADFLOAT
%}.

    "
        1.0 isFinite
        self NaN isFinite
        self infinity isFinite
        (0.0 uncheckedDivide: 0.0) isFinite
        (1.0 uncheckedDivide: 0.0) isFinite
    "
! !

!QuadFloat methodsFor:'testing'!

isQuadFloat
    "return true, if the receiver is some kind of quad floating point number (iee quad precision)"

    ^ true
! !

!QuadFloat class methodsFor:'documentation'!

version_CVS
    ^ '$Header$'
! !