set	prototyped
set	nooptimize
set	stdio FEATURE/standards
hdr	float,limits,math,values
lib,npt	frexp,frexpl,ldexp,ldexpl,finite,finitel,isinfl,isnanl,copysign,copysignl,powf,pow,powl FEATURE/standards math.h -lm
lib	fpclassify -lm note{ fpclassify present and works }end link{
		#include <sys/types.h>
		#include <sys/stat.h>
		#include <stdlib.h>
		#include <unistd.h>
		#include <math.h>
		int main() { return fpclassify(-0.0); }
	}end
lib	isinf -lm note{ isinf present and works }end link{
		#include <sys/types.h>
		#include <sys/stat.h>
		#include <stdlib.h>
		#include <unistd.h>
		#include <math.h>
		int main() { return isinf(-0.0); }
	}end
lib	isnan -lm note{ isnan present and works }end link{
		#include <sys/types.h>
		#include <sys/stat.h>
		#include <stdlib.h>
		#include <unistd.h>
		#include <math.h>
		int main() { return isnan(-0.0); }
	}end
lib	signbit -lm note{ signbit present and works }end link{
		#include <sys/types.h>
		#include <sys/stat.h>
		#include <stdlib.h>
		#include <unistd.h>
		#include <math.h>
		int main() { return signbit(-0.0); }
	}end

tst	ast_no_um2fm note{ no unsigned intmax => floatmax cast }end nolink{
	#include "FEATURE/common"
	int
	main()
	{
		_ast_fltmax_t		f = 0;
		unsigned _ast_intmax_t	i = 0;
		f = i;
		i = f;
		return f == i;
	}
}end

tst	ast_mpy_overflow_fpe note{ fpe on mpy overflow }end noexecute{
	int
	main()
	{
		float	f;
		float	p;
		int	i;

		i = 0;
		p = f = 1.0;
		do
		{
			p = f;
			f *= 2.0;
		} while (f != p && ++i < 1024);
		return 0;
	}
}end

tst	ast_div_underflow_fpe note{ fpe on div underflow }end noexecute{
	int
	main()
	{
		float	f;
		float	p;
		int	i;

		i = 0;
		p = f = 1.0;
		do
		{
			p = f;
			f /= 2.0;
		} while (f != p && ++i < 1024);
		return 0;
	}
}end

