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

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

#include <ieee.h>

typedef union{
     double d;
     struct {
	unsigned long hi, lo;
	} ul;
} udouble;

typedef union{
     float f;
     unsigned long ul;
} ufloat;

NUMCLASS classdouble(x)
udouble x;
{
    unsigned long expon, hifract;

	expon = x.ul.hi & 0x7ff00000;
	hifract = x.ul.hi & 0xfffff;

	if (expon == 0x7ff00000)
	{
		if (hifract | x.ul.lo)
			if (hifract & 0x80000)
				return(QNAN);
			else
				return(SNAN);
		else
			return(INFINITE);
	}
	if (expon == 0)
	{
		if ((hifract == 0) && (x.ul.lo == 0))
			return(ZERONUM);
		else
			return(DENORMALNUM);
	}
	return(NORMALNUM);
}

NUMCLASS classfloat(x)
double x;
{
	ufloat y;
	unsigned long expon, fract;

	y.f = (float) x;
	expon = y.ul & 0x7f800000;
	fract = y.ul & 0x007fffff;
	
	if (expon == 0x7f800000)
	{	if (fract)
			if (fract & 0x00400000)
				return(QNAN);
			else
				return(SNAN);		/* will never happen */
		else
			return(INFINITE);
	}
	if (expon == 0)
	{	if (fract == 0)
			return(ZERONUM);
		else
			return(DENORMALNUM);
	}
	return(NORMALNUM);
}

isnan(x)
udouble x;
{
	return( ((x.ul.hi & 0x7ff00000) == 0x7ff00000) &&
		((x.ul.hi & 0xfffff) | x.ul.lo) );
}

unordered(x,y)
udouble x,y;
{
	return( ( ((x.ul.hi & 0x7ff00000) == 0x7ff00000) &&
		  ((x.ul.hi & 0xfffff) | x.ul.lo) )
	     || ( ((y.ul.hi & 0x7ff00000) == 0x7ff00000) &&
		  ((y.ul.hi & 0xfffff) | y.ul.lo) ) );
}

finite(x)
udouble x;
{
	return( (x.ul.hi & 0x7ff00000) != 0x7ff00000);
}

double infinity()
{
	udouble x;
	x.ul.hi = 0x7ff00000;
	x.ul.lo = 0;
	return(x.d);
}
