mat ls_solve_od(const mat &A, const mat &B)
{
    int m=A.rows(), n=A.cols(), N=B.cols(), j;
    double beta;
    mat A2(A), B2(B), B3(n,N), submat, submat2;
    vec tmp(n), v;

//    it_assert1(m >= n, "The system is under-determined!");
    //it_assert1(m == B.rows(), "The number of rows in A must equal the number of rows in B!");

    // Perform a Householder QR factorization
    for (j=0; j<n; j++) {
	house(rvectorize(A2(j, m-1, j, j)), v, beta);
	v *= sqrt(beta);
	// 	submat.ref(A2, j,m-1, j,n-1);
 	submat = A2(j,m-1,j,n-1);
	sub_v_vT_m(submat, v);
	// 	submat.ref(B2, j,m-1, 0,N-1);
 	submat = B2(j,m-1,0,N-1);
	sub_v_vT_m(submat, v);
    }

    //    submat.ref(A2, 0,n-1,0,n-1);
    //    submat2.ref(B2, 0,n-1,0,N-1);
    submat = A2(0,n-1,0,n-1);
    submat2 = B2(0,n-1,0,N-1);
    for (j=0; j<N; j++) {
	backward_substitution(submat, submat2.get_col(j), tmp);
	B3.set_col(j, tmp);
    }
    
    return B3;
}
Beispiel #2
0
void solve_direct_methods()
{
	unsigned int dimension;
#if DEBUG
	int k;
#endif
	double *vector_temp = NULL;

	//printf("\n\nSolving (Forward/Backward) ...\n\n");
	
	dimension = circuit_simulation.number_of_nodes + circuit_simulation.group2_elements;

	if (circuit_simulation.matrix_sparsity == SPARSE)
	{
		vector_temp = ( double * ) calloc( dimension, sizeof(double) );

		if (vector_temp == NULL)
		{
			printf( "Could not allocate matrices.\n" );
			printf( "Terminating.\n" );
			exit( -1 );
		}

		memcpy( vector_x, vector_b, dimension * sizeof(double) );

		if (circuit_simulation.matrix_type == NONSPD)
		{ /*Forward Backward LU*/
			cs_di_ipvec( N->pinv, vector_x, vector_temp, dimension );
			cs_di_lsolve( N->L, vector_temp );
			cs_di_usolve( N->U, vector_temp );
			cs_di_ipvec( S->q, vector_temp, vector_x, dimension );
		}
		else
		{/*Forward Backward Cholesky*/
			cs_di_ipvec( S->pinv, vector_x, vector_temp, dimension );
			cs_di_lsolve( N->L, vector_temp );
			cs_di_ltsolve( N->L, vector_temp );
			cs_di_pvec( S->pinv, vector_temp, vector_x, dimension );
		}

		free( vector_temp );
	}
	else
	{
		forward_substitution();
		backward_substitution();
	}
	
	#if DEBUG
		printf("\nVector x:\n\n");
		for(k = 0; k < dimension; k++)
		{
			printf("%12lf\n", vector_x[k]);
		}

		printf("\n\n");
        #endif

}
vec backward_substitution(const mat &U, int q, const vec &b)
{
void backward_substitution(const mat &U, int q, const vec &b, vec &x);
    vec x(U.rows());
    backward_substitution(U, q, b, x);

    return x;
}
Beispiel #4
0
/*************************************************************************

	Subroutine to multiply the inverse of a square matrix and 
		by another matrix without computing the inverse

*************************************************************************/
void inverse_matrix_multiply (int nrows1, float **matrix1, int ncols2,
	int nrows2, float **matrix2, float **out_matrix)
/*************************************************************************
Input Parameters:
nrows1		number of rows (and columns) of matrix to invert
matrix1		square matrix to invert
ncols2		number of coulmns of second matrix
nrows2		number of rows of second matrix
matrix		second matrix (multiplicator)

Output Parameters:
out_matrix	matrix containing the product of the inverse of the first 
		matrix by the second one. 
Note:
matrix1 and matrix2 are not destroyed (not clobbered)
*************************************************************************
Credits:
	Adapted from discussions in Numerical Recipes in C by Gabriel Alvarez (1995)
*************************************************************************/

