/* fltdll.c - Test floating arithmetic in a DLL */

/* Copyright (C) 19881-1991 Phar Lap Software, Inc. */


#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <ctype.h>
#include <string.h>
#include <float.h>
#include <errno.h>
#include <pltypes.h>

#ifdef __WATCOMC__
#define _cabs cabs
#define _ecvt ecvt
#define _fcvt fcvt
#define _gcvt gcvt
#define _hypot hypot
#endif

//
// Macro for referencing imported data variables from DLLs
//
#define IMPVAR(varname, type) (***(type ***)((UCHAR *)(&varname) + 2))

// Data imported from FLTTEST.EXE
extern int imp_errno;	// this is the name given "errno" in the -IMPORT
			// switch when building FLTTEST.EXE
#define errno IMPVAR(imp_errno, int)	// this allows us to reference errno
					// by its usual name

/* COUNTOF macro -- Returns the number of elements in an array */

#define COUNTOF(a) (sizeof(a) / sizeof(a[0]))


/* abs_tab - Test table for the function "abs" */

int abs_tab[] = 
{
	1,
	0,
	-10,
	32767,
	-32767
};


/* acos_tab - Test table for the functions "acos" and "asin" */

double acos_tab[] = 
{
	1.0,
	-1.0,
	0.0,
	0.5,
	-0.25,
	2.0,
	-1000.0
};


/* atan_tab - Test table for the function "atan" */

double atan_tab[] = 
{
	1.0,
	-1.0,
	0.0,
	10.0,
	25.0,
	1000.0
};


/* atan2_tab - Test table for the function "atan2" */

struct
{
	double x;
	double y;
} atan2_tab[] = 
{
	1.0,	1.0,
	0.0,	1.0,
	1.0,	0.0,
	2.0,	5.0,
	-2.0,	3.0,
	4.5,	-10.0,
	0.0,	0.0
};


/* atof_tab - Test table for the function "atof" */

char *atof_tab[] =
{
	"123",
	"-1000",
	"+10",
	".100",
	"-0.123",
	"+1.1E5",
	"+1.1E-2",
	"-32768",
	"9999999999999999999999",
	""
};


/* atoi_tab - Test table for the function "atoi" */

char *atoi_tab[] =
{
	"123",
	"-1000",
	"+10",
	"abc",
	"1abc",
	"32768",
	"-32768",
	"9999999999999999999999",
	""
};


/* atol_tab - Test table for the function "atol" */

char *atol_tab[] =
{
	"123",
	"-1000",
	"+10",
	"abc",
	"1abc",
	"32768",
	"-32768",
	"9999999999999999999999",
	""
};

//#ifdef __BORLANDC__

/* cabs_tab - Test table for the function "cabs" */

struct complex cabs_tab[] =
{
	{2.0,1.0},
	{-2.1,0.1},
	{999999999999999999999.,-2.1},
	{-0.0000000000001,-2.1},
	{-0.0,0.000001},
	{7.0,0.0},
	{0.0,-110.0},
	{-77.0,0.0}
};

//#endif


/* ceil_tab - Test table for the function "ceil" */

double ceil_tab[] =
{
	1.1,
	0.,
	1.,
	10.,
	.005,
	-1.2,
	-10.5,
	-.9999
};	


/* cos_tab - Test table for the functions "cos", "sin", and "tan". */

double cos_tab[] = 
{
	1.0,
	-1.0,
	0.0,
	0.5,
	-0.25,
	2.0,
	-1000.0
};


/* cosh_tab - Test table for the functions "cosh", "sinh", and "tanh" */

double cosh_tab[] = 
{
	1.0,
	-1.0,
	0.0,
	0.5,
	-0.25,
	2.0,
	-1000.0
};


/* div_tab - Test table for the function "div" */

struct 
{
	int top;
	int bot;
} div_tab[] =
{
	30,	4,
	1,	2,
	10,	2,
	32767,	10,
};

/* ecvt_tab - Test table for the function "ecvt", "fcvt" and "gcvt" */

double ecvt_tab[] = 
{
	1.0,
	1e17,
	0.321,
	-1.5e2,
	-0.25e-02,
	90000000.0000009,
	-1000.0
};


/* exp_tab - Test table for the function "exp" */

