/* Steven Andrews, 5/99 */
/* See documentation called Cn doc */
/* Copyright 2003 by Steven Andrews.  Permission is granted
   for non-commercial use of and modifications to the code. */

#include "Rn.h"
#include "Cn.h"
#include "RnSort.h"
#include "math2.h"

float *makecmplx(float *ar,float *ai,float *c,int n) {
	int i;
	
	if(ar&&ai)
		for(i=0;i<n;i++)	{c[2*i]=ar[i];c[2*i+1]=ai[i];}
	else if(ar)
		for(i=0;i<n;i++)	{c[2*i]=ar[i];c[2*i+1]=0;}
	else if(ai)
		for(i=0;i<n;i++)	{c[2*i]=0;c[2*i+1]=ai[i];}
	else
		for(i=0;i<n;i++)	{c[2*i]=c[2*i+1]=0;}
	return c; }

float *real(float *a,float *cr,int n) {
	int i;
	
	for(i=0;i<n;i++)	cr[i]=a[2*i];
	return cr; }

float *imag(float *a,float *ci,int n) {
	int i;

	for(i=0;i<n;i++)	ci[i]=a[2*i+1];
	return ci; }

float *magnitude(float *a,float *cr,int n) {
	int i;
	
	for(i=0;i<n;i++) cr[i]=sqrt(a[2*i]*a[2*i]+a[2*i+1]+a[2*i+1]);
	return cr; }

float *cmplxphase(float *a,float *cr,int n) {
	int i;
	
	for(i=0;i<n;i++) cr[i]=a[2*i]?atan(a[2*i+1]/a[2*i]):0;
	return cr; }

float *CompConj(float *a,float *c,int n) {
	int i;
	
	for(i=0;i<2*n;i+=2)	c[i]=a[i];
	for(i=1;i<2*n;i+=2)	c[i]=-a[i];
	return c; }

float *rotateCV(float *a,float *c,int n,int p) {
	int i;
	float temp;
	
	if(p<0) p+=4*(-p/4+1);
	else p=p%4;
	if(p==1)
		for(i=0;i<2*n;i+=2)	{temp=-a[i+1];c[i+1]=a[i];c[i]=temp;}
	else if(p==2)
		for(i=0;i<2*n;i+=2)	{c[i]=-a[i];c[i+1]=-a[i+1];}
	else if(p==3)
		for(i=0;i<2*n;i+=2)	{temp=a[i+1];c[i+1]=-a[i];c[i]=temp;}
	else
		for(i=0;i<2*n;i+=2)	{c[i]=a[i];c[i+1]=a[i+1];}
	return c; }

float *rotate2CV(float *a,float *c,int n,float phi) {
	int i;
	float cp,sp,temp;
	
	cp=cos(phi);
	sp=sin(phi);
	for(i=0;i<2*n;i+=2)	{
		temp=cp*a[i]-sp*a[i+1];
		c[i+1]=sp*a[i]+cp*a[i+1];
		c[i]=temp;	}
	return c; }

float *multeikx(float *xr,float *a,float *c,int n,float k) {
	int i;
	float th,temp;
	
	for(i=0;i<n;i++)	{
		th=k*xr[i];
		temp=a[2*i]*cos(th)-a[2*i+1]*sin(th);
		c[2*i+1]=a[2*i]*sin(th)+a[2*i+1]*cos(th);
		c[2*i]=temp; }
	return c; }

float *multCV(float *a,float *b,float *c,int n) {
	int i;
	float temp;
	
	for(i=0;i<n;i++)	{
		temp=a[2*i]*b[2*i]-a[2*i+1]*b[2*i+1];
		c[2*i+1]=a[2*i]*b[2*i+1]+a[2*i+1]*b[2*i];
		c[2*i]=temp; }
	return c; }

float *deriv2CV(float *a,float *c,int n,int p) {
	int i;
	
	for(i=1;i<2*(n-1);i++)
		c[i]=a[i-2]+a[i+2]-2*a[i];
	if(p)	{														// set p=1 for periodic boundary conditions
		c[0]=a[2*n-2]+a[2]-2*a[0];
		c[1]=a[2*n-1]+a[3]-2*a[1];
		c[2*n-2]=a[2*n-4]+a[0]-2*a[2*n-2];
		c[2*n-1]=a[2*n-3]+a[1]-2*a[2*n-1]; }
	else {
		c[0]=a[0]+a[4]-2*a[2];
		c[1]=a[1]+a[5]-2*a[3];
		c[2*n-2]=a[2*n-6]+a[2*n-2]-2*a[2*n-4];
		c[2*n-1]=a[2*n-5]+a[2*n-1]-2*a[2*n-3]; }
	return c; }

