Clean up redundant complex type unions#7041
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #7041 +/- ##
==========================================
- Coverage 98.17% 98.17% -0.01%
==========================================
Files 1085 1085
Lines 94672 94683 +11
==========================================
+ Hits 92942 92952 +10
- Misses 1730 1731 +1 ☔ View full report in Codecov by Sentry. |
|
|
||
| def all_near_zero_mod( | ||
| a: Union[float, complex, Iterable[float], np.ndarray], period: float, *, atol: float = 1e-8 | ||
| a: Union[complex, Iterable[float], np.ndarray], period: float, *, atol: float = 1e-8 |
There was a problem hiding this comment.
| a: Union[complex, Iterable[float], np.ndarray], period: float, *, atol: float = 1e-8 | |
| a: Union[complex, Iterable[complex], np.ndarray], period: float, *, atol: float = 1e-8 |
There was a problem hiding this comment.
I actually went the opposite direction. The function fails on complex numbers (there's a mod operation in it), so I'm not sure why complex was an option at all.
| def __mul__( | ||
| self, other: Union[complex, int, float, numbers.Number] | ||
| ) -> 'cirq.PauliString[TKey]': | ||
| def __mul__(self, other: Union[complex, numbers.Number]) -> 'cirq.PauliString[TKey]': |
There was a problem hiding this comment.
I am getting True for issubclass(complex, numbers.Number) -
| def __mul__(self, other: Union[complex, numbers.Number]) -> 'cirq.PauliString[TKey]': | |
| def __mul__(self, other: numbers.Number) -> 'cirq.PauliString[TKey]': |
There was a problem hiding this comment.
Here also I went the opposite direction. numbers types are supposed to be for instanceof, but don't work well with mypy. SupportsComplex is the proper way to do it with mypy, but SupportsComplex comes with overhead. It only means it has __complex__ on it, which means you've got to call complex(other) before you can safely use it; code and time overhead. The only thing it improves is that mypy won't complain when using np.int64 or other tangential types, though they still work at run time regardless. So, just leaving this as complex, to be consistent with all our other complex parameter types.
We should keep in mind here that attribute access is much faster than np.real - In [3]: %timeit c.real
39.5 ns ± 1.52 ns per loop (mean ± std. dev. of 7 runs, 10,000,000 loops each)
In [4]: %timeit np.real(c)
231 ns ± 16.2 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each) |
* Clean up redundant complex type unions * format * fix numpy ufunc, one mypy err * Additional cleanup
Fixes #2375.
In type signatures,
Union[complex, float, int]and such can be simplified tocomplex, and this PR does so. Mypy does not work well withnumbers.Complexin type signatures, so this PR does not use it there.In
isinstancechecks,(complex, numbers.Complex)is always redundant, and this PR replaces it with justisinstance(numbers.Complex).isinstance(numbers.Complex)also returns true forfloatandintvalues, whereasisinstance(complex)returns false. Sometimes in the codeisinstance(complex)was just used to differentiate number from symbolic or None. I changed those toisinstance(number.Complex)for broader applicability. Sometimes,isinstance(complex)was intentionally added to excludefloat; for instancefloatdoes not have.imagor.real, and for those I left as-is. A follow-up item could be to replaceval.realetc. withnp.real(val)in those cases, which would allow standardizing onisinstance(numbers.Complex)everywhere.The specific bug in #2375 is fixed with an addition to
PauliString.__array_ufunc__.