/*
*	icalc - complex-expression parser
*
*	Built-in functions not included in cmath.c, since they're not
*	so mathematical.
*
*	(C) Martin W Scott, 1991.
*/

#include <stdio.h>
#include <math.h>
#include <time.h>
#include "complex.h"
#include "constant.h"

extern Symbol *ans;

static int prec = 8;		/* number of decimal places to print */
				/* (when they exist) */

void cprin(fp, prefix, suffix, z)	/* print a complex number to file fp */
	FILE *fp;
	char *prefix, *suffix;
	Complex z;
{
	fprintf(fp, prefix);

	if (z.imag == 0.0)
		fprintf(fp, "%10.*lg", prec, z.real);
	else if (z.real == 0.0)
		fprintf(fp, "%10.*lg i", prec, z.imag);
	else
		fprintf(fp, "%.*g %c %.*g i",
			prec, z.real, sign(z.imag), prec, abs(z.imag));

	fprintf(fp, suffix);
}

Complex printres(z)	/* prints and returns its argument */
	Complex z;
{
	cprin(stdout, "\t", "\n", z);
	return z;
}

Complex precision(z)	/* adjust decimal places shown */
	Complex z;
{
	prec = (int)z.real;
	return ans->u.val;
}


static double integer(x)	/* round x to NEAREST integer */
	double x;		/* if fractional part is 0.5, round UP */
{
	double f,i;

	f = modf(x,&i);
	if (abs(f) >= 0.5)
		if (x >= 0.0)
			return i + 1.0;
		else
			return i - 1.0;
	else return i;
}

Complex cinteger(z)	/* return REAL part to nearest integer */
	Complex z;
{
	z.real = integer(z.real);
	z.imag = 0.0;

	return z;
}
	
Complex cceil(z)	/* ceiling of REAL part of z */
	Complex z;
{
	z.real = ceil(z.real);
	z.imag = 0.0;
	return z;
}
	
Complex cfloor(z)	/* ceiling of REAL part of z */
	Complex z;
{
	z.real = floor(z.real);
	z.imag = 0.0;
	return z;
}

Complex csign(z)	/* sign of REAL part of z */
	Complex z;
{
	if (z.real > 0.0) z.real = 1.0;
	else if (z.real < 0.0) z.real = -1.0;
	z.imag = 0.0;
	return z;
}

/*
*	gettime(lasttime) 
*
*	returns the system time in seconds, less the real part of its
*	argument, lasttime.
*
*	eg. 	gettime({0,0}) returns system time.
*		gettime({3600,0}) returns system time less one hour.
*
*	Thus, it can be used as a simple timer within icalc scripts.
*/


#ifdef LATTICE & AMIGA		/* use higher-resolution time stuff */

Complex gettime(lasttime)
	Complex lasttime;
{
	double realtime;
	unsigned int clock[2];

	timer(clock);
	realtime = clock[0] + clock[1] / 1e6L;

	lasttime.real = realtime - lasttime.real;
	lasttime.imag = 0.0L;

	return lasttime;
}

#else	/* not on AMIGA - could possibly use other system-specific functions */

Complex gettime(lasttime)
	Complex lasttime;
{
	lasttime.real = (double)time(NULL) - lasttime.real;
	lasttime.imag = 0.0L;

	return lasttime;
}

#endif