macro{
	#if _hdr_float
	#include <float.h>
	#endif
	#if _hdr_limits
	#include <limits.h>
	#endif
	#if _hdr_math
	#include <math.h>
	#endif
	#if _hdr_values
	#include <values.h>
	#endif

	#if !defined(FLT_MIN_EXP) && defined(FMINEXP)
	#define FLT_MIN_EXP	FMINEXP
	#endif
	#if !defined(FLT_MIN) && defined(MINFLOAT)
	#define FLT_MIN		MINFLOAT
	#endif
	#if !defined(FLT_MAX_EXP) && defined(FMAXEXP)
	#define FLT_MAX_EXP	FMAXEXP
	#endif
	#if !defined(FLT_MAX) && defined(MAXFLOAT)
	#define FLT_MAX		MAXFLOAT
	#endif

	#if !defined(DBL_MIN_EXP) && defined(DMINEXP)
	#define DBL_MIN_EXP	DMINEXP
	#endif
	#if !defined(DBL_MIN) && defined(MINDOUBLE)
	#define DBL_MIN		MINDOUBLE
	#endif
	#if !defined(DBL_MAX_EXP) && defined(DMAXEXP)
	#define DBL_MAX_EXP	DMAXEXP
	#endif
	#if !defined(DBL_MAX) && defined(MAXDOUBLE)
	#define DBL_MAX		MAXDOUBLE
	#endif

	<<"#include <ast_common.h>">>
	#if _hdr_float
	<<"#include <float.h>">>
	#endif
	#if _hdr_math
	<<"#include <math.h>">>
	#endif
	#ifdef FLT_DIG
	<<"#ifndef FLT_DIG">>
	<<"#define FLT_DIG">>		FLT_DIG
	<<"#endif">>
	#endif
	#ifdef FLT_MAX
	<<"#ifndef FLT_MAX">>
	<<"#define FLT_MAX">>		FLT_MAX
	<<"#endif">>
	#endif
	#ifdef FLT_MAX_10_EXP
	<<"#ifndef FLT_MAX_10_EXP">>
	<<"#define FLT_MAX_10_EXP">>	FLT_MAX_10_EXP
	<<"#endif">>
	#endif
	#ifdef FLT_MAX_EXP
	<<"#ifndef FLT_MAX_EXP">>
	<<"#define FLT_MAX_EXP">>	FLT_MAX_EXP
	<<"#endif">>
	#endif
	#ifdef FLT_MIN
	<<"#ifndef FLT_MIN">>
	<<"#define FLT_MIN">>		FLT_MIN
	<<"#endif">>
	#endif
	#ifdef FLT_MIN_10_EXP
	<<"#ifndef FLT_MIN_10_EXP">>
	<<"#define FLT_MIN_10_EXP">>	FLT_MIN_10_EXP
	<<"#endif">>
	#endif
	#ifdef FLT_MIN_EXP
	<<"#ifndef FLT_MIN_EXP">>
	<<"#define FLT_MIN_EXP">>	FLT_MIN_EXP
	<<"#endif">>
	#endif

	#ifdef DBL_DIG
	<<"#ifndef DBL_DIG">>
	<<"#define DBL_DIG">>		DBL_DIG
	<<"#endif">>
	#endif
	#ifdef DBL_MAX
	<<"#ifndef DBL_MAX">>
	<<"#define DBL_MAX">>		DBL_MAX
	<<"#endif">>
	#endif
	#ifdef DBL_MAX_10_EXP
	<<"#ifndef DBL_MAX_10_EXP">>
	<<"#define DBL_MAX_10_EXP">>	DBL_MAX_10_EXP
	<<"#endif">>
	#endif
	#ifdef DBL_MAX_EXP
	<<"#ifndef DBL_MAX_EXP">>
	<<"#define DBL_MAX_EXP">>	DBL_MAX_EXP
	<<"#endif">>
	#endif
	#ifdef DBL_MIN
	<<"#ifndef DBL_MIN">>
	<<"#define DBL_MIN">>		DBL_MIN
	<<"#endif">>
	#endif
	#ifdef DBL_MIN_10_EXP
	<<"#ifndef DBL_MIN_10_EXP">>
	<<"#define DBL_MIN_10_EXP">>	DBL_MIN_10_EXP
	<<"#endif">>
	#endif
	#ifdef DBL_MIN_EXP
	<<"#ifndef DBL_MIN_EXP">>
	<<"#define DBL_MIN_EXP">>	DBL_MIN_EXP
	<<"#endif">>
	#endif

	#ifdef LDBL_DIG
	<<"#ifndef LDBL_DIG">>
	<<"#define LDBL_DIG">>		LDBL_DIG
	<<"#endif">>
	#endif
	#ifdef LDBL_MAX
	<<"#ifndef LDBL_MAX">>
	<<"#define LDBL_MAX">>		LDBL_MAX
	<<"#endif">>
	#endif
	#ifdef LDBL_MAX_10_EXP
	<<"#ifndef LDBL_MAX_10_EXP">>
	<<"#define LDBL_MAX_10_EXP">>	LDBL_MAX_10_EXP
	<<"#endif">>
	#endif
	#ifdef LDBL_MAX_EXP
	<<"#ifndef LDBL_MAX_EXP">>
	<<"#define LDBL_MAX_EXP">>	LDBL_MAX_EXP
	<<"#endif">>
	#endif
	#ifdef LDBL_MIN
	<<"#ifndef LDBL_MIN">>
	<<"#define LDBL_MIN">>		LDBL_MIN
	<<"#endif">>
	#endif
	#ifdef LDBL_MIN_10_EXP
	<<"#ifndef LDBL_MIN_10_EXP">>
	<<"#define LDBL_MIN_10_EXP">>	LDBL_MIN_10_EXP
	<<"#endif">>
	#endif
	#ifdef LDBL_MIN_EXP
	<<"#ifndef LDBL_MIN_EXP">>
	<<"#define LDBL_MIN_EXP">>	LDBL_MIN_EXP
	<<"#endif">>
	#endif
}end

