793 lines
18 KiB
C++
793 lines
18 KiB
C++
|
/********************************************************
|
||
|
* ██████╗ ██████╗████████╗██╗
|
||
|
* ██╔════╝ ██╔════╝╚══██╔══╝██║
|
||
|
* ██║ ███╗██║ ██║ ██║
|
||
|
* ██║ ██║██║ ██║ ██║
|
||
|
* ╚██████╔╝╚██████╗ ██║ ███████╗
|
||
|
* ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝
|
||
|
* Geophysical Computational Tools & Library (GCTL)
|
||
|
*
|
||
|
* Copyright (c) 2023 Yi Zhang (yizhang-geo@zju.edu.cn)
|
||
|
*
|
||
|
* GCTL is distributed under a dual licensing scheme. You can redistribute
|
||
|
* it and/or modify it under the terms of the GNU Lesser General Public
|
||
|
* License as published by the Free Software Foundation, either version 2
|
||
|
* of the License, or (at your option) any later version. You should have
|
||
|
* received a copy of the GNU Lesser General Public License along with this
|
||
|
* program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
*
|
||
|
* If the terms and conditions of the LGPL v.2. would prevent you from using
|
||
|
* the GCTL, please consider the option to obtain a commercial license for a
|
||
|
* fee. These licenses are offered by the GCTL's original author. As a rule,
|
||
|
* licenses are provided "as-is", unlimited in time for a one time fee. Please
|
||
|
* send corresponding requests to: yizhang-geo@zju.edu.cn. Please do not forget
|
||
|
* to include some description of your company and the realm of its activities.
|
||
|
* Also add information on how to contact you by electronic and paper mail.
|
||
|
******************************************************/
|
||
|
|
||
|
#include "../core/macro.h"
|
||
|
#include "mathfunc_ext.h"
|
||
|
#include "cmath"
|
||
|
|
||
|
void gctl::DTfilter(double **a,int m,int n,double A,double B,double Q,int sw)
|
||
|
{
|
||
|
int i,j;
|
||
|
for(i=0;i<m;i++)
|
||
|
{
|
||
|
for(j=0;j<n;j++)
|
||
|
{
|
||
|
switch(sw)
|
||
|
{
|
||
|
case 0:
|
||
|
{
|
||
|
if(a[i][j]>=A)
|
||
|
a[i][j]=Q;
|
||
|
break;
|
||
|
}
|
||
|
case 1:
|
||
|
{
|
||
|
if(a[i][j]<=A)
|
||
|
a[i][j]=Q;
|
||
|
break;
|
||
|
}
|
||
|
case 2:
|
||
|
{
|
||
|
if((a[i][j]<=A)||(a[i][j]>=B))
|
||
|
a[i][j]=Q;
|
||
|
break;
|
||
|
}
|
||
|
case 3:
|
||
|
{
|
||
|
if((a[i][j]>=A)&&(a[i][j]<=B))
|
||
|
a[i][j]=Q;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void gctl::DTari(double **a,int m,int n,double A,int sw)
|
||
|
{
|
||
|
int i,j;
|
||
|
for(i=0;i<m;i++)
|
||
|
{
|
||
|
for(j=0;j<n;j++)
|
||
|
{
|
||
|
switch(sw)
|
||
|
{
|
||
|
case 0: { a[i][j]+=A; break; }
|
||
|
case 1: { a[i][j]*=A; break; }
|
||
|
case 2: { a[i][j]=a[i][j]/(double)(A+1e-40); break; }
|
||
|
case 3: { a[i][j]*=a[i][j]; break; }
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void gctl::DTfunc(double **a,int m,int n,double A,double B,int sw)
|
||
|
{
|
||
|
int i,j;
|
||
|
double min,p;
|
||
|
if(sw==2)
|
||
|
{
|
||
|
min=(double)fabs(a[0][0]);
|
||
|
for(i=0;i<m;i++)
|
||
|
{
|
||
|
for(j=0;j<n;j++)
|
||
|
{
|
||
|
if(fabs(a[i][j])<min) min=(double)fabs(a[i][j]);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
for(i=0;i<m;i++)
|
||
|
{
|
||
|
for(j=0;j<n;j++)
|
||
|
{
|
||
|
switch(sw)
|
||
|
{
|
||
|
case 0: {a[i][j]=A+B*a[i][j];break;}
|
||
|
case 1: {a[i][j]=A*(double)exp((double)(B*a[i][j]));break;}
|
||
|
case 2:
|
||
|
{
|
||
|
p=(double)fabs(a[i][j])/(double)(a[i][j]+1e-80);
|
||
|
a[i][j]=A*p*(double)log((double)(B*(fabs(a[i][j])+1e-80)/(min+1e-80)));
|
||
|
break;
|
||
|
}
|
||
|
case 3: {a[i][j]=A*(double)pow((double)(a[i][j]+1e-80),(double)B);break;}
|
||
|
case 4: {a[i][j]=A*(double)atan((double)(B*a[i][j]));break;}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////
|
||
|
// Preparation & Extending Data
|
||
|
//
|
||
|
// zr/zi...first address of real/image data array
|
||
|
// m/n...number of line/point; m1/n1...extended m/n
|
||
|
// me/ne...{m1/n1=pow(2,me/ne)}; np/nq...{m1/n1=2*(np/nq)+m/n}
|
||
|
double gctl::prep(double **zr,double **zi,int m,int n,int m1,int n1,int np,int nq)
|
||
|
{
|
||
|
int i,j; double pjg;
|
||
|
pjg=(double)0;
|
||
|
if(m==1)
|
||
|
{ pjg=(zr[0][0]+zr[0][n-1])/(double)2.;
|
||
|
}
|
||
|
else
|
||
|
{ for(j=0;j<n;j++)
|
||
|
{ pjg+=(zr[0][j]+zr[m-1][j]);
|
||
|
}
|
||
|
for(i=1;i<(m-1);i++)
|
||
|
{ pjg+=(zr[i][0]+zr[i][n-1]);
|
||
|
}
|
||
|
pjg=pjg/(double)(2*m+2*n-4);
|
||
|
}
|
||
|
for(i=(m-1);i>=0;i--)
|
||
|
{ for(j=(n-1);j>=0;j--)
|
||
|
{ zr[i+np][j+nq]=zr[i][j]-pjg;
|
||
|
} }
|
||
|
//---------------------------------------------
|
||
|
// extending data
|
||
|
//---------------------------------------------
|
||
|
|
||
|
if(m>1)
|
||
|
{ for(i=np;i<(m+np);i++)
|
||
|
{ zr[i][n1-1]=(double)0;
|
||
|
for(j=0;j<nq;j++)
|
||
|
{ zr[i][j]=zr[i][nq]*(double)(1-cos(((double)GCTL_Pi*(double)j/(double)nq)))/(double)2;
|
||
|
zr[i][j+n+nq]=zr[i][n+nq-1]*(double)(1+cos(((double)GCTL_Pi*(double)(j+1)/(double)(n1-n-nq))))/2;
|
||
|
} }
|
||
|
for(j=0;j<n1;j++)
|
||
|
{ zr[m1-1][j]=(double)0;
|
||
|
for(i=0;i<np;i++)
|
||
|
{ zr[i][j]=zr[np][j]*(double)(1-cos(((double)GCTL_Pi*(double)i/(double)np)))/(double)2;
|
||
|
zr[i+m+np][j]=zr[m+np-1][j]*(double)(1+cos(((double)GCTL_Pi*(double)(i+1)/(double)(m1-m-np))))/(double)2;
|
||
|
} }
|
||
|
for(i=0;i<m1;i++)
|
||
|
{ for(j=0;j<n1;j++)
|
||
|
{ zi[i][j]=(double)0;
|
||
|
} }
|
||
|
}
|
||
|
else
|
||
|
{ for(j=0;j<nq;j++)
|
||
|
{ zr[0][j]=zr[0][nq]*(double)(1-cos(((double)GCTL_Pi*(double)j/(double)nq)))/(double)2;
|
||
|
zr[0][j+n+nq]=zr[0][n+nq-1]*(double)(1+cos(((double)GCTL_Pi*(double)(j+1)/(double)(n1-n-nq))))/(double)2;
|
||
|
}
|
||
|
for(j=0;j<n1;j++)
|
||
|
{ zi[0][j]=(double)0; }
|
||
|
}
|
||
|
return pjg;
|
||
|
}
|
||
|
///////////////////////////////////////////
|
||
|
////To extend the data in array a[][] from
|
||
|
//// a[m][n] to a[m+2*mx][n+2*nx]
|
||
|
void gctl::ext(double **a,int m,int n,int mx,int nx)
|
||
|
{ int i,j,i1,j1;
|
||
|
|
||
|
for(i=(m+mx-1);i>=mx;i--)
|
||
|
for(j=(n+nx-1);j>=nx;j--)
|
||
|
a[i][j]=a[i-mx][j-nx];
|
||
|
for(i=mx;i<(m+mx);i++)
|
||
|
{ for(j=0;j<nx;j++)
|
||
|
{ j1=n+nx+j;
|
||
|
a[i][j]=a[i][2*nx-j]; a[i][j1]=a[i][n+nx-2-j];
|
||
|
} }
|
||
|
for(j=0;j<n+2*nx;j++)
|
||
|
{ for(i=0;i<mx;i++)
|
||
|
{ i1=m+mx+i;
|
||
|
a[i][j]=a[2*mx-i][j]; a[i1][j]=a[m+mx-2-i][j];
|
||
|
} }
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
////////////////////////////////////////////
|
||
|
//To find the Maximun and Minimun of present array data
|
||
|
void gctl::MaxMin(double **a,int m,int n,double *MxMn)
|
||
|
{
|
||
|
double p;
|
||
|
MxMn[0]=MxMn[1]=a[0][0]; p=(double)0;
|
||
|
for(int i=0;i<m;i++)
|
||
|
{
|
||
|
for(int j=0;j<n;j++)
|
||
|
{
|
||
|
p+=a[i][j];
|
||
|
if(MxMn[1]<a[i][j])
|
||
|
MxMn[1]=a[i][j];
|
||
|
else if(MxMn[0]>a[i][j])
|
||
|
MxMn[0]=a[i][j];
|
||
|
}
|
||
|
}
|
||
|
MxMn[2]=p/(double)(m*n+1e-40);
|
||
|
}
|
||
|
|
||
|
double gctl::int4p(double x,double d,double y1,double y2,double y3,double y4)
|
||
|
{ double z,t;
|
||
|
t=y1*x*(x-d)/(2*d*d)-y2*(x+d)*(x-d)/(d*d)+y3*(x+d)*x/(2*d*d);
|
||
|
z=y2*(x-d)*(x-2*d)/(2*d*d)-y3*x*(x-2*d)/(d*d)+y4*x*(x-d)/(2*d*d);
|
||
|
z=(z+t)/2;
|
||
|
return(z);
|
||
|
}
|
||
|
|
||
|
void gctl::intp(double **a,int m,int n,int mi,int ni)
|
||
|
{ int i,j,k; double d,x;
|
||
|
// mi=(int)(dx0/dx+.0001)
|
||
|
// ---number of inserted rows + 1
|
||
|
// ni=(int)(dy0/dy+.0001)
|
||
|
// ---number of inserted columns + 1
|
||
|
ext(a,m,n,1,1);
|
||
|
for(i=m+1;i>=0;i--)
|
||
|
for(j=n+1;j>=0;j--)
|
||
|
a[i*mi][j*ni]=a[i][j];
|
||
|
d=(double)ni; //(0, d, 2d, 3d,) are y_values knawn
|
||
|
for(i=0;i<=(m+1)*mi;i+=mi)
|
||
|
{ for(j=0;j<=(n-2)*ni;j+=ni)
|
||
|
{ for(k=1;k<ni;k++)
|
||
|
{ x=(double)k; // y=f(x) is the value required
|
||
|
a[i][j+ni+k]=int4p(x,d,a[i][j],a[i][j+ni],a[i][j+2*ni],a[i][j+3*ni]);
|
||
|
}
|
||
|
} }
|
||
|
d=(double)mi; //(0, d, 2d, 3d,) are y_values knawn
|
||
|
for(j=ni;j<=n*ni;j++)
|
||
|
{ for(i=0;i<=(m-2)*mi;i+=mi)
|
||
|
{ for(k=1;k<mi;k++)
|
||
|
{ x=(double)k; // y=f(x) is the value required
|
||
|
a[i+mi+k][j]=int4p(x,d,a[i][j],a[i+mi][j],a[i+2*mi][j],a[i+3*mi][j]);
|
||
|
} } }
|
||
|
for(i=0;i<(m-1)*mi+1;i++)
|
||
|
for(j=0;j<(n-1)*ni+1;j++)
|
||
|
a[i][j]=a[i+mi][j+ni];
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
///////////////////////////////////////////////////////
|
||
|
/* Fast-Fourier_Transform */
|
||
|
|
||
|
/* zr/zi...first address of real/image data array */
|
||
|
/* m/n...number of line/point; m1/n1...extended m/n */
|
||
|
/* me/ne...{m1/n1=pow(2,me/ne)}; */
|
||
|
/* key... 0 for +FFT, 1 for -FFT */
|
||
|
/* 1-Dimension Fast Fourier Transform (FFT) */
|
||
|
void gctl::fft1(double *ar,double *ai,int m,int n,int key)
|
||
|
{ int i,j,k,k1,l1,l2,ip;
|
||
|
double *ir,*ii,*i1,*i2;
|
||
|
double f1,t1,t2,v,u,w1,w2,d,vu,pi1;
|
||
|
f1=(double)-1;
|
||
|
if(key==0) f1=(double)1;
|
||
|
j=0;
|
||
|
for(i=0,ir=ar,ii=ai;i<n;i++,ir++,ii++)
|
||
|
{ if(i<j)
|
||
|
{ i1=ar+j; i2=ai+j;
|
||
|
t1=*i1; t2=*i2; *i1=*ir; *i2=*ii; *ir=t1; *ii=t2;
|
||
|
}
|
||
|
k1=n/2;
|
||
|
while((j>=k1)&&(k1!=0))
|
||
|
{ j=j-k1; k1=k1/2;
|
||
|
}
|
||
|
j=j+k1;
|
||
|
}
|
||
|
for(j=1;j<m+1;j++)
|
||
|
{ l1=2;
|
||
|
for (i=1;i<j;i++) l1=2*l1;
|
||
|
l2=l1/2; pi1=(double)GCTL_Pi/(double)l2; v=(double)1; u=(double)0;
|
||
|
w1=(double)cos(pi1); w2=(double)sin(pi1);
|
||
|
for(k=1;k<l2+1;k++)
|
||
|
{ d=f1*u;
|
||
|
for(i=k-1;i<n-l1+k;i+=l1)
|
||
|
{ ip=i+l2; i1=ar+ip; i2=ai+ip; ir=ar+i; ii=ai+i;
|
||
|
t1=*i1*v+*i2*d; t2=*i2*v-*i1*d;
|
||
|
*i1=*ir-t1; *i2=*ii-t2; *ir=*ir+t1; *ii=*ii+t2;
|
||
|
}
|
||
|
vu=v*w1-u*w2; u=v*w2+u*w1; v=vu;
|
||
|
} }
|
||
|
if(key==0)
|
||
|
for(i=0,ir=ar,ii=ai;i<n;i++,ir++,ii++)
|
||
|
{ *ir/=n; *ii/=n;
|
||
|
}
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
void gctl::fft(double **zr,double **zi,int m1,int n1,int me,int ne,int key)
|
||
|
{
|
||
|
int i,j;
|
||
|
double *ir0,*ii0,*ir1,*ii1;
|
||
|
|
||
|
if(m1==1)
|
||
|
{
|
||
|
ir0=*(zr+0)+0; ii0=*(zi+0)+0;
|
||
|
fft1(ir0,ii0,ne,n1,key);
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
double *cr = new double [m1];
|
||
|
double *ci = new double [m1];
|
||
|
|
||
|
for(i=0;i<m1;i++)
|
||
|
{
|
||
|
ir0=*(zr+i)+0; ii0=*(zi+i)+0; ir1=*(zr+0)+i+8;
|
||
|
fft1(ir0,ii0,ne,n1,key);
|
||
|
}
|
||
|
|
||
|
for(j=0;j<n1;j++)
|
||
|
{
|
||
|
for(i=0;i<m1;i++)
|
||
|
{
|
||
|
cr[i]=*(*(zr+i)+j); ci[i]=*(*(zi+i)+j);
|
||
|
}
|
||
|
fft1(cr,ci,me,m1,key);
|
||
|
for(i=0;i<m1;i++)
|
||
|
{
|
||
|
ir1=*(zr+i)+j; ii1=*(zi+i)+j;
|
||
|
*ir1=cr[i]; *ii1=ci[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
delete[] cr;
|
||
|
delete[] ci;
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////////////////
|
||
|
// To form the metrix of factors /////////////////////////////
|
||
|
// x,y sould are positive
|
||
|
// n is order of f(x,y)
|
||
|
void gctl::fact(double **s,double *x,double *y,double *g,double *b,int mt,int n)
|
||
|
{ int i,j,l,l1,l2,lx,ly,k,k1,k2,kx,ky,kk;
|
||
|
double p,f1,f2,f3,f4;
|
||
|
for(i=0;i<=n;i++)
|
||
|
{ l1=(i+1)*i/2+1; l2=l1+i; lx=i; ly=0;
|
||
|
for(l=l1;l<=l2;l++)
|
||
|
{ for(j=0;j<=n;j++)
|
||
|
{ k1=(j+1)*j/2+1; k2=k1+j; kx=j; ky=0;
|
||
|
for(k=k1;k<=k2;k++)
|
||
|
{ p=0.;
|
||
|
for(kk=0;kk<mt;kk++)
|
||
|
{ f1=pow(x[kk],lx);
|
||
|
f2=pow(y[kk],ly);
|
||
|
f3=pow(x[kk],kx);
|
||
|
f4=pow(y[kk],ky);
|
||
|
p+=f1*f2*f3*f4;
|
||
|
}
|
||
|
s[l-1][k-1]=p;
|
||
|
kx=kx-1; ky=ky+1;
|
||
|
}
|
||
|
}
|
||
|
lx=lx-1; ly=ly+1;
|
||
|
}
|
||
|
}
|
||
|
for(j=0;j<=n;j++)
|
||
|
{ k1=(j+1)*j/2+1; k2=k1+j; kx=j; ky=0;
|
||
|
for(k=k1;k<=k2;k++)
|
||
|
{ p=0.;
|
||
|
for(kk=0;kk<mt;kk++)
|
||
|
{
|
||
|
f1=pow(x[kk],kx);
|
||
|
f2=pow(y[kk],ky);
|
||
|
p+=f1*f2*g[kk];
|
||
|
}
|
||
|
b[k-1]=p;
|
||
|
kx=kx-1; ky=ky+1;
|
||
|
}
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////////////////
|
||
|
// To form the metrix of factors /////////////////////////////
|
||
|
// x,y sould are positive
|
||
|
// m is heigher order of f(x,y) along between x and y,
|
||
|
void gctl::fact1(double **s,double *x,double *y,double *g,double *b,int mt,int n,int xLt,int yLt)
|
||
|
{ int i,j,l,l1,l2,lx,ly,k,k1,k2,kx,ky,kk,ks,ls;
|
||
|
double p,f1,f2,f3,f4;
|
||
|
ls=0;
|
||
|
for(i=0;i<=n;i++)
|
||
|
{
|
||
|
l1=(i+1)*i/2+1; l2=l1+i; lx=i; ly=0;
|
||
|
for(l=l1;l<=l2;l++)
|
||
|
{
|
||
|
if((lx>xLt)||(ly>yLt))
|
||
|
{
|
||
|
ls+=1; lx-=1; ly+=1; continue;
|
||
|
}
|
||
|
for(j=0;j<=n;j++)
|
||
|
{
|
||
|
k1=(j+1)*j/2+1; k2=k1+j; kx=j; ky=0;
|
||
|
ks=0;
|
||
|
for(k=k1;k<=k2;k++)
|
||
|
{
|
||
|
if((kx>xLt)||(ky>yLt))
|
||
|
{
|
||
|
ks+=1; kx-=1; ky+=1; continue;
|
||
|
}
|
||
|
p=0.;
|
||
|
for(kk=0;kk<mt;kk++)
|
||
|
{
|
||
|
f1=pow(x[kk],lx);
|
||
|
f2=pow(y[kk],ly);
|
||
|
f3=pow(x[kk],kx);
|
||
|
f4=pow(y[kk],ky);
|
||
|
p+=f1*f2*f3*f4;
|
||
|
}
|
||
|
s[l-1-ls][k-1-ks]=p;
|
||
|
kx=kx-1; ky=ky+1;
|
||
|
}
|
||
|
}
|
||
|
lx=lx-1; ly=ly+1;
|
||
|
}
|
||
|
}
|
||
|
ks=0;
|
||
|
for(j=0;j<=n;j++)
|
||
|
{
|
||
|
k1=(j+1)*j/2+1; k2=k1+j; kx=j; ky=0;
|
||
|
for(k=k1;k<=k2;k++)
|
||
|
{
|
||
|
if((kx>xLt)||(ky>yLt))
|
||
|
{
|
||
|
ks+=1; kx-=1; ky+=1; continue;
|
||
|
}
|
||
|
p=0.;
|
||
|
for(kk=0;kk<mt;kk++)
|
||
|
{
|
||
|
f1=pow(x[kk],kx);
|
||
|
f2=pow(y[kk],ky);
|
||
|
p+=f1*f2*g[kk];
|
||
|
}
|
||
|
b[k-1-ks]=p;
|
||
|
kx=kx-1; ky=ky+1;
|
||
|
}
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////////
|
||
|
//To calculate the multiply values of x and y/////////////
|
||
|
// x,y sould are positive
|
||
|
void gctl::tsv(double *s,double x,double y,int n)
|
||
|
//////////// n is order of f(x,y) in y,
|
||
|
{ int j,k,k1,k2,kx,ky;
|
||
|
s[0]=(double)1;
|
||
|
for(j=1;j<=n;j++)
|
||
|
{ k1=(j+1)*j/2+1; k2=k1+j; kx=j; ky=0;
|
||
|
for(k=k1;k<=k2;k++)
|
||
|
{ s[k-1]=pow(x,kx)*pow(y,ky);
|
||
|
kx=kx-1; ky=ky+1;
|
||
|
}
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////////
|
||
|
//To calculate the multiply values of x and y/////////////
|
||
|
// x,y sould are positive
|
||
|
void gctl::tsv1(double *s,double x,double y,int n,int xLt,int yLt)
|
||
|
//////////// n is higher order of f(x,y) along that between x and y
|
||
|
{ int j,k,k1,k2,kx,ky,ks;
|
||
|
ks=0;
|
||
|
s[0]=(double)1;
|
||
|
for(j=1;j<=n;j++)
|
||
|
{ k1=(j+1)*j/2+1; k2=k1+j; kx=j; ky=0;
|
||
|
for(k=k1;k<=k2;k++)
|
||
|
{ if((kx>xLt)||(ky>yLt))
|
||
|
{ ks+=1; kx-=1; ky+=1; continue; }
|
||
|
s[k-1-ks]=pow(x,kx)*pow(y,ky);
|
||
|
kx=kx-1; ky=ky+1;
|
||
|
}
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////
|
||
|
void gctl::tran(double **a,int n)
|
||
|
{ int i,j; double t;
|
||
|
for(i=0;i<n-1;i++)
|
||
|
{ for(j=i+1;j<n;j++)
|
||
|
{ t=a[i][j]; a[i][j]=a[j][i]; a[j][i]=t; }
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
void gctl::metrimult(double **a,double **b,int m,int n,int l,double **c)
|
||
|
{
|
||
|
int i,j,k; double p;
|
||
|
for(i=0;i<m;i++)
|
||
|
{ for(j=0;j<l;j++)
|
||
|
{ p=0.;
|
||
|
for(k=0;k<n;k++)
|
||
|
p+=a[i][k]*b[k][j];
|
||
|
c[i][j]=p;
|
||
|
}
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
///////////////////////////
|
||
|
|
||
|
//C*********************************************************************C
|
||
|
//C C
|
||
|
//C Calculation for Singular Values and Vecters C
|
||
|
//C C
|
||
|
//C*********************************************************************C
|
||
|
//C [ SVD.V2 ]
|
||
|
//C
|
||
|
//C******************************************************************C
|
||
|
//C
|
||
|
// SUBROUTINE SVD(MD,ND,M,N,A,U,V,Q,INDEX)
|
||
|
//C
|
||
|
//C CALLS NO OTHER ROUTINES
|
||
|
//C ( SINGULAR VALUE DECOMPOSITION )
|
||
|
//C FOR ALGO PROGRAM SEE WILKINSON+REINSC HANDBOOK
|
||
|
//C FOR AUTOMATIC COMPUTATION VOL 2 - LINEAR ALGEBRA, PG140-144,
|
||
|
//C TRANSLATED FROM ALGOL BY R.L.PARKER.
|
||
|
//C THE MATRIX A(M,N) IS DECOMPOSED. SINGULAR VALUES IN Q(N),
|
||
|
//C PRE-MATRIX IN U(M,N), POST-MATRIX IN V(N,N).
|
||
|
//C INDEX MAY BE 1,2,3 OR 4.
|
||
|
//C IF 1, FIND U,V;
|
||
|
//C IF 2, FIND ONLY U;
|
||
|
//C IF 3, FIND ONLY V;
|
||
|
//C IF 4, FIND NEITHER.
|
||
|
//C Translated from FORTRAN to C by Chen Chao in 1997
|
||
|
void gctl::svd_standalone(double **a,int m,int n,double **u,double **v,double *q,int Index)
|
||
|
{
|
||
|
int i,j,k,l;
|
||
|
double c,f,g,h,s,x,y,z;
|
||
|
double *e=new double [n];
|
||
|
double eps=(double)(1e-40);
|
||
|
double tol=(double)(1e-60);
|
||
|
for(i=0;i<m;i++)
|
||
|
for(j=0;j<n;j++)
|
||
|
u[i][j]=a[i][j];
|
||
|
|
||
|
//C HOUSEHOLDER REDUCTION TO BI-DIAGONAL FORM
|
||
|
g=(double)0; x=(double)0;
|
||
|
for(i=0;i<n;i++)
|
||
|
{
|
||
|
l=i+1; e[i]=g; g=(double)0;
|
||
|
if(i<m)
|
||
|
{
|
||
|
s=(double)0;
|
||
|
for(j=i;j<m;j++)
|
||
|
s+=u[j][i]*u[j][i];
|
||
|
if(s>=tol)
|
||
|
{
|
||
|
f=u[i][i];
|
||
|
g=-sqrt(s)*f/(fabs(f)+(double)1e-40);
|
||
|
h=f*g-s;
|
||
|
u[i][i]=f-g;
|
||
|
if(l<n)
|
||
|
{
|
||
|
for(j=l;j<n;j++)
|
||
|
{
|
||
|
s=(double)0;
|
||
|
for(k=i;k<m;k++)
|
||
|
s+=u[k][i]*u[k][j];
|
||
|
f=s/h;
|
||
|
for(k=i;k<m;k++)
|
||
|
u[k][j]+=f*u[k][i];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
//C/////////////////////////
|
||
|
q[i]=g; g=(double)0;
|
||
|
if(l<n)
|
||
|
{
|
||
|
s=(double)0;
|
||
|
for(j=l;j<n;j++)
|
||
|
s+=u[i][j]*u[i][j];
|
||
|
if(s>=tol)
|
||
|
{
|
||
|
f=u[i][i+1];
|
||
|
g=-sqrt(s)*f/(fabs(f)+(double)1e-40);
|
||
|
h=f*g-s;
|
||
|
u[i][i+1]=f-g;
|
||
|
for(j=l;j<n;j++)
|
||
|
e[j]=u[i][j]/h;
|
||
|
if(l<m)
|
||
|
{
|
||
|
for(j=l;j<m;j++)
|
||
|
{
|
||
|
s=(double)0;
|
||
|
for(k=l;k<n;k++)
|
||
|
s+=u[j][k]*u[i][k];
|
||
|
for(k=l;k<n;k++)
|
||
|
u[j][k]+=s*e[k];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
y=fabs(q[i])+fabs(e[i]);
|
||
|
if(y>x)
|
||
|
x=y;
|
||
|
}
|
||
|
//C
|
||
|
//C ACCUMULATION OF RIGHT-HAND TRANSFORMS (V)
|
||
|
//C
|
||
|
if((Index==1)||(Index==3))
|
||
|
{
|
||
|
v[n-1][n-1]=(double)1;
|
||
|
g=e[n-1];
|
||
|
for(i=n-2;i>=0;i--)
|
||
|
{
|
||
|
l=i+1;
|
||
|
if(g!=(double)0)
|
||
|
{
|
||
|
h=u[i][i+1]*g;
|
||
|
for(j=l;j<n;j++)
|
||
|
v[j][i]=u[i][j]/h;
|
||
|
for(j=l;j<n;j++)
|
||
|
{
|
||
|
s=(double)0;
|
||
|
for(k=l;k<n;k++)
|
||
|
s+=u[i][k]*v[k][j];
|
||
|
for(k=l;k<n;k++)
|
||
|
v[k][j]+=s*v[k][i];
|
||
|
}
|
||
|
}
|
||
|
for(j=l;j<n;j++)
|
||
|
{
|
||
|
v[j][i]=(double)0;
|
||
|
v[i][j]=(double)0;
|
||
|
}
|
||
|
v[i][i]=(double)1; g=e[i];
|
||
|
}
|
||
|
}
|
||
|
//C
|
||
|
//C ACCUMULATION OF LEFT-HAND TRANSFORMS ( U )
|
||
|
//C
|
||
|
if((Index==1)||(Index==2))
|
||
|
{
|
||
|
for(i=(n<m)?(n-1):(m-1);i>=0;i--)
|
||
|
{
|
||
|
l=i+1; g=q[i];
|
||
|
if(l<n)
|
||
|
for(j=l;j<n;j++)
|
||
|
u[i][j]=(double)0;
|
||
|
if(g!=(double)0)
|
||
|
{
|
||
|
h=u[i][i]*g;
|
||
|
if(l<n)
|
||
|
{
|
||
|
for(j=l;j<n;j++)
|
||
|
{
|
||
|
s=(double)0;
|
||
|
for(k=l;k<m;k++)
|
||
|
s+=u[k][i]*u[k][j];
|
||
|
f=s/h;
|
||
|
for(k=i;k<m;k++)
|
||
|
u[k][j]+=f*u[k][i];
|
||
|
}
|
||
|
}
|
||
|
for(j=i;j<m;j++)
|
||
|
u[j][i]=u[j][i]/g;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for(j=i;j<m;j++)
|
||
|
u[j][i]=(double)0;
|
||
|
}
|
||
|
u[i][i]+=(double)1;
|
||
|
}
|
||
|
}
|
||
|
//C
|
||
|
//C DIAGONALIZATION OF BI-DIAGONAL FORM
|
||
|
//C
|
||
|
eps*=x;
|
||
|
for(k=n-1;k>=0;k--)
|
||
|
{
|
||
|
label_380: /////////////C TEST F-SPLITTING
|
||
|
for(l=k;l>=0;l--)
|
||
|
{
|
||
|
if(fabs(e[l])<=eps)
|
||
|
goto label_440;
|
||
|
if(l==0)
|
||
|
continue;
|
||
|
if(fabs(q[l-1])<=eps)
|
||
|
goto label_410;
|
||
|
}
|
||
|
|
||
|
label_410: ///// CANCELLATION OF E(L), IF L .GT. 1
|
||
|
c=(double)0;
|
||
|
s=(double)1;
|
||
|
for(i=l;i<=k;i++)
|
||
|
{
|
||
|
f=s*e[i]; e[i]*=c;
|
||
|
if(fabs(f)<=eps)
|
||
|
goto label_440;
|
||
|
g=q[i]; q[i]=sqrt(f*f+g*g);
|
||
|
h=q[i]; c=g/h; s=-f/h;
|
||
|
if((Index==1)||(Index==2))
|
||
|
{
|
||
|
for(j=0;j<m;j++)
|
||
|
{
|
||
|
y=u[j][l-1]; z=u[j][i];
|
||
|
u[j][l-1]=y*c+z*s;
|
||
|
u[j][i]=-y*s+z*c;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
label_440: //// TEST F-CONVERGENCE
|
||
|
z=q[k];
|
||
|
if(l==k)
|
||
|
goto label_480;
|
||
|
/////////// SHIFT FROM BOTTOM 2 X 2 MINOR
|
||
|
x=q[l];
|
||
|
y=q[k-1];
|
||
|
g=e[k-1];
|
||
|
h=e[k];
|
||
|
f=(double)0.5*((y-z)*(y+z)+(g-h)*(g+h))/h/y;
|
||
|
g=sqrt(f*f+(double)1);
|
||
|
f=((x-z)*(x+z)+h*(y/(f+g*f/(fabs(f)+(double)1e-40))-h))/x;
|
||
|
///////////// NEXT Q-R TRANSFORMATION
|
||
|
c=(double)1;
|
||
|
s=(double)1;
|
||
|
for(i=l+1;i<=k;i++)
|
||
|
{
|
||
|
g=e[i]; y=q[i]; h=s*g; g=c*g;
|
||
|
z=sqrt(f*f+h*h);
|
||
|
e[i-1]=z; c=f/z; s=h/z;
|
||
|
f=x*c+g*s; g=-x*s+g*c;
|
||
|
h=y*s; y=y*c;
|
||
|
if((Index==1)||(Index==3))
|
||
|
{
|
||
|
for(j=0;j<n;j++)
|
||
|
{
|
||
|
x=v[j][i-1]; z=v[j][i];
|
||
|
v[j][i-1]=x*c+z*s;
|
||
|
v[j][i]=-x*s+z*c;
|
||
|
}
|
||
|
}
|
||
|
z=sqrt(f*f+h*h);
|
||
|
q[i-1]=z; c=f/z; s=h/z;
|
||
|
f=c*g+s*y; x=-s*g+c*y;
|
||
|
if((Index==1)||(Index==2))
|
||
|
{
|
||
|
for(j=0;j<m;j++)
|
||
|
{
|
||
|
y=u[j][i-1]; z=u[j][i];
|
||
|
u[j][i-1]=y*c+z*s;
|
||
|
u[j][i]=-y*s+z*c;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
e[l]=(double)0;
|
||
|
e[k]=f;
|
||
|
q[k]=x;
|
||
|
goto label_380;
|
||
|
|
||
|
label_480: ///////////C CONVERGENCE///////////////
|
||
|
if(z<(double)0)
|
||
|
{
|
||
|
q[k]=-z;
|
||
|
if((Index==1)||(Index==3))
|
||
|
{
|
||
|
for(j=0;j<n;j++)
|
||
|
v[j][k]=-v[j][k];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
delete[] e;
|
||
|
return ;
|
||
|
}
|