home *** CD-ROM | disk | FTP | other *** search
- /*------------------------------------------------------------------------
- * filename - tanh.cas
- *
- * function(s)
- * tanh - hyperbolic tangent function
- *-----------------------------------------------------------------------*/
-
- /*[]------------------------------------------------------------[]*/
- /*| |*/
- /*| Turbo C Run Time Library - Version 3.0 |*/
- /*| |*/
- /*| |*/
- /*| Copyright (c) 1987, 1990 by Borland International |*/
- /*| All Rights Reserved. |*/
- /*| |*/
- /*[]------------------------------------------------------------[]*/
-
-
- #pragma inline
- #include <asmrules.h>
-
- #include <_math.h>
- #include <math.h>
-
-
- /*--------------------------------------------------------------------------*
-
- Name tanh - hyperbolic tangent function
-
- Usage double tanh(double x);
-
- Prototype in math.h
-
- Description tanh calculates the hyperbolic tangent of the input.
-
- Return value tanh 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:
- tanh(x) = (exp(x) - exp(-x))/(exp(x) + exp(-x))/
- but there is a loss of precision in using this formula directly near 0.
-
- Since tanh(-x) = -tanh(x), compute tanh(|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)
- tanh(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
- double tanh (double x)
- {
- asm FLD DOUBLE (x)
- asm sub dh, dh
- asm mov cx, x [6]
- asm shl cx, 1
- asm rcr dh, 1 /* DH = sign */
- asm cmp cx, 8080h
- asm FABS
- asm ja tanh_extreme
-
- asm cmp cx, 7F8Ch
- asm jb tanh_small
-
- asm _FAST_ (_FEXP_) /* Exp (x) */
- asm FLD1
- asm FDIV st, st(1) /* Exp (-x) */
-
- /*
- tanh = 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)
-
- tanh_end:
- asm or dh, dh
- asm jns tanh_end2
- asm FCHS
- tanh_end2:
- return;
-
- /*
- tanh 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.
- */
- tanh_extreme:
- asm FSTP st(0) /* pop stack */
- asm FLD1
- goto tanh_end;
-
- tanh_small:
- asm cmp cx, 7BC0h
- asm jb tanh_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 tanh_end;
- }
- #pragma warn .rvl
-