1 1.6 christos /* $NetBSD: sfsqrt.c,v 1.6 2016/02/29 18:20:31 christos Exp $ */ 2 1.1 fredette 3 1.1 fredette /* $OpenBSD: sfsqrt.c,v 1.5 2001/03/29 03:58:19 mickey Exp $ */ 4 1.1 fredette 5 1.1 fredette /* 6 1.1 fredette * Copyright 1996 1995 by Open Software Foundation, Inc. 7 1.1 fredette * All Rights Reserved 8 1.1 fredette * 9 1.1 fredette * Permission to use, copy, modify, and distribute this software and 10 1.1 fredette * its documentation for any purpose and without fee is hereby granted, 11 1.1 fredette * provided that the above copyright notice appears in all copies and 12 1.1 fredette * that both the copyright notice and this permission notice appear in 13 1.1 fredette * supporting documentation. 14 1.1 fredette * 15 1.1 fredette * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE 16 1.1 fredette * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 17 1.1 fredette * FOR A PARTICULAR PURPOSE. 18 1.1 fredette * 19 1.1 fredette * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR 20 1.1 fredette * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 21 1.1 fredette * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, 22 1.1 fredette * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 23 1.1 fredette * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 24 1.1 fredette * 25 1.1 fredette */ 26 1.1 fredette /* 27 1.1 fredette * pmk1.1 28 1.1 fredette */ 29 1.1 fredette /* 30 1.1 fredette * (c) Copyright 1986 HEWLETT-PACKARD COMPANY 31 1.1 fredette * 32 1.1 fredette * To anyone who acknowledges that this file is provided "AS IS" 33 1.1 fredette * without any express or implied warranty: 34 1.1 fredette * permission to use, copy, modify, and distribute this file 35 1.1 fredette * for any purpose is hereby granted without fee, provided that 36 1.1 fredette * the above copyright notice and this notice appears in all 37 1.1 fredette * copies, and that the name of Hewlett-Packard Company not be 38 1.1 fredette * used in advertising or publicity pertaining to distribution 39 1.1 fredette * of the software without specific, written prior permission. 40 1.1 fredette * Hewlett-Packard Company makes no representations about the 41 1.1 fredette * suitability of this software for any purpose. 42 1.1 fredette */ 43 1.2 lukem 44 1.2 lukem #include <sys/cdefs.h> 45 1.6 christos __KERNEL_RCSID(0, "$NetBSD: sfsqrt.c,v 1.6 2016/02/29 18:20:31 christos Exp $"); 46 1.1 fredette 47 1.1 fredette #include "../spmath/float.h" 48 1.1 fredette #include "../spmath/sgl_float.h" 49 1.1 fredette 50 1.1 fredette /* 51 1.1 fredette * Single Floating-point Square Root 52 1.1 fredette */ 53 1.1 fredette 54 1.1 fredette /*ARGSUSED*/ 55 1.1 fredette int 56 1.5 skrll sgl_fsqrt(sgl_floating_point *srcptr, sgl_floating_point *dstptr, 57 1.5 skrll unsigned int *status) 58 1.1 fredette { 59 1.1 fredette register unsigned int src, result; 60 1.1 fredette register int src_exponent, newbit, sum; 61 1.4 thorpej register int guardbit = false, even_exponent; 62 1.1 fredette 63 1.1 fredette src = *srcptr; 64 1.1 fredette /* 65 1.1 fredette * check source operand for NaN or infinity 66 1.1 fredette */ 67 1.1 fredette if ((src_exponent = Sgl_exponent(src)) == SGL_INFINITY_EXPONENT) { 68 1.1 fredette /* 69 1.1 fredette * is signaling NaN? 70 1.1 fredette */ 71 1.1 fredette if (Sgl_isone_signaling(src)) { 72 1.1 fredette /* trap if INVALIDTRAP enabled */ 73 1.1 fredette if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); 74 1.1 fredette /* make NaN quiet */ 75 1.1 fredette Set_invalidflag(); 76 1.1 fredette Sgl_set_quiet(src); 77 1.1 fredette } 78 1.1 fredette /* 79 1.1 fredette * Return quiet NaN or positive infinity. 80 1.1 fredette * Fall thru to negative test if negative infinity. 81 1.1 fredette */ 82 1.1 fredette if (Sgl_iszero_sign(src) || Sgl_isnotzero_mantissa(src)) { 83 1.1 fredette *dstptr = src; 84 1.1 fredette return(NOEXCEPTION); 85 1.1 fredette } 86 1.1 fredette } 87 1.1 fredette 88 1.1 fredette /* 89 1.1 fredette * check for zero source operand 90 1.1 fredette */ 91 1.1 fredette if (Sgl_iszero_exponentmantissa(src)) { 92 1.1 fredette *dstptr = src; 93 1.1 fredette return(NOEXCEPTION); 94 1.1 fredette } 95 1.1 fredette 96 1.1 fredette /* 97 1.1 fredette * check for negative source operand 98 1.1 fredette */ 99 1.1 fredette if (Sgl_isone_sign(src)) { 100 1.1 fredette /* trap if INVALIDTRAP enabled */ 101 1.1 fredette if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); 102 1.1 fredette /* make NaN quiet */ 103 1.1 fredette Set_invalidflag(); 104 1.1 fredette Sgl_makequietnan(src); 105 1.1 fredette *dstptr = src; 106 1.1 fredette return(NOEXCEPTION); 107 1.1 fredette } 108 1.1 fredette 109 1.1 fredette /* 110 1.1 fredette * Generate result 111 1.1 fredette */ 112 1.1 fredette if (src_exponent > 0) { 113 1.1 fredette even_exponent = Sgl_hidden(src); 114 1.1 fredette Sgl_clear_signexponent_set_hidden(src); 115 1.1 fredette } 116 1.1 fredette else { 117 1.1 fredette /* normalize operand */ 118 1.1 fredette Sgl_clear_signexponent(src); 119 1.1 fredette src_exponent++; 120 1.1 fredette Sgl_normalize(src,src_exponent); 121 1.1 fredette even_exponent = src_exponent & 1; 122 1.1 fredette } 123 1.1 fredette if (even_exponent) { 124 1.1 fredette /* exponent is even */ 125 1.1 fredette /* Add comment here. Explain why odd exponent needs correction */ 126 1.1 fredette Sgl_leftshiftby1(src); 127 1.1 fredette } 128 1.1 fredette /* 129 1.1 fredette * Add comment here. Explain following algorithm. 130 1.1 fredette * 131 1.1 fredette * Trust me, it works. 132 1.1 fredette * 133 1.1 fredette */ 134 1.1 fredette Sgl_setzero(result); 135 1.1 fredette newbit = 1 << SGL_P; 136 1.1 fredette while (newbit && Sgl_isnotzero(src)) { 137 1.1 fredette Sgl_addition(result,newbit,sum); 138 1.1 fredette if(sum <= Sgl_all(src)) { 139 1.1 fredette /* update result */ 140 1.1 fredette Sgl_addition(result,(newbit<<1),result); 141 1.1 fredette Sgl_subtract(src,sum,src); 142 1.1 fredette } 143 1.1 fredette Sgl_rightshiftby1(newbit); 144 1.1 fredette Sgl_leftshiftby1(src); 145 1.1 fredette } 146 1.1 fredette /* correct exponent for pre-shift */ 147 1.1 fredette if (even_exponent) { 148 1.1 fredette Sgl_rightshiftby1(result); 149 1.1 fredette } 150 1.1 fredette 151 1.1 fredette /* check for inexact */ 152 1.1 fredette if (Sgl_isnotzero(src)) { 153 1.6 christos if (!even_exponent && Sgl_islessthan(result,src)) 154 1.1 fredette Sgl_increment(result); 155 1.1 fredette guardbit = Sgl_lowmantissa(result); 156 1.1 fredette Sgl_rightshiftby1(result); 157 1.1 fredette 158 1.1 fredette /* now round result */ 159 1.1 fredette switch (Rounding_mode()) { 160 1.1 fredette case ROUNDPLUS: 161 1.1 fredette Sgl_increment(result); 162 1.1 fredette break; 163 1.1 fredette case ROUNDNEAREST: 164 1.1 fredette /* stickybit is always true, so guardbit 165 1.1 fredette * is enough to determine rounding */ 166 1.1 fredette if (guardbit) { 167 1.1 fredette Sgl_increment(result); 168 1.1 fredette } 169 1.1 fredette break; 170 1.1 fredette } 171 1.1 fredette /* increment result exponent by 1 if mantissa overflowed */ 172 1.1 fredette if (Sgl_isone_hiddenoverflow(result)) src_exponent+=2; 173 1.1 fredette 174 1.1 fredette if (Is_inexacttrap_enabled()) { 175 1.1 fredette Sgl_set_exponent(result, 176 1.1 fredette ((src_exponent-SGL_BIAS)>>1)+SGL_BIAS); 177 1.1 fredette *dstptr = result; 178 1.1 fredette return(INEXACTEXCEPTION); 179 1.1 fredette } 180 1.1 fredette else Set_inexactflag(); 181 1.1 fredette } 182 1.1 fredette else { 183 1.1 fredette Sgl_rightshiftby1(result); 184 1.1 fredette } 185 1.1 fredette Sgl_set_exponent(result,((src_exponent-SGL_BIAS)>>1)+SGL_BIAS); 186 1.1 fredette *dstptr = result; 187 1.1 fredette return(NOEXCEPTION); 188 1.1 fredette } 189