/**
 * This class writes English and Picture files
 * for the exact compilation, derived in
 * Tuc07a- arXiv:0706.0479, for the evolution operator
 * e^{iH_{glue}}, where H_{glue} = g(|j1><j2| + h.c.),
 * for any two states j1, j2.
 */


public class GlueSEO_writer  extends SEO_writer{
	//private String 	_filePrefix;
	//private int 		_numBits;
	private double 	_strength;
	private int _j1, _j2;

/**
 * 
 */	
	public GlueSEO_writer(
	        String 	filePrefix,
	        int numBits,  
	        double strength,
			Pair pair)
	{ 	
	 	
    	super(filePrefix + "_qglue", numBits);
    	
		_strength = strength;
		_j1 = pair._x1;
		_j2 = pair._x2;
		int numRows = 1<<numBits;
		Throw.If(_j1<0 || _j1>= numRows, 
			"row or col number is out of bounds");
		Throw.If(_j2<0 || _j2>= numRows, 
			"row or col number is out of bounds");
		Throw.If(_j1==_j2, 
				"diagonal glue is not allowed");


		write();
		
        closeFiles();

	}
/**
 * 
 */	
    public GlueSEO_writer(
    		java.io.PrintWriter  englishOut,
    		java.io.PrintWriter  pictureOut,
    		Boolean doWrite,
    		int numBits,
    		int numBitsInP0Pad,  
	        double strength,
			Pair pair)  		
        {
        	super(englishOut, pictureOut, numBits, numBitsInP0Pad);
 
    		_strength = strength;
    		_j1 = pair._x1;
    		_j2 = pair._x2;
    		int numRows = 1<<numBits;
    		Throw.If(_j1<0 || _j1>= numRows, 
    			"row or col number is out of bounds");
    		Throw.If(_j2<0 || _j2>= numRows, 
    			"row or col number is out of bounds");
    		Throw.If(_j1==_j2, 
    				"diagonal glue is not allowed");

        	if(doWrite){write();}
        	
        }

/**
 * 
 */
	public void write(){
		
		int b = 0;
		int b0 = 0;
		while(b < _numBits){
			if(  ((_j1>>b)&1) != ((_j2>>b)&1) ){
				b0 = b;
				break;
			}
			b++;
		}
		int k;
		if( ((_j1>>b0)&1) == 0){
			k = _j1;
		}else{
			k = _j2;
		}
	
		
		writeU_SEO(b0);

		Controls controls = new Controls(_numBits, _numBits - 1);
		Boolean controlType;
		b = _numBits -1;
	    int controlCounter = 0;
	    while(b>=0){
	    	if(b!=b0){
	        	controlType = ((k>>b)&1)==1;
	            controls.setControl(controlCounter, b, controlType);
	        	controlCounter++;
	    	}
	    	b--;
	    }
        writeControlledGate(
			b0, //targetBitPosition, 
			controls, 
			new OneBitRot(_strength, OneBitRot.X_AXIS));
		
		writeU_SEO(b0);
		
	}
	
	
	
/**
 * 
 */
	private void writeU_SEO(int b0){
		Controls controls = new Controls(_numBits, 1);
		controls.setControl(0, b0, true);
		int b=0;
		while(b < _numBits){
			if( (b != b0) && 
				((_j1>>b)&1) != ((_j2>>b)&1) ){
				writeControlledGate(
					b, //targetBitPosition, 
					controls, 
					new SigX());
			}
			b++;
		}
	}

}
