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