////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
matriz aleatoria(int m,int n,int rango,bool im)
{
matriz C;
int div;
C.error=0;
C.im=im;
C.m=m;
C.n=n;
C.mostrable=true;
reservarF(C.real,m,n,0);
if(im)reservarF(C.imaj,m,n,0);
srand(time(0));
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
{
div=rand()%15;
if(div==0)div=1;
C.real[i][j]=(rand()%rango)/div;
if(im)C.imaj[i][j]=(rand()%rango)/div;
}
return C;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void reservarF(double **&C,int i,int j,int init)
{
C=new double*[i];
for(int x=0;x<i;x++)
{
C[x]=new double[j];
memset((void*)C[x],init, sizeof (double)*i);
}
}
////////////////////////////////////////////////////////////////////////////////
double strTof(const char *c)
{
float ent=0.0,dec=0,aux=0;
short int bandera=0,sig=1,f=0;
float d=10.0,num=0.0,den=1.0;
for(int x=0;c[x]!=' '&&c[x]!=';'&&c[x]!=']'&&c[x]!=','&&c[x]!=0;x++)
{
if(bandera&&c[x]>='0'&&c[x]<='9')
dec=dec+(c[x]-48)/d,d*=10;
else if(c[x]>='0'&&c[x]<='9'&&!bandera)
ent=ent*10+c[x]-48;
if(c[x]=='.')
bandera=1;
if(c[x]=='-')
sig=-1;
if(c[x]=='/')
bandera=0,num=(ent+dec),f=1,ent=0,dec=0,d=10.0;
}
if(!f)num=(ent+dec)*sig;
if(f)den=(ent+dec)*sig;
aux=num/den;
return aux;
}
/////////////////////////////////////////////////////////////////////////////////
int strToint(const char *string)
{
int ent=0;
for(int x=0;string[x]!=0;x++)
if(string[x]>='0'&&string[x]<='9')
ent=ent*10+string[x]-48;
return ent;
}
////////////////////////////////////////////////////////////////////////////////
double cos(float angulo,bool deg)
{
bool neg=false;
if(angulo<0){angulo=-angulo;neg=true;}
float C[6]={-0.5,0.041667,-0.001389,0.000025,-0.0000002755,0.00000000208767};
float num=1.0,m=1.0,t,t2=1.0;
if(deg)angulo=PI*angulo/180.0;
int rad=(int)(2.0*angulo/PI),cuadrante;
cuadrante=rad%4;
angulo-=((float)rad*PI/2.0);
if(cuadrante==1||cuadrante==3)
angulo-=PI/2.0;
t=angulo*angulo;
for(int x=0;x<6;x++)
{
t2*=t;
num+=C[x]*t2;
}
if(cuadrante==1||cuadrante==2)
num=-num;
if(neg)num=-num;
return num;
}
////////////////////////////////////////////////////////////////////////////////
double sen(float angulo,bool deg)
{
float r;
bool neg=false;
if(angulo<0.0){angulo=-angulo;neg=true;}
if(deg)
angulo=PI*angulo/180.0;
r=cos(abs(angulo-PI/2.0),false);
if(neg)r=-r;
return r;
}
////////////////////////////////////////////////////////////////////////////////
double tan(float angulo,bool deg)
{
float O,A;
if(angulo<0.0)angulo=-angulo;
if(deg)
angulo=PI*angulo/180.0;
O=sen(angulo,false);
A=cos(angulo,false);
return O/A;
}
////////////////////////////////////////////////////////////////////////////////
double e(float x)
{
long double aux,sum=1.0,p=1.0,f=1.0,mult=1.0;
bool b=false;
int m;
aux=x;
if(x<0.0)
aux=-aux;
if(aux>0)b=true;
m=(int)aux;
aux=aux-m;
for(int i=0;i<m;i++)mult*=exp;
for(int i=1;i<=30&&b;i++)
{
p*=aux;
f*=i;
sum+=(p/f);
}
if(x>=0.0)
return sum*mult;
else
return (1.0/sum)*mult;
}
////////////////////////////////////////////////////////////////////////////////////
double ln(float x)
{
long double num=0.0,a=1.0,mult=1.0;
bool ban=false;
if(x>6)
{
int r=3;
if(x>5000000)r=4;
for(int i=0;i<r;i++)
{
x=raiz(x);
mult*=2.0;
}
}
if(x>1)
x=1.0/x,ban=true;
for(int n=1;n<=30;n++)
{
a*=x-1;
if((n+1)%2)
num-=a/n;
else
num+=a/n;
}
if(ban)
num=-num;
return num*mult;
}
////////////////////////////////////////////////////////////////////////////////////////
double pow(float base,float potencia)
{
long double f=1,num=1.0,bas=1.0,a,N=1.0;
bool neg=false;
if(potencia<0)neg=true;
int mult=(int)abs(potencia);
for(int x=0;x<mult;x++)N*=base;
potencia=abs(potencia)-mult;
a=potencia*ln(base);
for(int n=1;n<=50&&potencia>0.0;n++)
{
f*=n;
bas*=a;
num+=bas/f;
}
if(neg)return 1/(N*num);
else return N*num;
}
/////////////////////////////////////////////////////////////////////////////////////////
double log(float base,float x)
{
float A,X;
A=ln(base);
X=ln(x);
return (double)X/A;
}
///////////////////////////////////////////////////////////////////////////////////////////
matriz abs(matriz A)
{
matriz C,T;
C.error=0;
reservarF(C.real,1,1,0);
if(A.m==1&&A.n>1||A.m>1&&A.n==1)
{
T=tran(A);
if(A.m==1&&A.n>1)
C=multiplicar(A,T);
else if(A.m>1&&A.n==1)
C=multiplicar(T,A);
C.real[0][0]=raiz(C.real[0][0]);
}
else if(A.n==A.m)
{
C=detC(A);
if(A.n==A.m&&A.im&&A.m==1)
C.real[0][0]=raiz(pow(A.real[0][0],2)+pow(A.imaj[0][0],2)),C.im=0;
}
else C.error=1;
if(C.real[0][0]<0)C.real[0][0]=-C.real[0][0];
return C;
}
///////////////////////////////////////////////////////////////////////////////////////////
double abs(double a)
{
double r;
if(a<0)r=-a;
else r=a;
return r;
}
///////////////////////////////////////////////////////////////////////////////////////////
bool matriz::capturar_matriz(const char *cadena)
{
int i=1,c=0,j;
char *string,*aux;
string=new char[2];
for(int x=0;cadena[x]!=0;x++)
if(cadena[x]==';')i++;
else if(cadena[x]==' ')c++;
j=c/i+1;
m=i;
n=j;
reservarF(real,i,j,0);
i=0,c=0,j=0;
for(int x=0;cadena[x]!=0;x++)
{
if(cadena[x]!=';'&&cadena[x]!=' ')
{
aux=string;
string[c]=cadena[x];
string[c+1]=0;
string=aux;
c++;
aux=new char[c+2];
}
if(cadena[x]==';'||cadena[x]==' ')
{
real[i][j]=strTof(string);
if(cadena[x]==';')i++,j=0,c=0;
else if(cadena[x]==' ')j++,c=0;
}
}
real[i][j]=strTof(string);
}
////////////////////////////////////////////////////////////////////////////////////////////////
double raiz(float x)
{
double r=x,t=0;
while (t!=r)
{
t=r;
r=(x/r+r)/2;
}
return (float)r;
}
//////////////////////////////////////////////////////////////////////////////////////////////////
void matriz::ceros_imag()
{
if(!im)
{
reservarF(imaj,m,n,0);
im=1;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////
matriz subM(matriz A,int i,int j)
{
matriz C;
int X=0;
int Y=0;
if(i>0) C.m=A.m-1;else C.m=0;
if(j>0)C.n=A.n-1;else C.n=0;
C=ceros(C.m,C.n,A.im);
if(i>0&&j>0)
for(int x=0;x<A.m;x++)
{
for(int y=0;y<A.n&&x!=i-1;y++)
{
if(y!=j-1)
{
C.real[X][Y]=A.real[x][y];
if(C.im)C.imaj[X][Y]=A.imaj[x][y];
Y++;
}
}
Y=0;
if(x!=i-1)X++;
}
else C.error=1;
return C;
}
///////////////////////////////////////////////////////////////////////////////////////////////
void dft(matriz X,matriz &C)
{
int N=X.n;
C=ceros(1,N,true);
float Wnk[2]={0.0,0.0};
for(int k=0;k<N;k++)
for(int n=0;n<N;n++)
{
Wnk[0]=cos(2*PI*n*k/N,false);
Wnk[1]=-sen(2*PI*n*k/N,false);
C.real[0][k]+=X.real[0][n]*Wnk[0];
C.imaj[0][k]+=X.real[0][n]*Wnk[1];
}
}
///////////////////////
matriz auxiliar,resp;
DWORD threadId[4];
/////////////////////////////////////////////////////////////////////////////////////////////////
DWORD WINAPI hilo1(LPVOID args)
{
double W1[2]={0.0,0.0},W2[2]={0.0,0.0},W3[2]={0.0,0.0},W4[2]={0.0,0.0},Wn[2]={0.0,0.0};
double R=0.0,I=0.0;
int N=auxiliar.n;
for(int k=0;k<N/4;k++)
for(int n=0;n<N/4;n++)
{
Wn[0]=cos(2*PI*n/N,false);
Wn[1]=-sen(2*PI*n/N,false);
W1[0]=cos(8*PI*n*k/N,false);//////////////////////////////////////////////////////////Real
W1[1]=-sen(8*PI*n*k/N,false);/////////////////////////////////////////////////////////Imaginario
W2[0]=W1[0]*Wn[0]-W1[1]*Wn[1];
W2[1]=W1[0]*Wn[1]+W1[1]*Wn[0];
W3[0]=W2[0]*Wn[0]-W2[1]*Wn[1];
W3[1]=W2[0]*Wn[1]+W2[1]*Wn[0];
W4[0]=W3[0]*Wn[0]-W3[1]*Wn[1];
W4[1]=W3[0]*Wn[1]+W3[1]*Wn[0];
R=auxiliar.real[0][n]+auxiliar.real[0][n+N/4]+auxiliar.real[0][n+N/2]+auxiliar.real[0][n+3*N/4];
resp.real[0][4*k]+=R*W1[0];
resp.imaj[0][4*k]+=R*W1[1];
}
threadId[0]=0;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
DWORD WINAPI hilo2(LPVOID args)
{
double W1[2]={0.0,0.0},W2[2]={0.0,0.0},W3[2]={0.0,0.0},W4[2]={0.0,0.0},Wn[2]={0.0,0.0};
double R=0.0,I=0.0;
int N=auxiliar.n;
for(int k=0;k<N/4;k++)
for(int n=0;n<N/4;n++)
{
Wn[0]=cos(2*PI*n/N,false);
Wn[1]=-sen(2*PI*n/N,false);
W1[0]=cos(8*PI*n*k/N,false);//////////////////////////////////////////////////////////Real
W1[1]=-sen(8*PI*n*k/N,false);/////////////////////////////////////////////////////////Imaginario
W2[0]=W1[0]*Wn[0]-W1[1]*Wn[1];
W2[1]=W1[0]*Wn[1]+W1[1]*Wn[0];
W3[0]=W2[0]*Wn[0]-W2[1]*Wn[1];
W3[1]=W2[0]*Wn[1]+W2[1]*Wn[0];
W4[0]=W3[0]*Wn[0]-W3[1]*Wn[1];
W4[1]=W3[0]*Wn[1]+W3[1]*Wn[0];
R=auxiliar.real[0][n]-auxiliar.real[0][n+N/2];
I=auxiliar.real[0][n+3*N/4]-auxiliar.real[0][n+N/4];
resp.real[0][4*k+1]+=R*W2[0]-I*W2[1];
resp.imaj[0][4*k+1]+=R*W2[1]+W2[0]*I;
}
threadId[1]=0;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
DWORD WINAPI hilo3(LPVOID args)
{
double W1[2]={0.0,0.0},W2[2]={0.0,0.0},W3[2]={0.0,0.0},W4[2]={0.0,0.0},Wn[2]={0.0,0.0};
double R=0.0,I=0.0;
int N=auxiliar.n;
for(int k=0;k<N/4;k++)
for(int n=0;n<N/4;n++)
{
Wn[0]=cos(2*PI*n/N,false);
Wn[1]=-sen(2*PI*n/N,false);
W1[0]=cos(8*PI*n*k/N,false);//////////////////////////////////////////////////////////Real
W1[1]=-sen(8*PI*n*k/N,false);/////////////////////////////////////////////////////////Imaginario
W2[0]=W1[0]*Wn[0]-W1[1]*Wn[1];
W2[1]=W1[0]*Wn[1]+W1[1]*Wn[0];
W3[0]=W2[0]*Wn[0]-W2[1]*Wn[1];
W3[1]=W2[0]*Wn[1]+W2[1]*Wn[0];
W4[0]=W3[0]*Wn[0]-W3[1]*Wn[1];
W4[1]=W3[0]*Wn[1]+W3[1]*Wn[0];
R=auxiliar.real[0][n]-auxiliar.real[0][n+N/2];
I=auxiliar.real[0][n+N/4]-auxiliar.real[0][n+3*N/4];
resp.real[0][4*k+3]+=R*W4[0]-I*W4[1];
resp.imaj[0][4*k+3]+=R*W4[1]+W4[0]*I;
}
threadId[2]=0;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
DWORD WINAPI hilo4(LPVOID args)
{
double W1[2]={0.0,0.0},W2[2]={0.0,0.0},W3[2]={0.0,0.0},W4[2]={0.0,0.0},Wn[2]={0.0,0.0};
double R=0.0,I=0.0;
int N=auxiliar.n;
for(int k=0;k<N/4;k++)
for(int n=0;n<N/4;n++)
{
Wn[0]=cos(2*PI*n/N,false);
Wn[1]=-sen(2*PI*n/N,false);
W1[0]=cos(8*PI*n*k/N,false);//////////////////////////////////////////////////////////Real
W1[1]=-sen(8*PI*n*k/N,false);/////////////////////////////////////////////////////////Imaginario
W2[0]=W1[0]*Wn[0]-W1[1]*Wn[1];
W2[1]=W1[0]*Wn[1]+W1[1]*Wn[0];
W3[0]=W2[0]*Wn[0]-W2[1]*Wn[1];
W3[1]=W2[0]*Wn[1]+W2[1]*Wn[0];
W4[0]=W3[0]*Wn[0]-W3[1]*Wn[1];
W4[1]=W3[0]*Wn[1]+W3[1]*Wn[0];
// I=auxiliar.real[0][n+N/4]-auxiliar.real[0][n+3*N/4];
R=auxiliar.real[0][n]-auxiliar.real[0][n+N/4]+auxiliar.real[0][n+N/2]-auxiliar.real[0][n+3*N/4];
resp.real[0][4*k+2]+=R*W3[0];
resp.imaj[0][4*k+2]+=R*W3[1];
}
threadId[3]=0;
}
///////////////////////////////////////////////////
void fft4(matriz X,matriz &C)
{
HANDLE tareas[4];
int residuo=X.n%4;
if(residuo>0)residuo=4-residuo;
auxiliar=aumentar(X,ceros(1,residuo,false),1);//X;
resp=ceros(1,X.n+residuo,true);
for(int x=0;x<4;x++)threadId[x]=x+1;
int val[4];
tareas[0]=CreateThread( NULL, 0,hilo1, &val[0], 0, &threadId[0]);
tareas[1]=CreateThread( NULL, 0,hilo2, &val[1], 0, &threadId[1]);
tareas[2]=CreateThread( NULL, 0,hilo3, &val[2], 0, &threadId[2]);
tareas[3]=CreateThread( NULL, 0,hilo4, &val[3], 0, &threadId[3]);
while(!(threadId[0]==0&&threadId[1]==0&&threadId[2]==0&&threadId[3]==0));
C=resp;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void ifft4(matriz X,matriz &C)
{
int N=X.n*X.m;
float W1[2]={0.0,0.0},W2[2]={0.0,0.0},W3[2]={0.0,0.0},W4[2]={0.0,0.0},Wk[2]={0.0,0.0};
float R=0.0,I=0.0;
C=ceros(1,N,false);
for(int n=0;n<N/4;n++)
{
for(int k=0;k<N/4;k++)
{
Wk[0]=cos(2*PI*k/N,false);
Wk[1]=sen(2*PI*k/N,false);
W1[0]=cos(8*PI*n*k/N,false);
W1[1]=sen(8*PI*n*k/N,false);
W2[0]=W1[0]*Wk[0]-W1[1]*Wk[1];
W2[1]=W1[0]*Wk[1]+W1[1]*Wk[0];
W3[0]=W2[0]*Wk[0]-W2[1]*Wk[1];
W3[1]=W2[0]*Wk[1]+W2[1]*Wk[0];
W4[0]=W3[0]*Wk[0]-W3[1]*Wk[1];
W4[1]=W3[0]*Wk[1]+W3[1]*Wk[0];
R=X.real[0][k]+X.real[0][k+N/4]+X.real[0][k+N/2]+X.real[0][k+3*N/4];
I=X.imaj[0][k]+X.imaj[0][k+N/4]+X.imaj[0][k+N/2]+X.imaj[0][k+3*N/4];
C.real[0][4*n]+=R*W1[0]-I*W1[1];
R=X.real[0][k]-X.real[0][k+N/2]-X.imaj[0][k+N/4]+X.imaj[0][k+3*N/4];
I=X.imaj[0][k]-X.imaj[0][k+N/2]+X.real[0][k+N/4]-X.real[0][k+3*N/4];
C.real[0][4*n+1]+=R*W2[0]-W2[1]*I;
R=X.real[0][k]-X.real[0][k+N/2]+X.imaj[0][k+N/4]-X.imaj[0][k+3*N/4];
I=X.imaj[0][k]-X.imaj[0][k+N/2]-X.real[0][k+N/4]+X.real[0][k+3*N/4];
C.real[0][4*n+3]+=R*W4[0]-W4[1]*I;
R=X.real[0][k]-X.real[0][k+N/4]+X.real[0][k+N/2]-X.real[0][k+3*N/4];
I=X.imaj[0][k]-X.imaj[0][k+N/4]+X.imaj[0][k+N/2]-X.imaj[0][k+3*N/4];
C.real[0][4*n+2]+=R*W3[0]-W3[1]*I;
}
C.real[0][4*n]/=N;
C.real[0][4*n+1]/=N;
C.real[0][4*n+2]/=N;
C.real[0][4*n+3]/=N;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
matriz M_func(matriz A,int x,bool deg)
{
matriz R;
R=ceros(A.m,A.n,A.im);
for(int i=0;i<R.m;i++)
for(int j=0;j<R.n;j++)
switch(x)
{
case 0:R.real[i][j]=sen(A.real[i][j],deg);break;////sen
case 1:R.real[i][j]=cos(A.real[i][j],deg);break;////cos
case 2:R.real[i][j]=tan(A.real[i][j],deg);break;///tan
case 3:R.real[i][j]=raiz(A.real[i][j]);break;///raiz
case 4:R.real[i][j]=ln(A.real[i][j]);break;////logaritmo natural
case 5:R.real[i][j]=e(A.real[i][j]);
if(R.im)
{
float m=R.real[i][j];
R.real[i][j]=m*cos(A.imaj[i][j],false);
R.imaj[i][j]=m*sen(A.imaj[i][j],false);
}
break;/////exponencial
}
return R;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
matriz subMat(matriz A,matriz B)
{
matriz C;
int m1,n1,m2,n2;
if(A.m==2&&A.n==2&&!A.im)
{
m1=A.real[0][0]-1;n1=A.real[0][1]-1;
m2=A.real[1][0];n2=A.real[1][1];
if(m1<B.m&&m2<=B.m&n1<B.n&&n2<=B.n)
{
C=ceros(m2-m1,n2-n1,B.im);
for(int x=m1;x<m2;x++)
for(int y=n1;y<n2;y++)
{
C.real[x-m1][y-n1]=B.real[x][y];
if(B.im)
C.imaj[x-m1][y-n1]=B.imaj[x][y];
}
}
}
return C;
}