float *integCV(float *a,float *c,int n) {
	int i;
	
	c[0]=a[0]/2;
	c[1]=a[1]/2;
	for(i=2;i<2*n;i++)
		c[i]=c[i-2]+(a[i-2]+a[i])/2;
	return c; }

float FTStartDflt(float *xr,int n) {
	if(n%2) return -3.14159265358*(n-1.0)/n*(n-1.0)/(xr[n-1]-xr[0]);
	else return -3.14159265358*(n-1.0)/(xr[n-1]-xr[0]); }

float *fourier(float *xr,float *a,float *kr,float *c,int nx,int nk,int isign) {
	int i,j;
	double sumr,sumi,dx,cp,sp;
	
	dx=(xr[nx-1]-xr[0])/(nx-1)/sqrt(2*PI);
	for(i=0;i<nk;i++)	{
		sumr=sumi=0;
		for(j=0;j<nx;j++)	{		// sum+=exp(isign*kr*xr)*a[j]
			cp=cos(kr[i]*xr[j]);
			sp=isign*sin(kr[i]*xr[j]);
			sumr+=cp*a[2*j]-sp*a[2*j+1];
			sumi+=cp*a[2*j+1]+sp*a[2*j]; }
		c[2*i]=sumr*dx;
		c[2*i+1]=sumi*dx; }
	return c; }

float *realcosft(float *xr,float *ar,float *kr,float *cr,int nx,int nk) {
	int i,j;
	double sumr,dx;

	dx=(xr[nx-1]-xr[0])/(nx-1)/sqrt(PI/2);
	for(i=0;i<nk;i++)	{
		sumr=0;
		for(j=0;j<nx;j++)
			sumr+=cos(kr[i]*xr[j])*ar[j];
		cr[i]=sumr*dx; }
	return cr; }

float *hankel(float *xr,float *ar,float *kr,float *cr,int nx,int nk,int samp) {
	int i,j;
	double sum,dx,x;

	dx=(xr[nx-1]-xr[0])/(nx-1);
	dx/=samp;
	for(i=0;i<nk;i++) {
		sum=0;
		j=-2;
		for(x=xr[0];x<=xr[nx-1];x+=dx)
			sum+=interpolate1(xr,ar,nx,&j,x)*bessj0(kr[i]*x)*x;
		cr[i]=sum*dx; }
	return cr; }

float *fft(float *xr,float *a,float *kr,float *c,int nn,int isign) {
	int ofst;
	double dx,dk;
	
	float *data;
	int n,mmax,m,j,istep,i;
	double wtemp,wr,wpr,wpi,wi,theta;
	float tempr,tempi;
	
	copyV(a,c,2*nn);
	data=c-1;
	// start of Numerical Recipes procedure	
	n=nn<<1;
	j=1;
	for(i=1;i<n;i+=2)	{
		if(j>i)	{
			tempr=data[j];data[j]=data[i];data[i]=tempr;
			tempi=data[j+1];data[j+1]=data[i+1];data[i+1]=tempi;}
		m=n>>1;
		while(m>=2&&j>m)	{
			j-=m;
			m>>=1; }
		j+=m; }
	mmax=2;
	while(n>mmax)	{
		istep=2*mmax;
		theta=6.28318530717959/(isign*mmax);
		wtemp=sin(0.5*theta);
		wpr=-2.0*wtemp*wtemp;
		wpi=sin(theta);
		wr=1.0;
		wi=0.0;
		for(m=1;m<mmax;m+=2)	{
			for(i=m;i<=n;i+=istep)	{
				j=i+mmax;
				tempr=wr*data[j]-wi*data[j+1];
				tempi=wr*data[j+1]+wi*data[j];
				data[j]=data[i]-tempr;
				data[j+1]=data[i+1]-tempi;
				data[i]+=tempr;
				data[i+1]+=tempi; }
			wr=(wtemp=wr)*wpr-wi*wpi+wr;
			wi=wi*wpr+wtemp*wpi+wi; }
		mmax=istep; }
	// end of Numerical Recipes procedure
	dx=(xr[nn-1]-xr[0])/(nn-1);
	dk=2*PI/(nn*dx);
	ofst=floor(kr[0]/dk+0.5);
	for(j=0;j<nn;j++) kr[j]=(j+ofst)*dk;
	leftrotV(c,c,2*nn,2*ofst);
	multKV(dx/sqrt(2*PI),c,c,2*nn);
	multeikx(kr,c,c,nn,-xr[0]);
	return c; }




