#include <std.h>
#include <assert.h>
#include <twotable.h>
#include <iostream.h>


double twotable_c::operator()(double x, double y) C
{
 BOOL ok=TRUE;

 if(x<xr && (ok=dnxok))
	x = xr.low;
 else if(x>xr && (ok&=upxok))
	x = xr.high;

 if(y<yr && (ok&=dnyok))
	y = yr.low;
 else if(y>yr && (ok&=upyok))
	y = yr.high;

 if(!ok){
	ENTER_FCN("twotable_c::operator()");
	cout << flush;
	cerr << "X or Y out of range (" << x << ", " << y
		 << ") for twotable'" << name < "'\n";
	assert(0);
	}

 double t;
 int ix = (int)(t = (x-xr.low)*xratio);
 double u;
 int iy = (int)(u = (y-yr.low)*yratio);
 if(ix == data.size())
	ix--;
 if(iy == data[0].size())
	iy--;
 t -= ix;
 u -= iy;

 C double tu = t*u;
 return (1-t-u+tu)*data[ix][iy] + (t-tu)*data[ix+1][iy] + tu*data[ix+1][iy+1]
		+(u-tu)*data[ix][iy+1];
}

twotable_c::twotable_c(C Range(double)& xxr, C Range(double)& yyr,
						int nx, int ny,
						double (*f)(double x, double y, C void *p),
						C void *p,
						unsigned ok_dir, C char *nm)
	: xr(xxr), yr(yyr), name(nm), data(nx)
{
 ENTER_FCN("twotable_c::twotable_c((*f)())");
 assert(xxr && yyr && f && nx>0 && ny>0);
 xratio = (nx-1)/(xr.high - xr.low);
 yratio = (ny-1)/(yr.high - yr.low);
 upxok = (ok_dir & X_up) ? TRUE : FALSE;
 dnxok = (ok_dir & X_dn) ? TRUE : FALSE;
 upyok = (ok_dir & Y_up) ? TRUE : FALSE;
 dnyok = (ok_dir & Y_dn) ? TRUE : FALSE;

 int i;
 for(i=0;i<nx;i++)	{
 	data[i].size(ny);
	C double x = xr.low + i/xratio;
	int j;
	for(j=0;j<ny;j++)
		data[i][j] = (*f)(x, yr.low + j/yratio, p);
	}
}

twotable_c::twotable_c(C Range(double)& xxr, C Range(double)& yyr,
						int nx, int ny, C float *C*d,
						unsigned ok_dir, C char *nm)
	: xr(xxr), yr(yyr), name(nm), data(nx)
{
 ENTER_FCN("twotable_c::twotable_c(float**)");
 assert(xxr && yyr && d && nx>0 && ny>0);
 xratio = (nx-1)/(xr.high - xr.low);
 yratio = (ny-1)/(yr.high - yr.low);
 upxok = (ok_dir & X_up) ? TRUE : FALSE;
 dnxok = (ok_dir & X_dn) ? TRUE : FALSE;
 upyok = (ok_dir & Y_up) ? TRUE : FALSE;
 dnyok = (ok_dir & Y_dn) ? TRUE : FALSE;

 int i;
 for(i=0;i<nx;i++)	{
 	data[i].size(ny);
	int j;
	for(j=0;j<ny;j++)
		data[i][j] = d[i][j];
	}
}
