Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/parisc/math-emu/sfsqrt.c
10817 views
1
/*
2
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
3
*
4
* Floating-point emulation code
5
* Copyright (C) 2001 Hewlett-Packard (Paul Bame) <[email protected]>
6
*
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2, or (at your option)
10
* any later version.
11
*
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
16
*
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
*/
21
/*
22
* BEGIN_DESC
23
*
24
* File:
25
* @(#) pa/spmath/sfsqrt.c $Revision: 1.1 $
26
*
27
* Purpose:
28
* Single Floating-point Square Root
29
*
30
* External Interfaces:
31
* sgl_fsqrt(srcptr,nullptr,dstptr,status)
32
*
33
* Internal Interfaces:
34
*
35
* Theory:
36
* <<please update with a overview of the operation of this file>>
37
*
38
* END_DESC
39
*/
40
41
42
#include "float.h"
43
#include "sgl_float.h"
44
45
/*
46
* Single Floating-point Square Root
47
*/
48
49
/*ARGSUSED*/
50
unsigned int
51
sgl_fsqrt(
52
sgl_floating_point *srcptr,
53
unsigned int *nullptr,
54
sgl_floating_point *dstptr,
55
unsigned int *status)
56
{
57
register unsigned int src, result;
58
register int src_exponent;
59
register unsigned int newbit, sum;
60
register boolean guardbit = FALSE, even_exponent;
61
62
src = *srcptr;
63
/*
64
* check source operand for NaN or infinity
65
*/
66
if ((src_exponent = Sgl_exponent(src)) == SGL_INFINITY_EXPONENT) {
67
/*
68
* is signaling NaN?
69
*/
70
if (Sgl_isone_signaling(src)) {
71
/* trap if INVALIDTRAP enabled */
72
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
73
/* make NaN quiet */
74
Set_invalidflag();
75
Sgl_set_quiet(src);
76
}
77
/*
78
* Return quiet NaN or positive infinity.
79
* Fall through to negative test if negative infinity.
80
*/
81
if (Sgl_iszero_sign(src) || Sgl_isnotzero_mantissa(src)) {
82
*dstptr = src;
83
return(NOEXCEPTION);
84
}
85
}
86
87
/*
88
* check for zero source operand
89
*/
90
if (Sgl_iszero_exponentmantissa(src)) {
91
*dstptr = src;
92
return(NOEXCEPTION);
93
}
94
95
/*
96
* check for negative source operand
97
*/
98
if (Sgl_isone_sign(src)) {
99
/* trap if INVALIDTRAP enabled */
100
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
101
/* make NaN quiet */
102
Set_invalidflag();
103
Sgl_makequietnan(src);
104
*dstptr = src;
105
return(NOEXCEPTION);
106
}
107
108
/*
109
* Generate result
110
*/
111
if (src_exponent > 0) {
112
even_exponent = Sgl_hidden(src);
113
Sgl_clear_signexponent_set_hidden(src);
114
}
115
else {
116
/* normalize operand */
117
Sgl_clear_signexponent(src);
118
src_exponent++;
119
Sgl_normalize(src,src_exponent);
120
even_exponent = src_exponent & 1;
121
}
122
if (even_exponent) {
123
/* exponent is even */
124
/* Add comment here. Explain why odd exponent needs correction */
125
Sgl_leftshiftby1(src);
126
}
127
/*
128
* Add comment here. Explain following algorithm.
129
*
130
* Trust me, it works.
131
*
132
*/
133
Sgl_setzero(result);
134
newbit = 1 << SGL_P;
135
while (newbit && Sgl_isnotzero(src)) {
136
Sgl_addition(result,newbit,sum);
137
if(sum <= Sgl_all(src)) {
138
/* update result */
139
Sgl_addition(result,(newbit<<1),result);
140
Sgl_subtract(src,sum,src);
141
}
142
Sgl_rightshiftby1(newbit);
143
Sgl_leftshiftby1(src);
144
}
145
/* correct exponent for pre-shift */
146
if (even_exponent) {
147
Sgl_rightshiftby1(result);
148
}
149
150
/* check for inexact */
151
if (Sgl_isnotzero(src)) {
152
if (!even_exponent && Sgl_islessthan(result,src))
153
Sgl_increment(result);
154
guardbit = Sgl_lowmantissa(result);
155
Sgl_rightshiftby1(result);
156
157
/* now round result */
158
switch (Rounding_mode()) {
159
case ROUNDPLUS:
160
Sgl_increment(result);
161
break;
162
case ROUNDNEAREST:
163
/* stickybit is always true, so guardbit
164
* is enough to determine rounding */
165
if (guardbit) {
166
Sgl_increment(result);
167
}
168
break;
169
}
170
/* increment result exponent by 1 if mantissa overflowed */
171
if (Sgl_isone_hiddenoverflow(result)) src_exponent+=2;
172
173
if (Is_inexacttrap_enabled()) {
174
Sgl_set_exponent(result,
175
((src_exponent-SGL_BIAS)>>1)+SGL_BIAS);
176
*dstptr = result;
177
return(INEXACTEXCEPTION);
178
}
179
else Set_inexactflag();
180
}
181
else {
182
Sgl_rightshiftby1(result);
183
}
184
Sgl_set_exponent(result,((src_exponent-SGL_BIAS)>>1)+SGL_BIAS);
185
*dstptr = result;
186
return(NOEXCEPTION);
187
}
188
189