Google
 

Trailing-Edge - PDP-10 Archives - SRI_NIC_PERM_FS_1_19910112 - kcc-4/lib/math/modf.c
There are 8 other files named modf.c in the archive. Click here to see a list.
/*
 *	MODF.C - split floating point number into int and fractional parts
 *
 *	This code conforms with the description of the modf function
 *	as defined in Harbison and Steele's "C: A Reference Manual",
 *	section 11.3.18
 *
 *	For the DECSYSTEM-20 the double precision word format is:
 *
 *	 WORD N	=>	SEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMMMMMM
 *	 WORD N+1 =>	XMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
 */

#include "c-env.h"		/* So can see what format we're using */

#define SIGN_MASK 0400000000000		/* Mask for sign bit */
#define EXP_MASK  0377000000000		/* Mask for exponent */
#define MANT_MASK 0400777777777		/* Mask for mantissa */
#define LEXP_MASK 0377			/* Mask for shifted exponent */
#define EXP_SHIFTS 27			/* Shifts for exp in LSBs */

double
modf(x, nptr)
double x;
int *nptr;
{
#if 0
/*
 *	note that this code is buggy in that there is no such thing as
 *	a long int on this machine (i assumed it was a double-word int);
 *	so the shifting operations are single-word, and all 2nd word
 *	precision is flushed!  lose lose
 */
	int exp, *vptr, negative = 0;
	long int *y;
	double z;

	vptr = (int *) &x;		/* point to first word of double */
	exp = ((unsigned) (*vptr & EXP_MASK) >> EXP_SHIFTS); /* extract exp */
	if (x < 0) {			/* if negative number, exponent is */
		exp = ~exp & LEXP_MASK; /* stored as 1's complement, so fix */
		negative = 1;		/* flag to save double comparisons */
	}
	exp -= 128;			/* make it signed, not excess-128 */
	if (exp <= 0) {			/* mant * 2^0 is less than 1 */
		*nptr = 0;		/* so return 0 as integer part */
		return x;		/* and original number as fraction */
	}
	else {
		z = x;			/* copy this so we don't lose bits */
		if (negative)		/* if negative number, mantissa */
			*vptr = -*vptr; /* is 2's complement too */
		*vptr &= MANT_MASK;	/* nuke old exponent to 0 */
		y = (long int *) &x;	/* point to double-word x */
		(unsigned) *y >>= (EXP_SHIFTS - exp); /* >> mant to make int */
		*nptr = (negative) ? -*vptr : *vptr; /* 1st word is int part */
		x = z;			/* get back x */
		*y <<= exp;		/* shift remaining bits to */
		*vptr &= (MANT_MASK ^ SIGN_MASK); /* decimal-point position */
		if (negative && *vptr != 0)
			*vptr |= (~128 & LEXP_MASK) << EXP_SHIFTS | SIGN_MASK;
		else
			*vptr |= (128 << EXP_SHIFTS); /* stick in new exp */
		return x += 0.0;	/* normalize and return result */
	}
	/* End of commented-out stuff */
#elif CENV_DFL_H	/* PDP-10 hardware double prec fmt, only */

#asm
	EXTERN $ZERO	/* From CRT */

	DMOVE 1,-2(17)		; Get double arg
	SKIPGE 3,1		; Check for negative number, remember sign in 3
	 JRST [	DMOVN 1,1	; Negative, so turn it over
		DMOVEM 1,-2(17)	; Must store back for possible later ref.
		JRST .+1]
	LDB 4,[331000,,1]	; Get exponent (assume positive)
	TLZ 1,777000		; Zap exponent out of the double
	ASHC 1,-233(4)		; Get integral part in AC 1, fraction in 2
	MOVEM 1,@-3(17)		; Store integer part
	CAIL 4,233		; Did we shift left or right?
	 JRST modf5		; Positive shift, left.

	; Negative shift
	; Shifted right - fraction bits lost off low-order end.
	; Integer did not overflow, and was completely contained within
	; high-order word.
	SETO 1,			; Turn on all bits in integer part to get mask
	MOVNS 4
	LSH 1,233(4)		; Reverse the shift!
	TLZ 1,777000		; Zap mask, so we don't zap exponent field.
	ANDCA 1,-2(17)		; Mask out integer portion and get fract bits.
	MOVE 2,-1(17)		; Get low order word to restore complete fract.
	CAIA			; Skip over next instr and return.

	; Positive shift
	; Shifted left - no bits lost from fraction (altho integer may have
	; overflowed).  Only one instruction needed to fix us up!
MODF5:	 MOVSI 1,233000		; Clear integer part, reset exponent (128+27)
	DFAD 1,$ZERO		; Normalize by adding zero.
	CAIL 3,0		; Done, unless original arg was negative.
	 POPJ 17,		; Return!
	MOVNS 3,@-3(17)		; Get the parts negated now.
	DMOVN 1,1

	; Drop thru to return
#endasm
#elif 0	/* Should be ELSE */
#error modf() not implemented for this CPU.
#endif
}