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