/* $Header:frexp.c 12.0$ */
/* $ACIS:frexp.c 12.0$ */
/* $Source: /ibm/acis/usr/src/lib/libc/ca/gen/RCS/frexp.c,v $ */

#ifndef lint
static char *rcsid = "$Header:frexp.c 12.0$";
#endif

/*
********************       IEEE VERSION    *****************************
*	double frexp (value, eptr)
*		double value;
*		int *eptr;
*
*	Frexp breaks "value" up into a fraction and an exponent.
*	It stores the exponent indirectly through eptr, and
*	returns the fraction.  More specifically, after
*
*		double d, frexp();
*		int e;
*		d = frexp (x, &e);
*
*	then |d| will be less than 1, and x will be equal to d*(2**e).
*	Further, if x is not zero, d will be no less than 1/2, and if
*	x is zero, both d and e will be zero too.
*/

#include <machine/fp.h>
#define MAXINT 2147483647

FP_DOUBLE frexp(value,expr)
DOUBLE value;
int *expr;
{
	register int i, expon;
	DOUBLE rval;

	if (((value.dfracth & LO31BITS) == 0) && (value.dfractl == 0))
	{       *expr = 0;
		return(_Double(value));
	}                                      /* done if old value is zero */
	expon = (value.dfracth >> 20) & 0x7ff;
	if (expon == 0)
	{	*expr = -1021;
		while (!(value.dfracth & 0x00100000))
		{	value.dfracth = (value.dfracth << 1) | 
					(value.dfractl >> 31);
			value.dfractl <<= 1;
			*expr = *expr - 1;
		}
		rval.dfracth = 0x3fe00000 | (value.dfracth & 0x800fffff);
		rval.dfractl = value.dfractl;
		return(_Double(rval));
	}
	if (expon == 0x7ff)
	{	if ((value.dfracth & 0xfffff) | (value.dfractl))     /* NaN */
		{	*expr = 0;				/* exp = 0  */
			return(_Double(value));			/* same NaN */
		}
		else						     /* INF */
		{	*expr = 50000;				/* big exp  */
			rval.dfracth = 
				0x3fe00000 | (value.dfracth & 0x80000000);
			rval.dfractl = 0;			/* return .5 */
			return(_Double(rval));
		}
	}
	*expr = expon - 0x3fe;
	rval.dfracth = (value.dfracth & 0x800fffff) | 0x3fe00000;
	rval.dfractl = value.dfractl;
	return(_Double(rval));
}