tst	- note{ missing floating point limits }end output{
	#include "FEATURE/common"
	#include <stdio.h>
	#if _hdr_float
	#include <float.h>
	#endif
	#if _hdr_limits
	#include <limits.h>
	#endif
	#if _hdr_math
	#include <math.h>
	#endif
	#if _hdr_values
	#include <values.h>
	#endif
	#include <signal.h>
	#ifdef SIGFPE
	static int caught = 0;
	#if _STD_
	static void catch(int sig)
	#else
	static void catch(sig) int sig;
	#endif
	{
		signal(sig, SIG_IGN);
		caught++;
	}
	#endif
	int
	main()
	{
		register int		i;
		register int		s;
		float			f;
		float			pf;
		float			mf;
		float			xf;
		double			d;
		double			pd;
		double			md;
		char*			fp;
	#if _ast_fltmax_double
		char*			fs = "";
		char*			ds = "";
	#else
		_ast_fltmax_t		l;
		_ast_fltmax_t		pl;
		_ast_fltmax_t		ml;
		char*			fs = "F";
		char*			ds = "";
		char*			ls = "L";
	#endif
		unsigned long		u;
		unsigned _ast_intmax_t	w;
		unsigned _ast_intmax_t	pw;
		unsigned _ast_intmax_t	x;
		unsigned short		us;
		unsigned int		ui;
		unsigned long		ul;
		unsigned _ast_intmax_t	uq;
	
	#ifdef SIGFPE
		signal(SIGFPE, catch);
	#endif
		printf("\n");
		printf("\n");
		us = 0;
		us = ~us;
		i = 0;
		while (us /= 10)
			i++;
		printf("#define USHRT_DIG		%d\n", i);
		ui = 0;
		ui = ~ui;
		i = 0;
		while (ui /= 10)
			i++;
		printf("#define UINT_DIG		%d\n", i);
		ul = 0;
		ul = ~ul;
		i = 0;
		while (ul /= 10)
			i++;
		printf("#define ULONG_DIG		%d\n", i);
		if (sizeof(uq) > sizeof(ul))
		{
			uq = 0;
			uq = ~uq;
			i = 0;
			while (uq /= 10)
				i++;
			printf("#define ULLONG_DIG		%d\n", i);
			printf("#define UINTMAX_DIG		ULLONG_DIG\n");
		}
		else
			printf("#define UINTMAX_DIG		ULONG_DIG\n");
		printf("\n");
		w = 1;
		do
		{
			pw = w;
			w *= 2;
			f = (_ast_intmax_t)w;
			x = (_ast_intmax_t)f;
		} while (w > pw && w == x);
		w = (pw - 1) + pw;
		u = ~0;
		if (u > w)
			u = w;
		printf("#define FLT_ULONG_MAX		%lu.0F\n", u);
		if (sizeof(w) > sizeof(u))
		{
			printf("#define FLT_ULLONG_MAX		%llu.0F\n", w);
			printf("#define FLT_UINTMAX_MAX		FLT_ULLONG_MAX\n");
		}
		else
		{
			printf("#define FLT_ULLONG_MAX		FLT_ULONG_MAX\n");
			printf("#define FLT_UINTMAX_MAX		FLT_ULONG_MAX\n");
		}
		u /= 2;
		w /= 2;
		printf("#define FLT_LONG_MAX		%lu.0F\n", u);
		if (sizeof(w) > sizeof(u))
		{
			printf("#define FLT_LLONG_MAX		%llu.0F\n", w);
			printf("#define FLT_INTMAX_MAX		FLT_LLONG_MAX\n");
		}
		else
		{
			printf("#define FLT_LLONG_MAX		FLT_LONG_MAX\n");
			printf("#define FLT_INTMAX_MAX		FLT_LONG_MAX\n");
		}
		u++;
		w++;
		printf("#define FLT_LONG_MIN		(-%lu.0F)\n", u);
		if (sizeof(w) > sizeof(u))
		{
			printf("#define FLT_LLONG_MIN		(-%llu.0F)\n", w);
			printf("#define FLT_INTMAX_MIN		FLT_LLONG_MIN\n");
		}
		else
		{
			printf("#define FLT_LLONG_MIN		FLT_LONG_MIN\n");
			printf("#define FLT_INTMAX_MIN		FLT_LONG_MIN\n");
		}
	#ifdef FLT_DIG
		s = FLT_DIG;
	#else
		f = pf = 1.0;
		s = -1;
		do
		{
			s++;
			f *= 10.0;
		} while (f != (f + pf));
	#endif
	#if defined(FLT_MIN) && defined(FLT_MIN_EXP)
		i = FLT_MIN_EXP;
		mf = FLT_MIN;
	#else
		i = 3;
		f = pf = 1.0;
		do
		{
			i--;
			mf = pf;
			pf = f;
			f /= 2.0;
		} while (f < pf);
	#ifdef FLT_MIN_EXP
		i = FLT_MIN_EXP;
	#endif
	#ifdef FLT_MIN
		mf = FLT_MIN;
	#endif
	#endif
	#ifndef FLT_DIG
		printf("#ifndef FLT_DIG\n");
		printf("#define FLT_DIG			%d\n", s);
		printf("#endif\n");
	#endif
	#ifndef FLT_MIN
		printf("#ifndef FLT_MIN\n");
		printf("#define FLT_MIN			%.*E%s\n", s + 1, mf, fs);
		printf("#endif\n");
	#endif
	#ifndef FLT_MIN_EXP
		printf("#ifndef FLT_MIN_EXP\n");
		printf("#define FLT_MIN_EXP		(%d)\n", i);
		printf("#endif\n");
	#endif

	#if defined(FLT_MAX) && defined(FLT_MAX_EXP)
		i = FLT_MAX_EXP;
		f = FLT_MAX;
	#else
		i = -1;
		f = pf = 1.0;
		do
		{
			i++;
			mf = pf;
			pf = f;
			f *= 2.0;
		} while (f > pf);
	#ifdef FLT_MAX_EXP
		i = FLT_MAX_EXP;
	#endif
	#ifdef FLT_MAX
		f = FLT_MAX;
	#endif
	#endif
	#ifdef FLT_MAX_EXP
		i = FLT_MAX_EXP;
	#else
		f = 1;
		do
		{
			f *= 2.0;
		} while (mf == (mf + f));
		f = (mf - f) * 2.0 + f;
	#endif
		xf = f;
	#ifndef FLT_MAX
		printf("#ifndef FLT_MAX\n");
		printf("#define FLT_MAX			%.*E%s\n", s + 1, f, fs);
		printf("#endif\n");
	#endif
	#ifndef FLT_MAX_EXP
		printf("#ifndef FLT_MAX_EXP\n");
		printf("#define FLT_MAX_EXP		%d\n", i);
		printf("#endif\n");
	#endif

	#ifdef FLT_MIN_10_EXP
		i = FLT_MIN_10_EXP;
	#else
		i = 2;
		f = 1.0;
		do
		{
			i--;
			pf = f;
			f /= 10.0;
		} while (f < pf);
	#endif
	#ifndef FLT_MIN_10_EXP
		printf("#ifndef FLT_MIN_10_EXP\n");
		printf("#define FLT_MIN_10_EXP		(%d)\n", i);
		printf("#endif\n");
	#endif

	#ifdef FLT_MAX_10_EXP
		i = FLT_MAX_10_EXP;
	#else
		i = -2;
		f = 1.0;
		do
		{
			i++;
			pf = f;
			f *= 10.0;
		} while (f > pf);
	#endif
	#ifndef FLT_MAX_10_EXP
		printf("#ifndef FLT_MAX_10_EXP\n");
		printf("#define FLT_MAX_10_EXP		%d\n", i);
		printf("#endif\n");
	#endif

		printf("\n");
		w = 1;
		do
		{
			pw = w;
			w *= 2;
			d = (_ast_intmax_t)w;
			x = (_ast_intmax_t)d;
		} while (w > pw && w == x);
		w = (pw - 1) + pw;
		u = ~0;
		if (u > w)
			u = w;
		printf("#define DBL_ULONG_MAX		%lu.0\n", u);
		if (sizeof(w) > sizeof(u))
		{
			printf("#define DBL_ULLONG_MAX		%llu.0\n", w);
			printf("#define DBL_UINTMAX_MAX		DBL_ULLONG_MAX\n");
		}
		else
		{
			printf("#define DBL_ULLONG_MAX		DBL_ULONG_MAX\n");
			printf("#define DBL_UINTMAX_MAX		DBL_ULONG_MAX\n");
		}
		u /= 2;
		w /= 2;
		printf("#define DBL_LONG_MAX		%lu.0\n", u);
		if (sizeof(w) > sizeof(u))
		{
			printf("#define DBL_LLONG_MAX		%llu.0\n", w);
			printf("#define DBL_INTMAX_MAX		DBL_LLONG_MAX\n");
		}
		else
		{
			printf("#define DBL_LLONG_MAX		DBL_LONG_MAX\n");
			printf("#define DBL_INTMAX_MAX		DBL_LONG_MAX\n");
		}
		u++;
		w++;
		printf("#define DBL_LONG_MIN		(-%lu.0)\n", u);
		if (sizeof(w) > sizeof(u))
		{
			printf("#define DBL_LLONG_MIN		(-%llu.0)\n", w);
			printf("#define DBL_INTMAX_MIN		DBL_LLONG_MIN\n");
		}
		else
		{
			printf("#define DBL_LLONG_MIN		DBL_LONG_MIN\n");
			printf("#define DBL_INTMAX_MIN		DBL_LONG_MIN\n");
		}
	#ifdef DBL_DIG
		s = DBL_DIG;
	#else
		d = pd = 1.0;
		s = -1;
		do
		{
			s++;
			d *= 10.0;
		} while (d != (d + pd));
	#endif
	#if defined(DBL_MIN) && defined(DBL_MIN_EXP)
		i = DBL_MIN_EXP;
		md = DBL_MIN;
	#else
		i = 3;
		d = pd = 1.0;
		do
		{
			i--;
			md = pd;
			pd = d;
			d /= 2.0;
		} while (d < pd);
	#ifdef DBL_MIN_EXP
		i = DBL_MIN_EXP;
	#endif
	#ifdef DBL_MIN
		md = DBL_MIN;
	#endif
	#endif
	#ifndef DBL_DIG
		printf("#ifndef DBL_DIG\n");
		printf("#define DBL_DIG			%d\n", s);
		printf("#endif\n");
	#endif
	#ifndef DBL_MIN
		printf("#ifndef DBL_MIN\n");
		printf("#define DBL_MIN			%.*E%s\n", s + 1, md, ds);
		printf("#endif\n");
	#endif
	#ifndef DBL_MIN_EXP
		printf("#ifndef DBL_MIN_EXP\n");
		printf("#define DBL_MIN_EXP		(%d)\n", i);
		printf("#endif\n");
	#endif

	#if defined(DBL_MAX) && defined(DBL_MAX_EXP)
		i = DBL_MAX_EXP;
		d = DBL_MAX;
	#else
		i = -1;
		d = pd = 1.0;
		do
		{
			i++;
			md = pd;
			pd = d;
			d *= 2.0;
		} while (d > pd);
		d = 1.0;
		do
		{
			d *= 2.0;
		} while (md == (md + d));
		d = (md - d) * 2.0 + d;
	#ifdef DBL_MAX_EXP
		i = DBL_MAX_EXP;
	#endif
	#ifdef DBL_MAX
		d = DBL_MAX;
	#endif
	#endif
	#ifndef DBL_MAX
		printf("#ifndef DBL_MAX\n");
		printf("#define DBL_MAX			%.*E%s\n", s + 1, d, ds);
		printf("#endif\n");
	#endif
	#ifndef DBL_MAX_EXP
		printf("#ifndef DBL_MAX_EXP\n");
		printf("#define DBL_MAX_EXP		%d\n", i);
		printf("#endif\n");
	#endif

	#ifdef DBL_MIN_10_EXP
		i = DBL_MIN_10_EXP;
	#else
		i = 2;
		d = 1.0;
		do
		{
			i--;
			pd = d;
			d /= 10.0;
		} while (d < pd);
	#endif
	#ifndef DBL_MIN_10_EXP
		printf("#ifndef DBL_MIN_10_EXP\n");
		printf("#define DBL_MIN_10_EXP		(%d)\n", i);
		printf("#endif\n");
	#endif

	#ifdef DBL_MAX_10_EXP
		i = DBL_MAX_10_EXP;
	#else
		i = -2;
		d = 1.0;
		do
		{
			i++;
			pd = d;
			d *= 10.0;
		} while (d > pd);
	#endif
	#ifndef DBL_MAX_10_EXP
		printf("#ifndef DBL_MAX_10_EXP\n");
		printf("#define DBL_MAX_10_EXP		%d\n", i);
		printf("#endif\n");
	#endif

	#if !_ast_fltmax_double
		printf("\n");
		w = 1;
		do
		{
			pw = w;
			w *= 2;
			l = (_ast_intmax_t)w;
			x = (_ast_intmax_t)l;
		} while (w > pw && w == x);
		w = (pw - 1) + pw;
		u = ~0;
		if (u > w)
			u = w;
		printf("#define LDBL_ULONG_MAX		%lu.0L\n", u);
		if (sizeof(w) > sizeof(u))
		{
			printf("#define LDBL_ULLONG_MAX		%llu.0L\n", w);
			printf("#define LDBL_UINTMAX_MAX	LDBL_ULLONG_MAX\n");
		}
		else
		{
			printf("#define LDBL_ULLONG_MAX		LDBL_ULONG_MAX\n");
			printf("#define LDBL_UINTMAX_MAX	LDBL_ULONG_MAX\n");
		}
		u /= 2;
		w /= 2;
		printf("#define LDBL_LONG_MAX		%lu.0L\n", u);
		if (sizeof(w) > sizeof(u))
		{
			printf("#define LDBL_LLONG_MAX		%llu.0L\n", w);
			printf("#define LDBL_INTMAX_MAX		LDBL_LLONG_MAX\n");
		}
		else
		{
			printf("#define LDBL_LLONG_MAX		LDBL_LONG_MAX\n");
			printf("#define LDBL_INTMAX_MAX		LDBL_LONG_MAX\n");
		}
		u++;
		w++;
		printf("#define LDBL_LONG_MIN		(-%lu.0L)\n", u);
		if (sizeof(w) > sizeof(u))
		{
			printf("#define LDBL_LLONG_MIN		(-%llu.0L)\n", w);
			printf("#define LDBL_INTMAX_MIN		LDBL_LLONG_MIN\n");
		}
		else
		{
			printf("#define LDBL_LLONG_MIN		LDBL_LONG_MIN\n");
			printf("#define LDBL_INTMAX_MIN		LDBL_LONG_MIN\n");
		}
	#ifdef LDBL_DIG
		s = LDBL_DIG;
	#else
		l = pl = 1.0L;
		s = -1;
		do
		{
			s++;
			l *= 10.0L;
		} while (l != (l + pl));
	#endif
	#if defined(LDBL_MIN) && defined(LDBL_MIN_EXP)
		i = LDBL_MIN_EXP;
		ml = LDBL_MIN;
	#else
		i = 3;
		l = pl = 1.0L;
		do
		{
			i--;
			ml = pl;
			pl = l;
			l /= 2.0L;
		} while (l < pl);
	#ifdef LDBL_MIN_EXP
		i = LDBL_MIN_EXP;
	#endif
	#ifdef LDBL_MIN
		ml = LDBL_MIN;
	#endif
	#endif
	#ifndef LDBL_DIG
		printf("#ifndef LDBL_DIG\n");
		printf("#define LDBL_DIG		%d\n", s);
		printf("#endif\n");
	#endif
	#ifndef LDBL_MIN
		printf("#ifndef LDBL_MIN\n");
		printf("#define LDBL_MIN		%.*LE%s\n", s + 1, ml, ls);
		printf("#endif\n");
	#endif
	#ifndef LDBL_MIN_EXP
		printf("#ifndef LDBL_MIN_EXP\n");
		printf("#define LDBL_MIN_EXP		(%d)\n", i);
		printf("#endif\n");
	#endif

	#if defined(LDBL_MAX) && defined(LDBL_MAX_EXP)
		i = LDBL_MAX_EXP;
		l = LDBL_MAX;
	#else
		i = -1;
		l = pl = 1.0L;
		do
		{
			i++;
			ml = pl;
			pl = l;
			l *= 2.0L;
		} while (l > pl);
		l = 1.0L;
		do
		{
			l *= 2.0L;
		} while (ml == (ml + l));
		l = (ml - l) * 2.0L + l;
	#ifdef LDBL_MAX_EXP
		i = LDBL_MAX_EXP;
	#endif
	#ifdef LDBL_MAX
		l = LDBL_MAX;
	#endif
	#endif
	#ifndef LDBL_MAX
		printf("#ifndef LDBL_MAX\n");
		printf("#define LDBL_MAX		%.*LE%s\n", s + 1, l, ls);
		printf("#endif\n");
	#endif
	#ifndef LDBL_MAX_EXP
		printf("#ifndef LDBL_MAX_EXP\n");
		printf("#define LDBL_MAX_EXP		%d\n", i);
		printf("#endif\n");
	#endif

	#ifdef LDBL_MIN_10_EXP
		i = LDBL_MIN_10_EXP;
	#else
		i = 2;
		l = 1.0L;
		do
		{
			i--;
			pl = l;
			l /= 10.0L;
		} while (l < pl);
	#endif
	#ifndef LDBL_MIN_10_EXP
		printf("#ifndef LDBL_MIN_10_EXP\n");
		printf("#define LDBL_MIN_10_EXP		(%d)\n", i);
		printf("#endif\n");
	#endif

	#ifdef LDBL_MAX_10_EXP
		i = LDBL_MAX_10_EXP;
	#else
		i = -2;
		l = 1.0L;
		do
		{
			i++;
			pl = l;
			l *= 10.0L;
		} while (l > pl);
	#endif
	#ifndef LDBL_MAX_10_EXP
		printf("#ifndef LDBL_MAX_10_EXP\n");
		printf("#define LDBL_MAX_10_EXP		%d\n", i);
		printf("#endif\n");
	#endif
		fp = "LDBL";
	#else
		fp = "DBL";
	#endif

	printf("\n");
	printf("#define FLTMAX_UINTMAX_MAX	%s_UINTMAX_MAX\n", fp);
	printf("#define FLTMAX_INTMAX_MAX	%s_INTMAX_MAX\n", fp);
	printf("#define FLTMAX_INTMAX_MIN	%s_INTMAX_MIN\n", fp);

	#ifdef SIGFPE
		if (!caught)
		{
	#if !__MVS__
			f = xf;
			f *= 2;
			if (!f)
	#endif
				caught = 1;
		}
		if (caught)
			printf("\n#define _ast_fltsig		%d\n", SIGFPE);
	#endif

		printf("\n");
	#if !_lib_frexp || _npt_frexp
		printf("extern double		frexp(double, int*);\n");
	#endif
	#if !_lib_frexpl || _npt_frexpl
		printf("extern _ast_fltmax_t	frexpl(_ast_fltmax_t, int*);\n");
	#endif
	#if !_lib_ldexp || _npt_ldexp
		printf("extern double		ldexp(double, int);\n");
	#endif
	#if !_lib_ldexpl || _npt_ldexpl
		printf("extern _ast_fltmax_t	ldexpl(_ast_fltmax_t, int);\n");
	#endif

		return 0;
	}
}end fail{
	echo '#error Output block #1 in src/lib/libast/features/float failed to compile. Rebuild with IFFEFLAGS=-d1 to debug.'
}end

