1 /* $OpenBSD: frnd.c,v 1.8 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 /* @(#)frnd.c: Revision: 2.7.88.1 Date: 93/12/07 15:06:24 */ 16 17 #include "float.h" 18 #include "sgl_float.h" 19 #include "dbl_float.h" 20 #include "quad_float.h" 21 #include "cnv_float.h" 22 23 /* 24 * Single Floating-point Round to Integer 25 */ 26 27 /*ARGSUSED*/ 28 int 29 sgl_frnd(srcptr, null, dstptr, status) 30 sgl_floating_point *srcptr, *null, *dstptr; 31 unsigned int *status; 32 { 33 register unsigned int src, result; 34 register int src_exponent; 35 register int inexact = FALSE; 36 37 src = *srcptr; 38 /* 39 * check source operand for NaN or infinity 40 */ 41 if ((src_exponent = Sgl_exponent(src)) == SGL_INFINITY_EXPONENT) { 42 /* 43 * is signaling NaN? 44 */ 45 if (Sgl_isone_signaling(src)) { 46 /* trap if INVALIDTRAP enabled */ 47 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); 48 /* make NaN quiet */ 49 Set_invalidflag(); 50 Sgl_set_quiet(src); 51 } 52 /* 53 * return quiet NaN or infinity 54 */ 55 *dstptr = src; 56 return(NOEXCEPTION); 57 } 58 /* 59 * Need to round? 60 */ 61 if ((src_exponent -= SGL_BIAS) >= SGL_P - 1) { 62 *dstptr = src; 63 return(NOEXCEPTION); 64 } 65 /* 66 * Generate result 67 */ 68 if (src_exponent >= 0) { 69 Sgl_clear_exponent_set_hidden(src); 70 result = src; 71 Sgl_rightshift(result,(SGL_P-1) - (src_exponent)); 72 /* check for inexact */ 73 if (Sgl_isinexact_to_fix(src,src_exponent)) { 74 inexact = TRUE; 75 /* round result */ 76 switch (Rounding_mode()) { 77 case ROUNDPLUS: 78 if (Sgl_iszero_sign(src)) Sgl_increment(result); 79 break; 80 case ROUNDMINUS: 81 if (Sgl_isone_sign(src)) Sgl_increment(result); 82 break; 83 case ROUNDNEAREST: 84 if (Sgl_isone_roundbit(src,src_exponent)) 85 if (Sgl_isone_stickybit(src,src_exponent) 86 || (Sgl_isone_lowmantissa(result))) 87 Sgl_increment(result); 88 } 89 } 90 Sgl_leftshift(result,(SGL_P-1) - (src_exponent)); 91 if (Sgl_isone_hiddenoverflow(result)) 92 Sgl_set_exponent(result,src_exponent + (SGL_BIAS+1)); 93 else Sgl_set_exponent(result,src_exponent + SGL_BIAS); 94 } 95 else { 96 result = src; /* set sign */ 97 Sgl_setzero_exponentmantissa(result); 98 /* check for inexact */ 99 if (Sgl_isnotzero_exponentmantissa(src)) { 100 inexact = TRUE; 101 /* round result */ 102 switch (Rounding_mode()) { 103 case ROUNDPLUS: 104 if (Sgl_iszero_sign(src)) 105 Sgl_set_exponent(result,SGL_BIAS); 106 break; 107 case ROUNDMINUS: 108 if (Sgl_isone_sign(src)) 109 Sgl_set_exponent(result,SGL_BIAS); 110 break; 111 case ROUNDNEAREST: 112 if (src_exponent == -1) 113 if (Sgl_isnotzero_mantissa(src)) 114 Sgl_set_exponent(result,SGL_BIAS); 115 } 116 } 117 } 118 *dstptr = result; 119 if (inexact) { 120 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); 121 else Set_inexactflag(); 122 } 123 return(NOEXCEPTION); 124 } 125 126 /* 127 * Double Floating-point Round to Integer 128 */ 129 130 /*ARGSUSED*/ 131 int 132 dbl_frnd(srcptr, null, dstptr, status) 133 dbl_floating_point *srcptr, *null, *dstptr; 134 unsigned int *status; 135 { 136 register unsigned int srcp1, srcp2, resultp1, resultp2; 137 register int src_exponent; 138 register int inexact = FALSE; 139 140 Dbl_copyfromptr(srcptr,srcp1,srcp2); 141 /* 142 * check source operand for NaN or infinity 143 */ 144 if ((src_exponent = Dbl_exponent(srcp1)) == DBL_INFINITY_EXPONENT) { 145 /* 146 * is signaling NaN? 147 */ 148 if (Dbl_isone_signaling(srcp1)) { 149 /* trap if INVALIDTRAP enabled */ 150 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); 151 /* make NaN quiet */ 152 Set_invalidflag(); 153 Dbl_set_quiet(srcp1); 154 } 155 /* 156 * return quiet NaN or infinity 157 */ 158 Dbl_copytoptr(srcp1,srcp2,dstptr); 159 return(NOEXCEPTION); 160 } 161 /* 162 * Need to round? 163 */ 164 if ((src_exponent -= DBL_BIAS) >= DBL_P - 1) { 165 Dbl_copytoptr(srcp1,srcp2,dstptr); 166 return(NOEXCEPTION); 167 } 168 /* 169 * Generate result 170 */ 171 if (src_exponent >= 0) { 172 Dbl_clear_exponent_set_hidden(srcp1); 173 resultp1 = srcp1; 174 resultp2 = srcp2; 175 Dbl_rightshift(resultp1,resultp2,(DBL_P-1) - (src_exponent)); 176 /* check for inexact */ 177 if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) { 178 inexact = TRUE; 179 /* round result */ 180 switch (Rounding_mode()) { 181 case ROUNDPLUS: 182 if (Dbl_iszero_sign(srcp1)) 183 Dbl_increment(resultp1,resultp2); 184 break; 185 case ROUNDMINUS: 186 if (Dbl_isone_sign(srcp1)) 187 Dbl_increment(resultp1,resultp2); 188 break; 189 case ROUNDNEAREST: 190 if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent)) 191 if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) 192 || (Dbl_isone_lowmantissap2(resultp2))) 193 Dbl_increment(resultp1,resultp2); 194 } 195 } 196 Dbl_leftshift(resultp1,resultp2,(DBL_P-1) - (src_exponent)); 197 if (Dbl_isone_hiddenoverflow(resultp1)) 198 Dbl_set_exponent(resultp1,src_exponent + (DBL_BIAS+1)); 199 else Dbl_set_exponent(resultp1,src_exponent + DBL_BIAS); 200 } 201 else { 202 resultp1 = srcp1; /* set sign */ 203 Dbl_setzero_exponentmantissa(resultp1,resultp2); 204 /* check for inexact */ 205 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { 206 inexact = TRUE; 207 /* round result */ 208 switch (Rounding_mode()) { 209 case ROUNDPLUS: 210 if (Dbl_iszero_sign(srcp1)) 211 Dbl_set_exponent(resultp1,DBL_BIAS); 212 break; 213 case ROUNDMINUS: 214 if (Dbl_isone_sign(srcp1)) 215 Dbl_set_exponent(resultp1,DBL_BIAS); 216 break; 217 case ROUNDNEAREST: 218 if (src_exponent == -1) 219 if (Dbl_isnotzero_mantissa(srcp1,srcp2)) 220 Dbl_set_exponent(resultp1,DBL_BIAS); 221 } 222 } 223 } 224 Dbl_copytoptr(resultp1,resultp2,dstptr); 225 if (inexact) { 226 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); 227 else Set_inexactflag(); 228 } 229 return(NOEXCEPTION); 230 } 231 232 /*ARGSUSED*/ 233 int 234 quad_frnd(srcptr, null, dstptr, status) 235 quad_floating_point *srcptr, *null, *dstptr; 236 unsigned int *status; 237 { 238 return(UNIMPLEMENTEDEXCEPTION); 239 } 240