18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Linux/PA-RISC Project (http://www.parisc-linux.org/) 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Floating-point emulation code 68c2ecf20Sopenharmony_ci * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci/* 98c2ecf20Sopenharmony_ci * BEGIN_DESC 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * File: 128c2ecf20Sopenharmony_ci * @(#) pa/spmath/sfsqrt.c $Revision: 1.1 $ 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * Purpose: 158c2ecf20Sopenharmony_ci * Single Floating-point Square Root 168c2ecf20Sopenharmony_ci * 178c2ecf20Sopenharmony_ci * External Interfaces: 188c2ecf20Sopenharmony_ci * sgl_fsqrt(srcptr,nullptr,dstptr,status) 198c2ecf20Sopenharmony_ci * 208c2ecf20Sopenharmony_ci * Internal Interfaces: 218c2ecf20Sopenharmony_ci * 228c2ecf20Sopenharmony_ci * Theory: 238c2ecf20Sopenharmony_ci * <<please update with a overview of the operation of this file>> 248c2ecf20Sopenharmony_ci * 258c2ecf20Sopenharmony_ci * END_DESC 268c2ecf20Sopenharmony_ci*/ 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#include "float.h" 308c2ecf20Sopenharmony_ci#include "sgl_float.h" 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci/* 338c2ecf20Sopenharmony_ci * Single Floating-point Square Root 348c2ecf20Sopenharmony_ci */ 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci/*ARGSUSED*/ 378c2ecf20Sopenharmony_ciunsigned int 388c2ecf20Sopenharmony_cisgl_fsqrt( 398c2ecf20Sopenharmony_ci sgl_floating_point *srcptr, 408c2ecf20Sopenharmony_ci unsigned int *nullptr, 418c2ecf20Sopenharmony_ci sgl_floating_point *dstptr, 428c2ecf20Sopenharmony_ci unsigned int *status) 438c2ecf20Sopenharmony_ci{ 448c2ecf20Sopenharmony_ci register unsigned int src, result; 458c2ecf20Sopenharmony_ci register int src_exponent; 468c2ecf20Sopenharmony_ci register unsigned int newbit, sum; 478c2ecf20Sopenharmony_ci register boolean guardbit = FALSE, even_exponent; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci src = *srcptr; 508c2ecf20Sopenharmony_ci /* 518c2ecf20Sopenharmony_ci * check source operand for NaN or infinity 528c2ecf20Sopenharmony_ci */ 538c2ecf20Sopenharmony_ci if ((src_exponent = Sgl_exponent(src)) == SGL_INFINITY_EXPONENT) { 548c2ecf20Sopenharmony_ci /* 558c2ecf20Sopenharmony_ci * is signaling NaN? 568c2ecf20Sopenharmony_ci */ 578c2ecf20Sopenharmony_ci if (Sgl_isone_signaling(src)) { 588c2ecf20Sopenharmony_ci /* trap if INVALIDTRAP enabled */ 598c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); 608c2ecf20Sopenharmony_ci /* make NaN quiet */ 618c2ecf20Sopenharmony_ci Set_invalidflag(); 628c2ecf20Sopenharmony_ci Sgl_set_quiet(src); 638c2ecf20Sopenharmony_ci } 648c2ecf20Sopenharmony_ci /* 658c2ecf20Sopenharmony_ci * Return quiet NaN or positive infinity. 668c2ecf20Sopenharmony_ci * Fall through to negative test if negative infinity. 678c2ecf20Sopenharmony_ci */ 688c2ecf20Sopenharmony_ci if (Sgl_iszero_sign(src) || Sgl_isnotzero_mantissa(src)) { 698c2ecf20Sopenharmony_ci *dstptr = src; 708c2ecf20Sopenharmony_ci return(NOEXCEPTION); 718c2ecf20Sopenharmony_ci } 728c2ecf20Sopenharmony_ci } 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci /* 758c2ecf20Sopenharmony_ci * check for zero source operand 768c2ecf20Sopenharmony_ci */ 778c2ecf20Sopenharmony_ci if (Sgl_iszero_exponentmantissa(src)) { 788c2ecf20Sopenharmony_ci *dstptr = src; 798c2ecf20Sopenharmony_ci return(NOEXCEPTION); 808c2ecf20Sopenharmony_ci } 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci /* 838c2ecf20Sopenharmony_ci * check for negative source operand 848c2ecf20Sopenharmony_ci */ 858c2ecf20Sopenharmony_ci if (Sgl_isone_sign(src)) { 868c2ecf20Sopenharmony_ci /* trap if INVALIDTRAP enabled */ 878c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); 888c2ecf20Sopenharmony_ci /* make NaN quiet */ 898c2ecf20Sopenharmony_ci Set_invalidflag(); 908c2ecf20Sopenharmony_ci Sgl_makequietnan(src); 918c2ecf20Sopenharmony_ci *dstptr = src; 928c2ecf20Sopenharmony_ci return(NOEXCEPTION); 938c2ecf20Sopenharmony_ci } 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci /* 968c2ecf20Sopenharmony_ci * Generate result 978c2ecf20Sopenharmony_ci */ 988c2ecf20Sopenharmony_ci if (src_exponent > 0) { 998c2ecf20Sopenharmony_ci even_exponent = Sgl_hidden(src); 1008c2ecf20Sopenharmony_ci Sgl_clear_signexponent_set_hidden(src); 1018c2ecf20Sopenharmony_ci } 1028c2ecf20Sopenharmony_ci else { 1038c2ecf20Sopenharmony_ci /* normalize operand */ 1048c2ecf20Sopenharmony_ci Sgl_clear_signexponent(src); 1058c2ecf20Sopenharmony_ci src_exponent++; 1068c2ecf20Sopenharmony_ci Sgl_normalize(src,src_exponent); 1078c2ecf20Sopenharmony_ci even_exponent = src_exponent & 1; 1088c2ecf20Sopenharmony_ci } 1098c2ecf20Sopenharmony_ci if (even_exponent) { 1108c2ecf20Sopenharmony_ci /* exponent is even */ 1118c2ecf20Sopenharmony_ci /* Add comment here. Explain why odd exponent needs correction */ 1128c2ecf20Sopenharmony_ci Sgl_leftshiftby1(src); 1138c2ecf20Sopenharmony_ci } 1148c2ecf20Sopenharmony_ci /* 1158c2ecf20Sopenharmony_ci * Add comment here. Explain following algorithm. 1168c2ecf20Sopenharmony_ci * 1178c2ecf20Sopenharmony_ci * Trust me, it works. 1188c2ecf20Sopenharmony_ci * 1198c2ecf20Sopenharmony_ci */ 1208c2ecf20Sopenharmony_ci Sgl_setzero(result); 1218c2ecf20Sopenharmony_ci newbit = 1 << SGL_P; 1228c2ecf20Sopenharmony_ci while (newbit && Sgl_isnotzero(src)) { 1238c2ecf20Sopenharmony_ci Sgl_addition(result,newbit,sum); 1248c2ecf20Sopenharmony_ci if(sum <= Sgl_all(src)) { 1258c2ecf20Sopenharmony_ci /* update result */ 1268c2ecf20Sopenharmony_ci Sgl_addition(result,(newbit<<1),result); 1278c2ecf20Sopenharmony_ci Sgl_subtract(src,sum,src); 1288c2ecf20Sopenharmony_ci } 1298c2ecf20Sopenharmony_ci Sgl_rightshiftby1(newbit); 1308c2ecf20Sopenharmony_ci Sgl_leftshiftby1(src); 1318c2ecf20Sopenharmony_ci } 1328c2ecf20Sopenharmony_ci /* correct exponent for pre-shift */ 1338c2ecf20Sopenharmony_ci if (even_exponent) { 1348c2ecf20Sopenharmony_ci Sgl_rightshiftby1(result); 1358c2ecf20Sopenharmony_ci } 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci /* check for inexact */ 1388c2ecf20Sopenharmony_ci if (Sgl_isnotzero(src)) { 1398c2ecf20Sopenharmony_ci if (!even_exponent && Sgl_islessthan(result,src)) 1408c2ecf20Sopenharmony_ci Sgl_increment(result); 1418c2ecf20Sopenharmony_ci guardbit = Sgl_lowmantissa(result); 1428c2ecf20Sopenharmony_ci Sgl_rightshiftby1(result); 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci /* now round result */ 1458c2ecf20Sopenharmony_ci switch (Rounding_mode()) { 1468c2ecf20Sopenharmony_ci case ROUNDPLUS: 1478c2ecf20Sopenharmony_ci Sgl_increment(result); 1488c2ecf20Sopenharmony_ci break; 1498c2ecf20Sopenharmony_ci case ROUNDNEAREST: 1508c2ecf20Sopenharmony_ci /* stickybit is always true, so guardbit 1518c2ecf20Sopenharmony_ci * is enough to determine rounding */ 1528c2ecf20Sopenharmony_ci if (guardbit) { 1538c2ecf20Sopenharmony_ci Sgl_increment(result); 1548c2ecf20Sopenharmony_ci } 1558c2ecf20Sopenharmony_ci break; 1568c2ecf20Sopenharmony_ci } 1578c2ecf20Sopenharmony_ci /* increment result exponent by 1 if mantissa overflowed */ 1588c2ecf20Sopenharmony_ci if (Sgl_isone_hiddenoverflow(result)) src_exponent+=2; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci if (Is_inexacttrap_enabled()) { 1618c2ecf20Sopenharmony_ci Sgl_set_exponent(result, 1628c2ecf20Sopenharmony_ci ((src_exponent-SGL_BIAS)>>1)+SGL_BIAS); 1638c2ecf20Sopenharmony_ci *dstptr = result; 1648c2ecf20Sopenharmony_ci return(INEXACTEXCEPTION); 1658c2ecf20Sopenharmony_ci } 1668c2ecf20Sopenharmony_ci else Set_inexactflag(); 1678c2ecf20Sopenharmony_ci } 1688c2ecf20Sopenharmony_ci else { 1698c2ecf20Sopenharmony_ci Sgl_rightshiftby1(result); 1708c2ecf20Sopenharmony_ci } 1718c2ecf20Sopenharmony_ci Sgl_set_exponent(result,((src_exponent-SGL_BIAS)>>1)+SGL_BIAS); 1728c2ecf20Sopenharmony_ci *dstptr = result; 1738c2ecf20Sopenharmony_ci return(NOEXCEPTION); 1748c2ecf20Sopenharmony_ci} 175