	page	,132
        title   87triga   - inverse trigonometric functions - ASIN, ACOS, ATAN
;*** 
;87triga.asm - inverse trigonometric functions - ASIN, ACOS, ATAN
;
;   Copyright (c) 1984-88, Microsoft Corporation
;
;Purpose:
;   Routines for ASIN, ACOS, ATAN
;
;Revision History:
;
;   07/04/84	Greg Whitten
;		initial version
;
;   10/01/84	Brad Verheiden
;		Fixed bug in _rtforatnby0 which did not remove an
;		element from the floating stack
;
;   10/28/85	Jamie Bariteau
;		Added comment about inputs to fFATN2, made fFATN2
;		public
;		made _fFATN2 and _rtpiby2 public labels
;
;   10/30/87	Bill Johnston
;		Minor changes for new cmacros.
;
;   08/25/88	Bill Johnston
;		386 version.
;
;   02/10/92	Georgios Papagiannakopoulos
;		NT port -- Bug fix for atan(-INF)
;
;   03/27/92	GDP  support underflow
;
;
;*******************************************************************************

.xlist
	include cruntime.inc
	include mrt386.inc
	include elem87.inc
.list



	.data

extrn	_indefinite:tbyte
extrn	_piby2:tbyte

jmptab	OP_ASIN,4,<'asin',0,0>,<0,0,0,0,0,0>,1
    DNCPTR	codeoffset fFASN       ; 0000 TOS Valid non-0
    DNCPTR	codeoffset _rttosnpop	; 0001 TOS 0
    DNCPTR	codeoffset _tosnan1	; 0010 TOS NAN
    DNCPTR	codeoffset _rtindfnpop	; 0011 TOS Inf

jmptab	OP_ACOS,4,<'acos',0,0>,<0,0,0,0,0,0>,1
    DNCPTR	codeoffset fFACS       ; 0000 TOS Valid non-0
    DNCPTR	codeoffset _rtpiby2	; 0001 TOS 0
    DNCPTR	codeoffset _tosnan1	; 0010 TOS NAN
    DNCPTR	codeoffset _rtindfnpop	; 0011 TOS Inf

jmptab	OP_ATAN,4,<'atan',0,0>,<0,0,0,0,0,0>,1
    DNCPTR	codeoffset fFATN       ; 0000 TOS Valid non-0
    DNCPTR	codeoffset _rttosnpop	; 0001 TOS 0
    DNCPTR	codeoffset _tosnan1	; 0010 TOS NAN
    DNCPTR	codeoffset _rtforatninf ; 0011 TOS Inf

jmptab	OP_ATAN2,5,<'atan2',0>,<0,0,0,0,0,0>,2
    DNCPTR	codeoffset fFATN2	; 0000 NOS Valid non-0, TOS Valid non-0
    DNCPTR	codeoffset _rtforatnby0 ; 0001 NOS Valid non-0, TOS 0
    DNCPTR	codeoffset _tosnan2	; 0010 NOS Valid non-0, TOS NAN
    DNCPTR	codeoffset _rtforatn20	; 0011 NOS Valid non-0, TOS Inf
    DNCPTR	codeoffset _rtforatn20	; 0100 NOS 0, TOS Valid non-0
    DNCPTR	codeoffset _rtforatn200 ; 0101 NOS 0, TOS 0
    DNCPTR	codeoffset _tosnan2	; 0110 NOS 0, TOS NAN
    DNCPTR	codeoffset _rtforatn20	; 0111 NOS 0, TOS Inf
    DNCPTR	codeoffset _nosnan2	; 1000 NOS NAN, TOS Valid non-0
    DNCPTR	codeoffset _nosnan2	; 1001 NOS NAN, TOS 0
    DNCPTR	codeoffset _nan2	; 1010 NOS NAN, TOS NAN
    DNCPTR	codeoffset _nosnan2	; 1011 NOS NAN, TOS Inf
    DNCPTR	codeoffset _rtforatnby0	; 1100 NOS Inf, TOS Valid non-0
    DNCPTR	codeoffset _rtforatnby0	; 1101 NOS Inf, TOS 0
    DNCPTR	codeoffset _tosnan2	; 1110 NOS Inf, TOS NAN
    DNCPTR	codeoffset _rtindfpop	; 1111 NOS Inf, TOS Inf

page


	CODESEG

extrn	_rtchsifneg:near
extrn	_rtindfpop:near
extrn	_rtindfnpop:near
extrn	_rtnospop:near
extrn	_rtonenpop:near
extrn	_rttospop:near
extrn	_rttosnpop:near
extrn	_rttosnpopde:near
extrn	_rtzeronpop:near
extrn	_tosnan1:near
extrn	_tosnan2:near
extrn	_nosnan2:near
extrn	_nan2:near

