separate the vars
[AROS.git] / workbench / libs / mathieeedoubtrans / ieeedptanh.c
bloba39b6c3bdc4ca13d56238cbf176725cc31c6a6cd
1 /*
2 Copyright © 1995-2003, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include "mathieeedoubtrans_intern.h"
8 /*****************************************************************************
10 NAME */
12 AROS_LHQUAD1(double, IEEEDPTanh,
14 /* SYNOPSIS */
15 AROS_LHAQUAD(double, y, D0, D1),
17 /* LOCATION */
18 struct MathIeeeDoubTransBase *, MathIeeeDoubTransBase, 12, MathIeeeDoubTrans)
20 /* FUNCTION
21 Calculate hyperbolic tangens of the IEEE double precision number
23 INPUTS
25 RESULT
26 IEEE double precision floating point number
28 flags:
29 zero : result is zero
30 negative : result is negative
31 overflow : (not possible)
33 BUGS
35 INTERNALS
36 ( e^x - e^(-x) )
37 tanh(x) = ----------------
38 ( e^x + e^(-x) )
40 tanh( |x| >= 18 ) = 1
42 *****************************************************************************/
44 AROS_LIBFUNC_INIT
46 QUAD Res;
47 QUAD y2;
48 /* y2 = y & (IEEESPMantisse_Mask + IEEESPExponent_Mask ); */
49 Set_Value64(y2, y);
50 AND64QC
52 y2,
53 (IEEEDPMantisse_Mask_Hi + IEEEDPExponent_Mask_Hi),
54 (IEEEDPMantisse_Mask_Lo + IEEEDPExponent_Mask_Lo)
57 if ( is_geqC(y2, 0x40320000, 0x0) )
59 /*
60 tanh( x > 18 ) = 1
61 tanh( x <-18 ) = -1
63 if ( is_lessSC(y, 0x0, 0x0))
65 SetSR(Negative_Bit, Zero_Bit | Negative_Bit | Overflow_Bit);
66 Set_Value64C(Res, 0xbfefffff, 0xffffffff);
68 else
70 Set_Value64C(Res, 0x3fefffff, 0xffffffff);
72 return Res;
74 /* tanh(-x) = -tanh(x) */
76 QUAD One, tmp1, tmp2;
77 Set_Value64C(One, 0x3ff00000, 0x0);
79 Res = IEEEDPExp(y2);
80 tmp1 = IEEEDPDiv(One, Res);
81 Set_Value64(tmp2, tmp1);
82 OR64QC(tmp2, IEEEDPSign_Mask_Hi, IEEEDPSign_Mask_Lo);
83 Res = IEEEDPDiv
85 IEEEDPAdd(Res, tmp2),
86 IEEEDPAdd(Res, tmp1)
89 /* Result is zero */
90 if (is_eqC(Res, 0x0, 0x0) )
92 if (is_lessSC(y, 0x0, 0x0))
94 SetSR
96 Zero_Bit | Negative_Bit,
97 Zero_Bit | Negative_Bit | Overflow_Bit
100 else
102 SetSR(Zero_Bit, Zero_Bit | Negative_Bit | Overflow_Bit);
104 return Res;
107 /* Argument is negative -> result is negative */
108 if ( is_lessSC(y, 0x0, 0x0))
110 SetSR(Negative_Bit, Zero_Bit | Negative_Bit | Overflow_Bit);
111 OR64QC(Res, IEEEDPSign_Mask_Hi, IEEEDPSign_Mask_Lo);
112 return Res;
115 return Res;
117 AROS_LIBFUNC_EXIT