Home | History | Annotate | Line # | Download | only in spmath
fcnvxf.c revision 1.1
      1 /*	$NetBSD: fcnvxf.c,v 1.1 2002/06/05 01:04:25 fredette Exp $	*/
      2 
      3 /*	$OpenBSD: fcnvxf.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  *  Convert single fixed-point to single floating-point format
     51  */
     52 int
     53 sgl_to_sgl_fcnvxf(srcptr,dstptr,status)
     54 
     55 int *srcptr;
     56 sgl_floating_point *dstptr;
     57 unsigned int *status;
     58 {
     59 	register int src, dst_exponent;
     60 	register unsigned int result = 0;
     61 
     62 	src = *srcptr;
     63 	/*
     64 	 * set sign bit of result and get magnitude of source
     65 	 */
     66 	if (src < 0) {
     67 		Sgl_setone_sign(result);
     68 		Int_negate(src);
     69 	}
     70 	else {
     71 		Sgl_setzero_sign(result);
     72 		/* Check for zero */
     73 		if (src == 0) {
     74 			Sgl_setzero(result);
     75 			*dstptr = result;
     76 			return(NOEXCEPTION);
     77 		}
     78 	}
     79 	/*
     80 	 * Generate exponent and normalized mantissa
     81 	 */
     82 	dst_exponent = 16;    /* initialize for normalization */
     83 	/*
     84 	 * Check word for most significant bit set.  Returns
     85 	 * a value in dst_exponent indicating the bit position,
     86 	 * between -1 and 30.
     87 	 */
     88 	Find_ms_one_bit(src,dst_exponent);
     89 	/*  left justify source, with msb at bit position 1  */
     90 	if (dst_exponent >= 0) src <<= dst_exponent;
     91 	else src = 1 << 30;
     92 	Sgl_set_mantissa(result, src >> (SGL_EXP_LENGTH-1));
     93 	Sgl_set_exponent(result, 30+SGL_BIAS - dst_exponent);
     94 
     95 	/* check for inexact */
     96 	if (Int_isinexact_to_sgl(src)) {
     97 		switch (Rounding_mode()) {
     98 			case ROUNDPLUS:
     99 				if (Sgl_iszero_sign(result))
    100 					Sgl_increment(result);
    101 				break;
    102 			case ROUNDMINUS:
    103 				if (Sgl_isone_sign(result))
    104 					Sgl_increment(result);
    105 				break;
    106 			case ROUNDNEAREST:
    107 				Sgl_roundnearest_from_int(src,result);
    108 		}
    109 		if (Is_inexacttrap_enabled()) {
    110 			*dstptr = result;
    111 			return(INEXACTEXCEPTION);
    112 		}
    113 		else Set_inexactflag();
    114 	}
    115 	*dstptr = result;
    116 	return(NOEXCEPTION);
    117 }
    118 
    119 /*
    120  *  Single Fixed-point to Double Floating-point
    121  */
    122 int
    123 sgl_to_dbl_fcnvxf(srcptr,dstptr,status)
    124 
    125 int *srcptr;
    126 dbl_floating_point *dstptr;
    127 unsigned int *status;
    128 {
    129 	register int src, dst_exponent;
    130 	register unsigned int resultp1 = 0, resultp2 = 0;
    131 
    132 	src = *srcptr;
    133 	/*
    134 	 * set sign bit of result and get magnitude of source
    135 	 */
    136 	if (src < 0) {
    137 		Dbl_setone_sign(resultp1);
    138 		Int_negate(src);
    139 	}
    140 	else {
    141 		Dbl_setzero_sign(resultp1);
    142 		/* Check for zero */
    143 		if (src == 0) {
    144 			Dbl_setzero(resultp1,resultp2);
    145 			Dbl_copytoptr(resultp1,resultp2,dstptr);
    146 			return(NOEXCEPTION);
    147 		}
    148 	}
    149 	/*
    150 	 * Generate exponent and normalized mantissa
    151 	 */
    152 	dst_exponent = 16;    /* initialize for normalization */
    153 	/*
    154 	 * Check word for most significant bit set.  Returns
    155 	 * a value in dst_exponent indicating the bit position,
    156 	 * between -1 and 30.
    157 	 */
    158 	Find_ms_one_bit(src,dst_exponent);
    159 	/*  left justify source, with msb at bit position 1  */
    160 	if (dst_exponent >= 0) src <<= dst_exponent;
    161 	else src = 1 << 30;
    162 	Dbl_set_mantissap1(resultp1, (src >> (DBL_EXP_LENGTH - 1)));
    163 	Dbl_set_mantissap2(resultp2, (src << (33-DBL_EXP_LENGTH)));
    164 	Dbl_set_exponent(resultp1, (30+DBL_BIAS) - dst_exponent);
    165 	Dbl_copytoptr(resultp1,resultp2,dstptr);
    166 	return(NOEXCEPTION);
    167 }
    168 
    169 /*
    170  *  Double Fixed-point to Single Floating-point
    171  */
    172 int
    173 dbl_to_sgl_fcnvxf(srcptr,dstptr,status)
    174 
    175 dbl_integer *srcptr;
    176 sgl_floating_point *dstptr;
    177 unsigned int *status;
    178 {
    179 	int dst_exponent, srcp1;
    180 	unsigned int result = 0, srcp2;
    181 
    182 	Dint_copyfromptr(srcptr,srcp1,srcp2);
    183 	/*
    184 	 * set sign bit of result and get magnitude of source
    185 	 */
    186 	if (srcp1 < 0) {
    187 		Sgl_setone_sign(result);
    188 		Dint_negate(srcp1,srcp2);
    189 	}
    190 	else {
    191 		Sgl_setzero_sign(result);
    192 		/* Check for zero */
    193 		if (srcp1 == 0 && srcp2 == 0) {
    194 			Sgl_setzero(result);
    195 			*dstptr = result;
    196 			return(NOEXCEPTION);
    197 		}
    198 	}
    199 	/*
    200 	 * Generate exponent and normalized mantissa
    201 	 */
    202 	dst_exponent = 16;    /* initialize for normalization */
    203 	if (srcp1 == 0) {
    204 		/*
    205 		 * Check word for most significant bit set.  Returns
    206 		 * a value in dst_exponent indicating the bit position,
    207 		 * between -1 and 30.
    208 		 */
    209 		Find_ms_one_bit(srcp2,dst_exponent);
    210 		/*  left justify source, with msb at bit position 1  */
    211 		if (dst_exponent >= 0) {
    212 			srcp1 = srcp2 << dst_exponent;
    213 			srcp2 = 0;
    214 		}
    215 		else {
    216 			srcp1 = srcp2 >> 1;
    217 			srcp2 <<= 31;
    218 		}
    219 		/*
    220 		 *  since msb set is in second word, need to
    221 		 *  adjust bit position count
    222 		 */
    223 		dst_exponent += 32;
    224 	}
    225 	else {
    226 		/*
    227 		 * Check word for most significant bit set.  Returns
    228 		 * a value in dst_exponent indicating the bit position,
    229 		 * between -1 and 30.
    230 		 *
    231 		 */
    232 		Find_ms_one_bit(srcp1,dst_exponent);
    233 		/*  left justify source, with msb at bit position 1  */
    234 		if (dst_exponent > 0) {
    235 			Variable_shift_double(srcp1,srcp2,(32-dst_exponent),
    236 			 srcp1);
    237 			srcp2 <<= dst_exponent;
    238 		}
    239 		/*
    240 		 * If dst_exponent = 0, we don't need to shift anything.
    241 		 * If dst_exponent = -1, src = - 2**63 so we won't need to
    242 		 * shift srcp2.
    243 		 */
    244 		else srcp1 >>= -(dst_exponent);
    245 	}
    246 	Sgl_set_mantissa(result, (srcp1 >> (SGL_EXP_LENGTH - 1)));
    247 	Sgl_set_exponent(result, (62+SGL_BIAS) - dst_exponent);
    248 
    249 	/* check for inexact */
    250 	if (Dint_isinexact_to_sgl(srcp1,srcp2)) {
    251 		switch (Rounding_mode()) {
    252 			case ROUNDPLUS:
    253 				if (Sgl_iszero_sign(result))
    254 					Sgl_increment(result);
    255 				break;
    256 			case ROUNDMINUS:
    257 				if (Sgl_isone_sign(result))
    258 					Sgl_increment(result);
    259 				break;
    260 			case ROUNDNEAREST:
    261 				Sgl_roundnearest_from_dint(srcp1,srcp2,result);
    262 		}
    263 		if (Is_inexacttrap_enabled()) {
    264 			*dstptr = result;
    265 			return(INEXACTEXCEPTION);
    266 		}
    267 		else Set_inexactflag();
    268 	}
    269 	*dstptr = result;
    270 	return(NOEXCEPTION);
    271 }
    272 
    273 /*
    274  *  Double Fixed-point to Double Floating-point
    275  */
    276 int
    277 dbl_to_dbl_fcnvxf(srcptr,dstptr,status)
    278 
    279 dbl_integer *srcptr;
    280 dbl_floating_point *dstptr;
    281 unsigned int *status;
    282 {
    283 	register int srcp1, dst_exponent;
    284 	register unsigned int srcp2, resultp1 = 0, resultp2 = 0;
    285 
    286 	Dint_copyfromptr(srcptr,srcp1,srcp2);
    287 	/*
    288 	 * set sign bit of result and get magnitude of source
    289 	 */
    290 	if (srcp1 < 0) {
    291 		Dbl_setone_sign(resultp1);
    292 		Dint_negate(srcp1,srcp2);
    293 	}
    294 	else {
    295 		Dbl_setzero_sign(resultp1);
    296 		/* Check for zero */
    297 		if (srcp1 == 0 && srcp2 ==0) {
    298 			Dbl_setzero(resultp1,resultp2);
    299 			Dbl_copytoptr(resultp1,resultp2,dstptr);
    300 			return(NOEXCEPTION);
    301 		}
    302 	}
    303 	/*
    304 	 * Generate exponent and normalized mantissa
    305 	 */
    306 	dst_exponent = 16;    /* initialize for normalization */
    307 	if (srcp1 == 0) {
    308 		/*
    309 		 * Check word for most significant bit set.  Returns
    310 		 * a value in dst_exponent indicating the bit position,
    311 		 * between -1 and 30.
    312 		 */
    313 		Find_ms_one_bit(srcp2,dst_exponent);
    314 		/*  left justify source, with msb at bit position 1  */
    315 		if (dst_exponent >= 0) {
    316 			srcp1 = srcp2 << dst_exponent;
    317 			srcp2 = 0;
    318 		}
    319 		else {
    320 			srcp1 = srcp2 >> 1;
    321 			srcp2 <<= 31;
    322 		}
    323 		/*
    324 		 *  since msb set is in second word, need to
    325 		 *  adjust bit position count
    326 		 */
    327 		dst_exponent += 32;
    328 	}
    329 	else {
    330 		/*
    331 		 * Check word for most significant bit set.  Returns
    332 		 * a value in dst_exponent indicating the bit position,
    333 		 * between -1 and 30.
    334 		 */
    335 		Find_ms_one_bit(srcp1,dst_exponent);
    336 		/*  left justify source, with msb at bit position 1  */
    337 		if (dst_exponent > 0) {
    338 			Variable_shift_double(srcp1,srcp2,(32-dst_exponent),
    339 			 srcp1);
    340 			srcp2 <<= dst_exponent;
    341 		}
    342 		/*
    343 		 * If dst_exponent = 0, we don't need to shift anything.
    344 		 * If dst_exponent = -1, src = - 2**63 so we won't need to
    345 		 * shift srcp2.
    346 		 */
    347 		else srcp1 >>= -(dst_exponent);
    348 	}
    349 	Dbl_set_mantissap1(resultp1, srcp1 >> (DBL_EXP_LENGTH-1));
    350 	Shiftdouble(srcp1,srcp2,DBL_EXP_LENGTH-1,resultp2);
    351 	Dbl_set_exponent(resultp1, (62+DBL_BIAS) - dst_exponent);
    352 
    353 	/* check for inexact */
    354 	if (Dint_isinexact_to_dbl(srcp2)) {
    355 		switch (Rounding_mode()) {
    356 			case ROUNDPLUS:
    357 				if (Dbl_iszero_sign(resultp1)) {
    358 					Dbl_increment(resultp1,resultp2);
    359 				}
    360 				break;
    361 			case ROUNDMINUS:
    362 				if (Dbl_isone_sign(resultp1)) {
    363 					Dbl_increment(resultp1,resultp2);
    364 				}
    365 				break;
    366 			case ROUNDNEAREST:
    367 				Dbl_roundnearest_from_dint(srcp2,resultp1,
    368 				resultp2);
    369 		}
    370 		if (Is_inexacttrap_enabled()) {
    371 			Dbl_copytoptr(resultp1,resultp2,dstptr);
    372 			return(INEXACTEXCEPTION);
    373 		}
    374 		else Set_inexactflag();
    375 	}
    376 	Dbl_copytoptr(resultp1,resultp2,dstptr);
    377 	return(NOEXCEPTION);
    378 }
    379