{
	int i,j;		/* loop counters for rows and coulmns */
	float d;		/* to use in LU decomposition */
	int *idx;		/* to record permutations by partial pivoting*/
	float **scratch1;	/* array to hold input matrix1 */
	float *scratch2;	/* vector to hold column of input matrix2 */

	/* allocate working space */
	idx = alloc1int(nrows1);
	scratch1 = alloc2float(nrows1,nrows1);
	scratch2 = alloc1float(nrows2);

	/* copy input matrix1 to scratch to avoid clobbering */
	for (i=0; i<nrows1; i++)
		for (j=0; j<nrows1; j++)
			scratch1[i][j]=matrix1[i][j];

	/* do the LU decomposition */
	LU_decomposition (nrows1, scratch1, idx, &d);
	
	/* find inverse by columns */
	for (j=0; j<ncols2; j++) {
	
		/* copy column of second input matrix to scratch vector */
		for (i=0; i<nrows2; i++) scratch2[i]=matrix2[i][j];

		/* do backward substitution */
		backward_substitution (nrows1, scratch1, idx, scratch2);

		/* copy results to output matrix */
		for (i=0; i<nrows1; i++) out_matrix[i][j] = scratch2[i];
	}

	/* free allocated space */
	free2float(scratch1);
	free1float(scratch2);
}
vec ls_solve(const mat &L, int p, const mat &U, int q, const vec &b)
{
    vec x(L.rows());
  
    forward_substitution(L, p, b, x); // Solve Ly=b, Here y=x
    backward_substitution(U, q, x, x); // Solve Ux=y, Here x=y
  
    return x;
}
// simultaneous linear equation 
void solute_SLE_with_n_variables(double coefficient_matrix[N][N], double right_hand_vector[N], double solution_vector[N]){
    double l_matrix[N][N] = {0};
    double u_matrix[N][N] = {0};
    double mid_solution_vector[N];

    lu_decomposition(coefficient_matrix, l_matrix, u_matrix);
    forward_substitution(l_matrix, right_hand_vector, mid_solution_vector);
    backward_substitution(u_matrix, mid_solution_vector, solution_vector);
}
Beispiel #7
0
/************************************************************************
	
	Subroutine to invert a square non-singular matrix via LU
	decomposition. The original matrix is clobbered with the inverse

************************************************************************/
void inverse_matrix (int nrows, float **matrix)
/************************************************************************
Input:
nrows		number of rows (and columns) in matrix  to invert 
matrix		square, non-singular matrix to invert

Output:
matrix		inverted matrix
************************************************************************
Credits:
	Adapted from discussions in Numerical Recipes by Gabriel Alvarez (1995)

************************************************************************/
{
	int i,j;		/* loop counters */
	float d;		/* +/-1 depending on row interchanges even/odd*/
	int *idx;		/* vector of row permutations */
	float *column;		/* unit vector for backward substitution*/
	float **inverse;	/* array to hold the inverse matrix */

	/* allocate working space */
	idx = alloc1int(nrows);
	column = alloc1float(nrows);	
	inverse = alloc2float(nrows,nrows);

	/* first, do the LU decomposition of input matrix */
	LU_decomposition (nrows, matrix, idx, &d);

	/* find inverse by columns */
	for (j=0; j<nrows; j++) {

		/* unit vector corresponding to current column */
		for (i=0; i<nrows; i++) column[i]=0.0;
		column[j]=1.0;
			
		/* backward substitution column by column */
		backward_substitution (nrows, matrix, idx, column);

		/* compute inverse matrix column by column */
		for (i=0; i<nrows; i++)
			inverse[i][j]=column[i]; 
	}

	/* clobber original matrix with its inverse */
	for (i=0; i<nrows; i++)
		for (j=0; j<nrows; j++)
			matrix[i][j]=inverse[i][j];

	/* free allocated space */
	free1int(idx);
	free1float(column);
	free2float(inverse);
}
vec ls_solve_od(const mat &A, const vec &b)
{
    int m=A.rows(), n=A.cols();
    double beta;
    mat A2(A), submat;
    vec b2(b), v;

//    it_assert1(m >= n, "The system is under-determined!");
//    it_assert1(m == b.size(), "The number of rows in A must equal the length of b!");
    
    // Perform a Householder QR factorization
    for (int j=0; j<n; j++) {
	house(rvectorize(A2(j, m-1, j, j)), v, beta);
	v *= sqrt(beta);
	// 	submat.ref(A2, j,m-1, j,n-1);
 	submat = A2(j,m-1,j,n-1); // Time-consuming
	sub_v_vT_m(submat, v);
	b2.set_subvector(j,m-1, b2(j,m-1)- v*(v*b2(j,m-1)));
    }

    return backward_substitution(A2(0,n-1,0,n-1), b2(0,n-1));
}
Beispiel #9
0
    int
    lu_solver( const matrix<T1,D1,A1>&           A, 
               matrix<T2,D2,A2>&                 x, 
               const matrix<T3,D3,A3>&           b )
    {
        typedef matrix<T1,D1,A1>                 matrix_type;
        //typedef typename matrix_type::value_type value_type;
        typedef typename matrix_type::size_type  size_type;

        assert( A.row() == A.col() );
        assert( A.row() == b.row() );
        assert( b.col() == 1 );
        size_type const n = A.row();

        matrix_type L, U;
        // if lu decomposition failed, return 
        if ( lu_decomposition( A, L, U ) ) return 1;

        matrix_type Y;
        if( forward_substitution( L, Y, b ) ) return 1; // solve LY=b
        if( backward_substitution( U, x, Y )) return 1; //solve Ux=Y

        return 0;
    }
