# Proposal of Numpy-like "endpoint" option for linspace

**URL:** <https://discourse.julialang.org/t/proposal-of-numpy-like-endpoint-option-for-linspace/6916>\
**Category:** Internals & Design\
**Tags:** proposal\
**Created:** [November 6, 2017, 8:05pm UTC](https://discourse.julialang.org/t/proposal-of-numpy-like-endpoint-option-for-linspace/6916 "2017-11-06T20:05:10Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![favba](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/favba/32/2735_2.png) [@favba](https://discourse.julialang.org/u/favba)\
**Post date:** [November 6, 2017, 8:05pm UTC](https://discourse.julialang.org/t/proposal-of-numpy-like-endpoint-option-for-linspace/6916/1 "2017-11-06T20:05:10Z")

</div>

[Numpy](https://docs.scipy.org/doc/numpy/reference/generated/numpy.linspace.html) has an `endpoint::Bool` for the inclusion or not of the last point on their implementation of `linspace`.  
In my use case (where I use lots of fft’s) that is very handy. I think that would be a useful feature for Julia’s `linspace`.

* * *

That is rather easy to implement and I could do it myself, but I don’t know the “etiquette” for such things. Should I just make a PR with the necessary modifications? Open an Issue? Discuss it here?

And I guess making a signature like `linspace(start,stop,n=50,endpoint::Bool=true)` would make it a non-breaking change.

---

<div class="post-metadata">

**Author:** ![pkofod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pkofod/32/2179_2.png) [@pkofod](https://discourse.julialang.org/u/pkofod)\
**Post date:** [November 6, 2017, 8:07pm UTC](https://discourse.julialang.org/t/proposal-of-numpy-like-endpoint-option-for-linspace/6916/2 "2017-11-06T20:07:12Z")

</div>

> [@favba](#):
>
> Should I just make a PR with the necessary modifications? Open an Issue? Discuss it here?

Yes, yes, and yes 🙂

So, the thing is. It seems like you really want a function that does this. So if you do write it and make a PR, you already have what you need. However, the problem with a PR first approach is that you might have missed if this has already been discussed 200 times, so it is a good idea to ask here or open an issue. So… Yes 🙂

---

<div class="post-metadata">

**Author:** ![yakir12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yakir12/32/297_2.png) [@yakir12](https://discourse.julialang.org/u/yakir12)\
**Post date:** [November 6, 2017, 8:45pm UTC](https://discourse.julialang.org/t/proposal-of-numpy-like-endpoint-option-for-linspace/6916/3 "2017-11-06T20:45:30Z")

</div>

I find this useful as well, but on the other end… Like when you want a series but would rather not have the first element cause it’s usually zero.  
So something like:

```julia
linspace(start, stop, n = 50; startpoint :: Bool = true, endpoint :: Bool = true) 

```

---

<div class="post-metadata">

**Author:** ![ssfrr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ssfrr/32/3736_2.png) [@ssfrr](https://discourse.julialang.org/u/ssfrr)\
**Post date:** [November 6, 2017, 8:59pm UTC](https://discourse.julialang.org/t/proposal-of-numpy-like-endpoint-option-for-linspace/6916/4 "2017-11-06T20:59:06Z")

</div>

Not sure if there are any unforseen edgecases that would cause issues, but IMO this would definitely be useful, and has come up in my code.

`<bikeshed>`perhaps `withstart` and `withend` would be more clear names. `</bikeshed>`

---

<div class="post-metadata">

**Author:** ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)\
**Post date:** [November 6, 2017, 9:49pm UTC](https://discourse.julialang.org/t/proposal-of-numpy-like-endpoint-option-for-linspace/6916/5 "2017-11-06T21:49:51Z")

</div>

A reasonably straightforward way to express this is `linspace(a, b, n)[1:end-1]`, which also has a natural generalization to dropping multiple elements or dropping elements at the start. I don’t know about Numpy but in Julia this is just indexing a range with a range, which is quite efficient.

---

<div class="post-metadata">

**Author:** ![ssfrr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ssfrr/32/3736_2.png) [@ssfrr](https://discourse.julialang.org/u/ssfrr)\
**Post date:** [November 6, 2017, 10:08pm UTC](https://discourse.julialang.org/t/proposal-of-numpy-like-endpoint-option-for-linspace/6916/6 "2017-11-06T22:08:54Z")

</div>

It’d need to be `linspace(a, b, n+1)[1:end-1]`, which isn’t a monumental cognitive effort but it seems like `linspace(a, b, n; withend=false)` is more clear.

---

<div class="post-metadata">

**Author:** ![yakir12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yakir12/32/297_2.png) [@yakir12](https://discourse.julialang.org/u/yakir12)\
**Post date:** [November 7, 2017, 8:06am UTC](https://discourse.julialang.org/t/proposal-of-numpy-like-endpoint-option-for-linspace/6916/7 "2017-11-07T08:06:20Z")

</div>

I think that maybe there would be some resistance to add keywords to such a commonly used function (it might slow it down a bit), ~~but with [this](https://github.com/JuliaLang/julia/pull/22194) recently merged, my meager understanding is that this shouldn’t negatively effect compile times.~~

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [November 7, 2017, 10:30am UTC](https://discourse.julialang.org/t/proposal-of-numpy-like-endpoint-option-for-linspace/6916/8 "2017-11-07T10:30:29Z")

</div>

> [@yakir12](#):
>
> but with this recently merged, my meager understanding is that this shouldn’t negatively effect compile times.

So far, NamedTuples are not related to keyword argument at all.

---

<div class="post-metadata">

**Author:** ![yakir12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yakir12/32/297_2.png) [@yakir12](https://discourse.julialang.org/u/yakir12)\
**Post date:** [November 7, 2017, 10:35am UTC](https://discourse.julialang.org/t/proposal-of-numpy-like-endpoint-option-for-linspace/6916/9 "2017-11-07T10:35:47Z")

</div>

> [@kristoffer.carlsson](#):
>
> NamedTuples are not related to keyword argument at all.

Oops 😳

---

<div class="post-metadata">

**Author:** ![innerlee](https://avatars.discourse-cdn.com/v4/letter/i/b19c9b/32.png) [@innerlee](https://discourse.julialang.org/u/innerlee)\
**Post date:** [November 7, 2017, 10:55am UTC](https://discourse.julialang.org/t/proposal-of-numpy-like-endpoint-option-for-linspace/6916/10 "2017-11-07T10:55:09Z")

</div>

if `withstart=false`, then does the start point count for the `n`?

---

<div class="post-metadata">

**Author:** ![yakir12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yakir12/32/297_2.png) [@yakir12](https://discourse.julialang.org/u/yakir12)\
**Post date:** [November 7, 2017, 1:58pm UTC](https://discourse.julialang.org/t/proposal-of-numpy-like-endpoint-option-for-linspace/6916/11 "2017-11-07T13:58:51Z")

</div>

The idea would be to have `n` points without the first and/or last points of some series. I don’t care about the precise value of the delta between each member, I just care about having exactly `n` points and not having the first and/or last members of this series.

---

<div class="post-metadata">

**Author:** ![favba](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/favba/32/2735_2.png) [@favba](https://discourse.julialang.org/u/favba)\
**Post date:** [November 8, 2017, 4:33pm UTC](https://discourse.julialang.org/t/proposal-of-numpy-like-endpoint-option-for-linspace/6916/12 "2017-11-08T16:33:31Z")

</div>

Following @pkofod advise, I browsed the Issues related to `linspace` and it shows there was lots of discussion regarding it’s precision, whether it should return a range with precise step or a range where the start and end points are hit exactly (and therefore having a inexact step size). So this makes the discussion a little less simple than I guessed.

I guess it would make sense to maintain the same approach: hitting exactly the end-point. In our case, with `endpoint=false`, hitting the “virtual” endpoint exactly. I guess the safest way to do that would be to do `linspace(start,stop,n,endpoint=false) = linspace(start,stop,n+1)[1:n]`. It is not that strait-forward, but it isn’t that much expensive either.

* * *

> [@yakir12](#):
>
> I think that maybe there would be some resistance to add keywords to such a commonly used function (it might slow it down a bit), but with this recently merged, my meager understanding is that this shouldn’t negatively effect compile times.

I agree that having keywords would be cumbersome. Here is my idea: just adding those two methods to `linspace`, without modifying what has already been implemented:

```julia
julia> function Base.linspace(start::Number,stop::Number,n::Integer,inclusive::Tuple{Bool,Bool})
       if inclusive == (true,true)
         return linspace(start,stop,n)
       elseif inclusive == (false,false)
         return linspace(start,stop,n+2)[2:end-1]
       elseif inclusive == (true,false)
         return linspace(start,stop,n+1)[1:end-1]
       elseif inclusive == (false,true)
         return linspace(start,stop,n+1)[2:end]
       end
       end

julia> function Base.linspace(start::Number,stop::Number,inclusive::Tuple{Bool,Bool})
       if inclusive == (true,true)
         return linspace(start,stop)
       elseif inclusive == (false,false)
         return linspace(start,stop,52)[2:51]
       elseif inclusive == (true,false)
         return linspace(start,stop,51)[1:50]
       elseif inclusive == (false,true)
         return linspace(start,stop,51)[2:51]
       end
       end

julia> a = linspace(0,1)
0.0:0.02040816326530612:1.0

julia> a = linspace(0,1,(true,true))
0.0:0.02040816326530612:1.0

julia> a = linspace(0,1,(false,true))
0.02:0.02:1.0

julia> a[1] - step(a)
0.0

julia> a = linspace(0,1,(true,false))
0.0:0.02:0.98

julia> a[end] + step(a)
1.0

julia> a = linspace(0,1,(false,false))
0.0196078431372549:0.0196078431372549:0.9803921568627451

julia> a[1]-step(a)
0.0

julia> a[end]+step(a)
1.0

julia> a = linspace(0,1,20)
0.0:0.05263157894736842:1.0

julia> a = linspace(0,1,20,(true,true))
0.0:0.05263157894736842:1.0

julia> a = linspace(0,1,20,(false,true))
0.05:0.05:1.0

julia> a[1]-step(a)
0.0

julia> a = linspace(0,1,20,(false,false))
0.047619047619047616:0.047619047619047616:0.9523809523809523

julia> a[1]-step(a)
0.0

julia> a[end]+step(a)
1.0

```

---

<div class="post-metadata">

**Author:** ![benninkrs](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/benninkrs/32/3191_2.png) [@benninkrs](https://discourse.julialang.org/u/benninkrs)\
**Post date:** [January 22, 2018, 4:38am UTC](https://discourse.julialang.org/t/proposal-of-numpy-like-endpoint-option-for-linspace/6916/13 "2018-01-22T04:38:04Z")

</div>

Some years ago I had a similar need in my Matlab programming. FWIW here’s what I did: Instead of overloading `linspace`, I created a new function `binspace(a,b,n,[left|center|right])`. The meaning is that the interval `[a,b]` is divided into `n` equal sized subintervals or “bins”. What is returned is either the left endpoints, right endpoints, or center points of the bins, depending on the option given.

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [January 22, 2018, 3:58pm UTC](https://discourse.julialang.org/t/proposal-of-numpy-like-endpoint-option-for-linspace/6916/14 "2018-01-22T15:58:18Z")

</div>

That’s a nice insight — often you actually want to represent the _intervals_ between the values provided by `linspace`. You could take your idea one step farther with Julia and return a vector of [`IntervalSet`s](https://github.com/JuliaMath/IntervalSets.jl). Then instead of a `left|center|right` argument, you simply use `minimum.(binspace(a,b,n))`, `mean.(binspace(…))` or `maximum.(binspace(…))`, and in some cases you could use the intervals directly.
