longFloat precision constants;
authorClaus Gittinger <cg@exept.de>
Tue, 17 Jun 2003 13:51:01 +0200
changeset 7389 4fd487ca919a
parent 7388 bb89a53e2682
child 7390 1e770c64a291
longFloat precision constants; added more math functions
LongFloat.st
--- a/LongFloat.st	Tue Jun 17 13:50:24 2003 +0200
+++ b/LongFloat.st	Tue Jun 17 13:51:01 2003 +0200
@@ -14,7 +14,7 @@
 
 LimitedPrecisionReal variableByteSubclass:#LongFloat
 	instanceVariableNames:''
-	classVariableNames:'LongFloatZero LongFloatOne'
+	classVariableNames:'DefaultPrintFormat LongFloatZero LongFloatOne Pi E'
 	poolDictionaries:''
 	category:'Magnitude-Numbers'
 !
@@ -179,10 +179,10 @@
 "
     LongFloats represent rational numbers with limited precision.
     They use the C-compilers 'long double' format, which is usually
-    the IEE extended float format.
+    mapped to the IEE extended float or IEE quad float format.
  
     In contrast to Floats (which use the C-compilers 64bit 'double' format),
-    LongFloats give you 80, 96 or 128 bits floats.
+    LongFloats give you 80, 96 bit floats (extended) or 128 bit floats (quad).
     The actual number of bits depends on the underlying CPU
     (thus, longFloat code is not quaranteed to be portable).
  
@@ -192,13 +192,13 @@
  
     Representation:
         gcc-i386:
-            80bit ext-precision IEE floats stored in in 96bits (12bytes);
+            80bit extended IEE floats stored in in 96bits (12bytes);
             64 bit mantissa,
             16 bit exponent,
             19 decimal digits (approx)
  
         gcc-sparc:
-            128bit ext-precision IEE floats stored in in 128bits (16bytes);
+            128bit quad IEE floats (16bytes);
             64 bit mantissa,
             16 bit exponent,
             19 decimal digits (approx)
@@ -222,6 +222,33 @@
 "
 ! !
 
+!LongFloat class methodsFor:'initialization'!
+
+initialize
+    "do not write a literal constant here - we cannot depend on the underlying C-compiler here..."
+
+    DefaultPrintFormat := '.9'.  "/ 9 valid digits
+
+    "/ enough digits for 128bit IEEE quads
+    Pi := self readFrom:'3.1415926535897932384626433832795029'. "/ '3.14159265358979323846264338327950288419716939937510582097494459'.
+    E := self readFrom:'2.7182818284590452353602874713526625'.
+
+    "
+     self initialize
+    "      
+
+    "      
+     DefaultPrintFormat := '.19'. 
+     LongFloat pi printString.     
+
+     DefaultPrintFormat := '.9'. 
+     LongFloat pi printString.     
+
+     DefaultPrintFormat := '.6'. 
+     LongFloat pi printString.     
+    "
+! !
+
 !LongFloat class methodsFor:'instance creation'!
 
 basicNew
@@ -235,8 +262,11 @@
 
 %{  /* NOCONTEXT */
     OBJ newFloat;
-
-    __qMKLFLOAT(newFloat, 0.0);   /* OBJECT ALLOCATION */
+    if (sizeof(LONGFLOAT) == sizeof(double)) {
+        __qMKFLOAT(newFloat, 0.0);   /* OBJECT ALLOCATION */
+    } else {
+        __qMKLFLOAT(newFloat, 0.0);   /* OBJECT ALLOCATION */
+    }
     RETURN (newFloat);
 %}
 !
@@ -248,22 +278,26 @@
     OBJ newFloat;
     LONGFLOAT f;
 
