home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c082_144 / 1.ddi / MATHSRC.ZIP / ACOSASIN.CAS < prev    next >
Encoding:
Text File  |  1992-06-10  |  5.9 KB  |  209 lines

  1. /*------------------------------------------------------------------------
  2.  * filename - acosasin.cas
  3.  *
  4.  * function(s)
  5.  *        AcosAsin - compute acos or asin
  6.  *        acos     - trigonometric function
  7.  *        asin     - trigonometric function
  8.  *-----------------------------------------------------------------------*/
  9.  
  10. /*
  11.  *      C/C++ Run Time Library - Version 5.0
  12.  *
  13.  *      Copyright (c) 1987, 1992 by Borland International
  14.  *      All Rights Reserved.
  15.  *
  16.  */
  17.  
  18.  
  19. #pragma inline
  20. #include <asmrules.h>
  21.  
  22. #include <_math.h>
  23. #include <math.h>
  24. #include <errno.h>
  25.  
  26. typedef unsigned short  bits16;
  27.  
  28. #ifndef NULL
  29. #   define NULL ((void *)0)
  30. #endif
  31.  
  32. static  unsigned short   NANINVTRIG [4] = {0,0,0x0440, 0x7FF8};
  33.  
  34. /*---------------------------------------------------------------------*
  35.  
  36. Name            AcosAsin - compute sin or cos
  37.  
  38. Usage           double AcosAsin (char *whoS, bits16 flags, double *xP);
  39.  
  40. Description     Computes acos or sin of the number pointed to by xP.
  41.  
  42. Return value    Returns acos or asin of xP.
  43.  
  44. *---------------------------------------------------------------------*/
  45. #pragma warn -rvl
  46. #pragma warn -use
  47.  
  48. static double near AcosAsin (char *whoS, bits16 flags, double *xP)
  49. {
  50.         volatile bits16 status;
  51.         volatile int temp;
  52.  
  53. asm     mov     dx, flags
  54. asm     mov     si, W0 (xP)
  55.  
  56. asm     mov     cx, SS_ [si+6]
  57. asm     and     BY0 (SS_ [si+7]), 07Fh          /* absolute value */
  58. asm     fld     DOUBLE (SS_ [si])
  59.  
  60. asm     shl     cx, 1
  61. asm     rcr     dh, 1                           /* DH = sign bit */
  62. asm     jcxz    acs_zero
  63.  
  64. asm     cmp     cx, 7FE0h                       /* biased exponent of 1.0 */
  65. asm     jnb     acs_extreme
  66. /*
  67.   Use the trig identity asin (x) = atan (x / sqrt (1 - x^2)).
  68. */
  69. asm     FLD1
  70. asm     FLD     ST(1)                   /* duplicate X */
  71. asm     FMUL    ST(0), ST(0)            /* square it */
  72. asm     FSUBP   ST(1), ST               /* 1 - X^2 */
  73. asm     FSQRT
  74. /*
  75.   We now have tangent = ST(1)/ST.  In order to use the FPATAN instruction
  76.   we must order them so that ST(1) < ST.  The special case of equality
  77.   (angle pi/4) must be treated separately.
  78. */
  79. asm     FCOM
  80. asm     FSTSW   W0 (status)
  81. asm     mov     ah, 41h                 /* C3, C0 are the important bits */
  82. asm     FWAIT
  83. /*
  84.   At this stage note that acos (x) = atan (sqrt (1-x^2) / x), which is
  85.   the inverse of the tangent ratio used for asin (x).  That is why
  86.   DL, the inversion flag, started as 0FF for acos, and 0 for asin.
  87. */
  88. asm     and     ah, BY1 (status)
  89. asm     jz      acs_atan
  90. asm     add     ah, ah
  91. asm     js      acs_pi_4
  92. asm     FXCH
  93. asm     not     dl                      /* remember the exchanged order */
  94.  
  95. acs_atan:
  96. asm     FPATAN                          /* arctan (ST(1) / ST) */
  97.  
  98. asm     or      dl, dl                  /* should ratio be inverted ? */
  99. asm     jz      acs_sign
  100.  
  101. asm     mov     W0 (temp), -1
  102. asm     FILD    W0 (temp)
  103. asm     FLDPI
  104. asm     FSCALE                          /* pi/2 */
  105. asm     FSTP    ST(1)
  106. asm     FSUBRP  st(1), st               /* ST = pi/2 - ST */
  107.  
  108. acs_sign:
  109. asm     or      dh, dh
  110. asm     jns     acs_end
  111.  
  112. asm     FCHS
  113.  
  114. asm     cmp     BY0 (flags), 0FFh       /* are we doing acos () ? */
  115. asm     jne     acs_end
  116.  
  117. asm     FLDPI
  118. asm     FADDP   ST(1), ST
  119.  
  120. acs_end:
  121.         return;
  122.  
  123. /*
  124.   Special cases.
  125. */
  126. acs_extreme:
  127. asm     ja      acs_domain
  128. asm     mov     ax, SS_ [si+4]          /* check for an exact value +- 1.0 */
  129. asm     or      ax, SS_ [si+2]
  130. asm     or      ax, SS_ [si]
  131. asm     jnz     acs_domain
  132. asm     jmp     short   acs_one
  133.  
  134. acs_zero:
  135. asm     mov     dh, 0                   /* make zero unsigned. */
  136. asm     FSTP    ST(0)                   /* pop stack */
  137. asm     cmp     BY0 (flags), 0FFh       /* are we doing acos () ? */
  138. asm     je      acs_resultP2
  139. acs_resultZ:
  140. asm     FLDZ
  141. asm     jmp     short   acs_sign
  142.  
  143. acs_one:
  144. asm     FSTP    ST(0)                   /* pop stack */
  145. asm     cmp     BY0 (flags), 0FFh       /* are we doing acos () ? */
  146. asm     je      acs_resultZ
  147. acs_resultP2:
  148. asm     mov     W0 (temp), -1
  149. asm     FILD    W0 (temp)
  150. asm     FLDPI
  151. asm     FSCALE                          /* pi/2 */
  152. asm     FSTP    ST(1)
  153. asm     jmp     short   acs_sign
  154.  
  155. acs_pi_4:
  156. asm     FSTP    ST(0)                   /* pop two items off the stack */
  157. asm     FSTP    ST(0)
  158. asm     mov     W0 (temp), -2
  159. asm     FILD    W0 (temp)
  160. asm     FLDPI
  161. asm     FSCALE                          /* pi/4 */
  162. asm     FSTP    ST(1)
  163. asm     jmp     short   acs_sign
  164.  
  165. /*
  166.   If the argument was outside [-1,+1] then it is a domain error.
  167. */
  168. acs_domain:
  169. asm     or      BY0 (SS_ [si+7]), dh    /* put the sign back */
  170. asm     FSTP    ST (0)                  /* pop x from stack */
  171.  
  172. #pragma warn -ret
  173.     return _matherr (DOMAIN, whoS, xP, NULL, *((double *) NANINVTRIG));
  174. #pragma warn .ret
  175. }
  176. #pragma warn .rvl
  177. #pragma warn .use
  178.  
  179. /*--------------------------------------------------------------------------*
  180.  
  181. Name            acos & asin - trigonometric functions
  182.  
  183. Usage           double acos(double x);
  184.                 double asin(double x);
  185.  
  186. Prototype in    math.h
  187.  
  188. Description     asin,   acos  return   the  arc   sine,  and   arc  cosine,
  189.                 respectively,  of the  input value.  Arguments to  asin and
  190.                 acos must be  in the range -1 to 1.  Arguments outside that
  191.                 range will cause asin or acos to return 0 and set errno to:
  192.                         EDOM    Domain error
  193.  
  194. Return value    acos returns a value in the range 0 to pi.
  195.                 asin returns a value in the range -pi/2 to pi/2.
  196.  
  197. *---------------------------------------------------------------------------*/
  198.  
  199. double _FARFUNC acos( double x )
  200. {
  201.         return  AcosAsin ("acos", 0xFF, &x);
  202. }
  203.  
  204.  
  205. double _FARFUNC asin( double x )
  206. {
  207.         return  AcosAsin ("asin", 0x00, &x);
  208. }
  209.