printing: simplify code where two paths do exactly the same thing

AFAICT, StrPrinter separates into two cases here but both of them
do the same thing.  Simplify the code.
CodePrinter has very similar code so fix same thing there too.
Merge pull request #8027 from cbm755/print_mul_fix

printing: simplify code where two paths do exactly the same thing
Refactor processing of inequalities with oo [1/9]

fixes #7775
Refactor processing of inequalities with oo [2/9]

If we don't know the boundedness: _eval_is_positive/negative should
return None.

fixes #7798
fixes #7841
Refactor processing of inequalities with oo [3/9]

fix tests in test_sets.py
Refactor processing of inequalities with oo [4/9]

fix wester's tests
Refactor processing of inequalities with oo [5/9]

fix tests for inequalities.py
Refactor processing of inequalities with oo [6/9]

More tests fixed
Refactor processing of inequalities with oo [7/9]

Add import for oo
Refactor processing of inequalities with oo [8/9]

Fix physics/quantum tests due to simple bug
in Expr._eval_interval (check for NegativeInfinity singleton)

(Thanks to Aaron Meurer for idea)
Refactor processing of inequalities with oo [9/9]

Fix doctests in delta.py
Merge pull request #7861 from skirpichev/oo-ineq

Refactor processing of inequalities with oo
minor docstring edit [skip ci]
bounded and unbounded are not antonyms

If we assume finite == !unbounded in assumptions, we
create an alias: finite=False is the same as unbounded=True
and vice versa. We don't want to do that. What we want is
behavior like integer and noninteger:

Dummy(integer=0) is not the same thing as Dummy(noninteger=1).
A noninteger is commutative, complex, hermitian, noninteger,
nonzero, and real while integer=0 is only commutative -- nothing
else is known about it (other than that it is not 0).

/!\ In general, it is much easier to comprehend what one means
by using only true attributes to desccribe it. If something is
not zero but still complex, say nonzero=True instead of zero=False.

So assumptions.py has been modified to make the following true:

```
finite   : 0 < abs(x) < oo
bounded  : 0 <= abs(x) < oo
unbounded : abs(x) == oo
```

The same is also true for zero and nonzero. If nonzero is True you
are talking about a complex number that is not zero. But if zero is
False you are only talking about a commutative object that is not
zero.

In addition, we not use is_unbounded = True not is_bounded = False
in the few places where this is defined. The former is an affirmation
of what the object *is* not an indication of what it is not.
Mul._eval_is_rational watches for real

Also, simplify Mul._eval_is_negative by having it simply
call to _eval_is_positive with a negated argument. This
reduces the amount of code to have to look at when working
on the assumptions.