+    if (sizeof(LONGFLOAT) == sizeof(double)) {
+        RETURN (aFloat);
+    }
+
     if (aFloat != nil) {
-	if (__qIsFloatLike(aFloat)) {
-	    f = (LONGFLOAT)(__floatVal(aFloat));
-	    __qMKLFLOAT(newFloat, f);   /* OBJECT ALLOCATION */
-	    RETURN (newFloat);
-	}
-	if (__qIsShortFloat(aFloat)) {
-	    f = (LONGFLOAT)(__shortFloatVal(aFloat));
-	    __qMKLFLOAT(newFloat, f);   /* OBJECT ALLOCATION */
-	    RETURN (newFloat);
-	}
-	if (__isSmallInteger(aFloat)) {
-	    f = (LONGFLOAT)(__smallIntegerVal(aFloat));
-	    __qMKLFLOAT(newFloat, f);   /* OBJECT ALLOCATION */
-	    RETURN (newFloat);
-	}
+        if (__qIsFloatLike(aFloat)) {
+            f = (LONGFLOAT)(__floatVal(aFloat));
+            __qMKLFLOAT(newFloat, f);   /* OBJECT ALLOCATION */
+            RETURN (newFloat);
+        }
+        if (__qIsShortFloat(aFloat)) {
+            f = (LONGFLOAT)(__shortFloatVal(aFloat));
+            __qMKLFLOAT(newFloat, f);   /* OBJECT ALLOCATION */
+            RETURN (newFloat);
+        }
+        if (__isSmallInteger(aFloat)) {
+            f = (LONGFLOAT)(__smallIntegerVal(aFloat));
+            __qMKLFLOAT(newFloat, f);   /* OBJECT ALLOCATION */
+            RETURN (newFloat);
+        }
     }
 %}.
     self error:'invalid argumnet'
@@ -296,17 +330,16 @@
 
 !LongFloat class methodsFor:'constants'!
 
+e
+    "return the constant e as LongFloat"
+
+    ^ E
+!
+
 pi
     "return the constant pi as LongFloat"
 
-    "the number of digits below is misleading: 
-     as the compiler does not (yet) know about longFloats, the constant is initially
-     only generated as double precision float. I.e. the number of digits will be only 
-     what doubl provides (certainly less than those here)"
-
-    ^ 3.14159265358979323846264338327950288419716939937510582097494459 asLongFloat
-
-    "Modified: 23.4.1996 / 09:26:31 / cg"
+    ^ Pi
 !
 
 unity
@@ -905,7 +938,9 @@
 exp
     "return e raised to the power of the receiver"
 
-%{  /* NOCONTEXT */
+    |useFallBack|
+
+%{ 
 #if defined(LONG_exp)
 
     LONGFLOAT rslt;
@@ -917,24 +952,32 @@
     if (! LONG_isnan(rslt))
 # endif
     if (__threadErrno == 0) {
-	__qMKLFLOAT(newFloat, rslt);
-	RETURN ( newFloat );
+        __qMKLFLOAT(newFloat, rslt);
+        RETURN ( newFloat );
     }
+#else
+    useFallBack := true;
 #endif
 %}.
+    useFallBack notNil ifTrue:[
+        ^ super exp
+    ].
+
     ^ self class
-	raise:#domainErrorSignal
-	receiver:self
-	selector:#exp
-	arguments:#()
-	errorString:'bad receiver in exp'
+        raise:#domainErrorSignal
+        receiver:self
+        selector:#exp
+        arguments:#()
+        errorString:'bad receiver in exp'
 !
 
 ln
     "return the natural logarithm of myself.
      Raises an exception, if the receiver is less or equal to zero."
 
-%{  /* NOCONTEXT */
+    |useFallBack|
+
+%{ 
 #if defined(LONG_log)
 
     LONGFLOAT val, rslt;
@@ -946,36 +989,44 @@
     if (val > 0.0)
 # endif
     {
-	__threadErrno = 0;
-	rslt = LONG_log(val);
+        __threadErrno = 0;
+        rslt = LONG_log(val);
 # ifdef LONG_isnan
         if (! LONG_isnan(rslt))
 # endif
-	{
-	    if (__threadErrno == 0) {
-		__qMKLFLOAT(newFloat, rslt);
-		RETURN ( newFloat );
-	    }
-	}
+        {
+            if (__threadErrno == 0) {
+                __qMKLFLOAT(newFloat, rslt);
+                RETURN ( newFloat );
+            }
+        }
     }
+#else
+    useFallBack := true;
 #endif
 %}.
+    useFallBack notNil ifTrue:[
+        ^ super ln
+    ].
+
     "
      an invalid value for logarithm
     "
     ^ self class
-	raise:#domainErrorSignal
-	receiver:self
-	selector:#ln
-	arguments:#()
-	errorString:'bad receiver in ln'
+        raise:#domainErrorSignal
+        receiver:self
+        selector:#ln
+        arguments:#()
+        errorString:'bad receiver in ln'
 !
 
 log10
     "return the base10 logarithm of myself.
      Raises an exception, if the receiver is less or equal to zero."
 
-%{  /* NOCONTEXT */
+    |useFallBack|
+
+%{ 
 #if defined(LONG_log10)
 
     LONGFLOAT val, rslt;
@@ -999,8 +1050,14 @@
             }
         }
     }
+#else
+    useFallBack := true;
 #endif
 %}.
