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