double exp_tab[] = 
{
	1.0,
	-1.0,
	0.0,
	0.5,
	-0.25,
	2.0,
	-1000.0
};


/* fabs_tab - Test table for the function "fabs" */

double fabs_tab[] =
{
	1.1,
	0.,
	1.,
	10.,
	.005,
	-1.2,
	-10.5,
	-.9999
};	

/* hyp_tab - Test table for the function "hypot" */

struct
{
	double a;
	double b;

} hyp_tab[] = 
{
	{ 3.0, 4.0 },
	{ -17.0, -.345 },
	{ 4.3e3, 99999. },
	{ 1e300 , 1e300 },
	{ 0.00000001,	-0.000001 },
	{ 3.0,	5.0 },
};

/* labs_tab - Test table for the function "labs" */

long labs_tab[] =
{
	1,
	0,
	-1,
	10,
	005,
	1200000,
	-105000000,
	-9999
};	

/* ldiv_tab - Test table for the function "ldiv" */

struct 
{
	long top;
	long bot;
} ldiv_tab[] =
{
	30L,	4L,
	1L,	2L,
	10L,	2L,
	32767,	10,
	9999999L,99999L	
};


/* frexp - Test table for the function "frexp" */

double frexp_tab[] =
{
	0.0,
	1.0,
	-1.0,
	0.4,
	0.5,
	0.6,
	4.5,
	5.1,
	10.0,
	100.0,
	1000.0
};


/* fmod - Test table for the function "fmod" */

struct
{
	double top;
	double bot;
} fmod_tab[] =
{
	7.5,	2.3,
	-7.5,	2.3,
	7.5,	-2.3,
	-7.5,	-2.3,
	49.0,	12.0,
	0.0,	10.,
	1.1,	.3
};


/* log - Test table for the function "log" and "log10" */

double log_tab[] =
{
	1.,
	10.,
	100.,
	.2,
	1234.567,
	10E10,
	10E-10,
	0.,
	-1.234
};


/* ldexp_tab - Test table for the function "ldexp" */

struct
{
	double val;
	int exp;
} ldexp_tab[] =
{
	1.0,	1,
	1.0,	2,
	1.0,	10,
	.5,	1,
	.5,	10,
	12.45,	2,
	1.,	1000,
	1.,	-2
};


/* modf_tab - Test table for the function "modf" */

double modf_tab[] =
{
	1.0,
	0.1,
	-1.0,
	-0.1,
	0.0,
	12.34,
	1234.5678
};


/* pow_tab - Test table for the function "pow" */

struct
{
	double x;
	double y;
} pow_tab[] =
{
	2.,	10.,
	2.,	.5,
	2.,	-3.,
	2.2,	4.4,
	10.,	2.,
	0.,	100.,
	100.,	0.,
	-2.,	3.,
	-2.,	-3.
};


/* sqrt - Test table for the function "sqrt" */

double sqrt_tab[] =
{
	0.,
	1.,
	2.,
	3.,
	4.,
	100.,
	1000.,
	1.5,
	1234.5678,
	10E11,
	-1.,
	-1000.
};


/* strtod_tab - Test table for the function "strtod" */

char *strtod_tab[] =
{
	"123",
	"-1000",
	"+10",
	".100",
	"-0.123",
	"+1.1E5",
	"+1.1E-2",
	"-32768",
	"          1234     ",
	"9999999999999999999999",
	"1.23XYZ",
	"",
	"1E999",
	"1E-999"
};


/* strtol_tab - Test table for the function "strtol" */

char *strtol_tab[] =
{
	"123",
	"-1000",
	"+10",
	"-32768",
	"          1234     ",
	"9999999999999999999999",
	"123XYZ",
	"",
	"--123",
};



/* dfmt_tab - Double test table for the function "printf" */

