220 lines
		
	
	
	
		
			4.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			220 lines
		
	
	
	
		
			4.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|   (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
 | |
|   See the copyright notice in the ACK home directory, in the file "Copyright".
 | |
| */
 | |
| 
 | |
| /* $Header$ */
 | |
| 
 | |
| /*
 | |
| #define	PRT_EXIT
 | |
| #define	PRT_TRAP
 | |
| #define	PRT_ENTRY
 | |
| 	COMPACT EXTEND FORMAT INTO FLOAT OF PROPER SIZE
 | |
| */
 | |
| 
 | |
| # include "FP_bias.h"
 | |
| # include "FP_shift.h"
 | |
| # include "FP_trap.h"
 | |
| # include "FP_types.h"
 | |
| # include "get_put.h"
 | |
| 
 | |
| compact(f,to,size)
 | |
| EXTEND	*f;
 | |
| _double	*to;
 | |
| int	size;
 | |
| {
 | |
| 	DOUBLE	*DBL;
 | |
| 	int	error = 0;
 | |
| 	SINGLE	*SGL;
 | |
| 	int	exact;
 | |
| 
 | |
| #ifdef	PRT_ENTRY
 | |
| 	prt_ext("enter compact:",f);
 | |
| #endif	PRT_ENTRY
 | |
| 	if (size == sizeof(_double))
 | |
| /********************************************************/
 | |
| /*
 | |
| 	COMPACT EXTENDED INTO DOUBLE
 | |
| */
 | |
| /********************************************************/
 | |
| 	{
 | |
| 		if ((f->m1|(f->m2 & DBL_ZERO)) == 0L)	{
 | |
| 			zrf8(to);
 | |
| 			goto leave;
 | |
| 		}
 | |
| 		f->exp += DBL_BIAS;	/* restore proper bias	*/
 | |
| 		if (f->exp > DBL_MAX)	{
 | |
| dbl_over:			trap(EFOVFL);
 | |
| #ifdef	PRT_TRAP
 | |
| 				prt_ext("FCOMPACT DBL OVERFLOW",f);
 | |
| #endif	PRT_TRAP
 | |
| 			f->exp = DBL_MAX;
 | |
| 			f->m1 = f->m2 = 0L;
 | |
| 			if (error++)
 | |
| 				return;
 | |
| 		}
 | |
| 		else if (f->exp < DBL_MIN)	{
 | |
| #ifdef	PRT_TRAP
 | |
| 			prt_ext("FCOMPACT DBL UNDERFLOW",f);
 | |
| #endif	PRT_TRAP
 | |
| 			trap(EFUNFL);
 | |
| 			f->exp = DBL_MIN;
 | |
| 			f->m1 = f->m2 = 0L;
 | |
| 			if (error++)
 | |
| 				return;
 | |
| 		}
 | |
| 			
 | |
| 		/* local CAST conversion		*/
 | |
| 		DBL = (DOUBLE *) to;
 | |
| 		/* check if answer is exact		*/
 | |
| 		/* (the last 11 bits are zero (0)	*/
 | |
| 
 | |
| 		exact = ((f->m2 & DBL_EXACT) == 0) ? 1 : 0;
 | |
| 
 | |
| 		/* because of special format shift only 10 bits */
 | |
| 		/* bit shift mantissa 10 bits		*/
 | |
| 
 | |
| 		/* first align within words, then do store operation */
 | |
| 
 | |
| 		DBL->_s.p1.fract = f->m1 >> DBL_RUNPACK;   /* plus 22 == 32 */
 | |
| 		DBL->_s.p2       = f->m2 >> DBL_RUNPACK;   /* plus 22 == 32 */
 | |
| 		DBL->_s.p2      |= (f->m1 << DBL_LUNPACK); /* plus 10 == 32 */
 | |
| 
 | |
| 		/* if not exact then round to nearest	*/
 | |
| 
 | |
| 		if (!exact)	{
 | |
| 		    /* INEXACT(); */
 | |
| 		    if (f->m2 & DBL_ROUNDUP)	{
 | |
| 			DBL->_s.p2++;	/* rounding up	*/
 | |
| 			if (DBL->_s.p2 == 0L) { /* carry out	*/
 | |
| #ifdef	PRT_RNDMSG
 | |
| 			    write(2,"rounding up lsb\n",16);
 | |
| #endif	PRT_RNDMSG
 | |
| 			    DBL->_s.p1.fract++;
 | |
| 			    if (DBL->_s.p1.fract & DBL_CARRYOUT) { /* carry out */
 | |
| #ifdef	PRT_RNDMSG
 | |
| 				write(2,"shift due to rounding\n",22);
 | |
| #endif	PRT_RNDMSG
 | |
| 				if (DBL->_s.p1.fract & 01)
 | |
| 				    DBL->_s.p2 = CARRYBIT;
 | |
| 				DBL->_s.p1.fract >>= 1;
 | |
| 				f->exp++;
 | |
| 			    }
 | |
| 			}
 | |
| 		    }
 | |
| 		}
 | |
| 		/*	check for overflow			*/
 | |
| 		if (f->exp > DBL_MAX)
 | |
| 		    goto dbl_over;
 | |
| 
 | |
| 		/* STORE EXPONENT:			*/
 | |
| 
 | |
| 		/* 1) clear leading bits (B4-B15)	*/
 | |
| 		DBL->_s.p1.fract &= DBL_MASK;
 | |
| 
 | |
| 		/* 2) shift and store exponent		*/
 | |
| 		f->exp <<= DBL_EXPSHIFT;
 | |
| 		DBL->_s.p1.fract |= ((long) f->exp << EXP_STORE);
 | |
| 	}
 | |
| 	else
 | |
| /********************************************************/
 | |
| /*
 | |
| 	COMPACT EXTENDED INTO FLOAT
 | |
| */
 | |
| /********************************************************/
 | |
| 	{
 | |
| 		/* local CAST conversion		*/
 | |
| 		SGL = (SINGLE *) to;
 | |
| 		if ((f->m1 & SGL_ZERO) == 0L)	{
 | |
| 			SGL->fract = 0L;
 | |
| 			goto leave;
 | |
| 		}
 | |
| 		f->exp += SGL_BIAS;	/* restore bias	*/
 | |
| 		if (f->exp > SGL_MAX)	{
 | |
| sgl_over:			trap(EFOVFL);
 | |
| #ifdef	PRT_TRAP
 | |
| 				prt_ext("FCOMPACT FLOAT OVERFLOW",f);
 | |
| #endif	PRT_TRAP
 | |
| 			f->exp = SGL_MAX;
 | |
| 			f->m1 = f->m2 = 0L;
 | |
| 			if (error++)
 | |
| 				return;
 | |
| 		}
 | |
| 		else if (f->exp < SGL_MIN)	{
 | |
| #ifdef	PRT_TRAP
 | |
| 			prt_ext("FCOMPACT FLOAT UNDERFLOW",f);
 | |
| #endif	PRT_TRAP
 | |
| 			trap(EFUNFL);
 | |
| 			f->exp = SGL_MIN;
 | |
| 			f->m1 = f->m2 = 0L;
 | |
| 			if (error++)
 | |
| 				return;
 | |
| 		}
 | |
| 		/* check if the answer is exact */
 | |
| 		/* the last 40 bits are zero	*/
 | |
| 		/* check first last bits of mantissa 1 */
 | |
| 		exact = ((f->m1 & SGL_EXACT) == 0) ? 1 : 0;
 | |
| 
 | |
| 		/* check last 32 bits in mantissa 2	*/
 | |
| 		if (exact) /* first part masks to zero	*/
 | |
| 			exact = (f->m2 == 0L) ? 1 : 0;
 | |
| 
 | |
| 		/* shift mantissa and store	*/
 | |
| 		SGL->fract = (f->m1 >> SGL_RUNPACK);
 | |
| 
 | |
| 		/* check for rounding to nearest	*/
 | |
| 		if (!exact)	{
 | |
| 			/* INEXACT(); */
 | |
| 			if (f->m1 & SGL_ROUNDUP) {
 | |
| 				SGL->fract++;
 | |
| #ifdef	PRT_RNDMSG
 | |
| 				write(2,"rounding up lsb\n",16);
 | |
| #endif	PRT_RNDMSG
 | |
| 			/* check normal */
 | |
| 				if (SGL->fract & SGL_CARRYOUT)	{
 | |
| 					SGL->fract >>= 1;
 | |
| 					f->exp++;
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		if (f->exp > SGL_MAX)
 | |
| 			goto sgl_over;
 | |
| 
 | |
| 		/* STORE EXPONENT			*/
 | |
| 		/* 1) clear leading bit of fraction	*/
 | |
| 		SGL->fract &= SGL_MASK; /* B23-B31 are 0 */
 | |
| 
 | |
| 		/* 2) shift and store exponent		*/
 | |
| 		f->exp <<= SGL_EXPSHIFT;
 | |
| 		SGL->fract |= ((long) f->exp << EXP_STORE);
 | |
| 	}
 | |
| 
 | |
| /********************************************************/
 | |
| /*
 | |
| 	STORE SIGN BIT
 | |
| */
 | |
| /********************************************************/
 | |
| 	if (f->sign)	{
 | |
| 		SGL = (SINGLE *) to;	/* make sure	*/
 | |
| 		SGL->fract |= CARRYBIT;
 | |
| 	}
 | |
| /********************************************************/
 | |
| /*
 | |
| 	STORE MANTISSA
 | |
| /*
 | |
| /********************************************************/
 | |
| 
 | |
| 	if (size == sizeof(_double)) {
 | |
| 		put4(DBL->_s.p1.fract, (char *) &DBL->_s.p1.fract);
 | |
| 		put4(DBL->_s.p2, (char *) &DBL->_s.p2);
 | |
| 	}
 | |
| 		else
 | |
| 		put4(SGL->fract, (char *) &SGL->fract);
 | |
| 
 | |
| leave:
 | |
| #ifdef	PRT_EXIT
 | |
| 	prt_ext("exit  compact:",f);
 | |
| 	prt_dbl((DOUBLE *) to,size); getchar();
 | |
| #endif	PRT_EXIT
 | |
| 	;	/* end of print statement or null statement */
 | |
| }
 |