Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/parisc/math-emu/dfsqrt.c
26288 views
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) <[email protected]>
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
}
183
184