struct
{
	char *fmtstr;
	double val;
} dfmt_tab[] =
{
	"%f",		1.23,
	"%f",		0.,
	"%f",		-456.789,
	"%f",		0.00001,
	"%e",		1.23,
	"%e",		0.,
	"%e",		-456.789,
	"%e",		0.00001,
	"%E",		1.23,
	"%E",		0.,
	"%E",		-456.789,
	"%E",		0.00001,
	"%g",		1.23,
	"%g",		0.,
	"%g",		-456.789,
	"%g",		0.00001,
	"%G",		1.23,
	"%G",		0.,
	"%G",		-456.789,
	"%G",		0.00001,
	"%10f",		1.23,
	"%10f",		0.,
	"%10f",		-456.789,
	"%10f",		0.00001,
	"%10.0f",	1.23,
	"%10.0f",	0.,
	"%10.0f",	-456.789,
	"%10.0f",	0.00001,
	"%10.4f",	1.23,
	"%10.4f",	0.,
	"%10.4f",	-456.789,
	"%10.4f",	0.00001,
	"%10e",		1.23,
	"%10e",		0.,
	"%10e",		-456.789,
	"%10e",		0.00001,
	"%10.0e",	1.23,
	"%10.0e",	0.,
	"%10.0e",	-456.789,
	"%10.0e",	0.00001,
	"%10.4e",	1.23,
	"%10.4e",	0.,
	"%10.4e",	-456.789,
	"%10.4e",	0.00001,
	"%10g",		1.23,
	"%10g",		0.,
	"%10g",		-456.789,
	"%10g",		0.00001,
	"%10.0g",	1.23,
	"%10.0g",	0.,
	"%10.0g",	-456.789,
	"%10.0g",	0.00001,
	"%10.4g",	1.23,
	"%10.4g",	0.,
	"%10.4g",	-456.789,
	"%10.4g",	0.00001
};


/* ifmt_tab - Integer test table for the function "printf" */

struct
{
	char *fmtstr;
	int val;
} ifmt_tab[] =
{
	"%i",		123,
	"%i",		0,
	"%i",		-12,
	"%c",		0x31,
	"%d",		123,
	"%d",		0,
	"%d",		-12,
	"%u",		123,
	"%u",		0,
	"%u",		-12,
	"%o",		123,
	"%o",		0,
	"%o",		-12,
	"%x",		123,
	"%x",		0,
	"%x",		-12,
	"%X",		123,
	"%X",		0,
	"%X",		-12,
	"%-10i",	123,
	"%10i",		123,
	"%+i",		123,
	"% i",		123,
	"%#0x",		123,
	"%#x",		123,
	"%#X",		123,
	"%1x",		123,
	"%2x",		123,
	"%3x",		123,
	"%4x",		123,
	"%5x",		123,
	"%6x",		123,
	"%7x",		123,
	"%8x",		123,
};


/* lfmt_tab - Long integer test table for the function "printf" */

struct
{
	char *fmtstr;
	long val;
} lfmt_tab[] =
{
	"%li",		123456L,
	"%li",		0L,
	"%li",		-12L,
	"%ld",		123456L,
	"%ld",		0L,
	"%ld",		-12L,
	"%lu",		123456L,
	"%lu",		0L,
	"%lu",		-12L,
	"%lo",		123456L,
	"%lo",		0L,
	"%lo",		-12L,
	"%lx",		123456L,
	"%lx",		0L,
	"%lx",		-12L,
	"%lX",		123456L,
	"%lX",		0L,
	"%lX",		-12L,
	"%-10li",	123456L,
	"%+li",		123456L,
	"% li",		123456L,
	"%#0lx",	123456L,
	"%#lx",		123456L,
	"%#lX",		123456L,
	"%1lx",		123456L,
	"%2lx",		123456L,
	"%3lx",		123456L,
	"%4lx",		123456L,
	"%5lx",		123456L,
	"%6lx",		123456L,
	"%7lx",		123456L,
	"%8lx",		123456L
};


/* sfmt_tab - String test table for the function "printf" */

struct
{
	char *fmtstr;
	char *valstr;
} sfmt_tab[] =
{
	"%s",		"",
	"%s",		"test 123",
	"%s",		"ABCDEFGHIJKLMNOPQRSTUVWXYZ",
	"%20s",		"",
	"%20s",		"test 123",
	"%20s",		"ABCDEFGHIJKLMNOPQRSTUVWXYZ",
	"%-20s",	"",
	"%-20s",	"test 123",
	"%-20s",	"ABCDEFGHIJKLMNOPQRSTUVWXYZ",
	"%%",		"Nothing"
};


char *errmsg();
void HC_FIX();

#ifdef __BORLANDC
extern int _8087;
#endif

