home *** CD-ROM | disk | FTP | other *** search
- /*------------------------------------------------------------------------
- * filename - sinhl.cas
- *
- * function(s)
- * sinhl - long double hyperbolic sine 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>
- #include <errno.h>
- #include <stddef.h>
-
- /*--------------------------------------------------------------------------*
-
- Name sinhl - long double hyperbolic sine function
-
- Usage long double sinhl(long double x);
-
- Prototype in math.h
-
- Description sinhl computes the hyperbolic sine of the input value.
-
- Return value sinhl returns the hyperbolic sine of the input value.
- For large arguments (absolute value greater than
- ~11356.5) the result will be _LHUGE_VAL of
- the appropriate sign and errno will be set to:
- ERANGE Range error.
-
- *---------------------------------------------------------------------------*/
-
- /*
- Algorithm.
-
- The usual formula is:
- sinhl(x) = .5*(expl(x) - expl(-x))
- but there is a loss of precision in using this formula directly near 0.
-
- Since sinhl(-x) = -sinhl(x), compute sinhl(|x|) and adjust the sign later.
-
- If 0 <= x < 2^-33, return x.
-
- If x >= 11356.5 call matherr.
-
- If x >= .3465, use
- y = expl(x)
- sinhl(x) = (y - 1/y)/2
-
- If 2^-33 <= x < .3465, use
- y = expl(x) - 1
- sinhl(x) = (y + y/(1 + y))/2
- where special chip functions are used to get expl(x)-1 accurately.
-
- */
-
- #pragma warn -rvl
- long double _FARFUNC sinhl (long double x)
- {
- asm FLD1
- asm mov ax, 7FFFh
- asm FCHS /* TOS = -1.0, used in FSCALE later */
- asm mov dx, x [8]
- asm and ax, dx /* select exponent */
-
- asm FLD LONGDOUBLE (x)
- asm cmp ax, 3fffh+13 /* 2^13 is the near the limit */
- asm jae sinhl_tooBig
-
- asm FABS
- asm cmp ax, 3FFDh /* compare with .3465 */
- asm jb jb_sinhl_small /* avoid "jmp out of range" error */
- asm ja sinhl_justFits
- asm cmp W0 (x [6]), 0B168h
- jb_sinhl_small:
- asm jb sinhl_small
-
- sinhl_justFits:
- __expld(); /* TOS = expl(x) */
-
- asm FLD1
- asm FDIV st, st(1) /* Exp (-x) */
- asm FSUBP st(1), st
- asm FSCALE /* sinhl (x) = (exp(x) - exp(-x)) / 2 */
-
- sinhl_end:
- asm FSTP st(1) /* discard the -1 */
- /* change sign if original argument was negative */
- asm or dh, dh
- asm jns sinhl_end2
- asm FCHS
- sinhl_end2:
- return;
-
- sinhl_tooBig:
- asm ja sinhl_over
- asm cmp W0 (x [6]), 0B172h
- asm jb sinhl_justFits
-
- sinhl_over:
- asm FSTP ST(0) /* pop two items off the stack */
- asm FSTP ST(0)
-
- #pragma warn -ret
- return __matherrl (OVERFLOW, "sinhl", &x, NULL,
- (_DX & 0x8000) ? - _LHUGE_VAL : _LHUGE_VAL);
- #pragma warn .ret
-
- sinhl_small:
- asm cmp ax, 3fffh-33 /* x < 2^-33 ? */
- asm jb sinhl_end /* x tiny, return x */
-
- asm FLDL2E
- asm FMUL
- asm F2XM1
- /* TOS = y = exp(x) - 1 */
- asm FLD1
- asm FADD st(0),st(1)
- /* stack = 1+y,y,-1 */
- asm FDIVR st(0),st(1)
- asm FADD
- asm FSCALE
- goto sinhl_end;
- }
- #pragma warn .rvl
-