+    useFallBack notNil ifTrue:[
+        ^ super log10
+    ].
+
     "
      an invalid value for logarithm
     "
@@ -1015,7 +1072,7 @@
 raisedTo:aNumber
     "return self raised to the power of aNumber"
 
-    |n|
+    |n useFallBack|
 
     n := aNumber asFloat.
 %{
@@ -1024,29 +1081,35 @@
     OBJ newFloat;
 
     if (__isFloatLike(n)) {
-	__threadErrno = 0;
-	rslt = LONG_pow(__longFloatVal(self), __floatVal(n));
+        __threadErrno = 0;
+        rslt = LONG_pow(__longFloatVal(self), __floatVal(n));
 # ifdef LONG_isnan
         if (! LONG_isnan(rslt))
 # endif
-	{
-	    if (__threadErrno == 0) {
-	        __qMKLFLOAT(newFloat, rslt);
-	        RETURN ( newFloat );
-	    }
-	}
+        {
+            if (__threadErrno == 0) {
+                __qMKLFLOAT(newFloat, rslt);
+                RETURN ( newFloat );
+            }
+        }
     }
+#else
+    useFallBack := true;
 #endif
 %}.
+    useFallBack notNil ifTrue:[
+        ^ super raisedTo:aNumber
+    ].
+
     "
      an invalid argument (not convertable to float ?)
     "
     ^ self class
-	raise:#domainErrorSignal
-	receiver:self
-	selector:#raisedTo:
-	arguments:(Array with:aNumber)
-	errorString:'bad receiver/arg in raisedTo:'
+        raise:#domainErrorSignal
+        receiver:self
+        selector:#raisedTo:
+        arguments:(Array with:aNumber)
+        errorString:'bad receiver/arg in raisedTo:'
 
     "Modified: / 16.11.2001 / 14:16:51 / cg"
 !
@@ -1055,7 +1118,9 @@
     "return the square root of myself.
      Raises an exception, if the receiver is less than zero."
 
