2005-04-17 02:20:36 +04:00
/* IEEE754 floating point arithmetic
* single precision square root
*/
/*
* MIPS floating point support
* Copyright ( C ) 1994 - 2000 Algorithmics Ltd .
*
* This program is free software ; you can distribute it and / or modify it
* under the terms of the GNU General Public License ( Version 2 ) as
* published by the Free Software Foundation .
*
* This program is distributed in the hope it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License
* for more details .
*
* You should have received a copy of the GNU General Public License along
* with this program ; if not , write to the Free Software Foundation , Inc . ,
2014-04-26 03:49:14 +04:00
* 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA .
2005-04-17 02:20:36 +04:00
*/
# include "ieee754sp.h"
2014-04-16 03:31:11 +04:00
union ieee754sp ieee754sp_sqrt ( union ieee754sp x )
2005-04-17 02:20:36 +04:00
{
int ix , s , q , m , t , i ;
unsigned int r ;
COMPXSP ;
/* take care of Inf and NaN */
EXPLODEXSP ;
2014-04-19 02:36:32 +04:00
ieee754_clearcx ( ) ;
2005-04-17 02:20:36 +04:00
FLUSHXSP ;
/* x == INF or NAN? */
switch ( xc ) {
2015-04-04 01:25:34 +03:00
case IEEE754_CLASS_SNAN :
return ieee754sp_nanxcpt ( x ) ;
2005-04-17 02:20:36 +04:00
case IEEE754_CLASS_QNAN :
/* sqrt(Nan) = Nan */
2015-04-04 01:25:30 +03:00
return x ;
2014-04-26 03:49:14 +04:00
2005-04-17 02:20:36 +04:00
case IEEE754_CLASS_ZERO :
/* sqrt(0) = 0 */
return x ;
2014-04-26 03:49:14 +04:00
2005-04-17 02:20:36 +04:00
case IEEE754_CLASS_INF :
if ( xs ) {
/* sqrt(-Inf) = Nan */
2014-04-19 02:36:32 +04:00
ieee754_setcx ( IEEE754_INVALID_OPERATION ) ;
2015-04-04 01:25:30 +03:00
return ieee754sp_indef ( ) ;
2005-04-17 02:20:36 +04:00
}
/* sqrt(+Inf) = Inf */
return x ;
2014-04-26 03:49:14 +04:00
2005-04-17 02:20:36 +04:00
case IEEE754_CLASS_DNORM :
case IEEE754_CLASS_NORM :
if ( xs ) {
/* sqrt(-x) = Nan */
2014-04-19 02:36:32 +04:00
ieee754_setcx ( IEEE754_INVALID_OPERATION ) ;
2015-04-04 01:25:30 +03:00
return ieee754sp_indef ( ) ;
2005-04-17 02:20:36 +04:00
}
break ;
}
ix = x . bits ;
/* normalize x */
m = ( ix > > 23 ) ;
if ( m = = 0 ) { /* subnormal x */
for ( i = 0 ; ( ix & 0x00800000 ) = = 0 ; i + + )
ix < < = 1 ;
m - = i - 1 ;
}
m - = 127 ; /* unbias exponent */
ix = ( ix & 0x007fffff ) | 0x00800000 ;
if ( m & 1 ) /* odd m, double x to make it even */
ix + = ix ;
m > > = 1 ; /* m = [m/2] */
/* generate sqrt(x) bit by bit */
ix + = ix ;
2017-11-02 14:14:04 +03:00
s = 0 ;
q = 0 ; /* q = sqrt(x) */
2005-04-17 02:20:36 +04:00
r = 0x01000000 ; /* r = moving bit from right to left */
while ( r ! = 0 ) {
t = s + r ;
if ( t < = ix ) {
s = t + r ;
ix - = t ;
q + = r ;
}
ix + = ix ;
r > > = 1 ;
}
if ( ix ! = 0 ) {
2014-04-19 02:36:32 +04:00
ieee754_setcx ( IEEE754_INEXACT ) ;
2005-04-17 02:20:36 +04:00
switch ( ieee754_csr . rm ) {
2014-04-30 13:21:55 +04:00
case FPU_CSR_RU :
2005-04-17 02:20:36 +04:00
q + = 2 ;
break ;
2014-04-30 13:21:55 +04:00
case FPU_CSR_RN :
2005-04-17 02:20:36 +04:00
q + = ( q & 1 ) ;
break ;
}
}
ix = ( q > > 1 ) + 0x3f000000 ;
ix + = ( m < < 23 ) ;
x . bits = ix ;
return x ;
}