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