Improved input validation in sparse's __mul__.

The input validation in the sparse matrix `__mul__` method is not 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.