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