tst	- note{ double exponent bitfoolery }end output{
	#include "FEATURE/common"
	#include <stdio.h>
	typedef union _dbl_exp_u
	{
		unsigned _ast_int4_t	e[sizeof(double) / 4];
		double			f;
	} _ast_dbl_exp_t;
	int
	main()
	{
		int			i;
		int			j;
		unsigned _ast_int4_t	e;
		_ast_dbl_exp_t		a;
		_ast_dbl_exp_t		b;
		a.f = 1;
		b.f = 2;
		for (i = 0; i < sizeof(a.e) / sizeof(a.e[0]); i++)
			if (e = a.e[i] ^ b.e[i])
			{
				for (j = i + 1; j < sizeof(a.e) / sizeof(a.e[0]); j++)
					if (a.e[j] ^ b.e[j])
						return 0;
				printf("typedef union _ast_dbl_exp_u\n{\n\tuint32_t\t\te[sizeof(double)/4];\n\tdouble\t\t\tf;\n} _ast_dbl_exp_t;\n\n");
				printf("#define _ast_dbl_exp_index	%d\n", i);
				for (i = 0; !(e & 1); e >>= 1, i++);
				printf("#define _ast_dbl_exp_shift	%d\n\n", i);
				return 0;
			}
		return 0;
	}
}end fail{
	echo '#error Output block #2 in src/lib/libast/features/float failed to compile. Rebuild with IFFEFLAGS=-d1 to debug.'
}end

