Improved input validation in sparse's __mul__.

The input validation in the sparse matrix __mul__ method is not very very robust, and there are cases in which NotImplemented should be returned, instead of raising an exception. For example, operators in the package PyOperators do have a shape attribute, but not an ndim one: the multiplication a * b where a is a sparse matrix and b a PyOperator will fail, since b's __rmul__ cannot be called.
While I was at it, I simplified it, since it was quite difficult to read. Sparse tests pass.