classification
Title: Simplify parsing of complex numbers and make complex('inf') valid.
Type: behavior Stage: patch review
Components: Interpreter Core Versions: Python 2.7
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: mark.dickinson Nosy List: eric.smith, mark.dickinson
Priority: normal Keywords: patch

Created on 2009-04-22 20:27 by mark.dickinson, last changed 2009-04-24 13:28 by mark.dickinson. This issue is now closed.

Files
File name Uploaded Description Edit
simplify_complex_parsing.patch mark.dickinson, 2009-04-22 20:27
simplify_complex_parsing_v2.patch mark.dickinson, 2009-04-23 08:35
Messages (7)
msg86328 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2009-04-22 20:27
Here's a patch that:

 1. greatly simplifies the complex parsing code in Objects/complexobject.c
 2. allows nans and infinities in constructing a complex number from
    a string
 3. fixes missing out-of-memory checks (PyOS_ascii_strtod can fail due to
    lack of memory).

Note that part 2. comes entirely for free with the parsing simplification.

But it seems to me that if float('inf') is valid, then complex('inf') 
should be valid too.  There are potential uses for being able to create a 
complex infinity when working with the complex projective plane (a natural 
domain for rational functions over the complex numbers).
msg86354 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2009-04-23 08:35
Updated patch:

4. also simplify complex printing:  no special handling for nans or
   infinities.  This means that e.g. complex(1, inf) prints as

   "1 + infj" instead of "1+inf*j".

   This might look ugly, but I think it's better than what was there
   before.  Complex reprs are now more uniform and easier to parse
   by external code.  And the expression "1 + inf*j" doesn't give
   the right thing anyway, even if you replace j by 1j and inf by
   float(inf):

>>> inf = float('inf')
>>> 1 + inf*j
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'j' is not defined
>>> 1 + inf*1j  # expect (1+infj), but get nan in real part:
(nan+infj)

   Furthermore, with these simplifications to printing and
   parsing, roundtripping now works:  the output of repr(z)
   is valid input to      

5. Print real part if it's negative zero: z =complex(-0.0, 0.0)
   now prints as -0 + 0j instead of just 0j, so again roundtripping
   works: complex(repr(z)) recovers z exactly.

6. Change PyOS_ascii_strtod to always output a sign when requested,
   even for nans.  As far as I can tell, the complex formatting is
   the only place that's affected by this.  Eric?
msg86359 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2009-04-23 10:02
Wow, that does greatly simplify printing. One nit: the variable named 
'im' isn't needed any more, you could just use 'pim'. Not sure if the 
asymmetry with 're' and 'pre' is worthwhile, though.

Mark Dickinson wrote:
> 6. Change PyOS_ascii_strtod to always output a sign when requested,
>    even for nans.  As far as I can tell, the complex formatting is
>    the only place that's affected by this.  Eric?

That's correct. It might make a difference when fixing issue 4482, 
though, at least for the %-formatting case. So if you're going to check 
this in, sooner is better than later for me.

Also, could this be backported to 2.7, so that 4482 can be fixed the 
same way in both versions?
msg86360 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2009-04-23 10:21
The fallback code, around line 633 in the patched version of pystrtod.c,
probably also needs to be modified. It's this code that would need
backporting to 2.7.
msg86374 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2009-04-23 19:22
Committed to py3k, r71818, with the changes Eric suggested.  I ran build 
and tests both with and without the -DPY_NO_SHORT_FLOAT_REPR compiler 
option.

Will backport.
msg86404 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2009-04-24 12:50
Backported to trunk in r71824.

Leaving open, as I now need forward port some bits of r71824 which
weren't in the r71818 checkin.

Note that with this change, some strings which were previously accepted 
by the complex constructor are no longer accepted.  Examples are:

'1..1j'
'1.11.1j'
'1e1.1j'

I consider this to be a bugfix:  I can't imagine that acceptance of 
those strings was intentional.  However, strings like:

'j'
'-j'
'4-j'

continue to be accepted.
msg86407 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2009-04-24 13:28
Extra bits forward ported in r71829.  Python 3.1 and 2.7 now both accept 
the same strings for the complex constructor.
History
Date User Action Args
2009-04-24 13:28:37mark.dickinsonsetstatus: open -> closed
resolution: fixed
messages: + msg86407
2009-04-24 12:50:34mark.dickinsonsetmessages: + msg86404
2009-04-23 19:22:11mark.dickinsonsetmessages: + msg86374
versions: + Python 2.7, - Python 3.1
2009-04-23 10:21:27eric.smithsetmessages: + msg86360
2009-04-23 10:02:24eric.smithsetmessages: + msg86359
title: Simplify parsing of complex numbers and make complex('inf') valid. -> Simplify parsing of complex numbers and make complex('inf') valid.
2009-04-23 08:35:53mark.dickinsonsetfiles: + simplify_complex_parsing_v2.patch
nosy: + eric.smith
messages: + msg86354

2009-04-22 20:29:25mark.dickinsonsetversions: + Python 3.1
priority: normal
assignee: mark.dickinson
components: + Interpreter Core
type: behavior
stage: patch review
2009-04-22 20:27:18mark.dickinsoncreate