tst	- note{ long double exponent bitfoolery }end output{
	#include "FEATURE/common"
	#include <stdio.h>
	typedef union _ast_fltmax_exp_u
	{
		unsigned _ast_int4_t	e[sizeof(_ast_fltmax_t) / 4];
		_ast_fltmax_t		f;
	} _ast_fltmax_exp_t;
	int
	main()
	{
		int			i;
		int			j;
		unsigned _ast_int4_t	e;
		_ast_fltmax_exp_t	a;
		_ast_fltmax_exp_t	b;
		a.f = 1;
		b.f = 2;
		for (i = 0; i < sizeof(a.e) / sizeof(a.e[0]); i++)
			if (e = a.e[i] ^ b.e[i])
			{
				for (j = i + 1; j < sizeof(a.e) / sizeof(a.e[0]); j++)
					if (a.e[j] ^ b.e[j])
						return 0;
				printf("typedef union _fltmax_exp_u\n{\n\tuint32_t\t\te[sizeof(_ast_fltmax_t)/4];\n\t_ast_fltmax_t\t\tf;\n} _ast_fltmax_exp_t;\n\n");
				printf("#define _ast_fltmax_exp_index\t%d\n", i);
				for (i = 0; !(e & 1); e >>= 1, i++);
				printf("#define _ast_fltmax_exp_shift\t%d\n\n", i);
				return 0;
			}
		return 0;
	}
}end fail{
	echo '#error Output block #3 in src/lib/libast/features/float failed to compile. Rebuild with IFFEFLAGS=-d1 to debug.'
}end

