/**
 * This class writes English and Picture files
 * for the exact compilation, derived in the paper Tuc08a
 * "QuanFou, QuanGlue, QuanOracle and QuanShi,
 * Four Special Purpose Quantum Compilers", by R.R.Tucci
 * arXiv:0802.2367, of the unitary matrix
 * that takes state |j> to |j + _shift>,
 * where the addition is mod the number of rows.
 *
 */


public class ShiftSEO_writer  extends SEO_writer{
	//private String 	_filePrefix;
	//private int 		_numBits;
    private int _shift;

/**
 * 
 */	
	public ShiftSEO_writer(
	        String 	filePrefix, 
	        int numBits,  
	        int shift)
	{ 	
	 	
    	super(filePrefix + "_qshi", numBits);
    	
		int numRows = 1<<numBits;
		Throw.If(Math.abs(_shift)>= numRows, 
			"shift is out of bounds");
		//negative shift is inverse of shift
		_shift = shift;

    	write();

        closeFiles();

	}
/**
 * 
 */
    public ShiftSEO_writer(
    		java.io.PrintWriter  englishOut,
    		java.io.PrintWriter  pictureOut,
    		Boolean doWrite,
    		int numBits,
    		int numBitsInP0Pad,  
	        int shift)
        {
        	super(englishOut, pictureOut, numBits, numBitsInP0Pad);
 
    		int numRows = 1<<numBits;
    		Throw.If(_shift<0 || _shift>= numRows, 
    			"shift is out of bounds");
    		_shift = shift;

        	if(doWrite){write();}
        }
     	
	
	
/**
 * 
 */
	public void write(){
		

		writeDFT_SEO(true);
		
		int numRows = 1<<_numBits;
		for(int j=0; j<_numBits; j++){
			double angle = -(2*Math.PI/numRows)*_shift*(1<<j);
			writeOneBitGate(j, new OneBitP1PhaseFactor(angle));			
		}

		writeDFT_SEO(false);
		
	}
/**
 * 
 */
	private void writeDFT_SEO(Boolean doNotInvert){
		
		int sign;
		if(doNotInvert){
			sign = 1;
		}else{
			sign = -1;
		}
		
    	//permutation R
		for(int j = _numBits - 1; j>=1; j--){
			for(int k = j-1; k>=0; k--){
				writeBitSwap(j,k);
			}
		}


		Controls controls = new Controls(_numBits, 1);
		int j, k;
		
		for(k=0; k<_numBits; k++){
			writeOneBitGate(k, new OneBitHadamard());
			controls.setControl(0, k, true);
			for(j=k+1; j<_numBits; j++){
				//note j>k so abs(j-k) = j-k
		        writeControlledGate(
					j, //targetBitPosition, 
					controls, 
					new OneBitP1PhaseFactor(
					sign*Math.PI/(1<<(j-k))));
			}
		}	
	}


}
