1 /* $NetBSD: frnd.c,v 1.1 2002/06/05 01:04:25 fredette Exp $ */ 2 3 /* $OpenBSD: frnd.c,v 1.5 2001/03/29 03:58:18 mickey Exp $ */ 4 5 /* 6 * Copyright 1996 1995 by Open Software Foundation, Inc. 7 * All Rights Reserved 8 * 9 * Permission to use, copy, modify, and distribute this software and 10 * its documentation for any purpose and without fee is hereby granted, 11 * provided that the above copyright notice appears in all copies and 12 * that both the copyright notice and this permission notice appear in 13 * supporting documentation. 14 * 15 * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE 16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 17 * FOR A PARTICULAR PURPOSE. 18 * 19 * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR 20 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 21 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, 22 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 23 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 24 * 25 */ 26 /* 27 * pmk1.1 28 */ 29 /* 30 * (c) Copyright 1986 HEWLETT-PACKARD COMPANY 31 * 32 * To anyone who acknowledges that this file is provided "AS IS" 33 * without any express or implied warranty: 34 * permission to use, copy, modify, and distribute this file 35 * for any purpose is hereby granted without fee, provided that 36 * the above copyright notice and this notice appears in all 37 * copies, and that the name of Hewlett-Packard Company not be 38 * used in advertising or publicity pertaining to distribution 39 * of the software without specific, written prior permission. 40 * Hewlett-Packard Company makes no representations about the 41 * suitability of this software for any purpose. 42 */ 43 44 #include "../spmath/float.h" 45 #include "../spmath/sgl_float.h" 46 #include "../spmath/dbl_float.h" 47 #include "../spmath/quad_float.h" 48 #include "../spmath/cnv_float.h" 49 50 /* 51 * Single Floating-point Round to Integer 52 */ 53 54 /*ARGSUSED*/ 55 int 56 sgl_frnd(srcptr,dstptr,status) 57 58 sgl_floating_point *srcptr, *dstptr; 59 unsigned int *status; 60 { 61 register unsigned int src, result; 62 register int src_exponent; 63 register int inexact = FALSE; 64 65 src = *srcptr; 66 /* 67 * check source operand for NaN or infinity 68 */ 69 if ((src_exponent = Sgl_exponent(src)) == SGL_INFINITY_EXPONENT) { 70 /* 71 * is signaling NaN? 72 */ 73 if (Sgl_isone_signaling(src)) { 74 /* trap if INVALIDTRAP enabled */ 75 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); 76 /* make NaN quiet */ 77 Set_invalidflag(); 78 Sgl_set_quiet(src); 79 } 80 /* 81 * return quiet NaN or infinity 82 */ 83 *dstptr = src; 84 return(NOEXCEPTION); 85 } 86 /* 87 * Need to round? 88 */ 89 if ((src_exponent -= SGL_BIAS) >= SGL_P - 1) { 90 *dstptr = src; 91 return(NOEXCEPTION); 92 } 93 /* 94 * Generate result 95 */ 96 if (src_exponent >= 0) { 97 Sgl_clear_exponent_set_hidden(src); 98 result = src; 99 Sgl_rightshift(result,(SGL_P-1) - (src_exponent)); 100 /* check for inexact */ 101 if (Sgl_isinexact_to_fix(src,src_exponent)) { 102 inexact = TRUE; 103 /* round result */ 104 switch (Rounding_mode()) { 105 case ROUNDPLUS: 106 if (Sgl_iszero_sign(src)) Sgl_increment(result); 107 break; 108 case ROUNDMINUS: 109 if (Sgl_isone_sign(src)) Sgl_increment(result); 110 break; 111 case ROUNDNEAREST: 112 if (Sgl_isone_roundbit(src,src_exponent)) 113 if (Sgl_isone_stickybit(src,src_exponent) 114 || (Sgl_isone_lowmantissa(result))) 115 Sgl_increment(result); 116 } 117 } 118 Sgl_leftshift(result,(SGL_P-1) - (src_exponent)); 119 if (Sgl_isone_hiddenoverflow(result)) 120 Sgl_set_exponent(result,src_exponent + (SGL_BIAS+1)); 121 else Sgl_set_exponent(result,src_exponent + SGL_BIAS); 122 } 123 else { 124 result = src; /* set sign */ 125 Sgl_setzero_exponentmantissa(result); 126 /* check for inexact */ 127 if (Sgl_isnotzero_exponentmantissa(src)) { 128 inexact = TRUE; 129 /* round result */ 130 switch (Rounding_mode()) { 131 case ROUNDPLUS: 132 if (Sgl_iszero_sign(src)) 133 Sgl_set_exponent(result,SGL_BIAS); 134 break; 135 case ROUNDMINUS: 136 if (Sgl_isone_sign(src)) 137 Sgl_set_exponent(result,SGL_BIAS); 138 break; 139 case ROUNDNEAREST: 140 if (src_exponent == -1) 141 if (Sgl_isnotzero_mantissa(src)) 142 Sgl_set_exponent(result,SGL_BIAS); 143 } 144 } 145 } 146 *dstptr = result; 147 if (inexact) { 148 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); 149 else Set_inexactflag(); 150 } 151 return(NOEXCEPTION); 152 } 153 154 /* 155 * Double Floating-point Round to Integer 156 */ 157 158 /*ARGSUSED*/ 159 int 160 dbl_frnd(srcptr,dstptr,status) 161 162 dbl_floating_point *srcptr, *dstptr; 163 unsigned int *status; 164 { 165 register unsigned int srcp1, srcp2, resultp1, resultp2; 166 register int src_exponent; 167 register int inexact = FALSE; 168 169 Dbl_copyfromptr(srcptr,srcp1,srcp2); 170 /* 171 * check source operand for NaN or infinity 172 */ 173 if ((src_exponent = Dbl_exponent(srcp1)) == DBL_INFINITY_EXPONENT) { 174 /* 175 * is signaling NaN? 176 */ 177 if (Dbl_isone_signaling(srcp1)) { 178 /* trap if INVALIDTRAP enabled */ 179 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); 180 /* make NaN quiet */ 181 Set_invalidflag(); 182 Dbl_set_quiet(srcp1); 183 } 184 /* 185 * return quiet NaN or infinity 186 */ 187 Dbl_copytoptr(srcp1,srcp2,dstptr); 188 return(NOEXCEPTION); 189 } 190 /* 191 * Need to round? 192 */ 193 if ((src_exponent -= DBL_BIAS) >= DBL_P - 1) { 194 Dbl_copytoptr(srcp1,srcp2,dstptr); 195 return(NOEXCEPTION); 196 } 197 /* 198 * Generate result 199 */ 200 if (src_exponent >= 0) { 201 Dbl_clear_exponent_set_hidden(srcp1); 202 resultp1 = srcp1; 203 resultp2 = srcp2; 204 Dbl_rightshift(resultp1,resultp2,(DBL_P-1) - (src_exponent)); 205 /* check for inexact */ 206 if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) { 207 inexact = TRUE; 208 /* round result */ 209 switch (Rounding_mode()) { 210 case ROUNDPLUS: 211 if (Dbl_iszero_sign(srcp1)) 212 Dbl_increment(resultp1,resultp2); 213 break; 214 case ROUNDMINUS: 215 if (Dbl_isone_sign(srcp1)) 216 Dbl_increment(resultp1,resultp2); 217 break; 218 case ROUNDNEAREST: 219 if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent)) 220 if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) 221 || (Dbl_isone_lowmantissap2(resultp2))) 222 Dbl_increment(resultp1,resultp2); 223 } 224 } 225 Dbl_leftshift(resultp1,resultp2,(DBL_P-1) - (src_exponent)); 226 if (Dbl_isone_hiddenoverflow(resultp1)) 227 Dbl_set_exponent(resultp1,src_exponent + (DBL_BIAS+1)); 228 else Dbl_set_exponent(resultp1,src_exponent + DBL_BIAS); 229 } 230 else { 231 resultp1 = srcp1; /* set sign */ 232 Dbl_setzero_exponentmantissa(resultp1,resultp2); 233 /* check for inexact */ 234 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { 235 inexact = TRUE; 236 /* round result */ 237 switch (Rounding_mode()) { 238 case ROUNDPLUS: 239 if (Dbl_iszero_sign(srcp1)) 240 Dbl_set_exponent(resultp1,DBL_BIAS); 241 break; 242 case ROUNDMINUS: 243 if (Dbl_isone_sign(srcp1)) 244 Dbl_set_exponent(resultp1,DBL_BIAS); 245 break; 246 case ROUNDNEAREST: 247 if (src_exponent == -1) 248 if (Dbl_isnotzero_mantissa(srcp1,srcp2)) 249 Dbl_set_exponent(resultp1,DBL_BIAS); 250 } 251 } 252 } 253 Dbl_copytoptr(resultp1,resultp2,dstptr); 254 if (inexact) { 255 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); 256 else Set_inexactflag(); 257 } 258 return(NOEXCEPTION); 259 } 260 261 /*ARGSUSED*/ 262 int 263 quad_frnd(srcptr,dstptr,status) 264 265 quad_floating_point *srcptr, *dstptr; 266 unsigned int *status; 267 { 268 return(UNIMPLEMENTEDEXCEPTION); 269 } 270 271