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