Home | History | Annotate | Line # | Download | only in spmath
fcnvfx.c revision 1.4
      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