home *** CD-ROM | disk | FTP | other *** search
- /*------------------------------------------------------------------------
- * filename - acossinl.cas
- *
- * function(s)
- * AcosAsinl - compute acosl or asinl
- * acosl - long double trigonometric function
- * asinl - long double trigonometric 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>
-
- typedef unsigned short bits16;
-
- #ifndef NULL
- # define NULL ((void *)0)
- #endif
-
- static unsigned short NANINVTRIGL [5] = {0,0,0,0xC022, 0x7FFF};
-
- /*---------------------------------------------------------------------*
-
- Name AcosAsinl - compute sin or cos
-
- Usage long double AcosAsinl (char *whoS, bits16 flags,
- long double *xP);
-
- Description Computes acosl or sinl of the number pointed to by xP.
-
- Return value Returns acosl or asinl of xP.
-
- *---------------------------------------------------------------------*/
- #pragma warn -rvl
- #pragma warn -use
-
- static long double near AcosAsinl (char *whoS, bits16 flags, long double *xP)
- {
- volatile bits16 status;
- volatile int temp;
-
- asm mov dx, flags
- asm mov si, W0 (xP)
-
- asm mov cx, SS_ [si+8]
- asm and BY0 (SS_ [si+9]), 07Fh /* absolute value */
- asm fld LONGDOUBLE (SS_ [si])
-
- asm shl cx, 1
- asm rcr dh, 1 /* DH = sign bit */
- asm jcxz acs_zero
-
- asm cmp cx, 7FFEh /* biased exponent of 1.0 */
- asm jnb acs_extreme
- /*
- Use the trig identity asin (x) = atan (x / sqrt (1 - x^2)).
- */
- asm FLD1
- asm FLD ST(1) /* duplicate X */
- asm FMUL ST(0), ST(0) /* square it */
- asm FSUBP ST(1), ST /* 1 - X^2 */
- asm FSQRT
- /*
- We now have tangent = ST(1)/ST. In order to use the FPATAN instruction
- we must order them so that ST(1) < ST. The special case of equality
- (angle pi/4) must be treated separately.
- */
- asm FCOM
- asm FSTSW W0 (status)
- asm mov ah, 41h /* C3, C0 are the important bits */
- asm FWAIT
- /*
- At this stage note that acos (x) = atan (sqrt (1-x^2) / x), which is
- the inverse of the tangent ratio used for asin (x). That is why
- DL, the inversion flag, started as 0FF for acos, and 0 for asin.
- */
- asm and ah, BY1 (status)
- asm jz acs_atan
- asm add ah, ah
- asm js acs_pi_4
- asm FXCH
- asm not dl /* remember the exchanged order */
-
- acs_atan:
- asm FPATAN /* arctan (ST(1) / ST) */
-
- asm or dl, dl /* should ratio be inverted ? */
- asm jz acs_sign
-
- asm mov W0 (temp), -1
- asm FILD W0 (temp)
- asm FLDPI
- asm FSCALE /* pi/2 */
- asm FSTP ST(1)
- asm FSUBRP st(1), st /* ST = pi/2 - ST */
-
- acs_sign:
- asm or dh, dh
- asm jns acs_end
-
- asm FCHS
-
- asm cmp BY0 (flags), 0FFh /* are we doing acos () ? */
- asm jne acs_end
-
- asm FLDPI
- asm FADDP ST(1), ST
-
- acs_end:
- return;
-
- /*
- Special cases.
- */
- acs_extreme:
- asm ja acs_domain
- asm mov ax, SS_ [si+6] /* check for an exact value +- 1.0 */
- asm xor ah, 80h
- asm or ax, SS_ [si+4]
- asm or ax, SS_ [si+2]
- asm or ax, SS_ [si]
- asm jnz acs_domain
- asm jmp short acs_one
-
- acs_zero:
- asm mov dh, 0 /* make zero unsigned. */
- asm FSTP ST(0) /* pop stack */
- asm cmp BY0 (flags), 0FFh /* are we doing acos () ? */
- asm je acs_resultP2
- acs_resultZ:
- asm FLDZ
- asm jmp short acs_sign
-
- acs_one:
- asm FSTP ST(0) /* pop stack */
- asm cmp BY0 (flags), 0FFh /* are we doing acos () ? */
- asm je acs_resultZ
- acs_resultP2:
- asm mov W0 (temp), -1
- asm FILD W0 (temp)
- asm FLDPI
- asm FSCALE /* pi/2 */
- asm FSTP ST(1)
- asm jmp short acs_sign
-
- acs_pi_4:
- asm FSTP ST(0) /* pop two items off the stack */
- asm FSTP ST(0)
- asm mov W0 (temp), -2
- asm FILD W0 (temp)
- asm FLDPI
- asm FSCALE /* pi/4 */
- asm FSTP ST(1)
- asm jmp short acs_sign
-
- /*
- If the argument was outside [-1,+1] then it is a domain error.
- */
- acs_domain:
- asm or BY0 (SS_ [si+9]), dh /* put the sign back */
- asm FSTP ST (0) /* pop x from stack */
-
- #pragma warn -ret
- return __matherrl (DOMAIN, whoS, xP, NULL, *((long double *) NANINVTRIGL));
- #pragma warn .ret
- }
- #pragma warn .rvl
- #pragma warn .use
-
- /*--------------------------------------------------------------------------*
-
- Name acosl & asinl - long double trigonometric functions
-
- Usage long double acosl(long double x);
- long double asinl(long double x);
-
- Prototype in math.h
-
- Description asinl, acosl return the arc sine, and arc cosine,
- respectively, of the input value. Arguments to asinl and
- acosl must be in the range -1 to 1. Arguments outside that
- range will cause asinl or acosl to return 0 and set errno to:
- EDOM Domain error
-
- Return value acosl returns a value in the range 0 to pi.
- asinl returns a value in the range -pi/2 to pi/2.
-
- *---------------------------------------------------------------------------*/
- long double _FARFUNC acosl (long double x)
- {
- return AcosAsinl ("acosl", 0xFF, &x);
- }
-
-
- long double _FARFUNC asinl (long double x)
- {
- return AcosAsinl ("asinl", 0x00, &x);
- }
-