#include <stdlib.h>
#include <string.h>
/*********************************************************
This is code for read-in tables in XPP
This should probably be accessible from within the program
as well. It will probably be added to the Numerics Menu
The files consist of y-values of a function evaluated at
equally spaced points as well as some header information.
They are ascii files of the form:
npts <-- Integer
xlo <--- fp
xhi <-- fp
y1 <-- fp
y2
...
yn
Thus dx = (xhi-xlo)/(npts-1)
If the first line of the file says "xyvals" then the table is of the
form: x1 < x2 < .... < xn
npts
x1 y1
x2 y2
...
xn yn
In the creation of the file, one can instead use the following:
table <name> % numpts xlo xhi formula
to create a "formula" table which is linearly interpolated
table <name> @ filename creates an array for two-valued
functions
filename has the following info:
nxpts
nypts
xlo
xhi
ylo
yhi
nx*ny points as follows
f(x1,y1), f(x2,y1),....,f(xn,y1),
...
f(x1,ym), ..., f(xn,ym)
to be added later
**************************************************************/
#include <math.h>
#include <stdio.h>
#define MAX_TAB 50
typedef struct {
double xlo,xhi,dx;
double *y,*x;
int n,flag,interp,autoeval;
int xyvals;
/* flag=0 if virgin array, flag=1 if already allocated; flag=2 for function
interp=0 for normal interpolation, interp=1 for 'step'
interp=2 for cubic spline
table and finally, xyvals=1 if both x and y vals are needed (xyvals=0
is faster lookup )*/
char filename[128],name[12];
}TABULAR;
TABULAR my_table[MAX_TAB];
double atof();
double get_ivar();
double evaluate();
extern int NTable;
extern int NCON,NSYM,NCON_START,NSYM_START;
extern int MAXSTOR;
extern float **storage;
set_auto_eval_flags(int f)
{
int i;
for(i=0;i<MAX_TAB;i++)
my_table[i].autoeval=f;
}
set_table_name(name,index)
char *name;
int index;
{
strcpy(my_table[index].name,name);
}
view_table(int index)
{
int i;
int n=my_table[index].n,len;
double *y=my_table[index].y;
double xlo=my_table[index].xlo,xhi=my_table[index].xhi,dx=my_table[index].dx;
len=n;
if(len>=MAXSTOR)len=MAXSTOR-1;
for(i=0;i<len;i++){
storage[0][i]=xlo+i*dx;
storage[1][i]=y[i];
}
refresh_browser(len);
}
new_lookup_com(int i)
{
char file[128];
int index,ok,status;
double xlo,xhi;
int npts;
char newform[80];
index=select_table();
if(index==-1)return;
if(i==1){
view_table(index);
return;
}
if(my_table[index].flag==1){
strcpy(file,my_table[index].filename);
status=file_selector("Load table",file,"*.tab");
if(status==0)return;
ok=load_table(file,index);
if(ok==1)strcpy(my_table[index].filename,file);
}
if(my_table[index].flag==2){
npts=my_table[index].n;
xlo=my_table[index].xlo;
xhi=my_table[index].xhi;
strcpy(newform,my_table[index].filename);
new_int("Auto-evaluate? (1/0)",&my_table[index].autoeval);
new_int("NPts: ",&npts);
new_float("Xlo: ",&xlo);
new_float("Xhi: ",&xhi);
new_string("Formula :",newform);
create_fun_table(npts,xlo,xhi,newform,index);
}
}
new_lookup_ok()
{
char file[128];
char name[10];
int index,ok;
double xlo,xhi;
int npts;
char newform[80];
if(NTable==0)return;
while(1){
name[0]=0;
new_string("Lookup name ",name);
if(strlen(name)==0)return;
index=find_lookup(name);
index=select_table();
if(index!=-1){
if(my_table[index].flag==1){
strcpy(file,my_table[index].filename);
if(new_string("Filename:",file)){
ok=load_table(file,index);
if(ok==1)strcpy(my_table[index].filename,file);
}
}
if(my_table[index].flag==2){
npts=my_table[index].n;
xlo=my_table[index].xlo;
xhi=my_table[index].xhi;
strcpy(newform,my_table[index].filename);
new_int("Auto-evaluate? (1/0)",&my_table[index].autoeval);
new_int("NPts: ",&npts);
new_float("Xlo: ",&xlo);
new_float("Xhi: ",&xhi);
new_string("Formula :",newform);
create_fun_table(npts,xlo,xhi,newform,index);
}
}
else err_msg("Not a Table function");
}
}
double lookupxy(x,n,xv,yv)
double x,*xv,*yv;
int n;
{
double dx,dy,x1,y1,x2,y2;
int i;
if(x<=xv[0])
return(yv[0]+(yv[1]-yv[0])*(x-xv[0])/(xv[1]-xv[0]));
if(x>=xv[n-1])
return(yv[n-1]+(yv[n-2]-yv[n-1])*(x-xv[n-1])/(xv[n-1]-xv[n-2]));
x1=xv[0];
y1=yv[0];
for(i=1;i<n;i++){
if(x<=xv[i]){
x2=xv[i];
y2=yv[i];
dx=x2-x1;
dy=y2-y1;
return(y1+dy*(x-x1)/dx);
}
x1=xv[i];
y1=yv[i];
}
return(yv[n-1]);
}
double tab_interp(xlo,h,x,y,n,i)
double h,x,xlo,*y;
int n,i;
{
double a,b,c,d;
double ym,y0,y1,y2;
double tt;
ym=y[i-1];
y0=y[i];
y1=y[i+1];
y2=y[i+2];
d=y0;
b=.5*(y1+ym-2*y0);
a=(3*(y0-y1)+y2-ym)/6;
c=(6*y1-y2-3*y0-2*ym)/6;
tt=(x-xlo)/h-i;
return d+tt*(c+tt*(b + tt*a));
}
double lookup(x,index)
int index;
double x;
{
double xlo=my_table[index].xlo,xhi=my_table[index].xhi,dx=my_table[index].dx;
double *y,*xv;
double x1,y1,y2;
int i1,i2,n=my_table[index].n;
y=my_table[index].y;
if(my_table[index].flag==0)return(0.0); /* Not defined */
if(my_table[index].xyvals==1)
return(lookupxy(x,n,my_table[index].x,y));
i1=(int)((x-xlo)/dx); /* (int)floor(x) instead of (int)x ??? */
if(my_table[index].interp==2&&i1>0&&i1<(n-2))
return tab_interp(xlo,dx,x,y,n,i1); /* if it is on the edge - use linear */
i2=i1+1;
if(i1>-1&&i2<n){
x1=dx*i1+xlo;
y1=y[i1];
y2=y[i2];
if (my_table[index].interp==0||my_table[index].interp==2)
return(y1+(y2-y1)*(x-x1)/dx);
else
{
#ifdef DEBUG
printf("index=%d; x=%lg; i1=%d; i2=%d; x1=%lg; y1=%lg; y2=%lg\n",index,x,i1,i2,x1,y1,y2);
#endif
return(y1);
};
}
if(i1<0)return(y[0]+(y[1]-y[0])*(x-xlo)/dx);
if(i2>=n)return(y[n-1]+(y[n-1]-y[n-2])*(x-xhi)/dx);
}
init_table()
{
int i;
for(i=0;i<MAX_TAB;i++) {
my_table[i].flag=0;
my_table[i].autoeval=1;
my_table[i].interp=0;
}
}
redo_all_fun_tables()
{
int i;
for(i=0;i<NTable;i++){
if(my_table[i].flag==2&&my_table[i].autoeval==1)
eval_fun_table(my_table[i].n,my_table[i].xlo,
my_table[i].xhi,my_table[i].filename,my_table[i].y);
}
update_all_ffts();
}
eval_fun_table(n,xlo,xhi,formula,y)
int n;
char *formula;
double xlo,xhi,*y;
{
int i;
int ok=0;
double dx,x;
double oldt;
int command[200],ncold=NCON,nsym=NSYM;
if(add_expr(formula,command,&i)){
err_msg("Illegal formula...");
NCON=ncold;
NSYM=nsym;
return(0);
}
oldt=get_ivar(0);
dx=(xhi-xlo)/((double)(n-1));
for(i=0;i<n;i++){
set_ivar(0,dx*i+xlo);
y[i]=evaluate(command);
}
set_ivar(0,oldt);
NCON=ncold;
NSYM=nsym;
return(1);
}
create_fun_table(npts,xlo,xhi,formula,index)
int npts;
int index;
double xlo,xhi;
char *formula;
{
int i,length=npts;
if(my_table[index].flag==1){
err_msg("Not a function table...");
return(0);
}
if(xlo>xhi){
err_msg("Xlo > Xhi ???");
return(0);
}
if(npts<2){
err_msg("Too few points...");
return(0);
}
if(my_table[index].flag==0){
my_table[index].y=(double *)malloc(length*sizeof(double));
}
else {
my_table[index].y=
(double *)realloc((void *)my_table[index].y,length*sizeof(double));
}
if(my_table[index].y==NULL){
err_msg("Unable to allocate table");
return(0);
}
my_table[index].flag=2;
if(eval_fun_table(npts,xlo,xhi,formula,my_table[index].y)){
my_table[index].xlo=xlo;
my_table[index].xhi=xhi;
my_table[index].n=npts;
my_table[index].dx=(xhi-xlo)/((double)(npts-1));
strcpy(my_table[index].filename,formula);
return(1);
}
return(0);
}
load_table(filename,index)
char *filename;
int index;
{
int i;
char bobtab[100];
char * bob;
int length;
double xlo,xhi;
FILE *fp;
bob = bobtab;
if(my_table[index].flag==2){
err_msg("Not a file table...");
return(0);
}
fp=fopen(filename,"r");
if(fp==NULL){
err_msg("File not found");
return(0);
}
my_table[index].interp=0;
fgets(bob,100,fp);
if (bob[0]=='i') /* closest step value */
{
my_table[index].interp=1;
bob++; /* skip past initial "i" to length */
};
if (bob[0]=='s') /* cubic spline */
{
my_table[index].interp=2;
bob++; /* skip past initial "i" to length */
};
length=atoi(bob);
if(length<2){
err_msg("Length too small");
fclose(fp);
return(0);
}
fgets(bob,100,fp);
xlo=atof(bob);
fgets(bob,100,fp);
xhi=atof(bob);
if(xlo>=xhi){
err_msg("xlo >= xhi ??? ");
fclose(fp);
return(0);
}
if(my_table[index].flag==0){
my_table[index].y=(double *)malloc(length*sizeof(double));
if(my_table[index].y==NULL){
err_msg("Unable to allocate table");
fclose(fp);
return(0);
}
for(i=0;i<length;i++){
fgets(bob,100,fp);
my_table[index].y[i]=atof(bob);
}
my_table[index].xlo=xlo;
my_table[index].xhi=xhi;
my_table[index].n=length;
my_table[index].dx=(xhi-xlo)/(length-1);
my_table[index].flag=1;
strcpy(my_table[index].filename,filename);
fclose(fp);
return(1);
}
my_table[index].y=
(double *)realloc((void *)my_table[index].y,length*sizeof(double));
if(my_table[index].y==NULL){
err_msg("Unable to reallocate table");
fclose(fp);
return(0);
}
for(i=0;i<length;i++){
fgets(bob,100,fp);
my_table[index].y[i]=atof(bob);
}
my_table[index].xlo=xlo;
my_table[index].xhi=xhi;
my_table[index].n=length;
my_table[index].dx=(xhi-xlo)/(length-1);
my_table[index].flag=1;
fclose(fp);
return(1);
}
get_lookup_len(int i)
{
return my_table[i].n;
}
/* network stuff
table name <type> ... arguments ...
conv npts weight variable_name klo khi end_cond
sparse npts variable filename
name(0 ... npts-1)
conv:
name(i) = sum(k=klo,khi) weight(k-klo)*variable(i+k)
with end_cond = zero means skip if off end
= periodic means wrap around
sparse:
need a file with the structure:
ncon i_1 w_1 ... i_ncon w_ncon
for npts lines
name(i) = sum(j=1,ncon_i) w_j name(i_j)
*/
syntax highlighted by Code2HTML, v. 0.9.1