home *** CD-ROM | disk | FTP | other *** search
- *
- * $VER: sinh.s 33.1 (22.1.97)
- *
- * hyperbolic sine
- *
- * Version history:
- *
- * 33.1 22.1.97 (c) Motorola
- *
- * - snipped from M68060SP sources
- *
-
- machine 68040
- fpu 1
-
- XDEF _sinh
- XDEF @sinh
-
- XREF @exp
- XREF @expm1
-
- *************************************************************************
- * sin(): computes the hyperbolic sine of a normalized input *
- * *
- * INPUT *************************************************************** *
- * fp0 = extended precision input *
- * *
- * OUTPUT ************************************************************** *
- * fp0 = sinh(X) *
- * *
- * ACCURACY and MONOTONICITY ******************************************* *
- * The returned result is within 3 ulps in 64 significant bit, *
- * i.e. within 0.5001 ulp to 53 bits if the result is subsequently *
- * rounded to double precision. The result is provably monotonic *
- * in double precision. *
- * *
- * ALGORITHM *********************************************************** *
- * *
- * SINH *
- * 1. If |X| > 16380 log2, go to 3. *
- * *
- * 2. (|X| <= 16380 log2) Sinh(X) is obtained by the formula *
- * y = |X|, sgn = sign(X), and z = expm1(Y), *
- * sinh(X) = sgn*(1/2)*( z + z/(1+z) ). *
- * Exit. *
- * *
- * 3. If |X| > 16480 log2, go to 5. *
- * *
- * 4. (16380 log2 < |X| <= 16480 log2) *
- * sinh(X) = sign(X) * exp(|X|)/2. *
- * However, invoking exp(|X|) may cause premature overflow. *
- * Thus, we calculate sinh(X) as follows: *
- * Y := |X| *
- * sgn := sign(X) *
- * sgnFact := sgn * 2**(16380) *
- * Y' := Y - 16381 log2 *
- * sinh(X) := sgnFact * exp(Y'). *
- * Exit. *
- * *
- * 5. (|X| > 16480 log2) sinh(X) must overflow. Return *
- * sign(X)*Huge*Huge to generate overflow and an infinity with *
- * the appropriate sign. Huge is the largest finite number in *
- * extended format. Exit. *
- * *
- *************************************************************************
-
- T1 dc.l $40C62D38,$D3D64634 ; 16381 LOG2 LEAD
- T2 dc.l $3D6F90AE,$B1E75CC7 ; 16381 LOG2 TRAIL
-
- _sinh
- fmove.d (4,sp),fp0
- @sinh
- fmove.x fp0,-(sp)
- move.l (sp),d1
- move.w (4,sp),d1
- move.l d1,a1 ; save (compacted) operand
- lea (12,sp),sp
- and.l #$7FFFFFFF,d1
- cmp.l #$400CB167,d1
- bgt.b .SINHBIG
-
- ;--THIS IS THE USUAL CASE, |X| < 16380 LOG2
- ;--Y = |X|, Z = EXPM1(Y), SINH(X) = SIGN(X)*(1/2)*( Z + Z/(1+Z) )
-
- fabs.x fp0
-
- move.l a1,-(sp) ; {a1}
- jsr @expm1 ; FP0 IS Z = EXPM1(Y)
- move.l (sp)+,a1 ; {a1}
-
- fmove.x fp0,fp1
- fadd.s #$3F800000,fp1 ; 1+Z
- fmove.x fp0,-(sp)
- fdiv.x fp1,fp0 ; Z/(1+Z)
- move.l a1,d1
- and.l #$80000000,d1
- or.l #$3F000000,d1
- fadd.x (sp)+,fp0
- move.l d1,-(sp)
- fmul.s (sp)+,fp0 ; last fp inst - possible exceptions set
- rts
-
- .SINHBIG
- cmp.l #$400CB2B3,d1
- bgt .t_ovfl
-
- fabs.x fp0
- fsub.d (T1,pc),fp0 ; (|X|-16381LOG2_LEAD)
- clr.l -(sp)
- move.l #$80000000,-(sp)
- move.l a1,d1
- and.l #$80000000,d1
- or.l #$7FFB0000,d1
- move.l d1,-(sp) ; EXTENDED FMT
- fsub.d (T2,pc),fp0 ; |X| - 16381 LOG2, ACCURATE
- jsr @exp
- fmul.x (sp)+,fp0 ; possible exception
- .t_ovfl
- rts
-