Skip to content

Change linspace to take a range argument.#1580

Merged
akern40 merged 8 commits into
rust-ndarray:masterfrom
Kwonunn:exclusive-linspace
Feb 5, 2026
Merged

Change linspace to take a range argument.#1580
akern40 merged 8 commits into
rust-ndarray:masterfrom
Kwonunn:exclusive-linspace

Conversation

@Kwonunn

@Kwonunn Kwonunn commented Jan 27, 2026

Copy link
Copy Markdown
Contributor

Add a linspace_exclusive function which creates a Linspace iterator which is exclusive at its upper bound. This is essentially the same as linspace(endpoint=False) in numpy.

Addresses #1169

Add a `linspace_exclusive` function which creates a `Linspace` iterator which is exclusive at its upper bound. This is essentially the same as `linspace(endpoint=False)` in numpy.
@Kwonunn

Kwonunn commented Jan 27, 2026

Copy link
Copy Markdown
Contributor Author

If this is a welcome addition I'll add some tests and an equivalent for logspace.

I thought about using std::ops::Range as the argument for a new linspace function, which would allow something like:

let a = linspace(0.0..10.0, 32); // exclusive
let b = linspace(0.0..=50.0, 32); // inclusive

I think this is nicer and more idiomatic, but I don't see a good way of adding it that doesn't also break backwards compatibility.

@nilgoyette

Copy link
Copy Markdown
Collaborator

I think this is nicer and more idiomatic

Interesting. I do find it nicer, but this is only my opinion. What's cool is that the same name could be reused instead of creating new names like linspace_exclusive. I'm gonna need @akern40 opinion on this matter.

@akern40

akern40 commented Jan 28, 2026

Copy link
Copy Markdown
Collaborator

Strongly agree, I love this approach, so my question is how we can make a smooth transition (or we'll just have to make a warning somehow?)

@Kwonunn

Kwonunn commented Jan 29, 2026

Copy link
Copy Markdown
Contributor Author

Since Rust doesn't do function overloading there really are only two options:

  1. Make a new function with a name like linspace_range, put a deprecation warning on the old one and tell people to migrate over.
  2. Change the function signature of linspace, which would be a backwards-incompatible change.

I don't know how opposed you are to these kinds of API changes, I'll leave it to you to decide.

@akern40

akern40 commented Jan 30, 2026

Copy link
Copy Markdown
Collaborator

I'm in favor of just doing a breaking change - I generally feel that we should take advantage of our 0.* status and move quickly towards 1.0, which is my real North Star for the library.

I might look into some sort of upgrade script, since this is a pretty simple fix. But it's probably not worth the time.

For now, can you please alter this PR to change linspace and its cousins to use the Range syntax?

@akern40 akern40 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for the work here! One quick note, and then a bigger idea / comment. Our formatting rules require running your formatter on +nightly; I'm guessing that's why many of the files have formatting changes.

Looking over the linspace and logspace implementations, it didn't occur to me that we'd have to handle ranges like .., ..b, and a... Panicking is certainly one way out of that, but I'd prefer not to add panic conditions to the library. That leaves us with two three choices, that I see:

  1. Go back to the linspace and linspace_inclusive designs
  2. Use a custom trait, FiniteRange<F>: RangeBounds<F>, implemented only for Range and RangeInclusive
  3. Switch to try_linspace instead of linspace, and return None if the range isn't finite.

Pro of option 2 is that the invariant is checked at compile time; con is that it will require users to import the trait. Pro of option 3 is that users don't have to import the trait, but con is that they need to check the values at runtime.

Personally I'd vote for Option 2, but I'm curious to hear if people feel differently.

@nilgoyette

Copy link
Copy Markdown
Collaborator

we'd have to handle ranges like .., ..b, and a..

Do we have to? I think that a..b and a..=b make sense in the context of linspace but I would prefer not enabling those other ranges.

@akern40

akern40 commented Feb 2, 2026

Copy link
Copy Markdown
Collaborator

Ah I meant "have to" as in "if we use the RangeBounds trait for a generic, we have to handle bad input like .. and a.."

@Kwonunn

Kwonunn commented Feb 2, 2026

Copy link
Copy Markdown
Contributor Author

I've implemented it with option 2, which in my testing seems to work perfectly ergonomically. The user does not need to import the trait themselves.

@Kwonunn Kwonunn changed the title Add linspace_exclusive function. Change linspace to take a range argument. Feb 2, 2026
@Kwonunn Kwonunn requested a review from akern40 February 2, 2026 15:23
@nilgoyette

Copy link
Copy Markdown
Collaborator

@Kwonunn Can you please fix the errors?

@Kwonunn

Kwonunn commented Feb 5, 2026

Copy link
Copy Markdown
Contributor Author

@nilgoyette I think this should fix all the tests

@nilgoyette

Copy link
Copy Markdown
Collaborator
    left  = [0.0, 0.09672354...], shape=[32], strides=[1], layout=CFcf (0xf), const ndim=1
    right = [0.0, 0.09983342, ...], shape=[32], strides=[1], layout=CFcf (0xf), const ndim=1

What you modified shouldn't have changed the test results.

@nilgoyette

Copy link
Copy Markdown
Collaborator

LGTM, but I'll let @akern40 finish his review.

@akern40 akern40 merged commit fd67f70 into rust-ndarray:master Feb 5, 2026
15 checks passed
@akern40

akern40 commented Feb 5, 2026

Copy link
Copy Markdown
Collaborator

Thank you for your contribution!

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.

3 participants