#define DLL_PROCESS_DETACH 0    
#define DLL_PROCESS_ATTACH 1    
ULONG DllEntryPoint(void *hDll, ULONG Reason, void *Reserved)
{
	if (Reason == DLL_PROCESS_ATTACH)
		printf("FLTDLL: Process attach\n");
	return TRUE;
}

/*

Main function

*/

flttest()

{

	extern void foo_exit();		

	div_t div_res;			/* "div" function result */
	ldiv_t ldiv_res;		/* "div" function result */
	register int i;			/* General loop counter */
	double fres;			/* Floating point (double) result */
	long lres;			/* Long result */
	char *p;			/* Generic pointer */
	int iexp;			/* Integer exponent */
	double ipart;			/* Integer part of a number */
	float float_res;		/* float size result */

	/* Tell the world who we are */

	printf("\n");
	printf("Floating Point C Library Test Suite\n");
	printf("(C) Copyright 1988-1991 Phar Lap Software, Inc.\n");
	printf("\n");

	/* abs - Absolute value function */

	for(i = 0; i < COUNTOF(abs_tab); ++i)
	{
		printf("abs(%i) = %i\n", abs_tab[i], abs(abs_tab[i]));
	}
	printf("\n");

	/* acos - Arc cosine function */

	for(i = 0; i < COUNTOF(acos_tab); ++i)
	{
		errno = 0;
		fres = acos(acos_tab[i]);
		HC_FIX(fres);
		if(errno != 0)
			printf("acos(%.4f): %s\n", acos_tab[i], errmsg(errno));
		else
			printf("acos(%.4f) = %.4f\n", acos_tab[i], fres);
	}
	printf("\n");


	/* asin - Arc sine function */

	for(i = 0; i < COUNTOF(acos_tab); ++i)
	{	
		errno = 0;
		fres = asin(acos_tab[i]);
		HC_FIX(fres);
		if(errno != 0)
			printf("asin(%.4f): %s\n", acos_tab[i], errmsg(errno));
		else
			printf("asin(%.4f) = %.4f\n", acos_tab[i], fres);
	}
	printf("\n");


	/* atan - Arc tangent function */

	for(i = 0; i < COUNTOF(atan_tab); ++i)
	{
		errno = 0;
		fres = atan(atan_tab[i]);
		HC_FIX(fres);
		if(errno != 0)
			printf("atan(%.4f): %s\n", atan_tab[i], errmsg(errno));
		else
			printf("atan(%.4f) = %.4f\n", atan_tab[i], fres);
	}
	printf("\n");


	/* atan2 - Arc tangent function */

	for(i = 0; i < COUNTOF(atan2_tab); ++i)
	{
		errno = 0;
		fres = atan2(atan2_tab[i].y, atan2_tab[i].x);
		HC_FIX(fres);
		if(errno != 0)
			printf("atan2(%.4f,%.4f): %s\n", 
			       atan2_tab[i].y, atan2_tab[i].x, errmsg(errno));
		else
			printf("atan2(%.4f,%.4f) = %.4f\n", 
			       atan2_tab[i].y, atan2_tab[i].x, fres);
	}
	printf("\n");

	/* atof - Convert ASCII to float */

	for(i = 0; i < COUNTOF(atof_tab); ++i)
	{
		printf("atof(\"%s\") = %.4f\n", atof_tab[i],
		       atof(atof_tab[i]));
	}
	printf("\n");

	/* atoi - Convert ASCII to integer */

	for(i = 0; i < COUNTOF(atoi_tab); ++i)
	{
		printf("atoi(\"%s\") = %i\n", atoi_tab[i],
		       atoi(atoi_tab[i]));
	}
	printf("\n");

	/* atol - Convert ASCII to long */

	for(i = 0; i < COUNTOF(atol_tab); ++i)
	{
		printf("atol(\"%s\") = %li\n", atol_tab[i],
		       atol(atol_tab[i]));
	}
	printf("\n");

//#ifdef __BORLANDC__

	/* cabs - Calculate complex absolute value */

	for(i = 0; i < COUNTOF(cabs_tab); ++i)
	{
		double x,y;
		double z;
		errno = 0;
		z = _cabs(cabs_tab[i]);
#ifdef __WATCOMC__
		x = cabs_tab[i].real;
		y = cabs_tab[i].imag;
#else
		x = cabs_tab[i].x;
		y = cabs_tab[i].y;
#endif
		if(errno != 0)
			printf("cabs(%.4f,%.4f): %s\n", x, y, errmsg(errno));
		else
			printf("cabs(%.4f,%.4f) = %.4f\n", x, y, z);
	}
	printf("\n");

//#endif

	/* ceil - Ceiling function */

	for(i = 0; i < COUNTOF(ceil_tab); ++i)
	{
		printf("ceil(%.4f) = %.4f\n", ceil_tab[i], ceil(ceil_tab[i]));
	}
	printf("\n");

	/* _clear87 - FPU clear status word and 
	   _status87 - read status word and 
	   _control87 - write control word */

//#if defined(_MSC_VER) || defined(_BORLANDC_)

	{
		unsigned old_cw;
		double y = 1.5e-100;
		_clear87();
		printf("Status before error %X\n",_status87());
		float_res=(float)y; /* underflow and loss of precision */
		printf("Status after error %X\n",_status87());
		_clear87();
		printf("Status after clear %X\n\n",_status87());

		printf("Attempting to mask DIV_BY_ZERO with control87()\n");

		old_cw = _control87(0,0);	/* save CW */
		printf("Old control word = %X\n",old_cw);

		_control87(EM_ZERODIVIDE, EM_ZERODIVIDE);

		printf("New control word = %X\n",_control87(0,0));

		float_res = (float)0.0;
		printf("Dividing: 1.0 / %f ...\n",float_res);
		float_res = ((float)1.0) / float_res;

		_clear87();
		_control87(old_cw,
			   EM_ZERODIVIDE);	/* restore CW */

		printf("Success!\n\n");

	}
//#endif

	/* cos - Cosine function */

	for(i = 0; i < COUNTOF(cos_tab); ++i)
	{
		errno = 0;
		fres = cos(cos_tab[i]);
		HC_FIX(fres);
		if(errno != 0)
			printf("cos(%.4f): %s\n", cos_tab[i], errmsg(errno));
		else
			printf("cos(%.4f) = %.4f\n", cos_tab[i], fres);
	}
	printf("\n");


	/* cosh - Hyperbolic cosine function */

	for(i = 0; i < COUNTOF(cosh_tab); ++i)
	{
		errno = 0;
		fres = cosh(cosh_tab[i]);
		HC_FIX(fres);
		if(errno != 0)
			printf("cosh(%.4f): %s\n", cosh_tab[i], errmsg(errno));
		else
			printf("cosh(%.4f) = %.4f\n", cosh_tab[i], fres);
	}
	printf("\n");


	/* div - Divide with remainder */

	for(i = 0; i < COUNTOF(div_tab); ++i)
	{
		div_res = div(div_tab[i].top, div_tab[i].bot);
		printf("div(%i,%i): quot = %i, rem = %i\n",
		       div_tab[i].top, div_tab[i].bot, 
		       div_res.quot, div_res.rem);
	}
	printf("\n");

//#ifdef __BORLANDC__

	/* ecvt - convert a floating point number to a string */

	for(i = 0; i < COUNTOF(ecvt_tab); ++i)
	{
		int dec;
		int sign;
		char *string;

		printf("ecvt(%.4f) = ",ecvt_tab[i]);

		string = _ecvt(ecvt_tab[i],10,&dec,&sign);

		if (sign)
			printf("-");
		else
			printf(" ");

		if (dec >= 0)
		{
			printf("%.*s", dec, string);
			printf(".%s",string+dec);
		}
		else
		{
			printf(".%.*s", -dec, "0000000000000000");
			printf("%s",string);
		}

		printf("\n");

	}
	printf("\n");

//#endif

	/* exp - Exponential function */

	for(i = 0; i < COUNTOF(exp_tab); ++i)
	{
		errno = 0;
		fres = exp(exp_tab[i]);
		HC_FIX(fres);
		if(errno != 0)
			printf("exp(%.4f): %s\n", exp_tab[i], errmsg(errno));
		else
			printf("exp(%.4f) = %.4f\n", exp_tab[i], fres);
	}
	printf("\n");


	/* fabs - Floating point absolute value function */

	for(i = 0; i < COUNTOF(fabs_tab); ++i)
	{
		printf("fabs(%.4f) = %.4f\n", fabs_tab[i], fabs(fabs_tab[i]));
	}
	printf("\n");

//#ifdef __BORLANDC__

	/* fcvt - convert a floating point number to a string */

	for(i = 0; i < COUNTOF(ecvt_tab); ++i)
	{
		int dec;
		int sign;
		char *string;

		printf("fcvt(%.4f) = ",ecvt_tab[i]);

		string = _fcvt(ecvt_tab[i],10,&dec,&sign);

		if (sign)
			printf("-");
		else
			printf(" ");

		if (dec >= 0)
		{
			printf("%.*s", dec, string);
			printf(".%s",string+dec);
		}
		else
		{
			printf(".%.*s", -dec, "0000000000000000");
			printf("%s",string);
		}

		printf("\n");

	}
	printf("\n");

//#endif
	

	/* floor - Floor function */

	for(i = 0; i < COUNTOF(ceil_tab); ++i)
	{
		printf("floor(%.4f) = %.4f\n", ceil_tab[i],
		       floor(ceil_tab[i]));
	}
	printf("\n");


	/* fmod - floating point mod function */

	for(i = 0; i < COUNTOF(fmod_tab); ++i)
	{
		printf("fmod(%.4f, %.4f) = %.4f\n", fmod_tab[i].top, 
		       fmod_tab[i].bot,
		       fmod(fmod_tab[i].top, fmod_tab[i].bot));
	}
	printf("\n");

//#ifdef __BORLANDC__

	/* _fpreset -  reset floating point package */

	{
		double y = 1.5e-100;
		_clear87();
		printf("Status before error %X\n",_status87());
		float_res=(float)y; /* underflow and loss of precision */
		printf("Status after error %X\n",_status87());
		_fpreset();
		printf("Status after _fpreset %X\n\n",_status87());

	}
//#endif

	/* frexp - Normalize a floating point number */

	for(i = 0; i < COUNTOF(frexp_tab); ++i)
	{
		fres = frexp(frexp_tab[i], &iexp);
		printf("frexp(%.4f) = %.4f, exp = %i\n", frexp_tab[i], fres,
		       iexp);
	}
	printf("\n");

//#ifdef __BORLANDC__

	/* gcvt - convert a floating point number to a string */

	for(i = 0; i < COUNTOF(ecvt_tab); ++i)
	{
		char string[20];

		printf("gcvt(%.4f) = ",ecvt_tab[i]);

		_gcvt(ecvt_tab[i],10,string);

		printf("%s\n",string);

	}
	printf("\n");

	/* hypot - calcultate hypotenuse of a triangle */

	for(i = 0; i < COUNTOF(hyp_tab); ++i)
	{
		double x;

		printf("hypot(%.4f, %.4f) = ", hyp_tab[i].a, hyp_tab[i].b);
		errno = 0;
		x = _hypot(hyp_tab[i].a, hyp_tab[i].b);
		if (errno != 0)
			printf("%s\n", errmsg(errno));
		else
			printf("%f\n", x);
	}
	printf("\n");

	/* labs - long absolute value function */

	for(i = 0; i < COUNTOF(fabs_tab); ++i)
	{
		printf("labs(%ld) = %ld\n", labs_tab[i], labs(labs_tab[i]));
	}
	printf("\n");


//#endif

	/* ldiv - Divide with remainder */

	for(i = 0; i < COUNTOF(ldiv_tab); ++i)
	{
		ldiv_res = ldiv(ldiv_tab[i].top, ldiv_tab[i].bot);
		printf("ldiv(%ld,%ld): quot = %ld, rem = %ld\n",
		       ldiv_tab[i].top, ldiv_tab[i].bot, 
		       ldiv_res.quot, ldiv_res.rem);
	}
	printf("\n");

	/* ldexp - Multiple value by a power of 2 */

	for(i = 0; i < COUNTOF(ldexp_tab); ++i)
	{
		errno = 0;
		fres = ldexp(ldexp_tab[i].val, ldexp_tab[i].exp);
		HC_FIX(fres);
		printf("ldexp(%.4f, %i)", ldexp_tab[i].val,
			       ldexp_tab[i].exp);
		if(errno != 0)
			printf(": %s\n", errmsg(errno));
		else
			printf(" = %.4f\n", fres);
	}
	printf("\n");




	/* log - Natural logarithm function */

	for(i = 0; i < COUNTOF(log_tab); ++i)
	{
		errno = 0;
		fres = log(log_tab[i]);
		HC_FIX(fres);
		if(errno != 0)
			printf("log(%.4f): %s\n", log_tab[i], errmsg(errno));
		else
			printf("log(%.4f) = %.4f\n", log_tab[i], fres);
	}
	printf("\n");


	/* log10 - Logarithm function (base 10) */

	for(i = 0; i < COUNTOF(log_tab); ++i)
	{
		errno = 0;
		fres = log10(log_tab[i]);
		HC_FIX(fres);
		if(errno != 0)
			printf("log10(%.4f): %s\n", log_tab[i],
		 	       errmsg(errno));
		else
			printf("log10(%.4f) = %.4f\n", log_tab[i], fres);
	}
	printf("\n");


	/* modf - Break a floating point number into integer and
	   fractional parts */

	for(i = 0; i < COUNTOF(modf_tab); ++i)
	{
		fres = modf(modf_tab[i], &ipart);
		printf("modf(%.4f) = %.4f and %.4f\n", 
			modf_tab[i], ipart, fres);
	}
	printf("\n");


	/* pow - Raise to the power function */

	for(i = 0; i < COUNTOF(pow_tab); ++i)
	{
		errno = 0;
		fres = pow(pow_tab[i].x, pow_tab[i].y);
		HC_FIX(fres);
		if(errno != 0)
		{
			printf("pow(%.4f, %.4f): %s\n", 
			       pow_tab[i].x, pow_tab[i].y, errmsg(errno));
		}
		else
		{
			printf("pow(%.4f, %.4f) = %.4f\n", 
			       pow_tab[i].x, pow_tab[i].y, fres);
		}
	}
	printf("\n");

#ifdef __BORLANDC__	

	/* pow10 - Raise 10 to the power function */

	for(i = 0; i < COUNTOF(pow_tab); ++i)
	{
		errno = 0;
		fres = pow10(pow_tab[i].y);
		if(errno != 0)
		{
			printf("pow10(%.4f): %s\n", 
			       pow_tab[i].y, errmsg(errno));
		}
		else
		{
			printf("pow10(%.4f) = %.4f\n", 
			       pow_tab[i].y, fres);
		}
	}
	printf("\n");

#endif

	/* printf - Write data with a format string */

	for(i = 0; i < COUNTOF(ifmt_tab); ++i)
	{
		printf("%i (%s) = ", ifmt_tab[i].val, ifmt_tab[i].fmtstr);
		printf(ifmt_tab[i].fmtstr, ifmt_tab[i].val);
		printf("\n");
	}
	printf("\n");
	for(i = 0; i < COUNTOF(dfmt_tab); ++i)
	{
		printf("%f (%s) = ", dfmt_tab[i].val, dfmt_tab[i].fmtstr);
		printf(dfmt_tab[i].fmtstr, dfmt_tab[i].val);
		printf("\n");
	}
	printf("\n");
	for(i = 0; i < COUNTOF(lfmt_tab); ++i)
	{
		printf("%li (%s) = ", lfmt_tab[i].val, lfmt_tab[i].fmtstr);
		printf(lfmt_tab[i].fmtstr, lfmt_tab[i].val);
		printf("\n");
	}
	printf("\n");
	for(i = 0; i < COUNTOF(sfmt_tab); ++i)
	{
		printf("%s (%s) = ", sfmt_tab[i].valstr, sfmt_tab[i].fmtstr);
		printf(sfmt_tab[i].fmtstr, sfmt_tab[i].valstr);
		printf("\n");
	}
	printf("\n");


	/* sin - Sine function */

	for(i = 0; i < COUNTOF(cos_tab); ++i)
	{
		errno = 0;
		fres = sin(cos_tab[i]);
		HC_FIX(fres);
		if(errno != 0)
			printf("sin(%.4f): %s\n", cos_tab[i], errmsg(errno));
		else
			printf("sin(%.4f) = %.4f\n", cos_tab[i], fres);
	}
	printf("\n");


	/* sinh - Hyperbolic sine function */

	for(i = 0; i < COUNTOF(cosh_tab); ++i)
	{
		errno = 0;
		fres = sinh(cosh_tab[i]);
		HC_FIX(fres);
		if(errno != 0)
			printf("sinh(%.4f): %s\n", cosh_tab[i], errmsg(errno));
		else
			printf("sinh(%.4f) = %.4f\n", cosh_tab[i], fres);
	}
	printf("\n");


	/* sqrt - Square root function */

	for(i = 0; i < COUNTOF(sqrt_tab); ++i)
	{
		errno = 0;
		fres = sqrt(sqrt_tab[i]);
		HC_FIX(fres);
		if(errno != 0)
			printf("sqrt(%.4f): %s\n", sqrt_tab[i], errmsg(errno));
		else
			printf("sqrt(%.4f) = %.4f\n", sqrt_tab[i], fres);
	}
	printf("\n");


	/* strtod - String to double conversion routine */

	for(i = 0; i < COUNTOF(strtod_tab); ++i)
	{
		errno = 0;
		fres = strtod(strtod_tab[i], &p);
		printf("strtod(%s) = %.4f, length = %i", strtod_tab[i],
		       fres, p - strtod_tab[i]);
		if(errno != 0)
			printf("  error: %s", errmsg(errno));
		printf("\n");
	}
	printf("\n");


	/* strtol - String to long conversion routine */

	for(i = 0; i < COUNTOF(strtol_tab); ++i)
	{
		errno = 0;
		lres = strtol(strtol_tab[i], &p, 10);
		printf("strtol(%s) = %li, length = %i", strtol_tab[i],
		       lres, p - strtol_tab[i]);
		if(errno != 0)
			printf("  error: %s", errmsg(errno));
		printf("\n");
	}
	printf("\n");

	/* strtoul - String to unsigned long conversion routine */

	for(i = 0; i < COUNTOF(strtol_tab); ++i)
	{
		errno = 0;
		lres = strtoul(strtol_tab[i], &p, 10);
		printf("strtoul(%s) = %lu, length = %i", strtol_tab[i],
		       lres, p - strtol_tab[i]);
		if(errno != 0)
			printf("  error: %s", errmsg(errno));
		printf("\n");
	}
	printf("\n");


	/* tan - Tangent function */

	for(i = 0; i < COUNTOF(cos_tab); ++i)
	{
		errno = 0;
		fres = tan(cos_tab[i]);
		HC_FIX(fres);
		if(errno != 0)
			printf("tan(%.4f): %s\n", cos_tab[i], errmsg(errno));
		else
			printf("tan(%.4f) = %.4f\n", cos_tab[i], fres);
	}
	printf("\n");


	/* tanh - Hyperbolic tanget function */

	for(i = 0; i < COUNTOF(cosh_tab); ++i)
	{
		errno = 0;
		fres = tanh(cosh_tab[i]);
		HC_FIX(fres);
		if(errno != 0)
			printf("tanh(%.4f): %s\n", cosh_tab[i], errmsg(errno));
		else
			printf("tanh(%.4f) = %.4f\n", cosh_tab[i], fres);
	}
	printf("\n");

#ifdef __BORLANDC__

	/* Done with functions */

	printf("All done testing functions - testing globals now ..\n\n");

	/* _8087 global */

	printf("Type of coprocessor: ");

	switch(_8087)
	{
		case 0: printf("<<None>>.\n"); break;
		case 1: printf("<<8087>>.\n"); break;
		case 2: printf("<<80287>>.\n"); break;
		case 3: printf("<<80387>>.\n"); break;
		default: printf("<<Unknown %d>>.\n",_8087); break;
	}

#endif

	/* All done */

	printf("\n\nAll done.\n\n");
	return 0;
}


/*

HC_FIX - Fix bug in High C 386 run-time library

*/

void HC_FIX(fres)

double fres;

{

	unsigned short *expp;

	expp = (unsigned short *)(((char *)&fres) + 6);
	if(errno == 0 &&
	   (*expp & 0x7FF0) == 0x7FF0) 	/* Turn NAN's into domain errors */
	{
		errno = EDOM;
	}

}


/*

errmsg - Error message routine

*/

char *errmsg(no)

int no;			/* Error number */

{

	static char lbuff[100];		/* Local buffer */

	switch(no)
	{

	case EDOM: return "Domain error";
	case ERANGE: return "Argument out of range";
	default: sprintf(lbuff, "Unknown error #%i", no);
	         return lbuff;
		
	}

}
