/**
 * This class gives Java methods dsyev() and dsteqr()
 * which come from Clapack. The class also gives
 * methods which illustrate the usage of dsyev() and dsteqr().
 */
public class NativeLinAlg {
/**
 * 
 */
    static {
        System.loadLibrary("NativeLinAlg");
    } 
/**
 * 
 */	
	public static native int dsyev(
		char		jobz_j,
		char		uplo_j, 
		int			n_j,
		double[]	a_j,
		int			lda_j,
		double[]	w_j,	
		double[]	work_j,
		int			lwork_j,
		int[]		info_j);
/**
 * 
 */	
	public static native int dsteqr(
			char		compz_j,
			int			n_j,
			double[]	d_j,
			double[]	e_j,
			double[]	z_j,
			int			ldz_j,
			double[]	work_j,
			int[]		info_j);
	
/**
 * 
 */
    public static void test_dsyev() {
    	int row, col;
    	
    	char jobz_j = 'V';
    	char uplo_j = 'U';
    	int n_j = 3;
     	double[] a_j = {1,2,3,2,1,4,3,4,1 };
    	//1 2 3
    	//2 1 4
    	//3 4 1
    	double[][] aa = new double[n_j][n_j]; 
     	for(row=0; row < n_j; row++){
    		for(col=0; col < n_j; col++){
    			aa[row][col] = a_j[col*n_j + row];  			
    		}
    	}

    	int	 lda_j = n_j;
     	double[] w_j = new double[n_j];
   	
    	int			lwork_j = 4*n_j;
    	double[]	work_j = new double[lwork_j];
    	int[]		info_j = {0};
    	
    	dsyev(	jobz_j,
    			uplo_j, 
    			n_j,
    			a_j,
    			lda_j,
    			w_j,	
    			work_j,
    			lwork_j,
    			info_j);
    	Throw.If(info_j[0] != 0, "clapack error");
    	
    	//eigenvectors are columns of omega
    	double[][] omega = new double[n_j][n_j];
     	for(row=0; row < n_j; row++){
    		for(col=0; col < n_j; col++){
    			omega[row][col] = a_j[col*n_j + row]; 			
    		}
    	}
     	
     	double[][] aaNew = new double[n_j][n_j];    	
     	for(row=0; row < n_j; row++){
    		for(col=0; col < n_j; col++){
    			aaNew[row][col] = 0;
	    		for(int k=0; k < n_j; k++){
	    			aaNew[row][col] += omega[row][k]*w_j[k]*omega[col][k];
	    		}
    		}
    	}
 
     	for(row=0; row < n_j; row++){
    		for(col=0; col < n_j; col++){
    			System.out.println(aaNew[row][col] - aa[row][col]);
    		}
    	}
   	
    }
/**
 * 
 */
    public static void test_dsteqr() {
    	
    	char compz_j = 'I';
    	int n_j = 4;
    	int dimSq = n_j*n_j;
    	double[] d_j = new double[n_j];
    	double[] e_j = new double[n_j - 1];
    	int k, row, col, index;
    	for(k=0; k< n_j - 1; k++){
    		d_j[k] = 0;
    		e_j[k] = 1;   		
    	}
    	if(n_j - 1 >= 0){
    		d_j[n_j - 1] = 0;
    	}
    	
    	double[][] zz = new double[n_j][n_j];
    	for(row=0; row < n_j; row++){
    		for(col=0; col < n_j; col++){
    			if(row==col){
    				zz[row][col] = 1;
    			}else{
    				zz[row][col] = 0;
    			}
    		}
    	}
    	
    	double[] z_j = new double[dimSq];
    	for(index = 0; index< dimSq; index++){
    		z_j[index] = zz[index%n_j][index/n_j];
    	}
    	
    	int ldz_j = n_j;
    	double[] work_j = new double[Math.max(1,2*n_j - 2)];
    	int[] info_j = {0};
    	
    	dsteqr(	compz_j,
    			n_j,
    			d_j,
    			e_j,
    			z_j,
    			ldz_j,
    			work_j,
    			info_j);    	
    	Throw.If(info_j[0] != 0, "clapack error");
   	
    	//eigenvectors are columns of omega
    	double[][] omega = new double[n_j][n_j];
     	for(row=0; row < n_j; row++){
    		for(col=0; col < n_j; col++){
    			omega[row][col] = z_j[col*n_j + row]; 			
    		}
    	}
     	
     	    	
     	double[][] zzNew = new double[n_j][n_j];
     	for(row=0; row < n_j; row++){
    		for(col=0; col < n_j; col++){
    			if((row==(col - 1)) || (row==(col + 1))){
    				zz[row][col] = 1;
    			}else{
    				zz[row][col] = 0;
    			}
    			zzNew[row][col] = 0;
	    		for(k=0; k < n_j; k++){
	    			zzNew[row][col] += omega[row][k]*d_j[k]*omega[col][k];
	    		}
    		}
    	}
 
     	for(row=0; row < n_j; row++){
    		for(col=0; col < n_j; col++){
    			System.out.println((zzNew[row][col] - zz[row][col]));
    		}
    	}

    	
    	
    }

/**
 * 
 */
    public static void main(String[] args) 
    {
    	//test_dsyev();
    	test_dsteqr();
    	
    }//end of main

}


