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