| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
…mbers
Before, handling of numbers with special values in components
(infinities, nans, signed zero) was invalid. Simple example:
>>> z = complex(1, -0.0)
>>> z*z
(1-0j)
>>> z**2
(1+0j)
Now:
>>> z**2
(1-0j)
|
@picnixz, I would appreciate your review on this pr. Or your opinion in the issue thread. |
Sorry, something went wrong.
|
I'll do it tomorrow! (Monday, Paris time) |
Sorry, something went wrong.
|
I need to think a bit more on the issue. I'll try to have something by the end of the day or tomorrow. Ideally, I would like to have no inconsistency between the generic algorithm and the non-generic one (namely, the result should be as if we were using the generic algorithm). |
Sorry, something went wrong.
I'm not sure if it's possible without too much code, that affects performance severely. BTW, I think that numpy code has no such special version for integer exponents. I'll double check. Edit: Ah, no. numpy mimics CPython here, at least in npy_math_complex.c.src. Edit2: JFR, some simple benchmarks. With specialized code (main): $ python -m pyperf timeit -q -s 'z=1+1j;e=20' 'pow(z,e)' Mean +- std dev: 237 ns +- 5 ns $ python -m pyperf timeit -q -s 'z=1+1j;e=90' 'pow(z,e)' Mean +- std dev: 259 ns +- 4 ns $ python -m pyperf timeit -q -s 'z=1+1j;e=110' 'pow(z,e)' Mean +- std dev: 579 ns +- 5 ns $ python -m pyperf timeit -q -s 'z=1+1j;e=200' 'pow(z,e)' Mean +- std dev: 571 ns +- 3 ns Without: $ python -m pyperf timeit -q -s 'z=1+1j;e=2' 'pow(z,e)' Mean +- std dev: 562 ns +- 3 ns $ python -m pyperf timeit -q -s 'z=1+1j;e=20' 'pow(z,e)' Mean +- std dev: 576 ns +- 2 ns $ python -m pyperf timeit -q -s 'z=1+1j;e=90' 'pow(z,e)' Mean +- std dev: 576 ns +- 3 ns $ python -m pyperf timeit -q -s 'z=1+1j;e=110' 'pow(z,e)' Mean +- std dev: 578 ns +- 4 ns $ python -m pyperf timeit -q -s 'z=1+1j;e=200' 'pow(z,e)' Mean +- std dev: 573 ns +- 3 ns |
Sorry, something went wrong.
Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
|
This PR is stale because it has been open for 30 days with no activity. |
Sorry, something went wrong.
|
@picnixz, this is ready for review again. See #117999 (comment) - we still can't avoid differences wrt generic algorithm for all values. But probably it's fine. |
Sorry, something went wrong.
|
I run on this following script, comparing pow() output wrt GNU MPC. This PR (and #124243 as well) introduce additional differences (32 broken test): --- 1 2026-08-20 03:33:59.886826488 +0300
+++ 2 2026-08-20 03:58:01.747376340 +0300
@@ -6,6 +6,8 @@
(-inf-infj) (-0.5+nanj) 0j (nan+nanj)
(-inf-infj) (-0-0j) (1-0j) (1+0j)
(-inf-infj) -0j (1-0j) (1+0j)
+(-inf-infj) (0.5-0j) (inf+nanj) (inf-infj)
+(-inf-infj) (0.5+0j) (inf+nanj) (inf-infj)
(-inf-infj) (0.5+nanj) (inf+nanj) (nan+nanj)
(-inf-infj) (inf+0.5j) (inf+nanj) (nan+nanj)
(-inf-infj) (inf+infj) (inf+nanj) (nan+nanj)
@@ -16,6 +18,8 @@
(-inf-0.5j) (-0.5+nanj) 0j (nan+nanj)
(-inf-0.5j) (-0-0j) (1-0j) (1+0j)
(-inf-0.5j) -0j (1-0j) (1+0j)
+(-inf-0.5j) (0.5-0j) (inf+nanj) (inf-infj)
+(-inf-0.5j) (0.5+0j) (inf+nanj) (inf-infj)
(-inf-0.5j) (0.5+nanj) (inf+nanj) (nan+nanj)
(-inf-0.5j) (inf+0.5j) (inf+nanj) (nan+nanj)
(-inf-0.5j) (inf+infj) (inf+nanj) (nan+nanj)
@@ -26,6 +30,8 @@
(-inf-0j) (-0.5+nanj) 0j (nan+nanj)
(-inf-0j) (-0-0j) (1-0j) (1+0j)
(-inf-0j) -0j (1-0j) (1+0j)
+(-inf-0j) (0.5-0j) (inf+nanj) (inf-infj)
+(-inf-0j) (0.5+0j) (inf+nanj) (inf-infj)
(-inf-0j) (0.5+nanj) (inf+nanj) (nan+nanj)
(-inf-0j) (inf+0.5j) (inf+nanj) (nan+nanj)
(-inf-0j) (inf+infj) (inf+nanj) (nan+nanj)
@@ -38,6 +44,8 @@
(-inf+0j) (-0.5+nanj) 0j (nan+nanj)
(-inf+0j) (-0-0j) (1-0j) (1+0j)
(-inf+0j) -0j (1-0j) (1+0j)
+(-inf+0j) (0.5-0j) (inf+nanj) (inf+infj)
+(-inf+0j) (0.5+0j) (inf+nanj) (inf+infj)
(-inf+0j) (0.5+nanj) (inf+nanj) (nan+nanj)
(-inf+0j) (inf-infj) (inf+nanj) (nan+nanj)
(-inf+0j) (inf-0.5j) (inf+nanj) (nan+nanj)
@@ -50,6 +58,8 @@
(-inf+0.5j) (-0.5+nanj) 0j (nan+nanj)
(-inf+0.5j) (-0-0j) (1-0j) (1+0j)
(-inf+0.5j) -0j (1-0j) (1+0j)
+(-inf+0.5j) (0.5-0j) (inf+nanj) (inf+infj)
+(-inf+0.5j) (0.5+0j) (inf+nanj) (inf+infj)
(-inf+0.5j) (0.5+nanj) (inf+nanj) (nan+nanj)
(-inf+0.5j) (inf-infj) (inf+nanj) (nan+nanj)
(-inf+0.5j) (inf-0.5j) (inf+nanj) (nan+nanj)
@@ -62,6 +72,8 @@
(-inf+infj) (-0.5+nanj) 0j (nan+nanj)
(-inf+infj) (-0-0j) (1-0j) (1+0j)
(-inf+infj) -0j (1-0j) (1+0j)
+(-inf+infj) (0.5-0j) (inf+nanj) (inf+infj)
+(-inf+infj) (0.5+0j) (inf+nanj) (inf+infj)
(-inf+infj) (0.5+nanj) (inf+nanj) (nan+nanj)
(-inf+infj) (inf-infj) (inf+nanj) (nan+nanj)
(-inf+infj) (inf-0.5j) (inf+nanj) (nan+nanj)
@@ -98,6 +110,8 @@
(-0.5-infj) (-0.5+nanj) 0j (nan+nanj)
(-0.5-infj) (-0-0j) (1-0j) (1+0j)
(-0.5-infj) -0j (1-0j) (1+0j)
+(-0.5-infj) (0.5-0j) (inf+nanj) (inf-infj)
+(-0.5-infj) (0.5+0j) (inf+nanj) (inf-infj)
(-0.5-infj) (0.5+nanj) (inf+nanj) (nan+nanj)
(-0.5-infj) (inf+0.5j) (inf+nanj) (nan+nanj)
(-0.5-infj) (inf+infj) (inf+nanj) (nan+nanj)
@@ -142,6 +156,8 @@
(-0.5+infj) (-0.5+nanj) 0j (nan+nanj)
(-0.5+infj) (-0-0j) (1-0j) (1+0j)
(-0.5+infj) -0j (1-0j) (1+0j)
+(-0.5+infj) (0.5-0j) (inf+nanj) (inf+infj)
+(-0.5+infj) (0.5+0j) (inf+nanj) (inf+infj)
(-0.5+infj) (0.5+nanj) (inf+nanj) (nan+nanj)
(-0.5+infj) (inf-infj) (inf+nanj) (nan+nanj)
(-0.5+infj) (inf-0.5j) (inf+nanj) (nan+nanj)
@@ -154,6 +170,8 @@
(-0-infj) (-0.5+nanj) 0j (nan+nanj)
(-0-infj) (-0-0j) (1-0j) (1+0j)
(-0-infj) -0j (1-0j) (1+0j)
+(-0-infj) (0.5-0j) (inf+nanj) (inf-infj)
+(-0-infj) (0.5+0j) (inf+nanj) (inf-infj)
(-0-infj) (0.5+nanj) (inf+nanj) (nan+nanj)
(-0-infj) (inf+0.5j) (inf+nanj) (nan+nanj)
(-0-infj) (inf+infj) (inf+nanj) (nan+nanj)
@@ -186,6 +204,8 @@
(-0+infj) (-0.5+nanj) 0j (nan+nanj)
(-0+infj) (-0-0j) (1-0j) (1+0j)
(-0+infj) -0j (1-0j) (1+0j)
+(-0+infj) (0.5-0j) (inf+nanj) (inf+infj)
+(-0+infj) (0.5+0j) (inf+nanj) (inf+infj)
(-0+infj) (0.5+nanj) (inf+nanj) (nan+nanj)
(-0+infj) (inf-infj) (inf+nanj) (nan+nanj)
(-0+infj) (inf-0.5j) (inf+nanj) (nan+nanj)
@@ -198,6 +218,8 @@
-infj (-0.5+nanj) 0j (nan+nanj)
-infj (-0-0j) (1-0j) (1+0j)
-infj -0j (1-0j) (1+0j)
+-infj (0.5-0j) (inf+nanj) (inf-infj)
+-infj (0.5+0j) (inf+nanj) (inf-infj)
-infj (0.5+nanj) (inf+nanj) (nan+nanj)
-infj (inf+0.5j) (inf+nanj) (nan+nanj)
-infj (inf+infj) (inf+nanj) (nan+nanj)
@@ -230,6 +252,8 @@
infj (-0.5+nanj) 0j (nan+nanj)
infj (-0-0j) (1-0j) (1+0j)
infj -0j (1-0j) (1+0j)
+infj (0.5-0j) (inf+nanj) (inf+infj)
+infj (0.5+0j) (inf+nanj) (inf+infj)
infj (0.5+nanj) (inf+nanj) (nan+nanj)
infj (inf-infj) (inf+nanj) (nan+nanj)
infj (inf-0.5j) (inf+nanj) (nan+nanj)
@@ -242,6 +266,8 @@
(0.5-infj) (-0.5+nanj) 0j (nan+nanj)
(0.5-infj) (-0-0j) (1-0j) (1+0j)
(0.5-infj) -0j (1-0j) (1+0j)
+(0.5-infj) (0.5-0j) (inf+nanj) (inf-infj)
+(0.5-infj) (0.5+0j) (inf+nanj) (inf-infj)
(0.5-infj) (0.5+nanj) (inf+nanj) (nan+nanj)
(0.5-infj) (inf+0.5j) (inf+nanj) (nan+nanj)
(0.5-infj) (inf+infj) (inf+nanj) (nan+nanj)
@@ -304,6 +330,8 @@
(0.5+infj) (-0.5+nanj) 0j (nan+nanj)
(0.5+infj) (-0-0j) (1-0j) (1+0j)
(0.5+infj) -0j (1-0j) (1+0j)
+(0.5+infj) (0.5-0j) (inf+nanj) (inf+infj)
+(0.5+infj) (0.5+0j) (inf+nanj) (inf+infj)
(0.5+infj) (0.5+nanj) (inf+nanj) (nan+nanj)
(0.5+infj) (inf-infj) (inf+nanj) (nan+nanj)
(0.5+infj) (inf-0.5j) (inf+nanj) (nan+nanj)
@@ -316,6 +344,8 @@
(inf-infj) (-0.5+nanj) 0j (nan+nanj)
(inf-infj) (-0-0j) (1-0j) (1+0j)
(inf-infj) -0j (1-0j) (1+0j)
+(inf-infj) (0.5-0j) (inf+nanj) (inf-infj)
+(inf-infj) (0.5+0j) (inf+nanj) (inf-infj)
(inf-infj) (0.5+nanj) (inf+nanj) (nan+nanj)
(inf-infj) (inf+0.5j) (inf+nanj) (nan+nanj)
(inf-infj) (inf+infj) (inf+nanj) (nan+nanj)
@@ -404,6 +434,8 @@
(inf+infj) (-0.5+nanj) 0j (nan+nanj)
(inf+infj) (-0-0j) (1-0j) (1+0j)
(inf+infj) -0j (1-0j) (1+0j)
+(inf+infj) (0.5-0j) (inf+nanj) (inf+infj)
+(inf+infj) (0.5+0j) (inf+nanj) (inf+infj)
(inf+infj) (0.5+nanj) (inf+nanj) (nan+nanj)
(inf+infj) (inf-infj) (inf+nanj) (nan+nanj)
(inf+infj) (inf-0.5j) (inf+nanj) (nan+nanj)
@@ -497,4 +529,4 @@
(nan+nanj) (-0-0j) (1-0j) (1+0j)
(nan+nanj) (-0+0j) (1-0j) (1+0j)
====================================================
-Failures: 496 (21%)
+Failures: 528 (22%)I think it's fine, assuming that on above examples output must match cmath.sqrt(base). |
Sorry, something went wrong.
There was a problem hiding this comment.
This PR looks good to me, and I would approve it if I had the necessary access to do so.
Without this PR, (inf+0j)**(1+0j) raises an OverflowError, which I think is broken. It's bad to raise an error, since it can crash an entire Python program if the programmer is not expecting it to be possible. Note that for the real-valued case:
>>> math.inf**1 inf
Sorry, something went wrong.
| continue | ||
| for n in range(1, 9): | ||
| with self.subTest(exponent=-n): | ||
| self.assertComplexesAreIdentical(c**-n, 1/(c**n)) |
There was a problem hiding this comment.
This assertion is an implementation detail. In the future, for example, one might want to use the C math library's cpow for both positive and negative small integers, in which case the two expressions may not be identical.
If this test is seen as documenting an eternal, unbreakable contract with users, then I don't like it. On the other hand, the understanding might be that Python can change the implementation and then simply change the test as well. I'm perfectly fine with that. (I'm not sure of the development culture here.)
I guess the comment about identical also applies to c**2 == c*c and maybe even c**1 == c. In MPC, (inf+1j)**(1+0j) gives (inf+nanj)....
Sorry, something went wrong.
Perhaps, we should factor out this fix, as it looks less controversial. Problem noticed e.g. here: #60200 (comment) |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
Before, handling of numbers with special values in components (infinities, nans, signed zero) was invalid. Simple example:
>>> z = complex(1, -0.0) >>> z*z (1-0j) >>> z**2 (1+0j) >>> complex('inf')**-1 0jNow:
>>> z**2 (1-0j) >>> complex('inf')**-1 -0jAlso, positive powers of infinite complex not raise anymore OverflowError's:
>>> complex('inf')**1 (inf+0j) >>> complex('inf')**0.5 (inf+nanj)