Linux-libre 5.4.49-gnu
[librecmc/linux-libre.git] / arch / parisc / math-emu / dfsqrt.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Linux/PA-RISC Project (http://www.parisc-linux.org/)
4  *
5  * Floating-point emulation code
6  *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
7  */
8 /*
9  * BEGIN_DESC
10  *
11  *  File:
12  *      @(#)    pa/spmath/dfsqrt.c              $Revision: 1.1 $
13  *
14  *  Purpose:
15  *      Double Floating-point Square Root
16  *
17  *  External Interfaces:
18  *      dbl_fsqrt(srcptr,nullptr,dstptr,status)
19  *
20  *  Internal Interfaces:
21  *
22  *  Theory:
23  *      <<please update with a overview of the operation of this file>>
24  *
25  * END_DESC
26 */
27
28
29 #include "float.h"
30 #include "dbl_float.h"
31
32 /*
33  *  Double Floating-point Square Root
34  */
35
36 /*ARGSUSED*/
37 unsigned int
38 dbl_fsqrt(
39             dbl_floating_point *srcptr,
40             unsigned int *nullptr,
41             dbl_floating_point *dstptr,
42             unsigned int *status)
43 {
44         register unsigned int srcp1, srcp2, resultp1, resultp2;
45         register unsigned int newbitp1, newbitp2, sump1, sump2;
46         register int src_exponent;
47         register boolean guardbit = FALSE, even_exponent;
48
49         Dbl_copyfromptr(srcptr,srcp1,srcp2);
50         /*
51          * check source operand for NaN or infinity
52          */
53         if ((src_exponent = Dbl_exponent(srcp1)) == DBL_INFINITY_EXPONENT) {
54                 /*
55                  * is signaling NaN?
56                  */
57                 if (Dbl_isone_signaling(srcp1)) {
58                         /* trap if INVALIDTRAP enabled */
59                         if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
60                         /* make NaN quiet */
61                         Set_invalidflag();
62                         Dbl_set_quiet(srcp1);
63                 }
64                 /*
65                  * Return quiet NaN or positive infinity.
66                  *  Fall through to negative test if negative infinity.
67                  */
68                 if (Dbl_iszero_sign(srcp1) || 
69                     Dbl_isnotzero_mantissa(srcp1,srcp2)) {
70                         Dbl_copytoptr(srcp1,srcp2,dstptr);
71                         return(NOEXCEPTION);
72                 }
73         }
74
75         /*
76          * check for zero source operand
77          */
78         if (Dbl_iszero_exponentmantissa(srcp1,srcp2)) {
79                 Dbl_copytoptr(srcp1,srcp2,dstptr);
80                 return(NOEXCEPTION);
81         }
82
83         /*
84          * check for negative source operand 
85          */
86         if (Dbl_isone_sign(srcp1)) {
87                 /* trap if INVALIDTRAP enabled */
88                 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
89                 /* make NaN quiet */
90                 Set_invalidflag();
91                 Dbl_makequietnan(srcp1,srcp2);
92                 Dbl_copytoptr(srcp1,srcp2,dstptr);
93                 return(NOEXCEPTION);
94         }
95
96         /*
97          * Generate result
98          */
99         if (src_exponent > 0) {
100                 even_exponent = Dbl_hidden(srcp1);
101                 Dbl_clear_signexponent_set_hidden(srcp1);
102         }
103         else {
104                 /* normalize operand */
105                 Dbl_clear_signexponent(srcp1);
106                 src_exponent++;
107                 Dbl_normalize(srcp1,srcp2,src_exponent);
108                 even_exponent = src_exponent & 1;
109         }
110         if (even_exponent) {
111                 /* exponent is even */
112                 /* Add comment here.  Explain why odd exponent needs correction */
113                 Dbl_leftshiftby1(srcp1,srcp2);
114         }
115         /*
116          * Add comment here.  Explain following algorithm.
117          * 
118          * Trust me, it works.
119          *
120          */
121         Dbl_setzero(resultp1,resultp2);
122         Dbl_allp1(newbitp1) = 1 << (DBL_P - 32);
123         Dbl_setzero_mantissap2(newbitp2);
124         while (Dbl_isnotzero(newbitp1,newbitp2) && Dbl_isnotzero(srcp1,srcp2)) {
125                 Dbl_addition(resultp1,resultp2,newbitp1,newbitp2,sump1,sump2);
126                 if(Dbl_isnotgreaterthan(sump1,sump2,srcp1,srcp2)) {
127                         Dbl_leftshiftby1(newbitp1,newbitp2);
128                         /* update result */
129                         Dbl_addition(resultp1,resultp2,newbitp1,newbitp2,
130                          resultp1,resultp2);  
131                         Dbl_subtract(srcp1,srcp2,sump1,sump2,srcp1,srcp2);
132                         Dbl_rightshiftby2(newbitp1,newbitp2);
133                 }
134                 else {
135                         Dbl_rightshiftby1(newbitp1,newbitp2);
136                 }
137                 Dbl_leftshiftby1(srcp1,srcp2);
138         }
139         /* correct exponent for pre-shift */
140         if (even_exponent) {
141                 Dbl_rightshiftby1(resultp1,resultp2);
142         }
143
144         /* check for inexact */
145         if (Dbl_isnotzero(srcp1,srcp2)) {
146                 if (!even_exponent && Dbl_islessthan(resultp1,resultp2,srcp1,srcp2)) {
147                         Dbl_increment(resultp1,resultp2);
148                 }
149                 guardbit = Dbl_lowmantissap2(resultp2);
150                 Dbl_rightshiftby1(resultp1,resultp2);
151
152                 /*  now round result  */
153                 switch (Rounding_mode()) {
154                 case ROUNDPLUS:
155                      Dbl_increment(resultp1,resultp2);
156                      break;
157                 case ROUNDNEAREST:
158                      /* stickybit is always true, so guardbit 
159                       * is enough to determine rounding */
160                      if (guardbit) {
161                             Dbl_increment(resultp1,resultp2);
162                      }
163                      break;
164                 }
165                 /* increment result exponent by 1 if mantissa overflowed */
166                 if (Dbl_isone_hiddenoverflow(resultp1)) src_exponent+=2;
167
168                 if (Is_inexacttrap_enabled()) {
169                         Dbl_set_exponent(resultp1,
170                          ((src_exponent-DBL_BIAS)>>1)+DBL_BIAS);
171                         Dbl_copytoptr(resultp1,resultp2,dstptr);
172                         return(INEXACTEXCEPTION);
173                 }
174                 else Set_inexactflag();
175         }
176         else {
177                 Dbl_rightshiftby1(resultp1,resultp2);
178         }
179         Dbl_set_exponent(resultp1,((src_exponent-DBL_BIAS)>>1)+DBL_BIAS);
180         Dbl_copytoptr(resultp1,resultp2,dstptr);
181         return(NOEXCEPTION);
182 }