package net.maizegenetics.matrixalgebra.Matrix;

import org.ejml.data.DenseMatrix64F;
import org.ejml.ops.SpecializedOps;

import cern.colt.matrix.DoubleFactory2D;
import cern.colt.matrix.DoubleMatrix2D;

public class DoubleMatrixFactory {
	public enum FactoryType {ejml, jblas, colt};
	private FactoryType myType;
	public static DoubleMatrixFactory DEFAULT = new DoubleMatrixFactory(FactoryType.ejml);
	
	public DoubleMatrixFactory(FactoryType type) {
		myType = type;
	}
	
	public static void setDefault(FactoryType type) {
		DoubleMatrixFactory.DEFAULT = new DoubleMatrixFactory(type);
	}
	
	public FactoryType getType() { return myType; }
	
	public DoubleMatrix make(int row, int col) {
		if (myType == FactoryType.ejml) return new EJMLDoubleMatrix(row, col);
		if (myType == FactoryType.colt) return new ColtDoubleMatrix(row, col);
		if (myType == FactoryType.jblas) return null;
		return null;
	}
	
	public DoubleMatrix make(int row, int col, double[] values) {
		if (myType == FactoryType.ejml) return new EJMLDoubleMatrix(row, col, values);
		if (myType == FactoryType.colt) return new ColtDoubleMatrix(row, col, values);
		if (myType == FactoryType.jblas) return null;
		return null;
	}

	public DoubleMatrix make(int row, int col, double value) {
		if (myType == FactoryType.ejml) return new EJMLDoubleMatrix(row, col, value);
		if (myType == FactoryType.colt) return new ColtDoubleMatrix(row, col, value);
		if (myType == FactoryType.jblas) return null;
		return null;
	}
	
	public DoubleMatrix make(double[][] values) {
		if (myType == FactoryType.ejml) return new EJMLDoubleMatrix(values);
		if (myType == FactoryType.colt) return new ColtDoubleMatrix(values);
		if (myType == FactoryType.jblas) return null;
		return null;
	}
	
	public DoubleMatrix identity(int n) {
		if (myType == FactoryType.ejml) return new EJMLDoubleMatrix(n);
		if (myType == FactoryType.colt) return new ColtDoubleMatrix(n);
		if (myType == FactoryType.jblas) return null;
		return null;
	}
	
	public DoubleMatrix diagonal(double[] diag) {
		if (myType == FactoryType.ejml) return new EJMLDoubleMatrix(diag);
		if (myType == FactoryType.colt) return new ColtDoubleMatrix(diag);
		if (myType == FactoryType.jblas) return null;
		return null;
	}
	
	public DoubleMatrix compose(DoubleMatrix[][] components) {
		
		if (myType == FactoryType.ejml) {
			int totalRows = 0;
			int totalCols = 0;
			int nRows = components.length;
			int nCols = components[0].length;
			for (int i = 0; i < nRows; i++) totalRows += components[i][0].numberOfRows();
			for (int i = 0; i < nCols; i++) totalCols += components[0][i].numberOfColumns();
			
			DenseMatrix64F result = new DenseMatrix64F(totalRows, totalCols);
			int startRow = 0;
			for (int r = 0; r < nRows; r++) {
				int startCol = 0;
				for (int c = 0; c < nCols; c++) {
					DenseMatrix64F dm = ((EJMLDoubleMatrix) components[r][c]).myMatrix;
					SpecializedOps.insert(dm, startRow, startCol, result);
					startCol += dm.numCols;
				}
				startRow += components[r][0].numberOfRows();
			}
			return new EJMLDoubleMatrix(result);
		}
		
		if (myType == FactoryType.colt) {
			int nRows = components.length;
			int nCols = components[0].length;
			DoubleMatrix2D[][] coltComponents = new DoubleMatrix2D[nRows][nCols];
			for (int r = 0; r < nRows; r++) {
				for (int c = 0; c < nCols; c++) {
					coltComponents[r][c] = ((ColtDoubleMatrix) components[r][c]).myMatrix;
				}
			}
			return new ColtDoubleMatrix(DoubleFactory2D.dense.compose(coltComponents));
		}
		
		if (myType == FactoryType.jblas) return null;
		return null;
	}
}

@@ -285,16 +285,22 @@
 as, colt
+, blas
 %7D;%0D%0A%09pri
@@ -990,32 +990,439 @@
 le%5B%5D values) %7B%0D%0A
+%09%09return this.make(row, col, values, false);%0D%0A%09%7D%0D%0A%0D%0A%09public DoubleMatrix make(int row, int col, double%5B%5D values, boolean columnMajor) %7B%0D%0A%09%09if (columnMajor) %7B%0D%0A%09%09%09if (myType == FactoryType.ejml)%7B%0D%0A%09%09%09%09DoubleMatrix temp = new EJMLDoubleMatrix(col, row, values);%0D%0A%09%09%09%09return temp.transpose();%0D%0A%09%09%09%7D else if (myType == FactoryType.colt) %7B%0D%0A%09%09%09%09return new ColtDoubleMatrix(row, col, values);%0D%0A%09%09%09%7D%0D%0A%09%09%7D else %7B%0D%0A%09
 %09%09if (myType == 
@@ -1481,32 +1481,33 @@
 ol, values);%0D%0A%09%09
+%09
 if (myType == Fa
@@ -1514,38 +1514,59 @@
 ctoryType.colt) 
-return
+%7B%0D%0A%09%09%09%09DoubleMatrix temp = 
  new ColtDoubleM
@@ -1567,32 +1567,32 @@
 oubleMatrix(
-row, col
+col, row
 , values);%0D%0A
@@ -1583,32 +1583,73 @@
  row, values);%0D%0A
+%09%09%09%09return temp.transpose();%0D%0A%09%09%09%7D%0D%0A%09%09%7D%0D%0A
 %09%09if (myType == 

add code for creating a matrix from a single dimension array allowing for column major or row major storage