Add complex literals?

Exactly same as in the Annex G. Special rules for imaginary type will apply for complex(0.0, <signed float>) instances. I did a draft patch in GitHub - skirpichev/cpython at complex-annex-g (only complex_neg/add/sub/mul were changed, no documentation changes, no comments, no optimizations).

With above - the eval(repr) round-trip problem will be fixed, as well as mentioned in Invalid "equivalents" of the complex type constructor in docs · Issue #109218 · python/cpython · GitHub identities (e.g. z==z.real+z.imag*1j). No changes in string parsing, only minor changes in the repr output (signed zero used for real component, if needed).

I believe, now this proposal is more precise to be discussed (and, probably, rejected:)). I would appreciate also @storchaka opinion, as this is a some minor modification of the “imaginary type” solution.

Oops. They aren’t exactly equivalent already. Above holds only for non-complex arguments:

>>> complex(a:=-0.0,b:=0j)+complex(c:=-0.0, d:=-0j)
0j
>>> complex(a + c, b + d)
(-0+0j)

And yes, the price will be, as I hope - mentioned special rules for complex(a, b) <op> complex(0.0, c), that will actually affect only corner cases (signed zeros, infinities, nans) in components, e.g. complex(-0.0, 1) + complex(0, 1) == complex(-0.0, 2).

Sorry, this is still not clear. I know what Annex G says, but I think you’re trying to apply the Annex G rules in the situation where an imaginary type exists to Python, where no imaginary type exists. Again, please spell out the exact rules (here, not in a PR) you’re proposing for complex + complex addition.

Yep, I’m not interested in the bizarre case where we’re passing complex arguments to the two-argument complex constructor. That case is so obscure as to be irrelevant. Let me rephrase:

I’d find it rather surprising if complex(a, b) + complex(c, d) weren’t exactly equivalent to complex(a + c, b + d) for Python floats a, b, c and d.

Again, it’s still not clear exactly what rules you’re proposing, but I suspect that whatever you’re proposing will break the above.

Ok, sorry. I’ll try to write out here all cases for addition.

I’m suggesting to represent the set of complexes, C, as a disjoint union of the set I = {complex(0, x)}, “imaginary numbers”, and it’s complement C\I = {complex(a, b) | a!=0}, “the rest” (a can be here -0.0!). When both operands are from “the rest” - usual addition rules work. For “imaginary numbers” we have:

(1)  complex(0, x) + complex(0, y) = complex(0, x + y)

Now mixed cases:

(2) real + complex(0, x) = complex(real, x)
(3) real + complex(a, b) = complex(real + a, b) (where a!=0)
(4) complex(0, x) + complex(a, b) = complex(a, x + b) (where a!=0)

(plus same rules for changed order of operands on lhs). I hope now it’s clear enough for addition and it also clear how to deduce similar rules for subtraction and multiplication from the annex G.

Sure, I have example (complex(-0.0, 1) + complex(0, 1) = complex(-0.0, 2)) above. More generally: complex(-0.0, x) + complex(0, y) = complex(-0.0, x+y) (rule 4) seems to be only exception from rules of usual complex arithmetics (wrt to addition). On a pro: this proposal should fix some other identities, that we have in docs (e.g. variants of complex(real, imag)==real+imag*1j).