home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
509.lha
/
ATS_v2.0
/
ats.cp
next >
Wrap
Text File
|
1991-05-06
|
12KB
|
669 lines
// ret.terms[i]=complex(0.0,0.0);
//
// C++ Routines to manipulate Taylor series for solving a differential
// equation.
//
// By Dennis J. Darland
// 4/3/91
// Public Domain
// Version 1.6
// Many enhancements expected.
// PROVIDED WITH NO WARRANTY.
//
#include "ats.h"
t_s::t_s()
{
alloc_terms=MAX_TERMS;
}
t_s::~t_s()
{
}
t_s::t_s(t_s &a)
{
alloc_terms=MAX_TERMS;
set_first(a.first_term);
set_last(a.last_term);
set_x0(a.x0);
set_h(a.h);
set_terms(*this,a.terms);
}
void t_s::set_first(int i)
{
first_term=i;
}
void t_s::set_last(int i)
{
last_term=i;
}
void t_s::set_h(complex h_in)
{
h=h_in;
}
void t_s::set_x0(complex x0_in)
{
x0=x0_in;
}
void set_data(t_s &a,t_s &b)
{
a.set_first(b.first_term);
a.set_last(b.last_term);
a.set_x0(b.x0);
a.set_h(b.h);
a.alloc_terms=MAX_TERMS;
}
void set_terms(t_s &ret,complex *values)
{
register int i;
for (i=0;i<MAX_TERMS;i++)
ret.terms[i]=values[i];
}
complex ats(int m,t_s &a,t_s &b,int j)
{
// function to implement Liebniz rule
complex cret;
register int i;
cret=complex(0.0,0.0);
for (i=j;i<=m;i++)
{
cret += a.terms[i]*b.terms[m-i];
}
return(cret);
}
complex att(int m,t_s &a,t_s &b,int j)
{
// function for modified Liebniz rule
complex ret;
register int i;
ret=complex(0.0,0.0);
if (j > m)
return(ret);
for (i=j;i<=m;i++)
{
ret += a.terms[i]*b.terms[m-i+1]*complex(double(m-i+1),0.0);
}
ret /= complex(double(m+1),0.0);
return(ret);
}
t_s & t_s::operator+=(t_s &b)
{
// Add taylor series
register int i;
if ((first_term != b.first_term)
|| (last_term != b.last_term))
report_error(0);
set_data(*this,b);
for (i=first_term; i < last_term;i++)
terms[i]+=b.terms[i];
return (*this);
}
t_s & t_s::operator-=(t_s &b)
{
// Subtract taylor series
register int i;
if ((first_term != b.first_term)
|| (last_term != b.last_term))
report_error(0);
set_data(*this,b);
for (i=first_term; i < last_term;i++)
terms[i]-=b.terms[i];
return (*this);
}
t_s& t_s::operator=(t_s &b)
{
// assign taylor series
register int i;
set_data(*this,b);
for (i=0; i < b.last_term;i++)
this->terms[i]=b.terms[i];
return(*this);
}
void display(t_s &a,int plot)
{
static pt=0;
FILE *plot_cmds;
char fname[64];
char cmd[81];
// display taylor series
register int i;
sprintf(fname,"ram:mapleplot_%d",pt);
pt++;
plot_cmds = fopen("ram:plottmp","w");
fprintf(plot_cmds,"plotdevice := amiga;\n");
fprintf(plot_cmds,"plot([");
cout << "alloc_terms=" << a.alloc_terms << "\n";
cout << "first_term =" << a.first_term << "\n";
cout << "last_term=" << a.last_term << "\n";
cout << "h=" << a.h << "\n";
cout << "x0=" << a.x0 << "\n";
for (i=0;i<a.last_term;i++)
{
cout << "terms[" << i << "]= " << real(a.terms[i]) << " + "
<< imag(a.terms[i]) << " I\n";
if (i != 0)
fprintf(plot_cmds,",");
fprintf(plot_cmds,"%d,sign(%g)*(ln(1+abs(%g)))\n",
i,real(a.terms[i]),real(a.terms[i]));
}
fprintf(plot_cmds,"]);\n");
fprintf(plot_cmds,"quit\n");
fclose(plot_cmds);
sprintf(cmd,"iconz <ram:plottmp >%s pltcvt",fname);
system(cmd);
if (plot>1)
{
sprintf(cmd,"maple <%s",fname);
system(cmd);
}
}
void t_s::report_error(int no)
{
cout << "ats error = " << no;
}
t_s operator+(t_s &a,t_s &b)
{
// Add two taylor series
register int i;
t_s ret;
complex ac,bc;
set_data(ret,a);
for (i=a.first_term;i<a.last_term;i++)
{
ac=a.terms[i];
bc=b.terms[i];
ret.terms[i]=ac+bc;
}
return(ret);
}
t_s operator-(t_s &a,t_s &b)
{
// Subtract two taylor series
register int i;
t_s ret;
complex ac,bc;
set_data(ret,a);
for (i=a.first_term;i<a.last_term;i++)
{
ac=a.terms[i];
bc=b.terms[i];
ret.terms[i]=ac-bc;
}
return(ret);
}
t_s operator*(t_s &a,t_s &b)
{
// Multiply two taylor series
register int i;
t_s ret;
set_data(ret,a);
ret.terms[0]=a.terms[0]*b.terms[0];
for (i=1;i<a.last_term;i++)
ret.terms[i]=ats(i,a,b,0);
return(ret);
}
t_s operator/(t_s &a,t_s &b)
{
// divide two taylor series
register int i;
t_s ret;
set_data(ret,a);
ret.terms[0]=a.terms[0]/b.terms[0];
for (i=1;i<a.last_term;i++)
{
ret.terms[i]=(a.terms[i]-ats(i,b,ret,1))/b.terms[0];
}
return(ret);
}
t_s x(t_s & a)
{
// independant variable - x
register int i;
t_s ret;
set_data(ret,a);
ret.terms[0]=a.x0;
ret.terms[1]=complex(1.0,0.0)*ret.h;
for (i=2;i<a.last_term;i++)
ret.terms[i]=complex(0.0,0.0);
return(ret);
}
t_s constant(t_s & a,complex b)
{
// constant - b
register int i;
t_s ret;
set_data(ret,a);
ret.terms[0]=b;
for (i=1;i<a.last_term;i++)
ret.terms[i]=complex(0.0,0.0);
return(ret);
}
t_s expt(t_s & y,t_s & y1)
{
// y to power y1
register int k,ka;
t_s ret,a1,a2;
set_data(ret,y);
set_data(a1,y);
set_data(a2,y);
ret.terms[0]=expt(y.terms[0],y1.terms[0]);
a1.terms[0]=lnn(y.terms[0]);
for (k=1;k<y.last_term;k++)
{
ka = k - 1;
a1.terms[k]=(y.terms[k] - att(ka,y,a1,1))/y.terms[0];
a2.terms[ka]=ats(k,y,a1,0)*complex(double(k),0.0)/y.h;
ret.terms[k]=ats(ka,ret,a2,0)*y.h/complex(double(k),0.0);
}
return(ret);
}
t_s sqrt(t_s & y)
{
// square root
register int k;
t_s ret;
set_data(ret,y);
ret.terms[0]=my_sqrt(y.terms[0]);
for (k=1;k<y.last_term;k++)
{
ret.terms[k]=complex(0.0,0.0);
ret.terms[k]=(y.terms[k]-ats(k,ret,ret,1))/(ret.terms[0]*
complex(2.0,0.0));
}
return(ret);
}
t_s exp(t_s & y)
{
// e to y power
register int k,ka;
t_s ret;
set_data(ret,y);
ret.terms[0]=exp(y.terms[0]);
for (k=1;k<y.last_term;k++)
{
ka = k - 1;
ret.terms[k]=att(ka,ret,y,0);
}
return(ret);
}
t_s log(t_s & y)
{
// ln of y
register int k,ka;
t_s ret;
set_data(ret,y);
ret.terms[0]=lnn(y.terms[0]);
ret.terms[1]=y.terms[1]/y.terms[0];
for (k=2;k<y.last_term;k++)
{
ka = k - 1;
ret.terms[k]=(y.terms[k] - att(ka,y,ret,1))/y.terms[0];
}
return(ret);
}
t_s sin(t_s & y)
{
// sin of y
register int k,ka;
t_s f,g;
set_data(f,y);
set_data(g,y);
f.terms[0]=sin(y.terms[0]);
g.terms[0]=cos(y.terms[0]);
for (k=1;k<y.last_term;k++)
{
ka = k - 1;
f.terms[k]=att(ka,g,y,0);
g.terms[k]=complex(-1.0,0.0)*att(ka,f,y,0);
}
return(f);
}
t_s cos(t_s & y)
{
// cos of y
register int k,ka;
t_s f,g;
set_data(f,y);
set_data(g,y);
f.terms[0]=sin(y.terms[0]);
g.terms[0]=cos(y.terms[0]);
for (k=1;k<y.last_term;k++)
{
ka = k - 1;
f.terms[k]=att(ka,g,y,0);
g.terms[k]=complex(-1.0,0.0)*att(ka,f,y,0);
}
return(g);
}
t_s tan(t_s & y)
{
// cos of y
register int k,ka;
t_s f,a1,a2;
set_data(f,y);
set_data(a1,y);
set_data(a2,y);
a1.terms[0]=sin(y.terms[0]);
a2.terms[0]=cos(y.terms[0]);
f.terms[0]=a1.terms[0]/a2.terms[0];
for (k=1;k<y.last_term;k++)
{
ka = k - 1;
a1.terms[k]=att(ka,a2,y,0);
a2.terms[k]=complex(-1.0,0.0)*att(ka,a1,y,0);
f.terms[k]=(a1.terms[k] - ats(k,a2,f,1))/a2.terms[0];
}
return(f);
}
t_s sinh(t_s & y)
{
// sinh of y
register int k,ka;
t_s f,g;
set_data(f,y);
set_data(g,y);
f.terms[0]=sinh(y.terms[0]);
g.terms[0]=cosh(y.terms[0]);
for (k=1;k<y.last_term;k++)
{
ka = k - 1;
f.terms[k]=att(ka,g,y,0);
g.terms[k]=att(ka,f,y,0);
}
return(f);
}
t_s cosh(t_s & y)
{
// cosh of y
register int k,ka;
t_s f,g;
set_data(f,y);
set_data(g,y);
f.terms[0]=sinh(y.terms[0]);
g.terms[0]=cosh(y.terms[0]);
for (k=1;k<y.last_term;k++)
{
ka = k - 1;
f.terms[k]=att(ka,g,y,0);
g.terms[k]=att(ka,f,y,0);
}
return(g);
}
t_s tanh(t_s & y)
{
// tanh of y
register int k,ka;
t_s f,a1,a2;
set_data(f,y);
set_data(a1,y);
set_data(a2,y);
a1.terms[0]=sinh(y.terms[0]);
a2.terms[0]=cosh(y.terms[0]);
f.terms[0]=a1.terms[0]/a2.terms[0];
for (k=1;k<y.last_term;k++)
{
ka = k - 1;
a1.terms[k]=att(ka,a2,y,0);
a2.terms[k]=att(ka,a1,y,0);
f.terms[k]=(a1.terms[k] - ats(k,a2,f,1))/a2.terms[0];
}
return(f);
}
t_s asin(t_s & y)
{
// asin of y
register int k,ka;
t_s f,a1;
set_data(f,y);
set_data(a1,y);
f.terms[0]=asin(y.terms[0]);
a1.terms[0]=cos(f.terms[0]);
for (k=1;k<y.last_term;k++)
{
ka = k - 1;
f.terms[k]=(y.terms[k] - att(ka,a1,f,1))/a1.terms[0];
a1.terms[k]=complex(-1.0,0.0)*att(ka,y,f,0);
}
return(f);
}
t_s acos(t_s & y)
{
// acos of y
register int k,ka;
t_s f,a1;
set_data(f,y);
set_data(a1,y);
f.terms[0]=acos(y.terms[0]);
a1.terms[0]=sin(f.terms[0]);
for (k=1;k<y.last_term;k++)
{
ka = k - 1;
f.terms[k]=complex(-1.0,0.0)*
(y.terms[k] + att(ka,a1,f,1))/a1.terms[0];
a1.terms[k]=att(ka,y,f,0);
}
return(f);
}
t_s atan(t_s & y)
{
// atan of y
register int k,ka;
t_s f,a1,a2;
set_data(f,y);
set_data(a1,y);
set_data(a2,y);
f.terms[0]=atan(y.terms[0]);
a1.terms[0]=sin(f.terms[0]);
a2.terms[0]=cos(f.terms[0]);
for (k=1;k<y.last_term;k++)
{
ka = k - 1;
f.terms[k]=(ats(k,y,a2,1)-y.terms[0]*att(ka,a1,f,1) -
att(ka,a2,f,1))/(a2.terms[0]+y.terms[0]*a1.terms[0]);
a1.terms[k]=att(ka,a2,f,0);
a2.terms[k]=complex(-1.0,0.0)*att(ka,a1,f,0);
}
return(f);
}
t_s deriv(t_s &a)
{
// derivative of a taylor series
register int i;
t_s ret;
set_data(ret,a);
for (i=a.first_term;i<a.last_term-1;i++)
{
if (i > 0)
ret.terms[i]=a.terms[i+1]*complex(double(i),0.0)/a.h;
else
ret.terms[i]=a.terms[i+1]/a.h;
}
ret.terms[a.last_term]=complex(0.0,0.0); // unknown but small
return(ret);
}
void diff_eq(t_s &ret2,t_s &y)
{
// solve 1st order ordinary differential equation provided in "equation".
register int k;
t_s work;
t_s work2;
work=y;
work2=y;
for (k=work.last_term;k<MAX_TERMS;k++)
{
// get derivative t_s (work) from function t_s work2
equation(work,work2);
set_term_from_deriv(k,work,work2);
}
ret2 = work2;
}
void higher_diff_eq(t_s &ret2,t_s &y,int n)
{
// solve 1st order ordinary differential equation provided in "equation".
register int k;
t_s work;
t_s work2;
work=y;
work2=y;
for (k=work.last_term;k<MAX_TERMS;k++)
{
// get derivative t_s (work) from function t_s work2
equation(work,work2);
higher_set_term_from_deriv(k,work,work2,n);
}
ret2 = work2;
}
void set_term_from_deriv(int i,t_s &dy,t_s &y)
{
if (i > 0)
y.terms[i]=dy.terms[i-1]*y.h/complex(double(i),0.0);
else
y.terms[i]=dy.terms[i-1]*y.h;
y.last_term++;
}
void higher_set_term_from_deriv(int i,t_s &dy,t_s &y,int n)
{
complex adj1,adj2;
adj1 = complex(1.0,0.0);
adj2 = complex(1.0,0.0);
for (int a=0;a<n;a++)
adj1 *= dy.h;
for (int b=0;b<n;b++)
{
if (i+b > 0)
{
adj2 *= complex(double(i+b),0.0);
}
}
y.terms[i]=dy.terms[i-n]*adj1/adj2;
y.last_term++;
}
void jump(t_s &y)
{
t_s y2;
y2 = y;
y2.terms[0] = complex(0.0,0.0);
for (int i = 0;i < y.last_term;i++)
{
y2.terms[0] += y.terms[i];
}
y2.x0 = y.x0 + y.h;
y2.last_term = 1;
y = y2;
}
void leap(t_s &y,int n)
{
t_s y2;
complex adj1,adj2;
y2 = y;
adj2 = complex(1.0,0.0);
for (int j = 0;j < n; j++)
{
y2.terms[j] = complex(0.0,0.0);
for (int i = 0;i < y.last_term-j;i++)
{
adj1 = complex(1.0,0.0);
for (int k = 1 ; k <= j; k++)
{
adj1 *= complex(double(i+k),0.0);
}
y2.terms[j] += y.terms[i+j]*adj1;
}
if (j > 0)
{
adj2 *= j;
y2.terms[j] /= adj2;
}
}
y2.x0 = y.x0 + y.h;
y2.last_term = n;
y = y2;
}
int get_last_term(t_s &y)
{
return(y.last_term);
}
double get_x0(t_s &y)
{
return(real(y.x0));
}
double get_y0(t_s &y)
{
return(real(y.terms[0]));
}
void adjust_h(t_s &y,complex new_h)
{
t_s y2;
complex t,adj;
t = new_h / y.h;
adj = t;
y2 = y;
for (int i = 1;i < y.last_term;i++)
{
y2.terms[i] = y.terms[i]*adj;
adj *= t;
}
y2.h = new_h;
y = y2;
}