'Matrix-matrix multiplication.
Performs the operation y=A*X where A is an MxN linear
operator and X dense N*K matrix or ndarray.
Parameters
X : {matrix, ndarray}
An array with shape (N,K).
Returns
Y : {matrix, ndarray}
A matrix or ndarray with shape (M,K) depending on
the type of the X argument.
Notes
This matmat wraps any user-specified matmat routine or overridden
_matmat method to ensure that y has the correct type.'

def matmat(self, X):

    X = np.asanyarray(X)
    if (X.ndim != 2):
        raise ValueError(('expected    2-d    ndarray    or    matrix,    not    %d-d' % X.ndim))
    (M, N) = self.shape
    if (X.shape[0] != N):
        raise ValueError(('dimension    mismatch:    %r,    %r' % (self.shape, X.shape)))
    Y = self._matmat(X)
    if isinstance(Y, np.matrix):
        Y = np.asmatrix(Y)
    return Y
