Skip to content

BUG: fix linspace returning NaN for equal infinite endpoints (gh-26699)#31620

Merged
mattip merged 1 commit into
numpy:mainfrom
Ijtihed:fix-linspace-inf-gh26699
Jul 6, 2026
Merged

BUG: fix linspace returning NaN for equal infinite endpoints (gh-26699)#31620
mattip merged 1 commit into
numpy:mainfrom
Ijtihed:fix-linspace-inf-gh26699

Conversation

@Ijtihed

@Ijtihed Ijtihed commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

PR summary

Fixes gh-26699.

np.linspace(np.inf, np.inf, N) returned [nan nan ... nan inf] instead of [inf inf ... inf]. The root cause is delta = stop - start producing nan via inf - inf which propagates through all subsequent multiplications,only the last element was rescued by the y[-1] = stop assignment

Fix: replace any nan in delta with zero wherever start == stop. The nan == nan is False identity ensures NaN inputs are unaffected in this case

AI Disclosure

Used Claude to make sure I didn't miss anything

@MaanasArora MaanasArora left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! This solves the specific issue, but I'm wondering about the performance cost where this new code is not invoked. I'm not sure if the corner case is bad enough to need this (and a lerp ufunc would be much better as stated in the issue!)

Comment thread numpy/_core/function_base.py Outdated
y /= div
if _mult_inplace:
y *= delta
with np.errstate(invalid='ignore'):

@MaanasArora MaanasArora Jun 13, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the RuntimeWarning which happens here with start=stop=inf is real, so maybe this isn't needed (even if we fix the actual output), or we should make it more focused to the error. In any case, we don't want to ignore errors for all the lines below!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any(isnan) short-circuits on the first element so for the common finite-scalar path the overhead is negligible. I agree a lerp ufunc is the right long-term fix but this is the minimum correct approach at the py level for now

errstate now wraps only the np.subtract call and all downstream arithmetic is back to normal, whoops

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like an antipattern to me. I am not sure it is threadsafe. So far we only use with errstate in helper functions like isclose and printing, I am not sure we want to start using it in core functions. Can we do the more specific if np.isinf() instead?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like an antipattern to me. I am not sure it is threadsafe. So far we only use with errstate in helper functions like isclose and printing, I am not sure we want to start using it in core functions. Can we do the more specific if np.isinf() instead?

thank you! I changed it accordingly

@Ijtihed Ijtihed force-pushed the fix-linspace-inf-gh26699 branch 2 times, most recently from 1f3faaa to 877ea76 Compare June 13, 2026 15:47
Comment thread numpy/_core/function_base.py Outdated
@Ijtihed

Ijtihed commented Jun 15, 2026

Copy link
Copy Markdown
Contributor Author

I noticed that the existing test for linspace(inf, -inf) was nearly a no-op, that -inf to inf had no test coverage, and that NaN input behavior was undocumented. I fixed all 3 in latest push.

edit: also added complex infinity tests

@Ijtihed Ijtihed force-pushed the fix-linspace-inf-gh26699 branch from 877ea76 to bca1f4f Compare June 15, 2026 16:24
@Ijtihed

Ijtihed commented Jun 16, 2026

Copy link
Copy Markdown
Contributor Author

removed the extra errstate wrappers, linspace(inf, -inf, N) now warns from the multiply and add as it should. also dropped the isnan guard since where(start == stop, 0, delta) already returns delta unchanged when there's no NaN to fix because ig the check was redundant

@Ijtihed Ijtihed force-pushed the fix-linspace-inf-gh26699 branch from bca1f4f to 01169e2 Compare June 16, 2026 05:08
Comment thread numpy/_core/function_base.py Outdated
@Ijtihed Ijtihed force-pushed the fix-linspace-inf-gh26699 branch from 01169e2 to ec573e7 Compare June 16, 2026 11:47
@Ijtihed

Ijtihed commented Jun 27, 2026

Copy link
Copy Markdown
Contributor Author

@MaanasArora :)

@MaanasArora

MaanasArora commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Thanks, this seems to have the least performance overhead now, but I'll still defer to someone more familiar with this area to evaluate if this should go in (not very familiar with this code, sorry!)

@Ijtihed Ijtihed force-pushed the fix-linspace-inf-gh26699 branch from ec573e7 to 4d6c7be Compare July 6, 2026 04:25
@mattip mattip merged commit a2dea97 into numpy:main Jul 6, 2026
86 of 87 checks passed
@mattip

mattip commented Jul 6, 2026

Copy link
Copy Markdown
Member

Thanks @Ijtihed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

linspace(inf, inf, N) outputs NaN

4 participants