1 /* $NetBSD: fcnvff.c,v 1.5 2007/02/22 05:46:30 thorpej Exp $ */ 2 3 /* $OpenBSD: fcnvff.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 <sys/cdefs.h> 45 __KERNEL_RCSID(0, "$NetBSD: fcnvff.c,v 1.5 2007/02/22 05:46:30 thorpej Exp $"); 46 47 #include "../spmath/float.h" 48 #include "../spmath/sgl_float.h" 49 #include "../spmath/dbl_float.h" 50 #include "../spmath/cnv_float.h" 51 52 /* 53 * Single Floating-point to Double Floating-point 54 */ 55 /*ARGSUSED*/ 56 int 57 sgl_to_dbl_fcnvff(srcptr,dstptr,status) 58 59 sgl_floating_point *srcptr; 60 dbl_floating_point *dstptr; 61 unsigned int *status; 62 { 63 register unsigned int src, resultp1, resultp2; 64 register int src_exponent; 65 66 src = *srcptr; 67 src_exponent = Sgl_exponent(src); 68 Dbl_allp1(resultp1) = Sgl_all(src); /* set sign of result */ 69 /* 70 * Test for NaN or infinity 71 */ 72 if (src_exponent == SGL_INFINITY_EXPONENT) { 73 /* 74 * determine if NaN or infinity 75 */ 76 if (Sgl_iszero_mantissa(src)) { 77 /* 78 * is infinity; want to return double infinity 79 */ 80 Dbl_setinfinity_exponentmantissa(resultp1,resultp2); 81 Dbl_copytoptr(resultp1,resultp2,dstptr); 82 return(NOEXCEPTION); 83 } 84 else { 85 /* 86 * is NaN; signaling or quiet? 87 */ 88 if (Sgl_isone_signaling(src)) { 89 /* trap if INVALIDTRAP enabled */ 90 if (Is_invalidtrap_enabled()) 91 return(INVALIDEXCEPTION); 92 /* make NaN quiet */ 93 else { 94 Set_invalidflag(); 95 Sgl_set_quiet(src); 96 } 97 } 98 /* 99 * NaN is quiet, return as double NaN 100 */ 101 Dbl_setinfinity_exponent(resultp1); 102 Sgl_to_dbl_mantissa(src,resultp1,resultp2); 103 Dbl_copytoptr(resultp1,resultp2,dstptr); 104 return(NOEXCEPTION); 105 } 106 } 107 /* 108 * Test for zero or denormalized 109 */ 110 if (src_exponent == 0) { 111 /* 112 * determine if zero or denormalized 113 */ 114 if (Sgl_isnotzero_mantissa(src)) { 115 /* 116 * is denormalized; want to normalize 117 */ 118 Sgl_clear_signexponent(src); 119 Sgl_leftshiftby1(src); 120 Sgl_normalize(src,src_exponent); 121 Sgl_to_dbl_exponent(src_exponent,resultp1); 122 Sgl_to_dbl_mantissa(src,resultp1,resultp2); 123 } 124 else { 125 Dbl_setzero_exponentmantissa(resultp1,resultp2); 126 } 127 Dbl_copytoptr(resultp1,resultp2,dstptr); 128 return(NOEXCEPTION); 129 } 130 /* 131 * No special cases, just complete the conversion 132 */ 133 Sgl_to_dbl_exponent(src_exponent, resultp1); 134 Sgl_to_dbl_mantissa(Sgl_mantissa(src), resultp1,resultp2); 135 Dbl_copytoptr(resultp1,resultp2,dstptr); 136 return(NOEXCEPTION); 137 } 138 139 /* 140 * Double Floating-point to Single Floating-point 141 */ 142 /*ARGSUSED*/ 143 int 144 dbl_to_sgl_fcnvff(srcptr,dstptr,status) 145 146 dbl_floating_point *srcptr; 147 sgl_floating_point *dstptr; 148 unsigned int *status; 149 { 150 register unsigned int srcp1, srcp2, result; 151 register int src_exponent, dest_exponent, dest_mantissa; 152 register int inexact = false, guardbit = false, stickybit = false; 153 register int lsb_odd = false; 154 int is_tiny = false; 155 156 Dbl_copyfromptr(srcptr,srcp1,srcp2); 157 src_exponent = Dbl_exponent(srcp1); 158 Sgl_all(result) = Dbl_allp1(srcp1); /* set sign of result */ 159 /* 160 * Test for NaN or infinity 161 */ 162 if (src_exponent == DBL_INFINITY_EXPONENT) { 163 /* 164 * determine if NaN or infinity 165 */ 166 if (Dbl_iszero_mantissa(srcp1,srcp2)) { 167 /* 168 * is infinity; want to return single infinity 169 */ 170 Sgl_setinfinity_exponentmantissa(result); 171 *dstptr = result; 172 return(NOEXCEPTION); 173 } 174 /* 175 * is NaN; signaling or quiet? 176 */ 177 if (Dbl_isone_signaling(srcp1)) { 178 /* trap if INVALIDTRAP enabled */ 179 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); 180 else { 181 Set_invalidflag(); 182 /* make NaN quiet */ 183 Dbl_set_quiet(srcp1); 184 } 185 } 186 /* 187 * NaN is quiet, return as single NaN 188 */ 189 Sgl_setinfinity_exponent(result); 190 Sgl_set_mantissa(result,Dallp1(srcp1)<<3 | Dallp2(srcp2)>>29); 191 if (Sgl_iszero_mantissa(result)) Sgl_set_quiet(result); 192 *dstptr = result; 193 return(NOEXCEPTION); 194 } 195 /* 196 * Generate result 197 */ 198 Dbl_to_sgl_exponent(src_exponent,dest_exponent); 199 if (dest_exponent > 0) { 200 Dbl_to_sgl_mantissa(srcp1,srcp2,dest_mantissa,inexact,guardbit, 201 stickybit,lsb_odd); 202 } 203 else { 204 if (Dbl_iszero_exponentmantissa(srcp1,srcp2)){ 205 Sgl_setzero_exponentmantissa(result); 206 *dstptr = result; 207 return(NOEXCEPTION); 208 } 209 if (Is_underflowtrap_enabled()) { 210 Dbl_to_sgl_mantissa(srcp1,srcp2,dest_mantissa,inexact, 211 guardbit,stickybit,lsb_odd); 212 } 213 else { 214 /* compute result, determine inexact info, 215 * and set Underflowflag if appropriate 216 */ 217 Dbl_to_sgl_denormalized(srcp1,srcp2,dest_exponent, 218 dest_mantissa,inexact,guardbit,stickybit,lsb_odd, 219 is_tiny); 220 } 221 } 222 /* 223 * Now round result if not exact 224 */ 225 if (inexact) { 226 switch (Rounding_mode()) { 227 case ROUNDPLUS: 228 if (Sgl_iszero_sign(result)) dest_mantissa++; 229 break; 230 case ROUNDMINUS: 231 if (Sgl_isone_sign(result)) dest_mantissa++; 232 break; 233 case ROUNDNEAREST: 234 if (guardbit) { 235 if (stickybit || lsb_odd) dest_mantissa++; 236 } 237 } 238 } 239 Sgl_set_exponentmantissa(result,dest_mantissa); 240 241 /* 242 * check for mantissa overflow after rounding 243 */ 244 if ((dest_exponent>0 || Is_underflowtrap_enabled()) && 245 Sgl_isone_hidden(result)) dest_exponent++; 246 247 /* 248 * Test for overflow 249 */ 250 if (dest_exponent >= SGL_INFINITY_EXPONENT) { 251 /* trap if OVERFLOWTRAP enabled */ 252 if (Is_overflowtrap_enabled()) { 253 /* 254 * Check for gross overflow 255 */ 256 if (dest_exponent >= SGL_INFINITY_EXPONENT+SGL_WRAP) 257 return(UNIMPLEMENTEDEXCEPTION); 258 259 /* 260 * Adjust bias of result 261 */ 262 Sgl_setwrapped_exponent(result,dest_exponent,ovfl); 263 *dstptr = result; 264 if (inexact) { 265 if (Is_inexacttrap_enabled()) 266 return(OVERFLOWEXCEPTION|INEXACTEXCEPTION); 267 else 268 Set_inexactflag(); 269 } 270 return(OVERFLOWEXCEPTION); 271 } 272 Set_overflowflag(); 273 inexact = true; 274 /* set result to infinity or largest number */ 275 Sgl_setoverflow(result); 276 } 277 /* 278 * Test for underflow 279 */ 280 else if (dest_exponent <= 0) { 281 /* trap if UNDERFLOWTRAP enabled */ 282 if (Is_underflowtrap_enabled()) { 283 /* 284 * Check for gross underflow 285 */ 286 if (dest_exponent <= -(SGL_WRAP)) 287 return(UNIMPLEMENTEDEXCEPTION); 288 /* 289 * Adjust bias of result 290 */ 291 Sgl_setwrapped_exponent(result,dest_exponent,unfl); 292 *dstptr = result; 293 if (inexact) { 294 if (Is_inexacttrap_enabled()) 295 return(UNDERFLOWEXCEPTION|INEXACTEXCEPTION); 296 else 297 Set_inexactflag(); 298 } 299 return(UNDERFLOWEXCEPTION); 300 } 301 /* 302 * result is denormalized or signed zero 303 */ 304 if (inexact && is_tiny) Set_underflowflag(); 305 306 } 307 else Sgl_set_exponent(result,dest_exponent); 308 *dstptr = result; 309 /* 310 * Trap if inexact trap is enabled 311 */ 312 if (inexact) { 313 if (Is_inexacttrap_enabled()) 314 return(INEXACTEXCEPTION); 315 else 316 Set_inexactflag(); 317 } 318 return(NOEXCEPTION); 319 } 320