-%{  /* NOCONTEXT */
+    |useFallBack|
+
+%{ 
 #if defined(LONG_sqrt)
 
     LONGFLOAT val, rslt;
@@ -1067,26 +1132,32 @@
     if (val >= 0.0)
 # endif
     {
-	__threadErrno = 0;
-	rslt = LONG_sqrt(val);
+        __threadErrno = 0;
+        rslt = LONG_sqrt(val);
 # ifdef LONG_isnan
         if (! LONG_isnan(rslt))
 # endif
-	{
-	    if (__threadErrno == 0) {
-		__qMKLFLOAT(newFloat, rslt);
-		RETURN ( newFloat );
-	    }
-	}
+        {
+            if (__threadErrno == 0) {
+                __qMKLFLOAT(newFloat, rslt);
+                RETURN ( newFloat );
+            }
+        }
     }
+#else
+    useFallBack := true;
 #endif
 %}.
+    useFallBack notNil ifTrue:[
+        ^ super sqrt
+    ].
+
     ^ self class
-	raise:#domainErrorSignal
-	receiver:self
-	selector:#sqrt
-	arguments:#()
-	errorString:'bad receiver in sqrt'
+        raise:#domainErrorSignal
+        receiver:self
+        selector:#sqrt
+        arguments:#()
+        errorString:'bad receiver in sqrt'
 
     "
      10 asLongFloat sqrt
@@ -1106,27 +1177,31 @@
 %{  /* NOCONTEXT */
 
     char buffer[64];
+    char fmtBuffer[20];
+    char *fmt;
     REGISTER char *cp;
     OBJ s;
 
+    if (__isString(@global(DefaultPrintFormat))) {
+        fmt = (char *) __stringVal(@global(DefaultPrintFormat));
+    } else {
+        fmt = ".9";
+    }
     /*
-     * actually only needed on sparc: since thisContext is
-     * in a global register, which gets destroyed by printf,
-     * manually save it here - very stupid ...
+     * build a printf format string
      */
-    __BEGIN_PROTECT_REGISTERS__
-
+    fmtBuffer[0] = '%';
+    strncpy(fmtBuffer+1, fmt, 10);
     if (sizeof(LONGFLOAT) == sizeof(double)) {
 #ifdef SYSV
-        sprintf(buffer, "%.6lg", __longFloatVal(self));
+        strcat(fmtBuffer, "lg");
 #else
-        sprintf(buffer, "%.6G", __longFloatVal(self));
+        strcat(fmtBuffer, "G");
 #endif
     } else {
-        sprintf(buffer, "%.6LG", __longFloatVal(self));
+        strcat(fmtBuffer, "LG");
     }
-
-    __END_PROTECT_REGISTERS__
+    sprintf(buffer, fmtBuffer, __longFloatVal(self));
 
     /* 
      * kludge to make integral float f prints as "f.0" (not as "f" as printf does)
@@ -1200,18 +1275,18 @@
 
 %{  /* NOCONTEXT */
 
-#if defined(i386) && defined(__GNUC__)
+#if defined(LONG_frexp)
     LONGFLOAT LONG_frexp();
     INT exp;
 
     __threadErrno = 0;
     LONG_frexp( __longFloatVal(self), &exp);
     if (__threadErrno == 0) {
-	RETURN (__MKSMALLINT(exp));
+        RETURN (__MKSMALLINT(exp));
     }
 #endif
 %}.
-    ^ self primitiveFailed
+    ^ super exponent
 
     "
      4.0 asLongFloat exponent    
@@ -1392,10 +1467,12 @@
 !LongFloat methodsFor:'trigonometric'!
 
 arcCos
-    "return the arccosine of myself (I am interpreted as radians).
+    "return the arccosine of the receiver (as radians).
      Raises an exception, if the receiver is not in -1..1"
 
-%{  /* NOCONTEXT */
+    |useFallBack|
+
+%{ 
 #if defined(LONG_acos)
 
     LONGFLOAT val, rslt;
@@ -1407,26 +1484,31 @@
     if ((val >= -1.0) && (val <= 1.0))
 # endif
     {
-	__threadErrno = 0;
-	rslt = LONG_acos(val);
+        __threadErrno = 0;
+        rslt = LONG_acos(val);
 # ifdef LONG_isnan
-	if (! LONG_isnan(rslt))
+        if (! LONG_isnan(rslt))
 # endif
-	{
-	    if (__threadErrno == 0) {
-		__qMKLFLOAT(newFloat, rslt);
-		RETURN ( newFloat );
-	    }
-	}
+        {
+            if (__threadErrno == 0) {
+                __qMKLFLOAT(newFloat, rslt);
+                RETURN ( newFloat );
+            }
+        }
     }
+#else
+    useFallBack := true;
 #endif
 %}.
+    useFallBack notNil ifTrue:[
+        ^ super arcCos
+    ].
     ^ self class
-	raise:#domainErrorSignal
-	receiver:self
-	selector:#arcCos
-	arguments:#()
-	errorString:'bad receiver in arcCos'
+        raise:#domainErrorSignal
+        receiver:self
+        selector:#arcCos
+        arguments:#()
+        errorString:'bad receiver in arcCos'
 
     "
      -10 asLongFloat arcCos
@@ -1436,10 +1518,11 @@
 !
 
 arcCosh
-    "return the hyperbolic arccosine of myself (I am interpreted as radians).
-     Raises an exception, if the receiver is not in -1..1"
+    "return the hyperbolic arccosine of the receiver."
  
-%{  /* NOCONTEXT */
+    |useFallBack|
+
+%{ 
 #if defined(LONG_acosh)
  
     LONGFLOAT val, rslt;
@@ -1448,7 +1531,7 @@
     val = __longFloatVal(self);
  
 # ifdef WIN32 /* dont know (yet) how to suppress the warnBox opened by win32 */
-    if ((val >= -1.0) && (val <= 1.0))
+    if (val >= 1.0)
 # endif
     {
         __threadErrno = 0;
@@ -1463,8 +1546,13 @@
             }
         }
     }
+#else
+    useFallBack := true;
 #endif
 %}.
+    useFallBack notNil ifTrue:[
+        ^ super arcCosh
+    ].
     ^ self class
         raise:#domainErrorSignal
         receiver:self
@@ -1480,10 +1568,12 @@
 !
 
 arcSin
-    "return the arcsine of myself (I am interpreted as radians).
+    "return the arcsine of the receiver (as radians).
      Raises an exception, if the receiver is not in -1..1"
 
-%{  /* NOCONTEXT */
+    |useFallBack|
+
+%{ 
 #if defined(LONG_asin)
 
     LONGFLOAT val, rslt;
@@ -1495,26 +1585,31 @@
     if ((val >= -1.0) && (val <= 1.0))
 # endif
     {
-	__threadErrno = 0;
-	rslt = LONG_asin(val);
+        __threadErrno = 0;
+        rslt = LONG_asin(val);
 # ifdef LONG_isnan
-	if (! LONG_isnan(rslt))
+        if (! LONG_isnan(rslt))
 # endif
-	{
-	    if (__threadErrno == 0) {
-		__qMKLFLOAT(newFloat, rslt);
-		RETURN ( newFloat );
-	    }
-	}
+        {
+            if (__threadErrno == 0) {
+                __qMKLFLOAT(newFloat, rslt);
+                RETURN ( newFloat );
+            }
+        }
     }
+#else
+    useFallBack := true;
 #endif
 %}.
+    useFallBack notNil ifTrue:[
+        ^ super arcSin
+    ].
     ^ self class
-	raise:#domainErrorSignal
-	receiver:self
-	selector:#arcSin
-	arguments:#()
-	errorString:'bad receiver in arcSin'
+        raise:#domainErrorSignal
+        receiver:self
+        selector:#arcSin
+        arguments:#()
+        errorString:'bad receiver in arcSin'
 
     "
      -10 asLongFloat arcSin
@@ -1524,10 +1619,11 @@
 !
 
 arcSinh
-    "return the hyperbolic arcsine of myself (I am interpreted as radians).
-     Raises an exception, if the receiver is not in -1..1"
+    "return the hyperbolic arcsine of the receiver."
  
-%{  /* NOCONTEXT */
+    |useFallBack|
+
+%{ 
 #if defined(LONG_asinh)
  
     LONGFLOAT val, rslt;
@@ -1536,7 +1632,7 @@
     val = __longFloatVal(self);
  
 # ifdef WIN32 /* dont know (yet) how to suppress the warnBox opened by win32 */
-    if ((val >= -1.0) && (val <= 1.0))
+    if (val >= 1.0)
 # endif
     {
         __threadErrno = 0;
@@ -1551,8 +1647,13 @@
             }
         }
     }
+#else
+    useFallBack := true;
 #endif
 %}.
+    useFallBack notNil ifTrue:[
+        ^ super arcSinh
+    ].
     ^ self class
         raise:#domainErrorSignal
         receiver:self
@@ -1568,9 +1669,11 @@
 !
 
 arcTan
-    "return the arctangent of myself as radians"
+    "return the arctangent of the receiver (as radians)"
 
-%{  /* NOCONTEXT */
+    |useFallBack|
+
+%{ 
 #if defined(LONG_atan)
 
     LONGFLOAT rslt;
@@ -1583,42 +1686,60 @@
 # endif
     {
         if (__threadErrno == 0) {
-	    __qMKLFLOAT(newFloat, rslt);
-	    RETURN ( newFloat );
-	}
-    }
-#endif
-%}.
-    ^ self class
-	raise:#domainErrorSignal
-	receiver:self
-	selector:#arcTan
-	arguments:#()
-	errorString:'bad receiver in arcTan'
-!
-
-arcTanh
-    "return the hyperbolic arctangent of myself as radians"
- 
-%{  /* NOCONTEXT */
-#if defined(LONG_atanh)
- 
-    LONGFLOAT rslt;
-    OBJ newFloat;
- 
-    __threadErrno = 0;
-    rslt = LONG_atanh(__longFloatVal(self));
-# ifdef LONG_isnan
-    if (! LONG_isnan(rslt))
-# endif
-    {
-        if (__threadErrno == 0) {
             __qMKLFLOAT(newFloat, rslt);
             RETURN ( newFloat );
         }
     }
+#else
+    useFallBack := true;
 #endif
 %}.
+    useFallBack notNil ifTrue:[
+        ^ super arcTan
+    ].
+    ^ self class
+        raise:#domainErrorSignal
+        receiver:self
+        selector:#arcTan
+        arguments:#()
+        errorString:'bad receiver in arcTan'
+!
+
+arcTanh
+    "return the hyperbolic arctangent of the receiver."
+ 
+    |useFallBack|
+
+%{ 
+#if defined(LONG_atanh)
+ 
+    LONGFLOAT val, rslt;
+    OBJ newFloat;
+
+    val = __longFloatVal(self);
+    __threadErrno = 0;
+# ifdef WIN32 /* dont know (yet) how to suppress the warnBox opened by win32 */
+    if ((val >= -1.0) && (val <= 1.0))
+# endif
+    {
+        rslt = LONG_atanh(val);
+# ifdef LONG_isnan
+        if (! LONG_isnan(rslt))
+# endif
+        {
+            if (__threadErrno == 0) {
+                __qMKLFLOAT(newFloat, rslt);
+                RETURN ( newFloat );
+            }
+        }
+    }
+#else
+    useFallBack := true;
+#endif
+%}.
+    useFallBack notNil ifTrue:[
+        ^ super arcTanh
+    ].
     ^ self class
         raise:#domainErrorSignal
         receiver:self
@@ -1628,9 +1749,11 @@
 !
 
 cos
-    "return the cosine of myself interpreted as radians"
+    "return the cosine of the receiver (interpreted as radians)"
 
-%{  /* NOCONTEXT */
+    |useFallBack|
+
+%{ 
 #if defined(LONG_cos)
 
     LONGFLOAT rslt;
@@ -1642,23 +1765,30 @@
     if (! LONG_isnan(rslt))
 # endif
     if (__threadErrno == 0) {
-	__qMKLFLOAT(newFloat, rslt);
-	RETURN ( newFloat );
+        __qMKLFLOAT(newFloat, rslt);
+        RETURN ( newFloat );
     }
+#else
+    useFallBack := true;
 #endif
 %}.
+    useFallBack notNil ifTrue:[
+        ^ super cos
+    ].
     ^ self class
-	raise:#domainErrorSignal
-	receiver:self
-	selector:#cos
-	arguments:#()
-	errorString:'bad receiver in cos'
+        raise:#domainErrorSignal
+        receiver:self
+        selector:#cos
+        arguments:#()
+        errorString:'bad receiver in cos'
 !
 
 cosh
-    "return the hyperbolic cosine of myself interpreted as radians"
+    "return the hyperbolic cosine of the receiver"
  
-%{  /* NOCONTEXT */
+    |useFallBack|
+
+%{ 
 #if defined(LONG_cosh)
  
     LONGFLOAT rslt;
@@ -1673,8 +1803,13 @@
         __qMKLFLOAT(newFloat, rslt);
         RETURN ( newFloat );
     }
+#else
+    useFallBack := true;
 #endif
 %}.
+    useFallBack notNil ifTrue:[
+        ^ super cosh
+    ].
     ^ self class
         raise:#domainErrorSignal
         receiver:self
@@ -1684,9 +1819,11 @@
 !
 
 sin
-    "return the sine of myself interpreted as radians"
+    "return the sine of the receiver (interpreted as radians)"
 
-%{  /* NOCONTEXT */
+    |useFallBack|
+
+%{ 
 #if defined(LONG_sin)
 
     LONGFLOAT rslt;
@@ -1694,27 +1831,34 @@
 
     __threadErrno = 0;
     rslt = LONG_sin(__longFloatVal(self));
-# ifdef LINUX /* and maybe others */
-    if (! isnan(rslt))
+# ifdef LONG_isnan
+    if (! LONG_isnan(rslt))
 # endif
     if (__threadErrno == 0) {
-	__qMKLFLOAT(newFloat, rslt);
-	RETURN ( newFloat );
+        __qMKLFLOAT(newFloat, rslt);
+        RETURN ( newFloat );
     }
+#else
+    useFallBack := true;
 #endif
 %}.
+    useFallBack notNil ifTrue:[
+        ^ super sin
+    ].
     ^ self class
-	raise:#domainErrorSignal
-	receiver:self
-	selector:#sin
-	arguments:#()
-	errorString:'bad receiver in sin'
+        raise:#domainErrorSignal
+        receiver:self
+        selector:#sin
+        arguments:#()
+        errorString:'bad receiver in sin'
 !
 
 sinh
-    "return the hyperbolic sine of myself interpreted as radians"
+    "return the hyperbolic sine of the receiver"
  
-%{  /* NOCONTEXT */
+    |useFallBack|
+
+%{ 
 #if defined(LONG_sinh)
  
     LONGFLOAT rslt;
@@ -1722,15 +1866,20 @@
  
     __threadErrno = 0;
     rslt = LONG_sinh(__longFloatVal(self));
-# ifdef LINUX /* and maybe others */
-    if (! isnan(rslt))
+# ifdef LONG_isnan
+    if (! LONG_isnan(rslt))
 # endif
     if (__threadErrno == 0) {
         __qMKLFLOAT(newFloat, rslt);
         RETURN ( newFloat );
     }
+#else
+    useFallBack := true;
 #endif
 %}.
+    useFallBack notNil ifTrue:[
+        ^ super sinh
+    ].
     ^ self class
         raise:#domainErrorSignal
         receiver:self
@@ -1740,9 +1889,11 @@
 !
 
 tan
-    "return the tangens of myself interpreted as radians"
+    "return the tangens of the receiver (interpreted as radians)"
 
-%{  /* NOCONTEXT */
+    |useFallBack|
+
+%{ 
 #if defined(LONG_tan)
 
     LONGFLOAT rslt;
@@ -1750,27 +1901,34 @@
 
     __threadErrno = 0;
     rslt = LONG_tan(__longFloatVal(self));
-# ifdef LINUX /* and maybe others */
-    if (! isnan(rslt))
+# ifdef LONG_isnan
+    if (! LONG_isnan(rslt))
 # endif
     if (__threadErrno == 0) {
-	__qMKLFLOAT(newFloat, rslt);
-	RETURN ( newFloat );
+        __qMKLFLOAT(newFloat, rslt);
+        RETURN ( newFloat );
     }
+#else
+    useFallBack := true;
 #endif
 %}.
+    useFallBack notNil ifTrue:[
+        ^ super tan
+    ].
     ^ self class
-	raise:#domainErrorSignal
-	receiver:self
-	selector:#tan
-	arguments:#()
-	errorString:'bad receiver in tan'
+        raise:#domainErrorSignal
+        receiver:self
+        selector:#tan
+        arguments:#()
+        errorString:'bad receiver in tan'
 !
 
 tanh
-    "return the hyperbolic tangens of myself interpreted as radians"
+    "return the hyperbolic tangens of the receiver"
  
-%{  /* NOCONTEXT */
+    |useFallBack|
+
+%{ 
 #if defined(LONG_tanh)
  
     LONGFLOAT rslt;
@@ -1778,15 +1936,20 @@
  
     __threadErrno = 0;
     rslt = LONG_tanh(__longFloatVal(self));
-# ifdef LINUX /* and maybe others */
-    if (! isnan(rslt))
+# ifdef LONG_isnan
+    if (! LONG_isnan(rslt))
 # endif
     if (__threadErrno == 0) {
         __qMKLFLOAT(newFloat, rslt);
         RETURN ( newFloat );
     }
+#else
+    useFallBack := true;
 #endif
 %}.
+    useFallBack notNil ifTrue:[
+        ^ super tanh
+    ].
     ^ self class
         raise:#domainErrorSignal
         receiver:self
@@ -2034,5 +2197,7 @@
 !LongFloat class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/LongFloat.st,v 1.29 2003-06-17 09:12:22 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/LongFloat.st,v 1.30 2003-06-17 11:51:01 cg Exp $'
 ! !
+
+LongFloat initialize!