class OGMatrixAlgebra extends MatrixAlgebra {

  @Override
  public Matrix<?> multiply(final Matrix<?> m1, final Matrix<?> m2) {
    Validate.notNull(m1, "m1");
    Validate.notNull(m2, "m2");
    if (m1 instanceof IdentityMatrix) {
      if (m2 instanceof IdentityMatrix) {
        return multiply((IdentityMatrix) m1, (IdentityMatrix) m2);
      } else if (m2 instanceof DoubleMatrix1D) {
        return multiply((IdentityMatrix) m1, (DoubleMatrix1D) m2);
      } else if (m2 instanceof DoubleMatrix2D) {
        return multiply((IdentityMatrix) m1, (DoubleMatrix2D) m2);
      }
      throw new IllegalArgumentException("can only handle IdentityMatrix by DoubleMatrix2D or DoubleMatrix1D, have " +
          m1.getClass() + " and " + m2.getClass());
    }
    if (m2 instanceof IdentityMatrix) {
      if (m1 instanceof DoubleMatrix1D) {
        return multiply((DoubleMatrix1D) m1, (IdentityMatrix) m2);
      } else if (m1 instanceof DoubleMatrix2D) {
        return multiply((DoubleMatrix2D) m1, (IdentityMatrix) m2);
      }
      throw new IllegalArgumentException("can only handle  DoubleMatrix2D or DoubleMatrix1D by IdentityMatrix, have " +
          m1.getClass() + " and " + m2.getClass());
    }
    if (m1 instanceof TridiagonalMatrix && m2 instanceof DoubleMatrix1D) {
      return multiply((TridiagonalMatrix) m1, (DoubleMatrix1D) m2);
    } else if (m1 instanceof DoubleMatrix1D && m2 instanceof TridiagonalMatrix) {
      return multiply((DoubleMatrix1D) m1, (TridiagonalMatrix) m2);
    } else if (m1 instanceof DoubleMatrix2D && m2 instanceof DoubleMatrix2D) {
      return multiply((DoubleMatrix2D) m1, (DoubleMatrix2D) m2);
    } else if (m1 instanceof DoubleMatrix2D && m2 instanceof DoubleMatrix1D) {
      return multiply((DoubleMatrix2D) m1, (DoubleMatrix1D) m2);
    } else if (m1 instanceof DoubleMatrix1D && m2 instanceof DoubleMatrix2D) {
      return multiply((DoubleMatrix1D) m1, (DoubleMatrix2D) m2);
    }
    throw new IllegalArgumentException(
        "Can only multiply two DoubleMatrix2D; a DoubleMatrix2D and a DoubleMatrix1D; or a DoubleMatrix1D and a DoubleMatrix2D. have " +
            m1.getClass() + " and " + m2.getClass());
  }

}