home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c082_122 / 2.ddi / MATHSRC.ZIP / TANH.CAS < prev    next >
Encoding:
Text File  |  1992-06-10  |  3.0 KB  |  135 lines

  1. /*------------------------------------------------------------------------
  2.  * filename - tanh.cas
  3.  *
  4.  * function(s)
  5.  *        tanh - hyperbolic tangent function
  6.  *-----------------------------------------------------------------------*/
  7.  
  8. /*
  9.  *      C/C++ Run Time Library - Version 5.0
  10.  *
  11.  *      Copyright (c) 1987, 1992 by Borland International
  12.  *      All Rights Reserved.
  13.  *
  14.  */
  15.  
  16.  
  17. #pragma inline
  18. #include <asmrules.h>
  19.  
  20. #include <_math.h>
  21. #include <math.h>
  22.  
  23.  
  24. /*--------------------------------------------------------------------------*
  25.  
  26. Name            tanh - hyperbolic tangent function
  27.  
  28. Usage           double tanh(double x);
  29.  
  30. Prototype in    math.h
  31.  
  32. Description     tanh calculates the hyperbolic tangent of the input.
  33.  
  34. Return value    tanh returns the hyperbolic tangent of the input value.
  35.                 For large arguments (magnitude greater than 32) the result
  36.                 will be +1.0 or -1.0.
  37.  
  38. *---------------------------------------------------------------------------*/
  39.  
  40. /*
  41. Algorithm.
  42.  
  43. The usual formula is:
  44.         tanh(x) = (exp(x) - exp(-x))/(exp(x) + exp(-x))/
  45. but there is a loss of precision in using this formula directly near 0.
  46.  
  47. Since tanh(-x) = -tanh(x), compute tanh(|x|) and adjust the sign later.
  48.  
  49. If 0 <= x < 2^-33, return x.
  50.  
  51. If x >= 32 return 1.
  52.  
  53. If x >= .17325, use
  54.         y = exp(x)
  55.         tanh(x) = (y - 1/y)/(y + 1/y)
  56.  
  57. If 2^-33 <= x < .17325, use
  58.         y = exp(2x) - 1
  59.         sinh(x) = y/(2 + y)
  60. where special chip functions are used to get exp(2x)-1 accurately.
  61.  
  62. */
  63.  
  64. #pragma warn -rvl
  65. double _FARFUNC tanh( double  x )
  66. {
  67. asm     FLD     DOUBLE (x)
  68. asm     sub     dh, dh
  69. asm     mov     cx, x [6]
  70. asm     shl     cx, 1
  71. asm     rcr     dh, 1                   /* DH = sign    */
  72. asm     cmp     cx, 8080h
  73. asm     FABS
  74. asm     ja      tanh_extreme
  75.  
  76. asm     cmp     cx, 7F8Ch
  77. asm     jb      tanh_small
  78.  
  79. #ifdef _Windows
  80.         _f87_Exp();
  81. #else
  82. asm     _FAST_  (_FEXP_)                /* Exp (x)      */
  83. #endif
  84.  
  85. asm     FLD1
  86. asm     FDIV    st, st(1)               /* Exp (-x)     */
  87.  
  88. /*
  89.   tanh = sinh / cosh = (exp(x) - exp(-x)) / (exp(x) + exp(-x))
  90. */
  91. asm     FLD     st(1)
  92. asm     FSUB    st, st(1)
  93. asm     FXCH
  94. asm     FADD    st, st(2)
  95. asm     FDIVP   st(1), st
  96. asm     FSTP    st(1)
  97.  
  98. tanh_end:
  99. asm     or      dh, dh
  100. asm     jns     tanh_end2
  101. asm     FCHS
  102. tanh_end2:
  103.         return;
  104.  
  105. /*
  106.   tanh is asymptotic to -1 for negative arguments and +1 for positives.
  107.   It approaches very fast, with exponentially increasing accuracy,
  108.   so it is 1.0 for IEEE accuracy when |x| > 23.
  109. */
  110. tanh_extreme:
  111. asm     FSTP    st(0)           /* pop stack    */
  112. asm     FLD1
  113.         goto tanh_end;
  114.  
  115. tanh_small:
  116. asm     cmp     cx, 7BC0h
  117. asm     jb      tanh_end
  118. asm     FLD1
  119. asm     FXCH
  120. asm     FSCALE
  121.  
  122. asm     FLDL2E
  123. asm     FMUL
  124. asm     F2XM1
  125. /* TOS = y = exp(2x) - 1 */
  126. asm     FXCH
  127. asm     FLD1
  128. asm     FADD
  129. asm     FADD    st(0),st(1)
  130. /* stack = 2+y,y */
  131. asm     FDIV
  132.         goto tanh_end;
  133. }
  134. #pragma warn .rvl
  135.