/**
 * This class creates a new instance of 
 * a Tree Incidence Matrix (TreeIncMat). 
 * The matrix looks like this for numBits = 3.
 * (matrix dimension is 2^numBits = 8)
 *
 * 
 * {0,0,0,0,0,0,0,0},
 * {0,0,1,1,0,0,0,0},
 * {0,1,0,0,1,1,0,0},
 * {0,1,0,0,0,0,1,1},
 * {0,0,1,0,0,0,0,0},
 * {0,0,1,0,0,0,0,0},
 * {0,0,0,1,0,0,0,0},
 * {0,0,0,1,0,0,0,0}
 * 
 * 
 */
public class TreeIncMat {
    
    private int _numBits;
    
    private int[][] _matrix;
      
/**
 * 
 */
    public TreeIncMat(int numBits) {
        Throw.If(numBits<1, "number of bits must be >= 1");                  
        _numBits = numBits;
        
        //_matrix automatically initialized to zero
        _matrix = new int[1<<numBits][1<<numBits];
      
        int[][] matrixB;
        //lam= int for lambda
        for(int lam=numBits; lam>0; lam--){
            
            //matrixB dimension is pow(2, lam-1)
            matrixB = buildMatrixB(lam-1);

            int numRowsB = 1<<lam;//numRowsB = number of rows in B           
            int row, col, rowPrime, colPrime;
                        
            //fill bottom-left quadrant of a_matrix
            for(row=numRowsB/2; row<numRowsB; row++){
                for(col=0; col<numRowsB/2; col++){
                    rowPrime = row - numRowsB/2;
                    _matrix[row][col] = matrixB[rowPrime][col];
                }
            }
            
            //fill top-right quadrant of a_matrix
            for(row=0; row<numRowsB/2; row++){
                for(col=numRowsB/2; col<numRowsB; col++){
                    colPrime = col - numRowsB/2;
                    // take transpose of matrixB by swapping row and colPrime
                    _matrix[row][col] = matrixB[colPrime][row];
                }
            }
            
        }//lam loop
    }
    
/**
 * matrixB looks like this for lam = 3.
 * (matrixB dimension is 2^lam = 8 rows)
 *
 * 0 0 0 0 1 0 0 0
 * 0 0 0 0 1 0 0 0
 * 0 0 0 0 0 1 0 0
 * 0 0 0 0 0 1 0 0
 * 0 0 0 0 0 0 1 0
 * 0 0 0 0 0 0 1 0
 * 0 0 0 0 0 0 0 1
 * 0 0 0 0 0 0 0 1
 *
 * 
 */
    private int[][] buildMatrixB(int lam){
        
        int numRowsB = (1<<lam);//2^lam
        
        // matrixB automatically intialized to zero
        int[][] matrixB = new int [numRowsB][numRowsB];
        
        int row, col;
        if(numRowsB>1){
            for(row=0; row<numRowsB; row += 2){
                col = row/2 + numRowsB/2;
                matrixB[row][col] = 1;
                matrixB[row+1][col] = 1;             
            }
        }
        
        return matrixB;
        
    }
 /**
  * 
  */   
    public String toString(){
        int numRows = _matrix.length;
        String output = "";
        output += "numRows="+ numRows + '\n';
        int row, col;
        for(row=0; row<numRows; row++){
            for(col=0; col<numRows; col++){
                output += _matrix[row][col] + " ";
            }
            output += '\n';
        }
        return output;
    }
/**
*
*/    
    public int getEntry(int row, int col) {
    	return _matrix[row][col];
    }
/**
 * 
 */    
    public static void main(String[] args){
        System.out.println("numBits = 1:");
        System.out.println((new TreeIncMat(1)).toString());
        System.out.println("numBits = 3:");
        System.out.println((new TreeIncMat(3)).toString());
       
    }
      
}
