1 /* $OpenBSD: fcnvfx.c,v 1.8 2010/07/30 18:05:23 kettenis 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 /* @(#)fcnvfx.c: Revision: 2.8.88.2 Date: 93/12/08 13:27:29 */ 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 Single Fixed-point 24 */ 25 /*ARGSUSED*/ 26 int 27 sgl_to_sgl_fcnvfx(srcptr, null, dstptr, status) 28 sgl_floating_point *srcptr, *null; 29 int *dstptr; 30 unsigned int *status; 31 { 32 register unsigned int src, temp; 33 register int src_exponent, result; 34 register int inexact = FALSE; 35 36 src = *srcptr; 37 src_exponent = Sgl_exponent(src) - SGL_BIAS; 38 39 /* 40 * Test for overflow 41 */ 42 if (src_exponent > SGL_FX_MAX_EXP) { 43 /* check for MININT */ 44 if ((src_exponent > SGL_FX_MAX_EXP + 1) || 45 Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) { 46 if (Sgl_iszero_sign(src)) result = 0x7fffffff; 47 else result = 0x80000000; 48 49 if (Is_invalidtrap_enabled()) { 50 return(INVALIDEXCEPTION); 51 } 52 Set_invalidflag(); 53 *dstptr = result; 54 return(NOEXCEPTION); 55 } 56 } 57 /* 58 * Generate result 59 */ 60 if (src_exponent >= 0) { 61 temp = src; 62 Sgl_clear_signexponent_set_hidden(temp); 63 Int_from_sgl_mantissa(temp,src_exponent); 64 if (Sgl_isone_sign(src)) result = -Sgl_all(temp); 65 else result = Sgl_all(temp); 66 67 /* check for inexact */ 68 if (Sgl_isinexact_to_fix(src,src_exponent)) { 69 inexact = TRUE; 70 /* round result */ 71 switch (Rounding_mode()) { 72 case ROUNDPLUS: 73 if (Sgl_iszero_sign(src)) result++; 74 break; 75 case ROUNDMINUS: 76 if (Sgl_isone_sign(src)) result--; 77 break; 78 case ROUNDNEAREST: 79 if (Sgl_isone_roundbit(src,src_exponent)) { 80 if (Sgl_isone_stickybit(src,src_exponent) 81 || (Sgl_isone_lowmantissa(temp))) { 82 if (Sgl_iszero_sign(src)) result++; 83 else result--; 84 } 85 } 86 } 87 } 88 } 89 else { 90 result = 0; 91 92 /* check for inexact */ 93 if (Sgl_isnotzero_exponentmantissa(src)) { 94 inexact = TRUE; 95 /* round result */ 96 switch (Rounding_mode()) { 97 case ROUNDPLUS: 98 if (Sgl_iszero_sign(src)) result++; 99 break; 100 case ROUNDMINUS: 101 if (Sgl_isone_sign(src)) result--; 102 break; 103 case ROUNDNEAREST: 104 if (src_exponent == -1) 105 if (Sgl_isnotzero_mantissa(src)) { 106 if (Sgl_iszero_sign(src)) result++; 107 else result--; 108 } 109 } 110 } 111 } 112 *dstptr = result; 113 if (inexact) { 114 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); 115 else Set_inexactflag(); 116 } 117 return(NOEXCEPTION); 118 } 119 120 /* 121 * Single Floating-point to Double Fixed-point 122 */ 123 /*ARGSUSED*/ 124 int 125 sgl_to_dbl_fcnvfx(srcptr, null, dstptr, status) 126 sgl_floating_point *srcptr, *null; 127 dbl_integer *dstptr; 128 unsigned int *status; 129 { 130 register int src_exponent, resultp1; 131 register unsigned int src, temp, resultp2; 132 register int inexact = FALSE; 133 134 src = *srcptr; 135 src_exponent = Sgl_exponent(src) - SGL_BIAS; 136 137 /* 138 * Test for overflow 139 */ 140 if (src_exponent > DBL_FX_MAX_EXP) { 141 /* check for MININT */ 142 if ((src_exponent > DBL_FX_MAX_EXP + 1) || 143 Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) { 144 if (Sgl_iszero_sign(src)) { 145 resultp1 = 0x7fffffff; 146 resultp2 = 0xffffffff; 147 } 148 else { 149 resultp1 = 0x80000000; 150 resultp2 = 0; 151 } 152 153 if (Is_invalidtrap_enabled()) { 154 return(INVALIDEXCEPTION); 155 } 156 Set_invalidflag(); 157 Dint_copytoptr(resultp1,resultp2,dstptr); 158 return(NOEXCEPTION); 159 } 160 Dint_set_minint(resultp1,resultp2); 161 Dint_copytoptr(resultp1,resultp2,dstptr); 162 return(NOEXCEPTION); 163 } 164 /* 165 * Generate result 166 */ 167 if (src_exponent >= 0) { 168 temp = src; 169 Sgl_clear_signexponent_set_hidden(temp); 170 Dint_from_sgl_mantissa(temp,src_exponent,resultp1,resultp2); 171 if (Sgl_isone_sign(src)) { 172 Dint_setone_sign(resultp1,resultp2); 173 } 174 175 /* check for inexact */ 176 if (Sgl_isinexact_to_fix(src,src_exponent)) { 177 inexact = TRUE; 178 /* round result */ 179 switch (Rounding_mode()) { 180 case ROUNDPLUS: 181 if (Sgl_iszero_sign(src)) { 182 Dint_increment(resultp1,resultp2); 183 } 184 break; 185 case ROUNDMINUS: 186 if (Sgl_isone_sign(src)) { 187 Dint_decrement(resultp1,resultp2); 188 } 189 break; 190 case ROUNDNEAREST: 191 if (Sgl_isone_roundbit(src,src_exponent)) 192 if (Sgl_isone_stickybit(src,src_exponent) || 193 (Dint_isone_lowp2(resultp2))) { 194 if (Sgl_iszero_sign(src)) { 195 Dint_increment(resultp1,resultp2); 196 } 197 else { 198 Dint_decrement(resultp1,resultp2); 199 } 200 } 201 } 202 } 203 } 204 else { 205 Dint_setzero(resultp1,resultp2); 206 207 /* check for inexact */ 208 if (Sgl_isnotzero_exponentmantissa(src)) { 209 inexact = TRUE; 210 /* round result */ 211 switch (Rounding_mode()) { 212 case ROUNDPLUS: 213 if (Sgl_iszero_sign(src)) { 214 Dint_increment(resultp1,resultp2); 215 } 216 break; 217 case ROUNDMINUS: 218 if (Sgl_isone_sign(src)) { 219 Dint_decrement(resultp1,resultp2); 220 } 221 break; 222 case ROUNDNEAREST: 223 if (src_exponent == -1) 224 if (Sgl_isnotzero_mantissa(src)) { 225 if (Sgl_iszero_sign(src)) { 226 Dint_increment(resultp1,resultp2); 227 } 228 else { 229 Dint_decrement(resultp1,resultp2); 230 } 231 } 232 } 233 } 234 } 235 Dint_copytoptr(resultp1,resultp2,dstptr); 236 if (inexact) { 237 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); 238 else Set_inexactflag(); 239 } 240 return(NOEXCEPTION); 241 } 242 243 /* 244 * Double Floating-point to Single Fixed-point 245 */ 246 /*ARGSUSED*/ 247 int 248 dbl_to_sgl_fcnvfx(srcptr, null, dstptr, status) 249 dbl_floating_point *srcptr, *null; 250 int *dstptr; 251 unsigned int *status; 252 { 253 register unsigned int srcp1,srcp2, tempp1,tempp2; 254 register int src_exponent, result; 255 register int inexact = FALSE; 256 257 Dbl_copyfromptr(srcptr,srcp1,srcp2); 258 src_exponent = Dbl_exponent(srcp1) - DBL_BIAS; 259 260 /* 261 * Test for overflow 262 */ 263 if (src_exponent > SGL_FX_MAX_EXP) { 264 /* check for MININT */ 265 if (Dbl_isoverflow_to_int(src_exponent,srcp1,srcp2)) { 266 if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff; 267 else result = 0x80000000; 268 269 if (Is_invalidtrap_enabled()) { 270 return(INVALIDEXCEPTION); 271 } 272 Set_invalidflag(); 273 *dstptr = result; 274 return(NOEXCEPTION); 275 } 276 } 277 /* 278 * Generate result 279 */ 280 if (src_exponent >= 0) { 281 tempp1 = srcp1; 282 tempp2 = srcp2; 283 Dbl_clear_signexponent_set_hidden(tempp1); 284 Int_from_dbl_mantissa(tempp1,tempp2,src_exponent); 285 if (Dbl_isone_sign(srcp1) && (src_exponent <= SGL_FX_MAX_EXP)) 286 result = -Dbl_allp1(tempp1); 287 else result = Dbl_allp1(tempp1); 288 289 /* check for inexact */ 290 if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) { 291 inexact = TRUE; 292 /* round result */ 293 switch (Rounding_mode()) { 294 case ROUNDPLUS: 295 if (Dbl_iszero_sign(srcp1)) 296 result++; 297 break; 298 case ROUNDMINUS: 299 if (Dbl_isone_sign(srcp1)) result--; 300 break; 301 case ROUNDNEAREST: 302 if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent)) 303 if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) || 304 (Dbl_isone_lowmantissap1(tempp1))) { 305 if (Dbl_iszero_sign(srcp1)) result++; 306 else result--; 307 } 308 } 309 /* check for overflow */ 310 if ((Dbl_iszero_sign(srcp1) && result < 0) || 311 (Dbl_isone_sign(srcp1) && result > 0)) { 312 313 if (Dbl_iszero_sign(srcp1)) 314 result = 0x7fffffff; 315 else 316 result = 0x80000000; 317 318 if (Is_overflowtrap_enabled()) { 319 if (Is_inexacttrap_enabled()) 320 return(OVERFLOWEXCEPTION|INEXACTEXCEPTION); 321 else Set_inexactflag(); 322 return(OVERFLOWEXCEPTION); 323 } 324 Set_overflowflag(); 325 *dstptr = result; 326 if (Is_inexacttrap_enabled() ) 327 return(INEXACTEXCEPTION); 328 else Set_inexactflag(); 329 return(NOEXCEPTION); 330 } 331 } 332 } 333 else { 334 result = 0; 335 336 /* check for inexact */ 337 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { 338 inexact = TRUE; 339 /* round result */ 340 switch (Rounding_mode()) { 341 case ROUNDPLUS: 342 if (Dbl_iszero_sign(srcp1)) result++; 343 break; 344 case ROUNDMINUS: 345 if (Dbl_isone_sign(srcp1)) result--; 346 break; 347 case ROUNDNEAREST: 348 if (src_exponent == -1) 349 if (Dbl_isnotzero_mantissa(srcp1,srcp2)) { 350 if (Dbl_iszero_sign(srcp1)) result++; 351 else result--; 352 } 353 } 354 } 355 } 356 *dstptr = result; 357 if (inexact) { 358 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); 359 else Set_inexactflag(); 360 } 361 return(NOEXCEPTION); 362 } 363 364 /* 365 * Double Floating-point to Double Fixed-point 366 */ 367 /*ARGSUSED*/ 368 int 369 dbl_to_dbl_fcnvfx(srcptr, null, dstptr, status) 370 dbl_floating_point *srcptr, *null; 371 dbl_integer *dstptr; 372 unsigned int *status; 373 { 374 register int src_exponent, resultp1; 375 register unsigned int srcp1, srcp2, tempp1, tempp2, resultp2; 376 register int inexact = FALSE; 377 378 Dbl_copyfromptr(srcptr,srcp1,srcp2); 379 src_exponent = Dbl_exponent(srcp1) - DBL_BIAS; 380 381 /* 382 * Test for overflow 383 */ 384 if (src_exponent > DBL_FX_MAX_EXP) { 385 /* check for MININT */ 386 if ((src_exponent > DBL_FX_MAX_EXP + 1) || 387 Dbl_isnotzero_mantissa(srcp1,srcp2) || Dbl_iszero_sign(srcp1)) { 388 if (Dbl_iszero_sign(srcp1)) { 389 resultp1 = 0x7fffffff; 390 resultp2 = 0xffffffff; 391 } 392 else { 393 resultp1 = 0x80000000; 394 resultp2 = 0; 395 } 396 397 if (Is_invalidtrap_enabled()) { 398 return(INVALIDEXCEPTION); 399 } 400 Set_invalidflag(); 401 Dint_copytoptr(resultp1,resultp2,dstptr); 402 return(NOEXCEPTION); 403 } 404 } 405 406 /* 407 * Generate result 408 */ 409 if (src_exponent >= 0) { 410 tempp1 = srcp1; 411 tempp2 = srcp2; 412 Dbl_clear_signexponent_set_hidden(tempp1); 413 Dint_from_dbl_mantissa(tempp1,tempp2,src_exponent, 414 resultp1, resultp2); 415 if (Dbl_isone_sign(srcp1)) { 416 Dint_setone_sign(resultp1,resultp2); 417 } 418 419 /* check for inexact */ 420 if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) { 421 inexact = TRUE; 422 /* round result */ 423 switch (Rounding_mode()) { 424 case ROUNDPLUS: 425 if (Dbl_iszero_sign(srcp1)) { 426 Dint_increment(resultp1,resultp2); 427 } 428 break; 429 case ROUNDMINUS: 430 if (Dbl_isone_sign(srcp1)) { 431 Dint_decrement(resultp1,resultp2); 432 } 433 break; 434 case ROUNDNEAREST: 435 if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent)) 436 if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) || 437 (Dint_isone_lowp2(resultp2))) { 438 if (Dbl_iszero_sign(srcp1)) { 439 Dint_increment(resultp1,resultp2); 440 } 441 else { 442 Dint_decrement(resultp1,resultp2); 443 } 444 } 445 } 446 } 447 } 448 else { 449 Dint_setzero(resultp1,resultp2); 450 451 /* check for inexact */ 452 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { 453 inexact = TRUE; 454 /* round result */ 455 switch (Rounding_mode()) { 456 case ROUNDPLUS: 457 if (Dbl_iszero_sign(srcp1)) { 458 Dint_increment(resultp1,resultp2); 459 } 460 break; 461 case ROUNDMINUS: 462 if (Dbl_isone_sign(srcp1)) { 463 Dint_decrement(resultp1,resultp2); 464 } 465 break; 466 case ROUNDNEAREST: 467 if (src_exponent == -1) 468 if (Dbl_isnotzero_mantissa(srcp1,srcp2)) { 469 if (Dbl_iszero_sign(srcp1)) { 470 Dint_increment(resultp1,resultp2); 471 } 472 else { 473 Dint_decrement(resultp1,resultp2); 474 } 475 } 476 } 477 } 478 } 479 Dint_copytoptr(resultp1,resultp2,dstptr); 480 if (inexact) { 481 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); 482 else Set_inexactflag(); 483 } 484 return(NOEXCEPTION); 485 } 486