;----------------------------------------------------------
;
;       INVERSE TRIGONOMETRIC FUNCTIONS
;
;----------------------------------------------------------
;
;       INPUTS - For single argument functions the argument
;                is the stack top.  For fFATN2 the numerator
;                is next to stack top, the denominator is
;                the stack top.
;                For single argument functions the sign is
;                in bit 2 of CL.  For fFATN2 the numerator
;                sign is bit 2 of CH, the denominator
;                sign is bit 2 of CL.
;
;		 Note:
;		 _clog calls fFATN2 with the signs of the arguments
;		 in bit 0 of CL and CH respectively.  This should
;		 work since fFATN2 tests for sign of numerator and
;		 denominator by using "or CL,CL" and "or CH,CH"
;
;       OUTPUT - The result is the stack top
;
;----------------------------------------------------------

lab fFASN
	call	AugmentSinCos		; num.=arg, den.=sqrt(1-arg^2)
	xchg	ch, cl			; sign(num.)=sign(arg)
	jmp	short fFPATAN


lab fFACS
	call	AugmentSinCos		; num.=arg, den.=sqrt(1-arg^2)
	fxch				; num.=sqrt(1-arg^2), den.=arg
	jmp	short fFPATAN


lab fFATN
	fabs
	fld1				; denominator is 1
	mov	ch, cl
	xor	cl, cl			; sign of denominator is +ve
	jmp	short fFPATAN


labelNP _fFATN2, PUBLIC
lab fFATN2
	mov	DSF.ErrorType, CHECKRANGE ; indicate possible over/under flow on exit
	fabs
	fxch
	fabs
	fxch

lab fFPATAN
	fpatan				; compute partial arctangent
	or	cl, cl			; if denominator was +ve
	JSZ	PatanNumeratorTest	;    bypass -ve denominator adjust
	fldpi
	fsubrp	st(1), st(0)		; change Patan to pi - Patan

lab PatanNumeratorTest
	or	ch, ch			; if numerator was +ve
	JSZ	PatanDone		;    bypass -ve numerator adjust
	fchs				; change Patan to -Patan

lab PatanDone
	ret

page

lab AugmentSinCos
	fabs				; NOS=x = |input|
	fld	st(0)			; NOS=x, TOS=x
	fld	st(0)			; NNOS=x, NOS=x, TOS=x
	fld1				; NNNOS=x, NNOS=x, NOS=x, TOS=1
	fsubrp	st(1),st(0)		; NNOS=x, NOS=x, TOS=1-x
	fxch				; NNOS=x, NOS=1-x, TOS=x
	fld1				; NNNOS=x, NNOS=1-x, NOS=x, TOS=1
	fadd				; NNOS=x, NOS=1-x, TOS=1+x
	fmul				; NOS=x, TOS=1-x^2
	ftst
	fstsw	DSF.StatusWord
	fwait
	test	CondCode, 1		; if 1-x^2 < 0
	JSNZ	DescriminantNeg 	;    return a NAN
	xor	ch, ch			; sign of TOS is +ve
	fsqrt				; NOS=x, TOS=sqrt(1-x^2)
	ret

lab DescriminantNeg
	pop	rax			; remove return address from stack
	jmp	_rtindfpop		; replace top of stack with a NAN

page
;----------------------------------------------------------
;
;       SPECIAL CASE RETURN FUNCTIONS
;
;----------------------------------------------------------
;
;       INPUTS - The signs of the last, second to last
;                arguments are in CH, CL respectively.
;
;       OUTPUT - The result is the stack top.
;
;----------------------------------------------------------

labelNP _rtpiby2, PUBLIC
	fstp	st(0)			; remove ST(0)
	fld	[_piby2]		; push pi/2 onto stack
	ret


lab _rtforatn20
	fstp	st(0)			; remove ST(0)
	or	cl ,cl			; if denominator is +ve
	JSZ	zeronpop		;    return zero
	fstp	st(0)
	fldpi				; push pi onto stack
	or	ch, ch			; if numerator was +ve
	JSZ	postv
	fchs
lab postv
	ret

lab zeronpop
	jmp	_rtzeronpop		; return 0.0


lab _rtforatn200
lab indfpop
	fstp	st(0)			; remove ST(0)
lab indfnpop
	jmp	_rtindfnpop		; return real indefinite


lab _rtforatnby0
	fstp	st(0)			; remove an argument before returning
	mov	cl, ch			; cl is sign(TOS)
	jmp	short _rtsignpiby2


lab _rtforatninf
lab _rtsignpiby2
	call	_rtpiby2		; push pi/2 onto stack
	jmp	_rtchsifneg		; return with sign change if negative

end
