home *** CD-ROM | disk | FTP | other *** search
- /*------------------------------------------------------------------------
- * filename - tanhl.cas
- *
- * function(s)
- * tanhl - long double hyperbolic tangent function
- *-----------------------------------------------------------------------*/
-
- /*
- * C/C++ Run Time Library - Version 5.0
- *
- * Copyright (c) 1987, 1992 by Borland International
- * All Rights Reserved.
- *
- */
-
-
- #pragma inline
- #include <asmrules.h>
-
- #include <_math.h>
- #include <math.h>
-
-
- /*--------------------------------------------------------------------------*
-
- Name tanhl - long double hyperbolic tangent function
-
- Usage long double tanhl(long double x);
-
- Prototype in math.h
-
- Description tanhl calculates the hyperbolic tangent of the input.
-
- Return value tanhl returns the hyperbolic tangent of the input value.
- For large arguments (magnitude greater than 32) the result
- will be +1.0 or -1.0.
-
- *---------------------------------------------------------------------------*/
-
- /*
- Algorithm.
-
- The usual formula is:
- tanhl(x) = (exp(x) - exp(-x))/(exp(x) + exp(-x))/
- but there is a loss of precision in using this formula directly near 0.
-
- Since tanhl(-x) = -tanhl(x), compute tanhl(|x|) and adjust the sign later.
-
- If 0 <= x < 2^-33, return x.
-
- If x >= 32 return 1.
-
- If x >= .17325, use
- y = exp(x)
- tanhl(x) = (y - 1/y)/(y + 1/y)
-
- If 2^-33 <= x < .17325, use
- y = exp(2x) - 1
- sinh(x) = y/(2 + y)
- where special chip functions are used to get exp(2x)-1 accurately.
-
- */
-
- #pragma warn -rvl
- long double _FARFUNC tanhl (long double x)
- {
- asm FLD LONGDOUBLE (x)
- asm sub dh, dh
- asm mov cx, x [8]
- asm shl cx, 1
- asm rcr dh, 1 /* DH = sign */
- asm cmp cx, 8008h
- asm FABS
- asm ja tanhl_extreme
-
- asm cmp cx, 7FF8h
- asm jb tanhl_small
-
- #ifdef _Windows
- _f87_Exp();
- #else
- asm _FAST_ (_FEXP_) /* Exp (x) */
- #endif
-
- asm FLD1
- asm FDIV st, st(1) /* Exp (-x) */
-
- /*
- tanhl = sinh / cosh = (exp(x) - exp(-x)) / (exp(x) + exp(-x))
- */
- asm FLD st(1)
- asm FSUB st, st(1)
- asm FXCH
- asm FADD st, st(2)
- asm FDIVP st(1), st
- asm FSTP st(1)
-
- tanhl_end:
- /* change sign if original argument was negative */
- asm or dh, dh
- asm jns tanhl_end2
- asm FCHS
- tanhl_end2:
- return;
-
- /*
- tanhl is asymptotic to -1 for negative arguments and +1 for positives.
- It approaches very fast, with exponentially increasing accuracy,
- so it is 1.0 for IEEE accuracy when |x| > 23.
- */
- tanhl_extreme:
- asm FSTP st(0) /* pop stack */
- asm FLD1
- goto tanhl_end;
-
- tanhl_small:
- asm cmp cx, 7FBCh
- asm jb tanhl_end
- asm FLD1
- asm FXCH
- asm FSCALE
- asm FLDL2E
- asm FMUL
- asm F2XM1
- /* TOS = y = exp(2x) - 1 */
- asm FXCH
- asm FLD1
- asm FADD
- asm FADD st(0),st(1)
- /* stack = 2+y,y */
- asm FDIV
- goto tanhl_end;
- }
- #pragma warn .rvl
-