page	,132
	title   87trigh   - hyperbolic trigonometric functions - SINH, COSH, TANH
;*** 
;87trigh.asm - hyperbolic trigonometric functions - SINH, COSH, TANH
;
;   Copyright (c) 1984-2001, Microsoft Corporation. All rights reserved.
;
;Purpose:
;   Routines for SINH, COSH, TANH
;
;Revision History:
;
;   07/04/84	Greg Whitten
;		initial version
;
;   10/31/85	Jamie Bariteau
;		made _fFSINH and _fFCOSH 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 --used CHECKOVER for detection of overflow
;
;*******************************************************************************

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

	.data

extrn	_logemax:tbyte
extrn	_infinity:tbyte
staticT _tanhmaxarg,	04003987E0C9996699000R

jmptab	OP_SINH,4,<'sinh',0,0>,<0,0,0,0,0,0>,1
    DNCPTR	codeoffset fFSINH	; 0000 TOS Valid non-0
    DNCPTR	codeoffset _rttosnpop	; 0001 TOS 0
    DNCPTR	codeoffset _tosnan1	; 0010 TOS NAN
    DNCPTR	codeoffset _rtforsnhinf ; 0011 TOS Inf

jmptab	OP_COSH,4,<'cosh',0,0>,<0,0,0,0,0,0>,1
    DNCPTR	codeoffset fFCOSH      ; 0000 TOS Valid non-0
    DNCPTR	codeoffset _rtonenpop	; 0001 TOS 0
    DNCPTR	codeoffset _tosnan1	; 0010 TOS NAN
    DNCPTR	codeoffset _rtforcshinf	; 0011 TOS Inf

jmptab	OP_TANH,4,<'tanh',0,0>,<0,0,0,0,0,0>,1
    DNCPTR	codeoffset fFTANH      ; 0000 TOS Valid non-0
    DNCPTR	codeoffset _rttosnpop	; 0001 TOS 0
    DNCPTR	codeoffset _tosnan1	; 0010 TOS NAN
    DNCPTR	codeoffset _rtfortnhinf ; 0011 TOS Inf

page

	CODESEG

extrn	_ffexpm1:near
extrn	_rtchsifneg:near
extrn	_rtindfnpop:near
extrn	_rtinfnpop:near
extrn	_rtonenpop:near
extrn	_rttospop:near
extrn	_rttosnpop:near
extrn	_rttosnpopde:near
extrn	_tosnan1:near

;----------------------------------------------------------
;
;       HYPERBOLIC FUNCTIONS
;
;----------------------------------------------------------
;
;       INPUTS - The argument is the stack top.
;                The sign of the argument is bit 2 of CL.
;
;       OUTPUT - The result is the stack top
;
;----------------------------------------------------------


labelNP _fFSINH, PUBLIC
lab fFSINH
	mov	DSF.ErrorType, CHECKOVER ; indicate possible overflow on exit
	call	fFEXPH			; compute e^x for hyperbolics
	or	bl, bl			; if e^x is infinite
	JSZ	_rtforsnhlarge		;    return as if x = affine infinity
	call	ExpHypCopyInv		; TOS = e^(-x), NOS = e^x
	fsubp	st(1), st(0)		; compute e^x - e^(-x) for hyperbolics
	jmp	short SinhCoshReturn


lab fFTANH
	fld	st(0)			; copy TOS
	fabs				; make TOS +ve
	fld	[_tanhmaxarg]		; get largest arg, roughly ln(2)(55)/2
	fcompp
	fstsw	DSF.StatusWord
	fwait
	test	CondCode, 041h		; if abs(arg) > XBIG (see tanh.h)
	JSNZ	_rtfortnhlarge		;    return as if x = affine infinity
	call	fFEXPH			; compute e^x for hyperbolics
	or	bl, bl			; if e^x is infinite
	JSZ	_rtfortnhlarge		;    return as if x = affine infinity
	fld	st(0)			; copy TOS
	call	ExpHypSum		; compute e^x + e^(-x) for hyperbolics
	fxch				; get copy of e^x
	call	ExpHypCopyInv		; TOS = e^(-x), NOS = e^x
	fsubp	st(1), st(0)		; compute e^x - e^(-x) for hyperbolics
	fdivrp	st(1), st(0)		; now TOS = tanh(x)
	ret


labelNP _fFCOSH, PUBLIC
lab fFCOSH
	mov	DSF.ErrorType, CHECKOVER ; indicate possible overflow on exit
	call	fFEXPH			; compute e^x for hyperbolics
	or	bl, bl			; if e^x is infinite
	JSZ	_rtforcnhlarge		;    return as if x = affine infinity
	call	ExpHypSum		; compute e^x + e^(-x) for hyperbolics

lab SinhCoshReturn
	fld1
	fchs
	fxch
	fscale				; divide result by 2
	jmp	_rttospop

page

lab _rtforsnhinf
	fstp	st(0)
	fld	[_infinity]
	jmp	_rtchsifneg		; change sign if argument -ve

lab _rtforcshinf
	fstp	st(0)
	fld	[_infinity]
	ret

lab infpositive
	ret

lab _rtforsnhlarge
	call	_rtinfnpop		; TOS = infinity

lab chsifneg
	jmp	_rtchsifneg		; change sign if argument -ve


lab _rtforcnhlarge
	jmp	_rtinfnpop		; TOS = infinity


lab _rtfortnhlarge
	mov	DSF.ErrorType, INEXACT
lab _rtfortnhinf
	call	_rtonenpop		; TOS = one
	jmp	chsifneg		; change sign if argument -ve

page

lab fFEXPH
	fldl2e
	fmul				; convert log base e to log base 2
	xor	rbx, rbx		; clear e^x, finite result flags
	call	_ffexpm1		; TOS = e^|x|-1 unscaled, NOS = scale
	not	bl			; set finite result flag
	test	CondCode, 1		; if fraction > 0 (TOS > 0)
	JSZ	ExpHypNoInvert		;    bypass e^x-1 invert
	call	ExpHypCopyInv		; TOS = e^(-x)-1, NOS = e^x-1
	fxch
	fstp	st(0)			; remove NOS

lab ExpHypNoInvert
	test	dl, 040h		; if integer part was zero
	JSNZ	ExpHypScaled		;    bypass scaling to avoid bug
	not	bh			; set e^x flag
	fld1
	fadd				; TOS = e^x unscaled
	fscale				; now TOS = e^x

lab ExpHypScaled
	jmp	_rttospop		; TOS = e^x-1 or e^x scaled

lab ExpHypSum
	call	ExpHypCopyInv		; TOS = e^(-x), NOS = e^x
	fadd				; TOS = e^x + e^(-x)
	or	bh, bh			; if e^x flag set
	JSNZ	ExpHypSumReturn 	;    bypass e^x-1 adjust
	fld1
	fadd	st(1),st
	fadd				; add 2 to result

lab ExpHypSumReturn
	ret

lab ExpHypCopyInv
	fld	st(0)			; TOS = e^x (or e^x-1)
	fld1				; TOS = 1, NOS = e^x (or e^x-1)
	or	bh, bh			; if e^x flag set
	JSNZ	ExpHypCopyInvReturn	;    bypass e^x-1 adjust
	fadd	st, st(1)		; TOS = e^x, NOS = e^x-1
	fchs				; TOS = -e^x, NOS = e^x-1
	fxch				; TOS = e^x-1, NOS = -e^x

lab ExpHypCopyInvReturn
	fdivrp	st(1), st(0)		; TOS = e^(-x) (or e^(-x)-1)
	ret

end