Home | History | Annotate | Line # | Download | only in spmath
      1 /*	$NetBSD: cnv_float.h,v 1.4 2019/02/06 05:04:41 mrg Exp $	*/
      2 
      3 /*	$OpenBSD: cnv_float.h,v 1.5 2001/03/29 03:58:17 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  * pmk1.1
     27  */
     28 /*
     29  * (c) Copyright 1986 HEWLETT-PACKARD COMPANY
     30  *
     31  * To anyone who acknowledges that this file is provided "AS IS"
     32  * without any express or implied warranty:
     33  *     permission to use, copy, modify, and distribute this file
     34  * for any purpose is hereby granted without fee, provided that
     35  * the above copyright notice and this notice appears in all
     36  * copies, and that the name of Hewlett-Packard Company not be
     37  * used in advertising or publicity pertaining to distribution
     38  * of the software without specific, written prior permission.
     39  * Hewlett-Packard Company makes no representations about the
     40  * suitability of this software for any purpose.
     41  */
     42 
     43 /*
     44  * Some more constants
     45  */
     46 #define SGL_FX_MAX_EXP 30
     47 #define DBL_FX_MAX_EXP 62
     48 #define QUAD_FX_MAX_EXP 126
     49 
     50 
     51 #define Dintp1(object) (object)
     52 #define Dintp2(object) (object)
     53 
     54 #define Qintp0(object) (object)
     55 #define Qintp1(object) (object)
     56 #define Qintp2(object) (object)
     57 #define Qintp3(object) (object)
     58 
     59 
     60 /*
     61  * These macros will be used specifically by the convert instructions.
     62  *
     63  *
     64  * Single format macros
     65  */
     66 
     67 #define Sgl_to_dbl_exponent(src_exponent,dest)			\
     68     Deposit_dexponent(dest,src_exponent+(DBL_BIAS-SGL_BIAS))
     69 
     70 #define Sgl_to_dbl_mantissa(src_mantissa,destA,destB)	\
     71     Deposit_dmantissap1(destA,src_mantissa>>3);		\
     72     Dmantissap2(destB) = src_mantissa << 29
     73 
     74 #define Sgl_isinexact_to_fix(sgl_value,exponent)	\
     75     ((exponent < (SGL_P - 1)) ?				\
     76      (Sall(sgl_value) << (SGL_EXP_LENGTH + 1 + exponent)) : false)
     77 
     78 #define Int_isinexact_to_sgl(int_value)	((int_value << (33 - SGL_EXP_LENGTH)) != 0)
     79 
     80 #define Sgl_roundnearest_from_int(int_value,sgl_value)			\
     81     if (int_value & 1<<(SGL_EXP_LENGTH - 2))   /* round bit */		\
     82 	if (((int_value << (34 - SGL_EXP_LENGTH)) != 0) || Slow(sgl_value))	\
     83 		Sall(sgl_value)++
     84 
     85 #define Dint_isinexact_to_sgl(dint_valueA,dint_valueB)		\
     86     (((Dintp1(dint_valueA) << (33 - SGL_EXP_LENGTH)) != 0) || Dintp2(dint_valueB))
     87 
     88 #define Sgl_roundnearest_from_dint(dint_valueA,dint_valueB,sgl_value)	\
     89     if (Dintp1(dint_valueA) & 1<<(SGL_EXP_LENGTH - 2))			\
     90 	if (((Dintp1(dint_valueA) << (34 - SGL_EXP_LENGTH)) != 0) ||	\
     91 	Dintp2(dint_valueB) || Slow(sgl_value)) Sall(sgl_value)++
     92 
     93 #define Dint_isinexact_to_dbl(dint_value)	\
     94     (Dintp2(dint_value) << (33 - DBL_EXP_LENGTH))
     95 
     96 #define Dbl_roundnearest_from_dint(dint_opndB,dbl_opndA,dbl_opndB)	\
     97     if (Dintp2(dint_opndB) & 1<<(DBL_EXP_LENGTH - 2))			\
     98        if ((Dintp2(dint_opndB) << (34 -DBL_EXP_LENGTH)) || Dlowp2(dbl_opndB))  \
     99 	  if ((++Dallp2(dbl_opndB))==0) Dallp1(dbl_opndA)++
    100 
    101 #define Sgl_isone_roundbit(sgl_value,exponent)			\
    102     ((Sall(sgl_value) << (SGL_EXP_LENGTH + 1 + exponent)) >> 31)
    103 
    104 #define Sgl_isone_stickybit(sgl_value,exponent)		\
    105     (exponent < (SGL_P - 2) ?				\
    106      Sall(sgl_value) << (SGL_EXP_LENGTH + 2 + exponent) : false)
    107 
    108 
    109 /*
    110  * Double format macros
    111  */
    112 
    113 #define Dbl_to_sgl_exponent(src_exponent,dest)			\
    114     dest = src_exponent + (SGL_BIAS - DBL_BIAS)
    115 
    116 #define Dbl_to_sgl_mantissa(srcA,srcB,dest,inexact,guard,sticky,odd)	\
    117     Shiftdouble(Dmantissap1(srcA),Dmantissap2(srcB),29,dest);	\
    118     guard = Dbit3p2(srcB);					\
    119     sticky = Dallp2(srcB)<<4;					\
    120     inexact = guard | sticky;					\
    121     odd = Dbit2p2(srcB)
    122 
    123 #define Dbl_to_sgl_denormalized(srcA,srcB,exp,dest,inexact,guard,sticky,odd,tiny) \
    124     Deposit_dexponent(srcA,1);						\
    125     tiny = true;							\
    126     if (exp >= -2) {							\
    127 	if (exp == 0) {							\
    128 	    inexact = Dallp2(srcB) << 3;				\
    129 	    guard = inexact >> 31;					\
    130 	    sticky = inexact << 1;					\
    131 	    Shiftdouble(Dmantissap1(srcA),Dmantissap2(srcB),29,dest);	\
    132 	    odd = dest << 31;						\
    133 	    if (inexact) {						\
    134 		switch(Rounding_mode()) {				\
    135 		    case ROUNDPLUS:					\
    136 			if (Dbl_iszero_sign(srcA)) {			\
    137 			    dest++;					\
    138 			    if (Sgl_isone_hidden(dest))	\
    139 				tiny = false;				\
    140 			    dest--;					\
    141 			}						\
    142 			break;						\
    143 		    case ROUNDMINUS:					\
    144 			if (Dbl_isone_sign(srcA)) {			\
    145 			    dest++;					\
    146 			    if (Sgl_isone_hidden(dest))	\
    147 				tiny = false;				\
    148 			    dest--;					\
    149 			}						\
    150 			break;						\
    151 		    case ROUNDNEAREST:					\
    152 			if (guard && (sticky || odd)) {			\
    153 			    dest++;					\
    154 			    if (Sgl_isone_hidden(dest))	\
    155 				tiny = false;				\
    156 			    dest--;					\
    157 			}						\
    158 			break;						\
    159 		}							\
    160 	    }								\
    161 		/* shift right by one to get correct result */		\
    162 		guard = odd;						\
    163 		sticky = inexact;					\
    164 		inexact |= guard;					\
    165 		dest >>= 1;						\
    166 		Deposit_dsign(srcA,0);					\
    167 		Shiftdouble(Dallp1(srcA),Dallp2(srcB),30,dest);		\
    168 		odd = dest << 31;					\
    169 	}								\
    170 	else {								\
    171 	    inexact = Dallp2(srcB) << (2 + exp);			\
    172 	    guard = inexact >> 31;					\
    173 	    sticky = inexact << 1;					\
    174 	    Deposit_dsign(srcA,0);					\
    175 	    if (exp == -2) dest = Dallp1(srcA);				\
    176 	    else Variable_shift_double(Dallp1(srcA),Dallp2(srcB),30-exp,dest); \
    177 	    odd = dest << 31;						\
    178 	}								\
    179     }									\
    180     else {								\
    181 	Deposit_dsign(srcA,0);						\
    182 	if (exp > (1 - SGL_P)) {					\
    183 	    dest = Dallp1(srcA) >> (- 2 - exp);				\
    184 	    inexact = Dallp1(srcA) << (34 + exp);			\
    185 	    guard = inexact >> 31;					\
    186 	    sticky = (inexact << 1) | Dallp2(srcB);			\
    187 	    inexact |= Dallp2(srcB);					\
    188 	    odd = dest << 31;						\
    189 	}								\
    190 	else {								\
    191 	    dest = 0;							\
    192 	    inexact = Dallp1(srcA) | Dallp2(srcB);			\
    193 	    if (exp == (1 - SGL_P)) {					\
    194 		guard = Dhidden(srcA);					\
    195 		sticky = Dmantissap1(srcA) | Dallp2(srcB);		\
    196 	    }								\
    197 	    else {							\
    198 		guard = 0;						\
    199 		sticky = inexact;					\
    200 	    }								\
    201 	    odd = 0;							\
    202 	}								\
    203     }									\
    204     exp = 0
    205 
    206 #define Dbl_isinexact_to_fix(dbl_valueA,dbl_valueB,exponent)		\
    207     (exponent < (DBL_P-33) ?						\
    208      Dallp2(dbl_valueB) || Dallp1(dbl_valueA) << (DBL_EXP_LENGTH+1+exponent) : \
    209      (exponent < (DBL_P-1) ? Dallp2(dbl_valueB) << (exponent + (33-DBL_P)) :   \
    210       false))
    211 
    212 #define Dbl_isoverflow_to_int(exponent,dbl_valueA,dbl_valueB)		\
    213     ((exponent > SGL_FX_MAX_EXP + 1) || Dsign(dbl_valueA)==0 ||		\
    214      Dmantissap1(dbl_valueA)!=0 || (Dallp2(dbl_valueB)>>21)!=0 )
    215 
    216 #define Dbl_isone_roundbit(dbl_valueA,dbl_valueB,exponent)	      \
    217     ((exponent < (DBL_P - 33) ?						\
    218       Dallp1(dbl_valueA) >> ((30 - DBL_EXP_LENGTH) - exponent) :	\
    219       Dallp2(dbl_valueB) >> ((DBL_P - 2) - exponent)) & 1)
    220 
    221 #define Dbl_isone_stickybit(dbl_valueA,dbl_valueB,exponent)		\
    222     (exponent < (DBL_P-34) ?						\
    223      (Dallp2(dbl_valueB) || Dallp1(dbl_valueA)<<(DBL_EXP_LENGTH+2+exponent)) : \
    224      (exponent<(DBL_P-2) ? (Dallp2(dbl_valueB) << (exponent + (34-DBL_P))) : \
    225       false))
    226 
    227 
    228 /* Int macros */
    229 
    230 #define Int_from_sgl_mantissa(sgl_value,exponent)	\
    231     Sall(sgl_value) =				\
    232 	(unsigned)(Sall(sgl_value) << SGL_EXP_LENGTH)>>(31 - exponent)
    233 
    234 #define Int_from_dbl_mantissa(dbl_valueA,dbl_valueB,exponent)	\
    235     Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),22,Dallp1(dbl_valueA)); \
    236     if (exponent < 31) Dallp1(dbl_valueA) >>= 30 - exponent;	\
    237     else Dallp1(dbl_valueA) <<= 1
    238 
    239 #define Int_negate(int_value) int_value = -int_value
    240 
    241 
    242 /* Dint macros */
    243 
    244 #define Dint_from_sgl_mantissa(sgl_value,exponent,dresultA,dresultB)	\
    245     {Sall(sgl_value) <<= SGL_EXP_LENGTH;  /*  left-justify  */		\
    246     if (exponent <= 31) {						\
    247 	Dintp1(dresultA) = 0;						\
    248 	Dintp2(dresultB) = (unsigned)Sall(sgl_value) >> (31 - exponent); \
    249     }									\
    250     else {								\
    251 	Dintp1(dresultA) = Sall(sgl_value) >> (63 - exponent);		\
    252 	Dintp2(dresultB) = Sall(sgl_value) << (exponent - 31);		\
    253     }}
    254 
    255 
    256 #define Dint_from_dbl_mantissa(dbl_valueA,dbl_valueB,exponent,destA,destB) \
    257     {if (exponent < 32) {						\
    258 	Dintp1(destA) = 0;						\
    259 	if (exponent <= 20)						\
    260 	    Dintp2(destB) = Dallp1(dbl_valueA) >> (20-(exponent));	\
    261 	else Variable_shift_double(Dallp1(dbl_valueA),Dallp2(dbl_valueB), \
    262 	     (52-(exponent)),Dintp2(destB));				\
    263     }									\
    264     else {								\
    265 	if (exponent <= 52) {						\
    266 	    Dintp1(destA) = Dallp1(dbl_valueA) >> (52-(exponent));	\
    267 	    if (exponent == 52) Dintp2(destB) = Dallp2(dbl_valueB);	\
    268 	    else Variable_shift_double(Dallp1(dbl_valueA),Dallp2(dbl_valueB), \
    269 	    52-exponent,Dintp2(destB));					\
    270 	}								\
    271 	else {								\
    272 	    Variable_shift_double(Dallp1(dbl_valueA),Dallp2(dbl_valueB), \
    273 	    84-exponent,Dintp1(destA));					\
    274 	    Dintp2(destB) = Dallp2(dbl_valueB) << ((exponent)-52);	\
    275 	}								\
    276     }}
    277 
    278 #define Dint_setzero(dresultA,dresultB)	\
    279     Dintp1(dresultA) = 0;	\
    280     Dintp2(dresultB) = 0
    281 
    282 #define Dint_setone_sign(dresultA,dresultB)		\
    283     Dintp1(dresultA) = ~Dintp1(dresultA);		\
    284     if ((Dintp2(dresultB) = -Dintp2(dresultB)) == 0) Dintp1(dresultA)++
    285 
    286 #define Dint_set_minint(dresultA,dresultB)		\
    287     Dintp1(dresultA) = 1<<31;				\
    288     Dintp2(dresultB) = 0
    289 
    290 #define Dint_isone_lowp2(dresultB)  (Dintp2(dresultB) & 01)
    291 
    292 #define Dint_increment(dresultA,dresultB)		\
    293     if ((++Dintp2(dresultB))==0) Dintp1(dresultA)++
    294 
    295 #define Dint_decrement(dresultA,dresultB)		\
    296     if ((Dintp2(dresultB)--)==0) Dintp1(dresultA)--
    297 
    298 #define Dint_negate(dresultA,dresultB)			\
    299     Dintp1(dresultA) = ~Dintp1(dresultA);		\
    300     if ((Dintp2(dresultB) = -Dintp2(dresultB))==0) Dintp1(dresultA)++
    301 
    302 #define Dint_copyfromptr(src,destA,destB) \
    303      Dintp1(destA) = src->wd0;		\
    304      Dintp2(destB) = src->wd1
    305 #define Dint_copytoptr(srcA,srcB,dest)	\
    306     dest->wd0 = Dintp1(srcA);		\
    307     dest->wd1 = Dintp2(srcB)
    308 
    309 
    310 /* other macros  */
    311 
    312 #define Find_ms_one_bit(value, position)	\
    313     {						\
    314 	int var;				\
    315 	for (var=8; var >=1; var >>= 1) {	\
    316 	    if (value >> (32 - position))	\
    317 		position -= var;		\
    318 		else position += var;		\
    319 	}					\
    320 	if ((value >> (32 - position)) == 0)	\
    321 	    position--;				\
    322 	else position -= 2;			\
    323     }
    324 
    325 /*
    326  * The following 4 functions handle the assignment of a floating point
    327  * number to a 32-bit integer in cases where the floating point number
    328  * is too large (or small) to fit in the integer field.
    329  *
    330  * In all these cases, HP-UX would return an UNIMPLEMENTEDEXCEPTION
    331  * resulting in a SIGFPE being sent to the process.  For BSD's math
    332  * library (and various other applications), this was unacceptable.
    333  * As a result, we now return maxint/minint (like most other OS's)
    334  * and either return an INEXACTEXCEPTION (SIGFPE) or set the inexact
    335  * flag (so that the program may continue execution).
    336  *
    337  * After discussing this with Jerry Huck @ HP, the one case where we
    338  * differ from BSD is for programs that try to convert a NaN to an
    339  * integer; in this case, we will return an UNIMPLEMENTEDEXCEPTION
    340  * since doing anything else would be completely unreasonable.
    341  *
    342  *	jef
    343  */
    344 
    345 #define	Dbl_return_overflow(srcp1, srcp2, resultp)	\
    346     {						\
    347 	if (Dbl_isnan(srcp1, srcp2))		\
    348 		return(UNIMPLEMENTEDEXCEPTION);	\
    349 	if (Dbl_iszero_sign(srcp1))		\
    350 		*resultp = 0x7fffffff;		\
    351 	else					\
    352 		*resultp = 0x80000000;		\
    353 	if (Is_overflowtrap_enabled()) {	\
    354 		if (Is_inexacttrap_enabled())	\
    355 			return(OVERFLOWEXCEPTION|INEXACTEXCEPTION);	\
    356 		else				\
    357 			Set_inexactflag();	\
    358 		return(OVERFLOWEXCEPTION);	\
    359 	}					\
    360 	return(NOEXCEPTION);			\
    361     }
    362 
    363 #define	Dbl_return_overflow_dbl(srcp1, srcp2, resultp)	\
    364     {						\
    365 	if (Dbl_isnan(srcp1, srcp2))		\
    366 		return(UNIMPLEMENTEDEXCEPTION);	\
    367 	if (Dbl_iszero_sign(srcp1)) {		\
    368 		Dint_copytoptr(0x7fffffff,0xffffffff,resultp); \
    369 	} else {				\
    370 		Dint_copytoptr(0x80000000,0x00000000,resultp); \
    371 	}					\
    372 	if (Is_overflowtrap_enabled()) {	\
    373 		if (Is_inexacttrap_enabled())	\
    374 			return(OVERFLOWEXCEPTION|INEXACTEXCEPTION);	\
    375 		else				\
    376 			Set_inexactflag();	\
    377 		return(OVERFLOWEXCEPTION);	\
    378 	}					\
    379 	return(NOEXCEPTION);			\
    380     }
    381 
    382 #define	Sgl_return_overflow(src, resultp)	\
    383     {						\
    384 	if (Sgl_isnan(src))			\
    385 		return(UNIMPLEMENTEDEXCEPTION);	\
    386 	if (Sgl_iszero_sign(src))		\
    387 		*resultp = 0x7fffffff;		\
    388 	else					\
    389 		*resultp = 0x80000000;		\
    390 	if (Is_overflowtrap_enabled()) {	\
    391 		if (Is_inexacttrap_enabled())	\
    392 			return(OVERFLOWEXCEPTION|INEXACTEXCEPTION);	\
    393 		else				\
    394 			Set_inexactflag();	\
    395 		return(OVERFLOWEXCEPTION);	\
    396 	}					\
    397 	return(NOEXCEPTION);			\
    398     }
    399 
    400 #define	Sgl_return_overflow_dbl(src, resultp)	\
    401     {						\
    402 	if (Sgl_isnan(src))			\
    403 		return(UNIMPLEMENTEDEXCEPTION);	\
    404 	if (Sgl_iszero_sign(src)) {		\
    405 		Dint_copytoptr(0x7fffffff,0xffffffff,resultp); \
    406 	} else {				\
    407 		Dint_copytoptr(0x80000000,0x00000000,resultp); \
    408 	}					\
    409 	if (Is_overflowtrap_enabled()) {	\
    410 		if (Is_inexacttrap_enabled())	\
    411 			return(OVERFLOWEXCEPTION|INEXACTEXCEPTION);	\
    412 		else				\
    413 			Set_inexactflag();	\
    414 		return(OVERFLOWEXCEPTION);	\
    415 	}					\
    416 	return(NOEXCEPTION);			\
    417     }
    418 
    419 int sgl_to_sgl_fcnvfx(sgl_floating_point *, sgl_floating_point *, unsigned int *);
    420 int sgl_to_dbl_fcnvfx(sgl_floating_point *, dbl_integer *, unsigned int *);
    421 int dbl_to_sgl_fcnvfx(dbl_floating_point *, int *, unsigned int *);
    422 int dbl_to_dbl_fcnvfx(dbl_floating_point *, dbl_integer *, unsigned int *);
    423 
    424 int sgl_to_sgl_fcnvfxt(sgl_floating_point *, int *, unsigned int *);
    425 int sgl_to_dbl_fcnvfxt(sgl_floating_point *, dbl_integer *, unsigned int *);
    426 int dbl_to_sgl_fcnvfxt(dbl_floating_point *, int *, unsigned int *);
    427 int dbl_to_dbl_fcnvfxt(dbl_floating_point *, dbl_integer *, unsigned int *);
    428 
    429 int sgl_to_sgl_fcnvxf(int *, sgl_floating_point *, unsigned int *);
    430 int sgl_to_dbl_fcnvxf(int *, dbl_floating_point *, unsigned int *);
    431 int dbl_to_sgl_fcnvxf(dbl_integer *, sgl_floating_point *, unsigned int *);
    432 int dbl_to_dbl_fcnvxf(dbl_integer *, dbl_floating_point *, unsigned int *);
    433 
    434 
    435 
    436