1 /* $OpenBSD: fcnvff.c,v 1.7 2003/04/10 17:27:58 mickey Exp $ */ 2 /* 3 (c) Copyright 1986 HEWLETT-PACKARD COMPANY 4 To anyone who acknowledges that this file is provided "AS IS" 5 without any express or implied warranty: 6 permission to use, copy, modify, and distribute this file 7 for any purpose is hereby granted without fee, provided that 8 the above copyright notice and this notice appears in all 9 copies, and that the name of Hewlett-Packard Company not be 10 used in advertising or publicity pertaining to distribution 11 of the software without specific, written prior permission. 12 Hewlett-Packard Company makes no representations about the 13 suitability of this software for any purpose. 14 */ 15 /* @(#)fcnvff.c: Revision: 2.8.88.1 Date: 93/12/07 15:06:09 */ 16 17 #include "float.h" 18 #include "sgl_float.h" 19 #include "dbl_float.h" 20 #include "cnv_float.h" 21 22 /* 23 * Single Floating-point to Double Floating-point 24 */ 25 /*ARGSUSED*/ 26 int 27 sgl_to_dbl_fcnvff(srcptr, null, dstptr, status) 28 sgl_floating_point *srcptr, *null; 29 dbl_floating_point *dstptr; 30 unsigned int *status; 31 { 32 register unsigned int src, resultp1, resultp2; 33 register int src_exponent; 34 35 src = *srcptr; 36 src_exponent = Sgl_exponent(src); 37 Dbl_allp1(resultp1) = Sgl_all(src); /* set sign of result */ 38 /* 39 * Test for NaN or infinity 40 */ 41 if (src_exponent == SGL_INFINITY_EXPONENT) { 42 /* 43 * determine if NaN or infinity 44 */ 45 if (Sgl_iszero_mantissa(src)) { 46 /* 47 * is infinity; want to return double infinity 48 */ 49 Dbl_setinfinity_exponentmantissa(resultp1,resultp2); 50 Dbl_copytoptr(resultp1,resultp2,dstptr); 51 return(NOEXCEPTION); 52 } 53 else { 54 /* 55 * is NaN; signaling or quiet? 56 */ 57 if (Sgl_isone_signaling(src)) { 58 /* trap if INVALIDTRAP enabled */ 59 if (Is_invalidtrap_enabled()) 60 return(INVALIDEXCEPTION); 61 /* make NaN quiet */ 62 else { 63 Set_invalidflag(); 64 Sgl_set_quiet(src); 65 } 66 } 67 /* 68 * NaN is quiet, return as double NaN 69 */ 70 Dbl_setinfinity_exponent(resultp1); 71 Sgl_to_dbl_mantissa(src,resultp1,resultp2); 72 Dbl_copytoptr(resultp1,resultp2,dstptr); 73 return(NOEXCEPTION); 74 } 75 } 76 /* 77 * Test for zero or denormalized 78 */ 79 if (src_exponent == 0) { 80 /* 81 * determine if zero or denormalized 82 */ 83 if (Sgl_isnotzero_mantissa(src)) { 84 /* 85 * is denormalized; want to normalize 86 */ 87 Sgl_clear_signexponent(src); 88 Sgl_leftshiftby1(src); 89 Sgl_normalize(src,src_exponent); 90 Sgl_to_dbl_exponent(src_exponent,resultp1); 91 Sgl_to_dbl_mantissa(src,resultp1,resultp2); 92 } 93 else { 94 Dbl_setzero_exponentmantissa(resultp1,resultp2); 95 } 96 Dbl_copytoptr(resultp1,resultp2,dstptr); 97 return(NOEXCEPTION); 98 } 99 /* 100 * No special cases, just complete the conversion 101 */ 102 Sgl_to_dbl_exponent(src_exponent, resultp1); 103 Sgl_to_dbl_mantissa(Sgl_mantissa(src), resultp1,resultp2); 104 Dbl_copytoptr(resultp1,resultp2,dstptr); 105 return(NOEXCEPTION); 106 } 107 108 /* 109 * Double Floating-point to Single Floating-point 110 */ 111 /*ARGSUSED*/ 112 int 113 dbl_to_sgl_fcnvff(srcptr, null, dstptr, status) 114 dbl_floating_point *srcptr, *null; 115 sgl_floating_point *dstptr; 116 unsigned int *status; 117 { 118 register unsigned int srcp1, srcp2, result; 119 register int src_exponent, dest_exponent, dest_mantissa; 120 register int inexact = FALSE, guardbit = FALSE, stickybit = FALSE; 121 register int lsb_odd = FALSE; 122 int is_tiny; 123 124 Dbl_copyfromptr(srcptr,srcp1,srcp2); 125 src_exponent = Dbl_exponent(srcp1); 126 Sgl_all(result) = Dbl_allp1(srcp1); /* set sign of result */ 127 /* 128 * Test for NaN or infinity 129 */ 130 if (src_exponent == DBL_INFINITY_EXPONENT) { 131 /* 132 * determine if NaN or infinity 133 */ 134 if (Dbl_iszero_mantissa(srcp1,srcp2)) { 135 /* 136 * is infinity; want to return single infinity 137 */ 138 Sgl_setinfinity_exponentmantissa(result); 139 *dstptr = result; 140 return(NOEXCEPTION); 141 } 142 /* 143 * is NaN; signaling or quiet? 144 */ 145 if (Dbl_isone_signaling(srcp1)) { 146 /* trap if INVALIDTRAP enabled */ 147 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); 148 else { 149 Set_invalidflag(); 150 /* make NaN quiet */ 151 Dbl_set_quiet(srcp1); 152 } 153 } 154 /* 155 * NaN is quiet, return as single NaN 156 */ 157 Sgl_setinfinity_exponent(result); 158 Sgl_set_mantissa(result,Dallp1(srcp1)<<3 | Dallp2(srcp2)>>29); 159 if (Sgl_iszero_mantissa(result)) Sgl_set_quiet(result); 160 *dstptr = result; 161 return(NOEXCEPTION); 162 } 163 /* 164 * Generate result 165 */ 166 Dbl_to_sgl_exponent(src_exponent,dest_exponent); 167 if (dest_exponent > 0) { 168 Dbl_to_sgl_mantissa(srcp1,srcp2,dest_mantissa,inexact,guardbit, 169 stickybit,lsb_odd); 170 } 171 else { 172 if (Dbl_iszero_exponentmantissa(srcp1,srcp2)){ 173 Sgl_setzero_exponentmantissa(result); 174 *dstptr = result; 175 return(NOEXCEPTION); 176 } 177 if (Is_underflowtrap_enabled()) { 178 Dbl_to_sgl_mantissa(srcp1,srcp2,dest_mantissa,inexact, 179 guardbit,stickybit,lsb_odd); 180 } 181 else { 182 /* compute result, determine inexact info, 183 * and set Underflowflag if appropriate 184 */ 185 Dbl_to_sgl_denormalized(srcp1,srcp2,dest_exponent, 186 dest_mantissa,inexact,guardbit,stickybit,lsb_odd, 187 is_tiny); 188 } 189 } 190 /* 191 * Now round result if not exact 192 */ 193 if (inexact) { 194 switch (Rounding_mode()) { 195 case ROUNDPLUS: 196 if (Sgl_iszero_sign(result)) dest_mantissa++; 197 break; 198 case ROUNDMINUS: 199 if (Sgl_isone_sign(result)) dest_mantissa++; 200 break; 201 case ROUNDNEAREST: 202 if (guardbit) { 203 if (stickybit || lsb_odd) dest_mantissa++; 204 } 205 } 206 } 207 Sgl_set_exponentmantissa(result,dest_mantissa); 208 209 /* 210 * check for mantissa overflow after rounding 211 */ 212 if ((dest_exponent>0 || Is_underflowtrap_enabled()) && 213 Sgl_isone_hidden(result)) dest_exponent++; 214 215 /* 216 * Test for overflow 217 */ 218 if (dest_exponent >= SGL_INFINITY_EXPONENT) { 219 /* trap if OVERFLOWTRAP enabled */ 220 if (Is_overflowtrap_enabled()) { 221 /* 222 * Check for gross overflow 223 */ 224 if (dest_exponent >= SGL_INFINITY_EXPONENT+SGL_WRAP) 225 return(UNIMPLEMENTEDEXCEPTION); 226 227 /* 228 * Adjust bias of result 229 */ 230 Sgl_setwrapped_exponent(result,dest_exponent,ovfl); 231 *dstptr = result; 232 if (inexact) { 233 if (Is_inexacttrap_enabled()) 234 return(OVERFLOWEXCEPTION|INEXACTEXCEPTION); 235 else 236 Set_inexactflag(); 237 } 238 return(OVERFLOWEXCEPTION); 239 } 240 Set_overflowflag(); 241 inexact = TRUE; 242 /* set result to infinity or largest number */ 243 Sgl_setoverflow(result); 244 } 245 /* 246 * Test for underflow 247 */ 248 else if (dest_exponent <= 0) { 249 /* trap if UNDERFLOWTRAP enabled */ 250 if (Is_underflowtrap_enabled()) { 251 /* 252 * Check for gross underflow 253 */ 254 if (dest_exponent <= -(SGL_WRAP)) 255 return(UNIMPLEMENTEDEXCEPTION); 256 /* 257 * Adjust bias of result 258 */ 259 Sgl_setwrapped_exponent(result,dest_exponent,unfl); 260 *dstptr = result; 261 if (inexact) { 262 if (Is_inexacttrap_enabled()) 263 return(UNDERFLOWEXCEPTION|INEXACTEXCEPTION); 264 else 265 Set_inexactflag(); 266 } 267 return(UNDERFLOWEXCEPTION); 268 } 269 /* 270 * result is denormalized or signed zero 271 */ 272 if (inexact && is_tiny) Set_underflowflag(); 273 274 } 275 else Sgl_set_exponent(result,dest_exponent); 276 *dstptr = result; 277 /* 278 * Trap if inexact trap is enabled 279 */ 280 if (inexact) { 281 if (Is_inexacttrap_enabled()) 282 return(INEXACTEXCEPTION); 283 else 284 Set_inexactflag(); 285 } 286 return(NOEXCEPTION); 287 } 288