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

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