class MatrixAlgebra {

  public Matrix<?> kroneckerProduct(final Matrix<?> m1, final Matrix<?> m2) {
    Validate.notNull(m1, "m1");
    Validate.notNull(m2, "m2");
    if (m1 instanceof DoubleMatrix2D && m2 instanceof DoubleMatrix2D) {
      final double[][] a = ((DoubleMatrix2D) m1).getData();
      final double[][] b = ((DoubleMatrix2D) m2).getData();
      final int aRows = a.length;
      final int aCols = a[0].length;
      final int bRows = b.length;
      final int bCols = b[0].length;
      final int rRows = aRows * bRows;
      final int rCols = aCols * bCols;
      final double[][] res = new double[rRows][rCols];
      for (int i = 0; i < aRows; i++) {
        for (int j = 0; j < aCols; j++) {
          final double t = a[i][j];
          if (t != 0.0) {
            for (int k = 0; k < bRows; k++) {
              for (int l = 0; l < bCols; l++) {
                res[i * bRows + k][j * bCols + l] = t * b[k][l];
              }
            }
          }
        }
      }
      return new DoubleMatrix2D(res);
    }
    throw new IllegalArgumentException("Can only calculate the Kronecker product of two DoubleMatrix2D.");
  }

}