tst	- -DN=1 - -DN=2 note{ _ast_fltmax_t maximum integral type }end output{
	#include <stdio.h>
	int
	main()
	{
	#if N == 1
		unsigned long long	m;
		long double		f = 123.456;

		m = f;
		if (!m || f == m)
			return 1;
		printf("#define _ast_flt_unsigned_max_t	unsigned long long\n");
	#else
		printf("#define _ast_flt_unsigned_max_t	unsigned long\n");
	#endif
		return 0;
	}
}end

tst	- -DSCAN=1 - -lm -DSTRTO=1 - -DMAC=1 - -DDIV=1 - -DEXP=1 - -DADD=1 - -DMPY=1 note{ INF and NAN memory representations }end output{
	#if MAC
	#define _AIX_COMPATIBILITY	1
	#define _FP_MODE_VARIABLE	1
	#endif
	#include "FEATURE/common"
	#include <stdio.h>
	#include <sys/types.h>
	#include <signal.h>
	#include <string.h>
	#if _hdr_float
	#include <float.h>
	#endif
	#if _hdr_limits
	#include <limits.h>
	#endif
	#if _hdr_math
	#include <math.h>
	#endif
	#if _hdr_values
	#include <values.h>
	#endif
	#if STRTO && _hdr_stdlib
	#include <stdlib.h>
	#endif
	#if !defined(FLT_MAX) && defined(MAXFLOAT)
	#define FLT_MAX		MAXFLOAT
	#endif
	#if !defined(DBL_MAX) && defined(MAXDOUBLE)
	#define DBL_MAX		MAXDOUBLE
	#endif
	#if _ast_fltmax_double
	#undef	LDBL_MAX
	#endif
	static void
	#if _STD_
	list(const char* typ, const char* var, void* val, int siz)
	#else
	list(typ, var, val, siz)
	char* typ;
	char* var;
	void* val;
	int siz;
	#endif
	{
		register unsigned char*	u = (unsigned char*)val;
		register unsigned char*	e = u + siz;
	
		printf("#define _ast_%s_%s_init\t0x%02x", typ, var, *u);
		while (++u < e)
			printf(",0x%02x", *u);
		printf("\n");
	}
	int
	main()
	{
	#if SCAN || STRTO
	#undef	NAN
	#define NAN	"NaN"
	#undef	INF
	#define INF	"INF"
	{
		float	f;

	#if SCAN
		if (sscanf(NAN, "%g", &f) != 1)
			return 1;
	#else
		f = atof(NAN);
	#endif
		list("flt", "nan", &f, sizeof(f));
	#if SCAN
		if (sscanf(INF, "%g", &f) != 1)
			return 1;
	#else
		f = atof(INF);
	#endif
		list("flt", "inf", &f, sizeof(f));
	}
	{
		double	f;
	#if STRTO
		char*	e;
	#endif

	#if SCAN
		if (sscanf(NAN, "%lg", &f) != 1)
			return 1;
	#else
		f = strtod(NAN, &e);
		if (*e)
			return 1;
	#endif
		list("dbl", "nan", &f, sizeof(f));
	#if SCAN
		if (sscanf(INF, "%lg", &f) != 1)
			return 1;
	#else
		f = strtod(INF, &e);
		if (*e)
			return 1;
	#endif
		list("dbl", "inf", &f, sizeof(f));
	}
	#ifdef LDBL_MAX
	{
		long double	f;
	#if STRTO
		char*	e;
	#endif

	memset(&f, '\0', sizeof(f));
	#if SCAN
		if (sscanf(NAN, "%Lg", &f) != 1)
			return 1;
	#else
		f = strtold(NAN, &e);
		if (*e)
			return 1;
	#endif
		list("ldbl", "nan", &f, sizeof(f));
	memset(&f, '\0', sizeof(f));
	#if SCAN
		if (sscanf(INF, "%Lg", &f) != 1)
			return 1;
	#else
		f = strtold(INF, &e);
		if (*e)
			return 1;
	#endif
		list("ldbl", "inf", &f, sizeof(f));
	}
	#endif
	#else
	#ifdef SIGFPE
		signal(SIGFPE, SIG_IGN);
	#endif
	#ifdef FLT_MAX
		{
			float	f = FLT_MAX;
	#if DIV
			float	z = 0;

			f = 0.0 / z;
			if (!f)
				return 1;
			list("flt", "nan", &f, sizeof(f));
			f = 1.0 / z;
			list("flt", "inf", &f, sizeof(f));
	#else
	#if ADD
			f += f;
	#endif
	#if EXP
			f = exp(f);
	#endif
	#if MPY
			f *= 2;
	#endif
	#if MAC
			f = FLT_QNAN;
	#endif
			list("flt", "nan", &f, sizeof(f));
	#if MAC
			f = FLT_INFINITY;
	#endif
			list("flt", "inf", &f, sizeof(f));
	#endif
		}
	#endif
	#ifdef DBL_MAX
		{
			double	f = DBL_MAX;
	#if DIV
			double	z = 0;

			f = 0.0 / z;
			if (!f)
				return 1;
			list("dbl", "nan", &f, sizeof(f));
			f = 1.0 / z;
			list("dbl", "inf", &f, sizeof(f));
	#else
	#if ADD
			f += f;
	#endif
	#if EXP
			f = exp(f);
	#endif
	#if MPY
			f *= 2;
	#endif
	#if MAC
			f = DBL_QNAN;
	#endif
			list("dbl", "nan", &f, sizeof(f));
	#if MAC
			f = DBL_INFINITY;
	#endif
			list("dbl", "inf", &f, sizeof(f));
	#endif
		}
	#endif
	#ifdef LDBL_MAX
		{
			long double	f = LDBL_MAX;
	#if DIV
			long double	z = 0;

			f = 0.0 / z;
			if (!f)
				return 1;
			list("ldbl", "nan", &f, sizeof(f));
			f = 1.0 / z;
			list("ldbl", "inf", &f, sizeof(f));
	#else
	#if ADD
			f += f;
	#endif
	#if EXP
			f = exp(f);
	#endif
	#if MPY
			f *= 2;
	#endif
	#if MAC
			f = LDBL_QNAN;
	#endif
			list("ldbl", "nan", &f, sizeof(f));
	#if MAC
			f = LDBL_INFINITY;
	#endif
			list("ldbl", "inf", &f, sizeof(f));
	#endif
		}
	#endif
	#endif
		return 0;
	}
}end

