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/dfsqrt.c $Revision: 1.1 $ 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * Purpose: 158c2ecf20Sopenharmony_ci * Double Floating-point Square Root 168c2ecf20Sopenharmony_ci * 178c2ecf20Sopenharmony_ci * External Interfaces: 188c2ecf20Sopenharmony_ci * dbl_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 "dbl_float.h" 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci/* 338c2ecf20Sopenharmony_ci * Double Floating-point Square Root 348c2ecf20Sopenharmony_ci */ 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci/*ARGSUSED*/ 378c2ecf20Sopenharmony_ciunsigned int 388c2ecf20Sopenharmony_cidbl_fsqrt( 398c2ecf20Sopenharmony_ci dbl_floating_point *srcptr, 408c2ecf20Sopenharmony_ci unsigned int *nullptr, 418c2ecf20Sopenharmony_ci dbl_floating_point *dstptr, 428c2ecf20Sopenharmony_ci unsigned int *status) 438c2ecf20Sopenharmony_ci{ 448c2ecf20Sopenharmony_ci register unsigned int srcp1, srcp2, resultp1, resultp2; 458c2ecf20Sopenharmony_ci register unsigned int newbitp1, newbitp2, sump1, sump2; 468c2ecf20Sopenharmony_ci register int src_exponent; 478c2ecf20Sopenharmony_ci register boolean guardbit = FALSE, even_exponent; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci Dbl_copyfromptr(srcptr,srcp1,srcp2); 508c2ecf20Sopenharmony_ci /* 518c2ecf20Sopenharmony_ci * check source operand for NaN or infinity 528c2ecf20Sopenharmony_ci */ 538c2ecf20Sopenharmony_ci if ((src_exponent = Dbl_exponent(srcp1)) == DBL_INFINITY_EXPONENT) { 548c2ecf20Sopenharmony_ci /* 558c2ecf20Sopenharmony_ci * is signaling NaN? 568c2ecf20Sopenharmony_ci */ 578c2ecf20Sopenharmony_ci if (Dbl_isone_signaling(srcp1)) { 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 Dbl_set_quiet(srcp1); 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 (Dbl_iszero_sign(srcp1) || 698c2ecf20Sopenharmony_ci Dbl_isnotzero_mantissa(srcp1,srcp2)) { 708c2ecf20Sopenharmony_ci Dbl_copytoptr(srcp1,srcp2,dstptr); 718c2ecf20Sopenharmony_ci return(NOEXCEPTION); 728c2ecf20Sopenharmony_ci } 738c2ecf20Sopenharmony_ci } 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci /* 768c2ecf20Sopenharmony_ci * check for zero source operand 778c2ecf20Sopenharmony_ci */ 788c2ecf20Sopenharmony_ci if (Dbl_iszero_exponentmantissa(srcp1,srcp2)) { 798c2ecf20Sopenharmony_ci Dbl_copytoptr(srcp1,srcp2,dstptr); 808c2ecf20Sopenharmony_ci return(NOEXCEPTION); 818c2ecf20Sopenharmony_ci } 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci /* 848c2ecf20Sopenharmony_ci * check for negative source operand 858c2ecf20Sopenharmony_ci */ 868c2ecf20Sopenharmony_ci if (Dbl_isone_sign(srcp1)) { 878c2ecf20Sopenharmony_ci /* trap if INVALIDTRAP enabled */ 888c2ecf20Sopenharmony_ci if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); 898c2ecf20Sopenharmony_ci /* make NaN quiet */ 908c2ecf20Sopenharmony_ci Set_invalidflag(); 918c2ecf20Sopenharmony_ci Dbl_makequietnan(srcp1,srcp2); 928c2ecf20Sopenharmony_ci Dbl_copytoptr(srcp1,srcp2,dstptr); 938c2ecf20Sopenharmony_ci return(NOEXCEPTION); 948c2ecf20Sopenharmony_ci } 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci /* 978c2ecf20Sopenharmony_ci * Generate result 988c2ecf20Sopenharmony_ci */ 998c2ecf20Sopenharmony_ci if (src_exponent > 0) { 1008c2ecf20Sopenharmony_ci even_exponent = Dbl_hidden(srcp1); 1018c2ecf20Sopenharmony_ci Dbl_clear_signexponent_set_hidden(srcp1); 1028c2ecf20Sopenharmony_ci } 1038c2ecf20Sopenharmony_ci else { 1048c2ecf20Sopenharmony_ci /* normalize operand */ 1058c2ecf20Sopenharmony_ci Dbl_clear_signexponent(srcp1); 1068c2ecf20Sopenharmony_ci src_exponent++; 1078c2ecf20Sopenharmony_ci Dbl_normalize(srcp1,srcp2,src_exponent); 1088c2ecf20Sopenharmony_ci even_exponent = src_exponent & 1; 1098c2ecf20Sopenharmony_ci } 1108c2ecf20Sopenharmony_ci if (even_exponent) { 1118c2ecf20Sopenharmony_ci /* exponent is even */ 1128c2ecf20Sopenharmony_ci /* Add comment here. Explain why odd exponent needs correction */ 1138c2ecf20Sopenharmony_ci Dbl_leftshiftby1(srcp1,srcp2); 1148c2ecf20Sopenharmony_ci } 1158c2ecf20Sopenharmony_ci /* 1168c2ecf20Sopenharmony_ci * Add comment here. Explain following algorithm. 1178c2ecf20Sopenharmony_ci * 1188c2ecf20Sopenharmony_ci * Trust me, it works. 1198c2ecf20Sopenharmony_ci * 1208c2ecf20Sopenharmony_ci */ 1218c2ecf20Sopenharmony_ci Dbl_setzero(resultp1,resultp2); 1228c2ecf20Sopenharmony_ci Dbl_allp1(newbitp1) = 1 << (DBL_P - 32); 1238c2ecf20Sopenharmony_ci Dbl_setzero_mantissap2(newbitp2); 1248c2ecf20Sopenharmony_ci while (Dbl_isnotzero(newbitp1,newbitp2) && Dbl_isnotzero(srcp1,srcp2)) { 1258c2ecf20Sopenharmony_ci Dbl_addition(resultp1,resultp2,newbitp1,newbitp2,sump1,sump2); 1268c2ecf20Sopenharmony_ci if(Dbl_isnotgreaterthan(sump1,sump2,srcp1,srcp2)) { 1278c2ecf20Sopenharmony_ci Dbl_leftshiftby1(newbitp1,newbitp2); 1288c2ecf20Sopenharmony_ci /* update result */ 1298c2ecf20Sopenharmony_ci Dbl_addition(resultp1,resultp2,newbitp1,newbitp2, 1308c2ecf20Sopenharmony_ci resultp1,resultp2); 1318c2ecf20Sopenharmony_ci Dbl_subtract(srcp1,srcp2,sump1,sump2,srcp1,srcp2); 1328c2ecf20Sopenharmony_ci Dbl_rightshiftby2(newbitp1,newbitp2); 1338c2ecf20Sopenharmony_ci } 1348c2ecf20Sopenharmony_ci else { 1358c2ecf20Sopenharmony_ci Dbl_rightshiftby1(newbitp1,newbitp2); 1368c2ecf20Sopenharmony_ci } 1378c2ecf20Sopenharmony_ci Dbl_leftshiftby1(srcp1,srcp2); 1388c2ecf20Sopenharmony_ci } 1398c2ecf20Sopenharmony_ci /* correct exponent for pre-shift */ 1408c2ecf20Sopenharmony_ci if (even_exponent) { 1418c2ecf20Sopenharmony_ci Dbl_rightshiftby1(resultp1,resultp2); 1428c2ecf20Sopenharmony_ci } 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci /* check for inexact */ 1458c2ecf20Sopenharmony_ci if (Dbl_isnotzero(srcp1,srcp2)) { 1468c2ecf20Sopenharmony_ci if (!even_exponent && Dbl_islessthan(resultp1,resultp2,srcp1,srcp2)) { 1478c2ecf20Sopenharmony_ci Dbl_increment(resultp1,resultp2); 1488c2ecf20Sopenharmony_ci } 1498c2ecf20Sopenharmony_ci guardbit = Dbl_lowmantissap2(resultp2); 1508c2ecf20Sopenharmony_ci Dbl_rightshiftby1(resultp1,resultp2); 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci /* now round result */ 1538c2ecf20Sopenharmony_ci switch (Rounding_mode()) { 1548c2ecf20Sopenharmony_ci case ROUNDPLUS: 1558c2ecf20Sopenharmony_ci Dbl_increment(resultp1,resultp2); 1568c2ecf20Sopenharmony_ci break; 1578c2ecf20Sopenharmony_ci case ROUNDNEAREST: 1588c2ecf20Sopenharmony_ci /* stickybit is always true, so guardbit 1598c2ecf20Sopenharmony_ci * is enough to determine rounding */ 1608c2ecf20Sopenharmony_ci if (guardbit) { 1618c2ecf20Sopenharmony_ci Dbl_increment(resultp1,resultp2); 1628c2ecf20Sopenharmony_ci } 1638c2ecf20Sopenharmony_ci break; 1648c2ecf20Sopenharmony_ci } 1658c2ecf20Sopenharmony_ci /* increment result exponent by 1 if mantissa overflowed */ 1668c2ecf20Sopenharmony_ci if (Dbl_isone_hiddenoverflow(resultp1)) src_exponent+=2; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci if (Is_inexacttrap_enabled()) { 1698c2ecf20Sopenharmony_ci Dbl_set_exponent(resultp1, 1708c2ecf20Sopenharmony_ci ((src_exponent-DBL_BIAS)>>1)+DBL_BIAS); 1718c2ecf20Sopenharmony_ci Dbl_copytoptr(resultp1,resultp2,dstptr); 1728c2ecf20Sopenharmony_ci return(INEXACTEXCEPTION); 1738c2ecf20Sopenharmony_ci } 1748c2ecf20Sopenharmony_ci else Set_inexactflag(); 1758c2ecf20Sopenharmony_ci } 1768c2ecf20Sopenharmony_ci else { 1778c2ecf20Sopenharmony_ci Dbl_rightshiftby1(resultp1,resultp2); 1788c2ecf20Sopenharmony_ci } 1798c2ecf20Sopenharmony_ci Dbl_set_exponent(resultp1,((src_exponent-DBL_BIAS)>>1)+DBL_BIAS); 1808c2ecf20Sopenharmony_ci Dbl_copytoptr(resultp1,resultp2,dstptr); 1818c2ecf20Sopenharmony_ci return(NOEXCEPTION); 1828c2ecf20Sopenharmony_ci} 183