int main(int argc, char* argv[])
{
	int rank, size;

	// Initialize the environment
	MPI_Init( &argc, &argv );
	MPI_Comm_rank( MPI_COMM_WORLD, &rank );
	MPI_Comm_size( MPI_COMM_WORLD, &size );

	// example of big matrix in column-major order
	int n = 100;
	double* A = (double*)malloc(sizeof(double)*n*n);
	int r = 0;
	int c = 0;
	double val = 1;
	for(c = 0; c < n; c++)
	{
		for(r = 0; r < n; r++)
		{
			if(r > c)
				A[c*n + r] = 0;
			else
			{
				A[c*n + r] = val;
				val++;
			}		
		}
	}	

	double* b = (double*)malloc(sizeof(double)*n);
	val = 1;
	c = 0;
	for(c = 0; c < n; c++)
	{
		b[c] = val;
		val++;
	}

	
	/*
	// example of small matrix
	int n = 8;
	// column-major order	
	double A[] = {1,0,0,0,0,0,0,0,
					1,-2,0,0,0,0,0,0,
					-1,-3,2,0,0,0,0,0,
					4,1,-3,2,0,0,0,0,
					1,1,1,-4,-4,0,0,0,
					1,-2,5,1,1,5,0,0,
					-1,-3,2,2,2,1,9,0,
					4,1,-3,2,2,2,2,2};

	double b[] = {8,5,0,4,8,5,0,4};
	*/
	double* x = (double*)malloc(sizeof(double)*n);
	
	int d = n/size;
	int first = rank * d;
	int last = (rank + 1) * d - 1;
	int count = d;
	
	worker_struct worker;
	worker.rank = rank;
	worker.size = size;
	worker.first_col = first;
	worker.last_col = last;
	worker.count = count;
	worker.c = (double*)malloc(sizeof(double)*n*d);

	
	struct timeval t1, t2;
	double delta;
	
	if(rank == 0)
		gettimeofday(&t1, NULL);

	/* Split the matrix and start computations */
	MPI_Scatter(A, d*n, MPI_DOUBLE,
				worker.c, d*n, MPI_DOUBLE,
				0, MPI_COMM_WORLD);				
	
	backward_substitution(worker, b, x, n);

	if(rank == 0)
	{
		gettimeofday(&t2, NULL);
		delta = (t2.tv_sec - t1.tv_sec) * 1000.0;
		delta += (t2.tv_usec - t1.tv_usec) / 1000.0;
		printf("Algorithm of %dx%d matrix with %d processors finished after %lf miliseconds = %lf seconds \n",n,n,size, delta, delta/1000.0);
	}

	// print results
	if(rank == 0)
	{
		// sleep just for print
		int i = 0;
		for(i = 0; i < n; i++)
		{
			//printf("x[%d] = %lf \n", i, x[i]);
		}
	}
	
	MPI_Finalize();
	return 0;
}
Beispiel #11
0
int main(int argc, char *argv[])
{
    int n1;			/* number of samples in input trace	 */
    int n1w;		/* number of samples in time window      */
    int N1w;	       	/* number of time windows		*/
    int n1ws;	       	/* number of samples in window (wo taper)*/
    int n1wf;	       	/* number of samples in first window     */
    int n1wi;	       	/* number of samples in intermed. window */
    int n1taper;	       	/* number of samples in taper		*/
    int n2;	       		/* number of input traces		*/
    int n3;	       		/* number of input sections		*/
    int n2w;	       	/* number of traces in window		*/
    int N2w;	       	/* number of spacial windows		*/
    int n2wu;	       	/* updated number of traces in window	*/
    int nfft;		/* transform length			*/
    int nf;			/* number of frequencies		*/
    int lenf;		/* number of traces for filter		*/
    int i2w,i2,jr,itt;	/* summation indexes			*/
    int i1,i3,i1w,ifq,ir;	/* summation indexes			*/
    int ig,ifv;		/* summation indexes			*/
    bool verb;		/* flag to get advisory messages	*/
    int *ipvt;		/* indices of pivot permutations	*/

    float *info;		/* index of last zero pivot		*/
    float dt;		/* sampling interval in secs		*/
    float df;		/* sample interval in Hz		*/
    float fmin;		/* minimum frequency to process in Hz	*/
    float fmax;		/* maximum frequency to process in Hz	*/
    float taper;		/* length of taper			*/
    float twlen;       	/* time window length 			*/
    float **tracein;      	/* real trace			   	*/
    float **traceout;     	/* real trace			   	*/
    float *traceintw;       /* real trace in time window - input   	*/
    float *traceinttw;      /* real trace in time window - input   	*/
    float *traceotw;       	/* real trace in time window - output   */
    float *traceottw;      	/* real trace in time window - output   */
    float *rauto;       	/* real part of autocorrelation   	*/
    float *iauto;       	/* imaginary part of autocorretation 	*/
    float **cautom;      	/* complex autocorrelation matrix	*/
    float *aav;       	/* advanced autocorrelation vector	*/

    kiss_fft_cpx *cdata;	/* complex transformed trace (window)  	*/
    kiss_fft_cpx **fdata;	/* data - freq. domain          	*/
    kiss_fft_cpx **fdataw;	/* data - freq. domain - in window     	*/
    kiss_fft_cpx *sfv;	/* single frequency vector 	  	*/
    kiss_fft_cpx **ffv;	/* filtered frequency vector 	  	*/
    kiss_fft_cpx *fv;	/* frequency vector		      	*/
    kiss_fft_cpx *sfvout;	/* single frequency output vector      	*/
    kiss_fft_cpx *sfvcj;	/* complex conjugate of sfv	  	*/
    kiss_fft_cpx *acorr;	/* autocorrelation output	  	*/
    kiss_fft_cpx *filter;	/* filter               	  	*/

    kiss_fftr_cfg forw, invs;
    sf_file in, out;

    sf_init(argc,argv);

    in = sf_input("in");
    out = sf_output("out");

    if(!sf_getbool("verb",&verb)) verb=false;
    /* flag to get advisory messages */
	
    if(!sf_histint(in, "n1", &n1))  sf_error("No n1 in input");  if (verb) sf_warning("n1 = %i",n1);
    if(!sf_histfloat(in, "d1", &dt)) sf_error("No d1 in input"); if (verb) sf_warning("dt= %f",dt);
    if(!sf_histint(in,"n2",&n2))   sf_error("No n2 in input");   if (verb) sf_warning("n2= %f",n2);
    if(!sf_histint(in,"n3",&n3))   n3=1; if (verb) sf_warning("n3= %f",n3);

    if(!sf_getfloat("taper",&taper)) taper=.1;
    /* length of taper */
    if (taper==0.0) taper=.004; 

    if(!sf_getfloat("fmin",&fmin)) fmin=1.;    
    /* minimum frequency to process in Hz */
    if (fmin==0.0)  if (verb) sf_warning("using fmin=1 Hz");

    if(!sf_getfloat("fmax",&fmax)) fmax=1./(2*dt); 
    /* maximum frequency to process in Hz */
    if (fmax==0.0) if (verb) sf_warning("using fmax=1/(2*dt) Hz");

    if (!sf_getfloat("twlen", &twlen)) twlen=(float)(n1-1)*dt;
    /* time window length */
    if (twlen<.3) {
	twlen=.3; if (verb) sf_warning("twlen cannot be less than .3s, using .3s");
    }
    /* setting taper and spatial and temporal windows */
    n1taper =roundf(taper/dt);
    n1taper = (n1taper%2 ? n1taper+1 : n1taper); 

    N1w = roundf((n1-1)*dt/twlen);

    if (N1w==1) taper=0.0;

    n1ws = roundf(twlen/dt) + 1;
    n1wf = n1ws + n1taper/2;
    n1wi = n1ws + n1taper;

    if (!sf_getint("n2w", &n2w)) n2w=10;
    /* number of traces in window */
    if (!n2w) {
	n2w = 10;
	if (verb) sf_warning("n2w cannot be zero, using 10 traces");
    }	
    if (verb) sf_warning("n2w = %i",n2w);

    n2wu = n2w;

    if (!sf_getint("lenf", &lenf)) lenf=4; 
    /* number of traces for filter */
    if (!lenf) if (verb) sf_warning("using lenf=4");	
	
    N2w = n2/n2w;

    /* Computute FFT optimization number */
    nfft = 2*kiss_fft_next_fast_size((n1wf+1)/2);

    forw = kiss_fftr_alloc(nfft,0,NULL,NULL);
    invs = kiss_fftr_alloc(nfft,1,NULL,NULL);

    nf = nfft/2 + 1;
    df = 1.0/(nfft*dt);

    /* space allocation */
    cdata 	= (kiss_fft_cpx*) sf_complexalloc(nfft);
    traceintw =sf_floatalloc(nfft);
    traceinttw=sf_floatalloc(nfft);
    fdata   =(kiss_fft_cpx**) sf_complexalloc2(nf,n2);
    fdataw  =(kiss_fft_cpx**) sf_complexalloc2(nf,2*n2w+2*lenf);
    tracein = sf_floatalloc2(n1,n2);
    traceout= sf_floatalloc2(n1,n2);
    sfv   = (kiss_fft_cpx*) sf_complexalloc(2*n2w+2*lenf);
    sfvcj = (kiss_fft_cpx*) sf_complexalloc(2*n2w+2*lenf);
    acorr= (kiss_fft_cpx*) sf_complexalloc(lenf+1);
    rauto  = sf_floatalloc(lenf+1);
    iauto  = sf_floatalloc(lenf+1);
    cautom = sf_floatalloc2(2*lenf,2*lenf);
    aav = sf_floatalloc(2*lenf);
    filter = (kiss_fft_cpx*) sf_complexalloc(2*lenf+1);
    ffv   = (kiss_fft_cpx**) sf_complexalloc2(nf,2*n2w);
    sfvout=(kiss_fft_cpx*) sf_complexalloc(2*n2w);
    fv   =(kiss_fft_cpx*) sf_complexalloc(nfft);
    traceotw = sf_floatalloc(nfft);
    traceottw= sf_floatalloc(nfft);
    ipvt 	= sf_intalloc(4*n2w);
    info	= sf_floatalloc(4*n2w);

    /* zero output file */
    memset((void *) traceout[0], 0, n2*n1*sizeof(float));


    for (i3=0;i3<n3;i3++)
    {
    /* load traces into the zero-offset array and close tmpfile */
    sf_floatread(tracein[0],n1*n2,in);	
	
    /* If dt not set, issue advisory on frequency step df */
    if (dt && verb) sf_warning("df=%f", 1.0/(nfft*dt));

    if (verb) sf_warning("nf=%i, df=%f, nfft=%i, n1taper=%i", nf,df,nfft,n1taper);

    /* loop over time windows */
    for (i1w=0;i1w<N1w;i1w++) {

	if (i1w>0 && i1w<N1w-1) n1w=n1wi; 
	else if (i1w==0) 
	    if (N1w>1) n1w = n1wf;
	    else        n1w = n1;
	else
	    n1w = n1 - n1ws*i1w + n1taper/2;
 
	if (verb) sf_warning("i1w=%i, N1w=%i, n1w=%i, twlen=%f", i1w,N1w,n1w,twlen); 

	/* zero fdata */
	memset((void *) fdata[0], 0, nf*n2*sizeof(kiss_fft_cpx));
     
	/* select data */
	for (i2=0;i2<n2;i2++) {
 
	    if (i1w>0)
		for (i1=0;i1<n1w;i1++)
		    traceintw[i1]=tracein[i2][i1 + i1w*n1ws - n1taper/2];
	    else
		for (i1=0;i1<n1w;i1++)  
		    traceintw[i1]=tracein[i2][i1];	  

	    memset((void *) (traceintw + n1w), 0, (nfft-n1w)*sizeof(float));
	    memset((void *) cdata, 0, nfft*sizeof(kiss_fft_cpx));

	    /* FFT from t to f */
	    for (i1=0;i1<nfft;i1++)
		traceinttw[i1]=(i1%2 ? -traceintw[i1] : traceintw[i1]);
	    kiss_fftr(forw, traceinttw, cdata);

	    /* Store values */    
	    for (ifq = 0; ifq < nf; ifq++) { 
		fdata[i2][ifq] = cdata[nf-1-ifq];
	    }
	}

	/* Loop over space windows */
	for (i2w=0;i2w<N2w;i2w++){

	    /* to take care of a possible incomplete last window */
	    if (n2<i2w*n2w+2*n2w) 
		n2wu = n2 - i2w*n2w;
	    else
		n2wu = n2w;

	    if (verb) {
		sf_warning("i2w=%i, n2=%i, n2w=%i",
			   i2w,n2,n2w);
		sf_warning("n2wu=%i, N2w=%i, lenf=%i",
			   n2wu,N2w,lenf);
	    }

	    /* zero fdataw */
	    for (i2=0;i2<n2w+2*lenf;i2++)
		memset((void *) fdataw[i2], 0, nf*sizeof(kiss_fft_cpx));

	    /* select data */
	    for (i2=0;i2<n2wu+2*lenf;i2++) 
		for (ifq = 0; ifq < nf; ifq++) {

		    if (i2w>0 && i2w<N2w-1)  
			fdataw[i2][ifq] = fdata[i2 + i2w*n2w - lenf][ifq];
		    else if (i2w==0)
			if (i2>=lenf && i2<n2w+lenf) 
			    fdataw[i2][ifq] = fdata[i2 - lenf][ifq];
			else if (i2<lenf) 
			    fdataw[i2][ifq] = fdata[0][ifq];
			else 
			    if (N2w>1) 
				fdataw[i2][ifq] = fdata[i2 - lenf][ifq];
			    else 
				fdataw[i2][ifq] = fdata[n2-1][ifq];
		    else
			if (i2<n2wu+lenf)
			    fdataw[i2][ifq] = fdata[i2 + i2w*n2w - lenf][ifq];
			else 
			    fdataw[i2][ifq] = fdata[n2-1][ifq];
		}

	    /* loop over frequencies */
	    for (ifq=0;ifq<nf;ifq++) {

		if ((float)ifq*df>=fmin && (float)ifq*df<=fmax) {

		    /* Loop over space window */
		    memset((void *) sfv, 0, (n2wu+2*lenf)*sizeof(kiss_fft_cpx));
		    memset((void *) sfvcj, 0, (n2wu+2*lenf)*sizeof(kiss_fft_cpx));

		    for (i2=0;i2<n2wu+2*lenf;i2++) {
	  
			sfv[i2]=fdataw[i2][ifq];
			sfvcj[i2]=sf_conjf(fdataw[i2][ifq]);
		    }

		    memset((void *) acorr, 0, (lenf+1)*sizeof(kiss_fft_cpx));

		    /* complex autocorrelation */
		    cxcor(n2wu,0,sfv,n2wu,0,sfv,lenf+1,0,acorr);

		    /* zeroing files */
		    memset((void *) rauto, 0, (lenf+1)*sizeof(float));
		    memset((void *) iauto, 0, (lenf+1)*sizeof(float));

		    /* taking real and imaginary parts */
		    for (i2=0;i2<lenf+1;i2++) {
			rauto[i2]=acorr[i2].r;
			iauto[i2]=acorr[i2].i;
		    }

		    /* zeroing files */
		    memset((void *) aav, 0, 2*lenf*sizeof(float));
		    memset((void *) filter, 0, (2*lenf+1)*sizeof(kiss_fft_cpx));
		    for (ir=0;ir<2*lenf;ir++) 
			memset((void *) cautom[ir], 0, 2*lenf*sizeof(float));

		    /* matrix problem */
		    for (ir=0;ir<lenf;ir++) 
			for (jr=0;jr<lenf;jr++) { 
			    if (ir>=jr) cautom[ir][jr]=acorr[ir-jr].r;
			    else        cautom[ir][jr]=acorr[jr-ir].r;
			}

		    for (ir=lenf;ir<2*lenf;ir++)
			for (jr=0;jr<lenf;jr++) {
			    if (ir-lenf<jr) cautom[ir][jr]=-acorr[jr-ir+lenf].i;
			    else            cautom[ir][jr]= acorr[ir-jr-lenf].i;
			}

		    for (ir=lenf;ir<2*lenf;ir++)
			for (jr=lenf;jr<2*lenf;jr++)
			    cautom[ir][jr]=cautom[ir-lenf][jr-lenf];

		    for (ir=0;ir<lenf;ir++)
			for (jr=lenf;jr<2*lenf;jr++)
			    cautom[ir][jr]=-cautom[ir+lenf][jr-lenf];

		    for (ig=0;ig<2*lenf;ig++) {
			if (ig<lenf) aav[ig]=acorr[ig+1].r;
			else aav[ig]=acorr[ig-lenf+1].i;
		    }

		    lu_decomposition(2*lenf,cautom,ipvt,info);
		    backward_substitution(2*lenf,cautom,ipvt,aav);
      
		    /* construct filter */
		    for (ifv=0,ig=lenf-1;ifv<lenf;ifv++,ig--) 
			filter[ifv]=sf_conjf(cmplx(aav[ig]/2.,aav[ig+lenf]/2.));

		    for (ifv=lenf+1,ig=0;ifv<2*lenf+1;ifv++,ig++) 
			filter[ifv]=cmplx(aav[ig]/2.,aav[ig+lenf]/2.);
	 
		    memset((void *) sfvout, 0, n2wu*sizeof(kiss_fft_cpx));

		    /* convolution of data with filter */
		    /* output is one sample ahead */
		    cconv(n2wu+2*lenf,-lenf,sfv,2*lenf+1,-lenf,filter,n2wu,0,sfvout); 

		    /* store filtered values */
		    for (i2=0;i2<n2wu;i2++) ffv[i2][ifq]=sfvout[i2];

		}
	    } /* end of frequencies loop */

	    /* loop along space windows */
	    for (i2=0;i2<n2wu;i2++) {
    
		/* select data */
		for (ifq=0,itt=nf-1;ifq<nf;ifq++,itt--)
		    fv[ifq] = ffv[i2][itt]; 

		memset((void *) (fv+nf), 0, (nfft-nf)*sizeof(kiss_fft_cpx));
		memset((void *) traceotw, 0, nfft*sizeof(float));

		/* FFT back from f to t and scaling */
		kiss_fftri(invs,fv,traceotw);
		for (i1=0;i1<SF_MIN(n1,nfft);i1++)
		    traceotw[i1]/=nfft; 
		for (i1=0;i1<SF_MIN(n1,nfft);i1++)
		    traceottw[i1]=(i1%2 ? -traceotw[i1] : traceotw[i1]); 
      
		/*loop along time */
		if (N1w>1) {
		    /* first portion of time window */
		    if (i1w>0) 
			for (i1=0;i1<n1taper;i1++)
			    traceout[i2w*n2w+i2][i1+i1w*n1ws-n1taper/2]+=
				traceottw[i1]*((float)(i1)*dt/taper);
		    else 
			for (i1=0;i1<n1taper;i1++)
			    traceout[i2w*n2w+i2][i1]=traceottw[i1];

		    /* intermediate portion of time window */
		    if (i1w>0) 
			for (i1=n1taper;i1<n1w-n1taper;i1++)
			    traceout[i2w*n2w+i2][i1+i1w*n1ws-n1taper/2]=traceottw[i1];
		    else 
			for (i1=n1taper;i1<n1w-n1taper;i1++)
			    traceout[i2w*n2w+i2][i1]=traceottw[i1];

		    /* last portion of time window */
		    if (i1w>0 && i1w<N1w-1) 
			for (i1=n1w-n1taper;i1<n1w;i1++)
			    traceout[i2w*n2w+i2][i1+i1w*n1ws-n1taper/2]+=
				traceottw[i1]*(1.-((float)(i1-n1w+n1taper))*dt/taper);
		    else if (i1w==N1w-1)
			for (i1=n1w-n1taper;i1<n1w;i1++)
			    traceout[i2w*n2w+i2][i1+i1w*n1ws-n1taper/2]=traceottw[i1];
		    else 
			for (i1=n1w-n1taper;i1<n1w;i1++)
			    traceout[i2w*n2w+i2][i1]+=traceottw[i1]*(1.-((float)(i1-n1w+n1taper))*dt/taper);
		}
		else {
		    for (i1=0;i1<n1;i1++) 
			traceout[i2w*n2w+i2][i1]=traceottw[i1];
		}

	    } /* end loop over space windows */

	} /* end loop over space windows */

    } /* end of time windows loop */
 
    /* Write output data to file */
    sf_floatwrite(traceout[0], n1*n2, out);
    if(verb) sf_warning("I3=%d is done!\n",i3+1);
    }

    /* Free allocated memory */
    free(traceintw);
    free(traceinttw);
    free(fdataw[0]);
    free(fdataw);
    free(sfv);
    free(sfvcj);
    free(acorr);
    free(rauto);
    free(iauto);
    free(cautom[0]);
    free(cautom);
    free(aav);
    free(filter);
    free(sfvout);
    free(fv);
    free(traceotw);
    free(traceottw);
    free(ffv[0]);
    free(ffv);
    free(tracein[0]);
    free(tracein);
    free(traceout[0]);
    free(traceout);

    exit(0);
}
/*! The type of preconditioner is asked by the user at the runtime*/
void Iterative_Solver::BiCG_preconditioner(SparseMatrix & spm, Vector<double> & X, Vector <double> & B, int choice){
	int number_of_iterations = 0;
//	cout << "Reached Here" << endl;
	Vector<double> Q;
	Q.set_size(X.get_size());
	Q.initialize();
	spm.multiply(X,Q);
	//	Q = spm*X;
	Vector<double> r;
	r.set_size(X.get_size());
	r.sub(B,Q);
	//	r = B - Q;
	Vector<double> r_star;
	r_star.set_size(X.get_size());
	r_star.copy_values(r);
	double beeta;
	double alpha = 1.0;
	double rho = 1.0;
	double omega = 1.0;
	//	double p1 = 0.0;
	double error = 199;
	Vector<double> temp;
	temp.set_size(X.get_size());
	temp.initialize();
	Vector<double> p1;
	p1.set_size(X.get_size());
	p1.initialize();
	Vector<double> v;
	v.set_size(X.get_size());
	v.initialize();
	Vector<double> s;
	s.set_size(X.get_size());
	s.initialize();
	Vector<double> t;
	t.set_size(X.get_size());
	t.initialize();
	Vector<double> temp1;
	temp1.set_size(X.get_size());
	temp1.initialize();
	SparseMatrix M;
//	cout << "Reached Here" << endl;
	Vector<double> y;
	y.set_size(X.get_size());
	Vector<double> z;
	z.set_size(X.get_size());
	if (choice == 0){
		M.initialize(X.get_size());
		M.extractdiagonal(spm);
	}
	else if (choice == 1){
		M.copy(spm);
		ILUDecomposition(M);

	}
	//	cout << "Line 145" << endl;
//	cout << "Iterations started" << endl;
	while(error > pow(10.0,-6)){
		temp.copy_values(X);
		//		cout << "Line 148" << endl;
		double rho_1 = r_star*r;
		//		cout << "Line 150" <<endl;
		beeta = (rho_1/rho)*(alpha/omega);
		//		cout << "Line 151" << endl;
		temp1.add(p1,v,-omega);
		//		p1 = r + (p1 - v*omega)*beeta;
		p1.add(r,temp1,beeta);
		if (choice == 0){
			//			y.multiply_dot(M,p1);
			M.multiply(p1,y);
			//			y.display();
		}

		else if(choice == 1){
			Vector<double> temp_y;
			temp_y.set_size(X.get_size());
			temp_y.initialize();
			forward_substitution(M,temp_y,p1);
			backward_substitution(M,y,temp_y);

		}
		else if(choice == 2){
			forward_substitution_Gauss_Siedel(spm,y,p1);
		}
		//		y.display();
		//		cout << "Line 153";
		spm.multiply(y,v);
		//		v = spm*p1;
		//		cout << "*******" << endl;
		//		v.display();
		alpha = rho_1/(r_star*v);
		//		cout << "Line 159";
		s.add(r,v,-alpha);
		//		cout << "Line 161";
		//		s = r - v*alpha;
		if(choice == 0){
			M.multiply(s,z);
			//			z.multiply_dot(M,s);

		}
		else if (choice == 1){
			Vector<double> temp_z;
			temp_z.set_size(X.get_size());
			temp_z.initialize();
			forward_substitution(M,temp_z,s);
			backward_substitution(M,z,temp_z);
		}
		else if(choice == 2){
			forward_substitution_Gauss_Siedel(spm,z,s);
		}
		spm.multiply(z,t);
		//		t.display();
		//		cout << "Line 164";
		//		t = spm*s;
		double tempval1 = t*s;
		double tempval2 = t*t;
		//		t.display();
		//		cout << tempval1 << endl;
		//		cout << tempval2 << endl;


		omega = (tempval1)/(tempval2);

		//		cout << "Line 167" << endl;
		//		temp1.initialize();
		temp1.add(X,y,alpha);
		X.add(temp1,z,omega);
		//		temp1.initialize();
		//		X = X + s*omega + p1*alpha;
		r.add(s,t,-omega);
		//		r = s - t*omega;
		rho = rho_1;
		//		cout << "Line 189" <<endl;
		error = cal_error(X,temp);
		number_of_iterations++;
	}
	cout << "number of iterations in BiCG" << number_of_iterations << endl;
//	M.del();
//	cout << "Value from Itsolver" << endl;
//	B.display();
}
int main(){
    int kadai;

    // 課題番号指定
    while(1){
        printf("課題番号: ");
        scanf("%d", &kadai);
        if (kadai < 1 || kadai > 8 || kadai == 7){
            printf("1~8!!\n");
        } else {
            break;
        }
    }

    if (kadai == 1){

        double coefficient_mat[N][N] = {{1, 0, 0}, {3, 1, 0}, {-2, 2, 1}};
        double right_hand_vec[N] = {2, 3, -1};
        double solution_vec[N];

        printf("--------------- L行列 ---------------\n");
        print_array(coefficient_mat);
        printf("------------- 右辺ベクトル ------------\n");
        print_vector(right_hand_vec);

        forward_substitution(coefficient_mat, right_hand_vec, solution_vec);

        printf("------------- 解ベクトル --------------\n");
        print_vector(solution_vec);

    } 
    else if (kadai == 2)
    {

        double coefficient_mat[N][N] = {{2, 1, -1}, {0, 3, 2}, {0, 0, -3}};
        double right_hand_vec[N] = {2, -3, 9};
        double solution_vec[N];

        printf("--------------- U行列 ----------------\n");
        print_array(coefficient_mat);
        printf("------------- 右辺ベクトル -------------\n");
        print_vector(right_hand_vec);

        backward_substitution(coefficient_mat, right_hand_vec, solution_vec);

        printf("-------------- 解ベクトル -------------\n");
        print_vector(solution_vec);

    }
    else if (kadai == 3)
    {

        double coefficient_mat[N][N];
        double l_matrix[N][N] = {{1, 0, 0}, {3, 1, 0}, {-2, 2, 1}};
        double u_matrix[N][N] = {{2, 1, -1}, {0, 3, 2}, {0, 0, -3}};

        mat_mlt(l_matrix, u_matrix, coefficient_mat);

        printf("---------- 係数行列 ----------\n");
        print_array(coefficient_mat);

    }
    else if (kadai == 4)
    {

        double coefficient_mat[N][N] = {{2, 1, -1}, {6, 6, -1}, {-4, 4, 3}};
        double l_matrix[N][N] = {0};
        double u_matrix[N][N] = {0};

        lu_decomposition(coefficient_mat, l_matrix, u_matrix);

        printf("---------- L行列 ----------\n");
        print_array(l_matrix);
        printf("---------- U行列 ----------\n");
        print_array(u_matrix);

    }
    else if (kadai == 5)
    {

        double coefficient_mat[N][N] = {{2, 1, -1}, {6, 6, -1}, {-4, 4, 3}};
        double right_hand_vec[N] = {2, 3, -1};
        double solution_vec[N];

        printf("---------- 係数行列 ----------\n");
        print_array(coefficient_mat);
        printf("---------- 右辺ベクトル ----------\n");
        print_vector(right_hand_vec);

        solute_SLE_with_n_variables(coefficient_mat, right_hand_vec, solution_vec);

        printf("---------- 解ベクトル ----------\n");
        print_vector(solution_vec);

    }
    else if (kadai == 6)
    {

        double h_coefficient_mat[N][N];
        double right_hand_vec[N];
        double solution_vec[N];

        int i, j;
        for (i = 0; i < N; i++){
            for (j = 0; j < N; j++){
                h_coefficient_mat[i][j] = pow(0.5, abs(i-j));
            }
        }
        printf("--------------- 行列H ---------------\n");
        print_array(h_coefficient_mat);

        for (i = 0; i < N; i++){
            right_hand_vec[i] = 3 - pow(2, i-N+1) - pow(2, -i);
        }
        printf("------------- 右辺ベクトル -------------\n");
        print_vector(right_hand_vec);

        solute_SLE_with_n_variables(h_coefficient_mat, right_hand_vec, solution_vec);

        printf("---------- 解ベクトル ----------\n");
        print_vector(solution_vec);

    }
    else if (kadai == 8)
    {

        double h_mat[N][N];
        double h_reverse_mat[N][N] = {0};
        double solution_mat[N][N];

        int i, j;
        for (i = 0; i < N; i++){
            for (j = 0; j < N; j++){
                h_mat[i][j] = pow(0.5, abs(i-j));
            }
        }

        evaluate_reverse_matrix(h_mat, h_reverse_mat);

        mat_mlt(h_mat, h_reverse_mat, solution_mat);
        printf("--------------- 行列H ---------------\n");
        print_array(h_mat);
        printf("------------ 行列Hの逆行列 ------------\n");
        print_array(h_reverse_mat);
        printf("---------- 解行列 ----------\n");
        print_array(solution_mat);
    } 

    return 0;
}