Home | History | Annotate | Line # | Download | only in spmath
      1 /*	$NetBSD: fcnvfxt.c,v 1.5 2012/02/04 17:03:09 skrll Exp $	*/
      2 
      3 /*	$OpenBSD: fcnvfxt.c,v 1.8 2010/07/30 18:05:23 kettenis 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: fcnvfxt.c,v 1.5 2012/02/04 17:03:09 skrll 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 floating-point to single fixed-point format
     54  *  with truncated result
     55  */
     56 /*ARGSUSED*/
     57 int
     58 sgl_to_sgl_fcnvfxt(sgl_floating_point *srcptr, int *dstptr,
     59     unsigned int *status)
     60 {
     61 	register unsigned int src, temp;
     62 	register int src_exponent, result;
     63 
     64 	src = *srcptr;
     65 	src_exponent = Sgl_exponent(src) - SGL_BIAS;
     66 
     67 	/*
     68 	 * Test for overflow
     69 	 */
     70 	if (src_exponent > SGL_FX_MAX_EXP) {
     71 		/* check for MININT */
     72 		if ((src_exponent > SGL_FX_MAX_EXP + 1) ||
     73 		Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
     74 			if (Sgl_iszero_sign(src)) result = 0x7fffffff;
     75 			else result = 0x80000000;
     76 
     77 			if (Is_invalidtrap_enabled()) {
     78 				return(INVALIDEXCEPTION);
     79 			}
     80 			Set_invalidflag();
     81 			*dstptr = result;
     82 			return(NOEXCEPTION);
     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 		*dstptr = result;
     95 
     96 		/* check for inexact */
     97 		if (Sgl_isinexact_to_fix(src,src_exponent)) {
     98 			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
     99 			else Set_inexactflag();
    100 		}
    101 	}
    102 	else {
    103 		*dstptr = 0;
    104 
    105 		/* check for inexact */
    106 		if (Sgl_isnotzero_exponentmantissa(src)) {
    107 			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
    108 			else Set_inexactflag();
    109 		}
    110 	}
    111 	return(NOEXCEPTION);
    112 }
    113 
    114 /*
    115  *  Single Floating-point to Double Fixed-point
    116  */
    117 /*ARGSUSED*/
    118 int
    119 sgl_to_dbl_fcnvfxt(sgl_floating_point *srcptr, dbl_integer *dstptr,
    120     unsigned int *status)
    121 {
    122 	register int src_exponent, resultp1;
    123 	register unsigned int src, temp, resultp2;
    124 
    125 	src = *srcptr;
    126 	src_exponent = Sgl_exponent(src) - SGL_BIAS;
    127 
    128 	/*
    129 	 * Test for overflow
    130 	 */
    131 	if (src_exponent > DBL_FX_MAX_EXP) {
    132 		/* check for MININT */
    133 		if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
    134 		Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
    135 			if (Sgl_iszero_sign(src)) {
    136 				resultp1 = 0x7fffffff;
    137 				resultp2 = 0xffffffff;
    138 			}
    139 			else {
    140 				resultp1 = 0x80000000;
    141 				resultp2 = 0;
    142 			}
    143 
    144 			if (Is_invalidtrap_enabled()) {
    145 				return(INVALIDEXCEPTION);
    146 			}
    147 			Set_invalidflag();
    148 			Dint_copytoptr(resultp1,resultp2,dstptr);
    149 			return(NOEXCEPTION);
    150 		}
    151 		Dint_set_minint(resultp1,resultp2);
    152 		Dint_copytoptr(resultp1,resultp2,dstptr);
    153 		return(NOEXCEPTION);
    154 	}
    155 	/*
    156 	 * Generate result
    157 	 */
    158 	if (src_exponent >= 0) {
    159 		temp = src;
    160 		Sgl_clear_signexponent_set_hidden(temp);
    161 		Dint_from_sgl_mantissa(temp,src_exponent,resultp1,resultp2);
    162 		if (Sgl_isone_sign(src)) {
    163 			Dint_setone_sign(resultp1,resultp2);
    164 		}
    165 		Dint_copytoptr(resultp1,resultp2,dstptr);
    166 
    167 		/* check for inexact */
    168 		if (Sgl_isinexact_to_fix(src,src_exponent)) {
    169 			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
    170 			else Set_inexactflag();
    171 		}
    172 	}
    173 	else {
    174 		Dint_setzero(resultp1,resultp2);
    175 		Dint_copytoptr(resultp1,resultp2,dstptr);
    176 
    177 		/* check for inexact */
    178 		if (Sgl_isnotzero_exponentmantissa(src)) {
    179 			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
    180 			else Set_inexactflag();
    181 		}
    182 	}
    183 	return(NOEXCEPTION);
    184 }
    185 
    186 /*
    187  *  Double Floating-point to Single Fixed-point
    188  */
    189 /*ARGSUSED*/
    190 int
    191 dbl_to_sgl_fcnvfxt(dbl_floating_point *srcptr, int *dstptr,
    192     unsigned int *status)
    193 {
    194 	register unsigned int srcp1, srcp2, tempp1, tempp2;
    195 	register int src_exponent, result;
    196 
    197 	Dbl_copyfromptr(srcptr,srcp1,srcp2);
    198 	src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
    199 
    200 	/*
    201 	 * Test for overflow
    202 	 */
    203 	if (src_exponent > SGL_FX_MAX_EXP) {
    204 		/* check for MININT */
    205 		if (Dbl_isoverflow_to_int(src_exponent,srcp1,srcp2)) {
    206 			if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff;
    207 			else result = 0x80000000;
    208 
    209 			if (Is_invalidtrap_enabled()) {
    210 				return(INVALIDEXCEPTION);
    211 			}
    212 			Set_invalidflag();
    213 			*dstptr = result;
    214 			return(NOEXCEPTION);
    215 		}
    216 	}
    217 	/*
    218 	 * Generate result
    219 	 */
    220 	if (src_exponent >= 0) {
    221 		tempp1 = srcp1;
    222 		tempp2 = srcp2;
    223 		Dbl_clear_signexponent_set_hidden(tempp1);
    224 		Int_from_dbl_mantissa(tempp1,tempp2,src_exponent);
    225 		if (Dbl_isone_sign(srcp1) && (src_exponent <= SGL_FX_MAX_EXP))
    226 			result = -Dbl_allp1(tempp1);
    227 		else result = Dbl_allp1(tempp1);
    228 		*dstptr = result;
    229 
    230 		/* check for inexact */
    231 		if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
    232 			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
    233 			else Set_inexactflag();
    234 		}
    235 	}
    236 	else {
    237 		*dstptr = 0;
    238 
    239 		/* check for inexact */
    240 		if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
    241 			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
    242 			else Set_inexactflag();
    243 		}
    244 	}
    245 	return(NOEXCEPTION);
    246 }
    247 
    248 /*
    249  *  Double Floating-point to Double Fixed-point
    250  */
    251 /*ARGSUSED*/
    252 int
    253 dbl_to_dbl_fcnvfxt(dbl_floating_point *srcptr, dbl_integer *dstptr,
    254     unsigned int *status)
    255 {
    256 	register int src_exponent, resultp1;
    257 	register unsigned int srcp1, srcp2, tempp1, tempp2, resultp2;
    258 
    259 	Dbl_copyfromptr(srcptr,srcp1,srcp2);
    260 	src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
    261 
    262 	/*
    263 	 * Test for overflow
    264 	 */
    265 	if (src_exponent > DBL_FX_MAX_EXP) {
    266 		/* check for MININT */
    267 		if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
    268 		Dbl_isnotzero_mantissa(srcp1,srcp2) || Dbl_iszero_sign(srcp1)) {
    269 			if (Dbl_iszero_sign(srcp1)) {
    270 				resultp1 = 0x7fffffff;
    271 				resultp2 = 0xffffffff;
    272 			}
    273 			else {
    274 				resultp1 = 0x80000000;
    275 				resultp2 = 0;
    276 			}
    277 
    278 			if (Is_invalidtrap_enabled()) {
    279 				return(INVALIDEXCEPTION);
    280 			}
    281 			Set_invalidflag();
    282 			Dint_copytoptr(resultp1,resultp2,dstptr);
    283 			return(NOEXCEPTION);
    284 		}
    285 	}
    286 	/*
    287 	 * Generate result
    288 	 */
    289 	if (src_exponent >= 0) {
    290 		tempp1 = srcp1;
    291 		tempp2 = srcp2;
    292 		Dbl_clear_signexponent_set_hidden(tempp1);
    293 		Dint_from_dbl_mantissa(tempp1,tempp2,src_exponent,
    294 		resultp1,resultp2);
    295 		if (Dbl_isone_sign(srcp1)) {
    296 			Dint_setone_sign(resultp1,resultp2);
    297 		}
    298 		Dint_copytoptr(resultp1,resultp2,dstptr);
    299 
    300 		/* check for inexact */
    301 		if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
    302 			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
    303 			else Set_inexactflag();
    304 		}
    305 	}
    306 	else {
    307 		Dint_setzero(resultp1,resultp2);
    308 		Dint_copytoptr(resultp1,resultp2,dstptr);
    309 
    310 		/* check for inexact */
    311 		if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
    312 			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
    313 			else Set_inexactflag();
    314 		}
    315 	}
    316 	return(NOEXCEPTION);
    317 }
    318