## WIP: Generalized matrix product and a fix in endomorphic MatrixProductOperator

I added a linear matrix multiplication operator that generalizes the endomorphic MatrixProductOperator. The output matches that of the endomorphic operator in case of an endomorphic application.

The target domain/domain tuple of the valid shape should be specified by the user, but I kept a standard RGSpace of the valid shape as the default.

Below is an example of an application.

dtuple = DomainTuple.make(((RGSpace(10),RGSpace(20),RGSpace(30),RGSpace(40)))

spaces = (1,3) (apply only to 2nd and 4th spaces of domain)

matrix = np.ones(shape=(5,15,25,20,40))

matop = GeneralMatrixProduct(dtuple,matrix,spaces,target=None)

According to the operator's convention,

target_shape = (10,5,30,15,25)

(since dtuple.shape = (10,20,30,40), the 20,40 axes are summed over, and to comply with the endomorphic MatrixProductOperator the 10,30 axes retain their positions and remaining axes of the matrix are filled in order)

matop.target = DomainTuple.make(RGSpace(shape = target_shape, distances = default, harmonic = False))

(unless a domain or DomainTuple with shape = target_shape is passed as the target)

returns Field.from_raw(matop.target, np,tensordot of matrix and field summed over appropriate axes)

I tested the operator's working on the example above, and that it coincides with the endomorphic MatrixProductOperator when the latter is applicable. Would this be a useful operator, and what else in it can be tested or changed?

The second change is in the endomorphic MatrixProductOperator, I fixed its functionality for application to a >1 dimensional domain (say an RGSpace(shape=(5,15,25))). The previous version uses np.dot instead of np.tensordot, so due to default axis convention in np.dot it doesn't work when more than one axes are to be summed over. I don't think this was intentional because the operator doesn't throw an error until it is applied to a field over such a domain.

There is one last change in the docstring of the matrix product operator. It has a line saying `If DomainTuple it is assumed to have only one entry`

, which I think is misleading because I can apply it to a domain tuple with many subspaces like the example above. I changed the line to `If Domain it is assumed to have only one subspace`

, which is what I observed.

@gedenhof , can you have a look at this?