8000 BUG: arange behaves poorly on complex numbers · Issue #10332 · numpy/numpy · GitHub
[go: up one dir, main page]

Skip to content

BUG: arange behaves poorly on complex numbers #10332

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Si 8000 gn up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
eric-wieser opened this issue Jan 5, 2018 · 10 comments
Open

BUG: arange behaves poorly on complex numbers #10332

eric-wieser opened this issue Jan 5, 2018 · 10 comments

Comments

@eric-wieser
Copy link
Member
eric-wieser commented Jan 5, 2018
>>> np.arange(0, 10, 2)
array([0, 2, 4, 6, 8])

# as above, cast to complex
>>> np.arange(0 + 0j, 10 + 0j, 2 + 0j)
array([], dtype=complex128)  #what?

# bizarre input needed to give expected output
>>> np.arange(0 + 0j, 10 + 10j, 2 + 0j)
# array([ 0.+0.j,  2.+0.j,  4.+0.j,  6.+0.j,  8.+0.j])

For some reason, it deliberately computes len as (c14792d)

c_len = (start - stop) / step
len = min(ceil(c_len.real), ceil(c_len.imag))

which for real-only values, gives 0.

I think a better approach would be to use one of

  1. ceil(abs(c_len)) - has semantics "use the circle centered at start and passing through end" as the end point

  2. ceil(c_len.real) - has semantics "use the projection of end onto the line start + k*step as the endpoint"

  3. above with assert c_len.imag == 0 - requires that end lies on that line, but prone to rounding error

  4. Project step onto the line between start and end, and use that instead

I like the look of 2 and 4

@eric-wieser
Copy link
Member Author
eric-wieser commented Jan 5, 2018

These proposals, for arange(0, 4 - 4j, 2) give:

  1. [0, 2, 4] (adjust end = 4*sqrt(2))
  2. [0, 2] (adjust end = 4)
  3. ValueError
  4. [0, 1-1j, 2-2j, 3-3j] (adjust step = 1-1j)

@seberg
Copy link
Member
seberg commented Jan 5, 2018

I somewhat like the look of a general error ;). I am serious though, if you have multiple good options, its likely hopelss to define something here. It does not seem useful to me (in the sense of transparent for a reader), except for linspaceable usages which are cleaner written in linspace of multiplication of an integer arange.
Heck, it even gets wonkier, numpy compares complex numbers using real first and imag second, which could define another even weirder method.

@eric-wieser
Copy link
Member Author
eric-wieser commented Jan 5, 2018

In the case when option 3 does not error, all of the other options are equivalent to it (and this is sufficient to be consistent with real numbers).

So arguably 3 is worth doing.

@eric-wieser
Copy link
Member Author
eric-wieser commented Jan 5, 2018

Althought without a step argument, I can think of no clear meaning for the following (shown with current results):

>>> np.arange(0, 4 + 4j)
array([ 0.+0.j,  1.+0.j,  2.+0.j,  3.+0.j])
>>> np.arange(0, 4 + 0j)
array([])

I suppose that since the current behaviour makes no sense at all, we should switch it to an error now, and consider allowing it in future.

@mhvk
Copy link
Contributor
mhvk commented Jan 6, 2018

Erroring on c_len.imag != 0 seems most reasonable. For anything else, one should really just construct oneself.

@eric-wieser

This comment has been minimized.

@eric-wieser
Copy link
Member Author
eric-wieser commented Jan 6, 2018

Shedding some light on the original code - I think it was intended to mean len = ceil(min(delta.real / step.real, delta.imag / step.imag)), which is not rotationally unbiased, but works correctly in all the cases that have an obvious definition.

Of course, (a + bi) / (c + di) != (a / c) + (b / d) i, so that's not actually what was implemented!

@mhvk

This comment has been minimized.

@seberg
Copy link
Member
seberg commented Jan 7, 2018

The c_len.imag == 0 solution seems good. I still think that for anything except for pretty much exact integers that might be a bit random (tiny error or scaling might cause exact 0 to be missed?), so in that sense I am not quite sure that simply forcing linspace isn't just as good.

OTOH, for purely imaginary or real numbers it sounds most reasonable.

@bjnath
Copy link
Contributor
bjnath commented Jun 12, 2020

Until the behavior is fixed, we should change the documentation to exclude complex args for start, stop, and step . The way it reads now, any number should work:

start : number, optional
...
stop : number
...
step : number, optional

I'll mention this issue in the PR so it will show up here; that will remind us when the code is fixed that the restrictions in the doc can be removed.

bjnath added a commit to bjnath/numpy-1 that referenced this issue Jun 12, 2020
As noted in issue numpy#10332, arange with complex start, stop, or step returns
an empty array.

Until the code is changed, specify that these args can only
be integer or real.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants
0