1 /* $OpenBSD: fcnvfx.c,v 1.5 2001/03/29 03:58:18 mickey Exp $ */ 2 3 /* 4 * Copyright 1996 1995 by Open Software Foundation, Inc. 5 * All Rights Reserved 6 * 7 * Permission to use, copy, modify, and distribute this software and 8 * its documentation for any purpose and without fee is hereby granted, 9 * provided that the above copyright notice appears in all copies and 10 * that both the copyright notice and this permission notice appear in 11 * supporting documentation. 12 * 13 * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE 14 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 15 * FOR A PARTICULAR PURPOSE. 16 * 17 * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR 18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 19 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, 20 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 21 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22 * 23 */ 24 /* 25 * pmk1.1 26 */ 27 /* 28 * (c) Copyright 1986 HEWLETT-PACKARD COMPANY 29 * 30 * To anyone who acknowledges that this file is provided "AS IS" 31 * without any express or implied warranty: 32 * permission to use, copy, modify, and distribute this file 33 * for any purpose is hereby granted without fee, provided that 34 * the above copyright notice and this notice appears in all 35 * copies, and that the name of Hewlett-Packard Company not be 36 * used in advertising or publicity pertaining to distribution 37 * of the software without specific, written prior permission. 38 * Hewlett-Packard Company makes no representations about the 39 * suitability of this software for any purpose. 40 */ 41 42 #include "../spmath/float.h" 43 #include "../spmath/sgl_float.h" 44 #include "../spmath/dbl_float.h" 45 #include "../spmath/cnv_float.h" 46 47 /* 48 * Single Floating-point to Single Fixed-point 49 */ 50 /*ARGSUSED*/ 51 int 52 sgl_to_sgl_fcnvfx(srcptr,dstptr,status) 53 54 sgl_floating_point *srcptr; 55 int *dstptr; 56 unsigned int *status; 57 { 58 register unsigned int src, temp; 59 register int src_exponent, result; 60 register int inexact = FALSE; 61 62 src = *srcptr; 63 src_exponent = Sgl_exponent(src) - SGL_BIAS; 64 65 /* 66 * Test for overflow 67 */ 68 if (src_exponent > SGL_FX_MAX_EXP) { 69 /* check for MININT */ 70 if ((src_exponent > SGL_FX_MAX_EXP + 1) || 71 Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) { 72 /* 73 * Since source is a number which cannot be 74 * represented in fixed-point format, return 75 * largest (or smallest) fixed-point number. 76 */ 77 Sgl_return_overflow(src,dstptr); 78 } 79 } 80 /* 81 * Generate result 82 */ 83 if (src_exponent >= 0) { 84 temp = src; 85 Sgl_clear_signexponent_set_hidden(temp); 86 Int_from_sgl_mantissa(temp,src_exponent); 87 if (Sgl_isone_sign(src)) result = -Sgl_all(temp); 88 else result = Sgl_all(temp); 89 90 /* check for inexact */ 91 if (Sgl_isinexact_to_fix(src,src_exponent)) { 92 inexact = TRUE; 93 /* round result */ 94 switch (Rounding_mode()) { 95 case ROUNDPLUS: 96 if (Sgl_iszero_sign(src)) result++; 97 break; 98 case ROUNDMINUS: 99 if (Sgl_isone_sign(src)) result--; 100 break; 101 case ROUNDNEAREST: 102 if (Sgl_isone_roundbit(src,src_exponent)) { 103 if (Sgl_isone_stickybit(src,src_exponent) 104 || (Sgl_isone_lowmantissa(temp))) { 105 if (Sgl_iszero_sign(src)) result++; 106 else result--; 107 } 108 } 109 } 110 } 111 } 112 else { 113 result = 0; 114 115 /* check for inexact */ 116 if (Sgl_isnotzero_exponentmantissa(src)) { 117 inexact = TRUE; 118 /* round result */ 119 switch (Rounding_mode()) { 120 case ROUNDPLUS: 121 if (Sgl_iszero_sign(src)) result++; 122 break; 123 case ROUNDMINUS: 124 if (Sgl_isone_sign(src)) result--; 125 break; 126 case ROUNDNEAREST: 127 if (src_exponent == -1) 128 if (Sgl_isnotzero_mantissa(src)) { 129 if (Sgl_iszero_sign(src)) result++; 130 else result--; 131 } 132 } 133 } 134 } 135 *dstptr = result; 136 if (inexact) { 137 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); 138 else Set_inexactflag(); 139 } 140 return(NOEXCEPTION); 141 } 142 143 /* 144 * Single Floating-point to Double Fixed-point 145 */ 146 /*ARGSUSED*/ 147 int 148 sgl_to_dbl_fcnvfx(srcptr,dstptr,status) 149 150 sgl_floating_point *srcptr; 151 dbl_integer *dstptr; 152 unsigned int *status; 153 { 154 register int src_exponent, resultp1; 155 register unsigned int src, temp, resultp2; 156 register int inexact = FALSE; 157 158 src = *srcptr; 159 src_exponent = Sgl_exponent(src) - SGL_BIAS; 160 161 /* 162 * Test for overflow 163 */ 164 if (src_exponent > DBL_FX_MAX_EXP) { 165 /* check for MININT */ 166 if ((src_exponent > DBL_FX_MAX_EXP + 1) || 167 Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) { 168 /* 169 * Since source is a number which cannot be 170 * represented in fixed-point format, return 171 * largest (or smallest) fixed-point number. 172 */ 173 Sgl_return_overflow_dbl(src,dstptr); 174 } 175 Dint_set_minint(resultp1,resultp2); 176 Dint_copytoptr(resultp1,resultp2,dstptr); 177 return(NOEXCEPTION); 178 } 179 /* 180 * Generate result 181 */ 182 if (src_exponent >= 0) { 183 temp = src; 184 Sgl_clear_signexponent_set_hidden(temp); 185 Dint_from_sgl_mantissa(temp,src_exponent,resultp1,resultp2); 186 if (Sgl_isone_sign(src)) { 187 Dint_setone_sign(resultp1,resultp2); 188 } 189 190 /* check for inexact */ 191 if (Sgl_isinexact_to_fix(src,src_exponent)) { 192 inexact = TRUE; 193 /* round result */ 194 switch (Rounding_mode()) { 195 case ROUNDPLUS: 196 if (Sgl_iszero_sign(src)) { 197 Dint_increment(resultp1,resultp2); 198 } 199 break; 200 case ROUNDMINUS: 201 if (Sgl_isone_sign(src)) { 202 Dint_decrement(resultp1,resultp2); 203 } 204 break; 205 case ROUNDNEAREST: 206 if (Sgl_isone_roundbit(src,src_exponent)) 207 if (Sgl_isone_stickybit(src,src_exponent) || 208 (Dint_isone_lowp2(resultp2))) { 209 if (Sgl_iszero_sign(src)) { 210 Dint_increment(resultp1,resultp2); 211 } 212 else { 213 Dint_decrement(resultp1,resultp2); 214 } 215 } 216 } 217 } 218 } 219 else { 220 Dint_setzero(resultp1,resultp2); 221 222 /* check for inexact */ 223 if (Sgl_isnotzero_exponentmantissa(src)) { 224 inexact = TRUE; 225 /* round result */ 226 switch (Rounding_mode()) { 227 case ROUNDPLUS: 228 if (Sgl_iszero_sign(src)) { 229 Dint_increment(resultp1,resultp2); 230 } 231 break; 232 case ROUNDMINUS: 233 if (Sgl_isone_sign(src)) { 234 Dint_decrement(resultp1,resultp2); 235 } 236 break; 237 case ROUNDNEAREST: 238 if (src_exponent == -1) 239 if (Sgl_isnotzero_mantissa(src)) { 240 if (Sgl_iszero_sign(src)) { 241 Dint_increment(resultp1,resultp2); 242 } 243 else { 244 Dint_decrement(resultp1,resultp2); 245 } 246 } 247 } 248 } 249 } 250 Dint_copytoptr(resultp1,resultp2,dstptr); 251 if (inexact) { 252 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); 253 else Set_inexactflag(); 254 } 255 return(NOEXCEPTION); 256 } 257 258 /* 259 * Double Floating-point to Single Fixed-point 260 */ 261 /*ARGSUSED*/ 262 int 263 dbl_to_sgl_fcnvfx(srcptr,dstptr,status) 264 265 dbl_floating_point *srcptr; 266 int *dstptr; 267 unsigned int *status; 268 { 269 register unsigned int srcp1,srcp2, tempp1,tempp2; 270 register int src_exponent, result; 271 register int inexact = FALSE; 272 273 Dbl_copyfromptr(srcptr,srcp1,srcp2); 274 src_exponent = Dbl_exponent(srcp1) - DBL_BIAS; 275 276 /* 277 * Test for overflow 278 */ 279 if (src_exponent > SGL_FX_MAX_EXP) { 280 /* check for MININT */ 281 if (Dbl_isoverflow_to_int(src_exponent,srcp1,srcp2)) { 282 /* 283 * Since source is a number which cannot be 284 * represented in fixed-point format, return 285 * largest (or smallest) fixed-point number. 286 */ 287 Dbl_return_overflow(srcp1,srcp2,dstptr); 288 } 289 } 290 /* 291 * Generate result 292 */ 293 if (src_exponent >= 0) { 294 tempp1 = srcp1; 295 tempp2 = srcp2; 296 Dbl_clear_signexponent_set_hidden(tempp1); 297 Int_from_dbl_mantissa(tempp1,tempp2,src_exponent); 298 if (Dbl_isone_sign(srcp1) && (src_exponent <= SGL_FX_MAX_EXP)) 299 result = -Dbl_allp1(tempp1); 300 else result = Dbl_allp1(tempp1); 301 302 /* check for inexact */ 303 if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) { 304 inexact = TRUE; 305 /* round result */ 306 switch (Rounding_mode()) { 307 case ROUNDPLUS: 308 if (Dbl_iszero_sign(srcp1)) result++; 309 break; 310 case ROUNDMINUS: 311 if (Dbl_isone_sign(srcp1)) result--; 312 break; 313 case ROUNDNEAREST: 314 if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent)) 315 if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) || 316 (Dbl_isone_lowmantissap1(tempp1))) { 317 if (Dbl_iszero_sign(srcp1)) result++; 318 else result--; 319 } 320 } 321 /* check for overflow */ 322 if ((Dbl_iszero_sign(srcp1) && result < 0) || 323 (Dbl_isone_sign(srcp1) && result > 0)) { 324 Dbl_return_overflow(srcp1,srcp2,dstptr); 325 } 326 } 327 } 328 else { 329 result = 0; 330 331 /* check for inexact */ 332 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { 333 inexact = TRUE; 334 /* round result */ 335 switch (Rounding_mode()) { 336 case ROUNDPLUS: 337 if (Dbl_iszero_sign(srcp1)) result++; 338 break; 339 case ROUNDMINUS: 340 if (Dbl_isone_sign(srcp1)) result--; 341 break; 342 case ROUNDNEAREST: 343 if (src_exponent == -1) 344 if (Dbl_isnotzero_mantissa(srcp1,srcp2)) { 345 if (Dbl_iszero_sign(srcp1)) result++; 346 else result--; 347 } 348 } 349 } 350 } 351 *dstptr = result; 352 if (inexact) { 353 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); 354 else Set_inexactflag(); 355 } 356 return(NOEXCEPTION); 357 } 358 359 /* 360 * Double Floating-point to Double Fixed-point 361 */ 362 /*ARGSUSED*/ 363 int 364 dbl_to_dbl_fcnvfx(srcptr,dstptr,status) 365 366 dbl_floating_point *srcptr; 367 dbl_integer *dstptr; 368 unsigned int *status; 369 { 370 register int src_exponent, resultp1; 371 register unsigned int srcp1, srcp2, tempp1, tempp2, resultp2; 372 register int inexact = FALSE; 373 374 Dbl_copyfromptr(srcptr,srcp1,srcp2); 375 src_exponent = Dbl_exponent(srcp1) - DBL_BIAS; 376 377 /* 378 * Test for overflow 379 */ 380 if (src_exponent > DBL_FX_MAX_EXP) { 381 /* check for MININT */ 382 if ((src_exponent > DBL_FX_MAX_EXP + 1) || 383 Dbl_isnotzero_mantissa(srcp1,srcp2) || Dbl_iszero_sign(srcp1)) { 384 /* 385 * Since source is a number which cannot be 386 * represented in fixed-point format, return 387 * largest (or smallest) fixed-point number. 388 */ 389 Dbl_return_overflow_dbl(srcp1,srcp2,dstptr); 390 } 391 } 392 393 /* 394 * Generate result 395 */ 396 if (src_exponent >= 0) { 397 tempp1 = srcp1; 398 tempp2 = srcp2; 399 Dbl_clear_signexponent_set_hidden(tempp1); 400 Dint_from_dbl_mantissa(tempp1,tempp2,src_exponent, 401 resultp1, resultp2); 402 if (Dbl_isone_sign(srcp1)) { 403 Dint_setone_sign(resultp1,resultp2); 404 } 405 406 /* check for inexact */ 407 if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) { 408 inexact = TRUE; 409 /* round result */ 410 switch (Rounding_mode()) { 411 case ROUNDPLUS: 412 if (Dbl_iszero_sign(srcp1)) { 413 Dint_increment(resultp1,resultp2); 414 } 415 break; 416 case ROUNDMINUS: 417 if (Dbl_isone_sign(srcp1)) { 418 Dint_decrement(resultp1,resultp2); 419 } 420 break; 421 case ROUNDNEAREST: 422 if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent)) 423 if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) || 424 (Dint_isone_lowp2(resultp2))) { 425 if (Dbl_iszero_sign(srcp1)) { 426 Dint_increment(resultp1,resultp2); 427 } 428 else { 429 Dint_decrement(resultp1,resultp2); 430 } 431 } 432 } 433 } 434 } 435 else { 436 Dint_setzero(resultp1,resultp2); 437 438 /* check for inexact */ 439 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { 440 inexact = TRUE; 441 /* round result */ 442 switch (Rounding_mode()) { 443 case ROUNDPLUS: 444 if (Dbl_iszero_sign(srcp1)) { 445 Dint_increment(resultp1,resultp2); 446 } 447 break; 448 case ROUNDMINUS: 449 if (Dbl_isone_sign(srcp1)) { 450 Dint_decrement(resultp1,resultp2); 451 } 452 break; 453 case ROUNDNEAREST: 454 if (src_exponent == -1) 455 if (Dbl_isnotzero_mantissa(srcp1,srcp2)) { 456 if (Dbl_iszero_sign(srcp1)) { 457 Dint_increment(resultp1,resultp2); 458 } 459 else { 460 Dint_decrement(resultp1,resultp2); 461 } 462 } 463 } 464 } 465 } 466 Dint_copytoptr(resultp1,resultp2,dstptr); 467 if (inexact) { 468 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); 469 else Set_inexactflag(); 470 } 471 return(NOEXCEPTION); 472 } 473