if	need_ast_pow_macros -lm note{ are IEEE pow macro replacements needed }end execute{
	#include <sys/types.h>
	#include <sys/stat.h>
	#include <stdlib.h>
	#include <unistd.h>
	#include <math.h>
	int main() { return pow(1.0, 1.0 / 0.0) == 1.0; }
}end {
	#define powf(x,y)	(((x)==1.0)?1.0:powf((x),(y)))
	#define pow(x,y)	(((x)==1.0)?1.0:pow((x),(y)))
	#define powl(x,y)	(((x)==1.0)?1.0:powl((x),(y)))
}
elif	tst need_ast_pow_funs -lm note{ are IEEE pow function replacements needed }end execute{
	#include <sys/types.h>
	#include <sys/stat.h>
	#include <stdlib.h>
	#include <unistd.h>
	#include <math.h>
	/* This bit of obfuscation defeats GCC's code optimizer. */
	double (*volatile _ast_ppow)(double,double);
	int main () { _ast_ppow = &pow; return (*_ast_ppow)(1.0, 1.0 / 0.0) == 1.0; }
}end {
	float			_ast_powf(float x, float y);
	double			_ast_pow(double x, double y);
	long double		_ast_powl(long double x, long double y);
	#define powf(x,y)	(_ast_powf((x),(y)))
	#define pow(x,y)	(_ast_pow((x),(y)))
	#define powl(x,y)	(_ast_powl((x),(y)))
}
endif
