Skip to content
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 “Sign 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

various LinSpace-related changes #17408

Closed
wants to merge 1 commit into from
Closed

various LinSpace-related changes #17408

wants to merge 1 commit into from

Conversation

StefanKarpinski
Copy link
Member

@StefanKarpinski StefanKarpinski commented Jul 14, 2016

@dpsanders
Copy link
Contributor

It's not clear to me why you would want to print a linspace (or, perhaps, a vector) vertically? Our screens tend to have more horizontal than vertical space, much of which is wasted.

@StefanKarpinski
Copy link
Member Author

Because it's different than everything else. We print vectors vertically and this is a type of vector. Printing this one thing horizontally is bizarrely inconsistent. We should either print linspaces like other vectors or print it in input form like other ranges.

@StefanKarpinski
Copy link
Member Author

Of course, the other issue is that given #14420, we should possibly just get rid of LinSpace altogether and just return a vector like we used to.

@StefanKarpinski
Copy link
Member Author

The reason for printing vectors vertically is that vectors correspond to columns of matrices. We used to print vectors horizontally and it was a source of constant confusion for people. Since we started printing vectors vertically, that confusion has vanished.

@dpsanders
Copy link
Contributor

Fair point. Could there be an IOContext - ish way to have this (column versus row printing) be user controllable?

@tkelman
Copy link
Contributor

tkelman commented Jul 15, 2016

Whatever multiline is called now could maybe be responsible for this?

We could also deprecate the linspace function and let MatlabCompat.jl implement it.

@timholy
Copy link
Member

timholy commented Jul 24, 2016

I don't think we should get rid of LinSpace, because in many ways I think it's the most sensible of all the Range types: it does what you most often want, specifying the range directly in terms of start, stop, and length. I'm sure I'm in the minority here (I seem to worry less than many about most ulp-level inaccuracies), but I'd even argue for switching to the brain-dead implementation

immutable NewLinSpace{T} <: OrdinalRange{T,T}
    start::T
    stop::T
    len::Int
    leninv::Float64

    NewLinSpace(start,stop,len) = new(start,stop,len,1/(len-1))
end
function NewLinSpace(start, stop, len::Integer)
    T = typeof((stop-start)*(1/(Int(len)-1)))
    NewLinSpace{T}(start, stop, len)
end

Base.step(r::NewLinSpace) = (last(r)-first(r))/(r.len-1)
Base.length(r::NewLinSpace) = r.len
Base.:-(r::NewLinSpace) = NewLinSpace(-r.stop, -r.start, r.len)
Base.getindex(r::NewLinSpace, i::Integer) = first(r)*((length(r)-i)*r.leninv) + last(r)*((i-1)*r.leninv)

Reasons:

  • it always gets the first and last point right
  • it always gets the length right
  • it works for any reasonable number type: complex numbers, SIUnits-like objects, Vec{N}, GradNumber, etc. nextfloat doesn't mean a lot when you're talking about Meter or 3.2+4.7im. Frankly I think that mathematical generality is a more important design consideration than ulp-level accuracy.
  • it's really fast because we avoid division, which always brings things to a crawl.

Obviously, we could have this in a package instead, and perhaps that is a reason to get rid of it from Base. But we shouldn't tuck it in MatlabCompat: it's such a fundamentally good idea that we shouldn't oblige people to accept a bunch of more dicey things 😄 along for the ride.

@tkelman
Copy link
Contributor

tkelman commented Jul 25, 2016

LinSpaces.jl then? could easily have many different variations within a package, allowing users to choose what features are or are not important to them as opposed to trying to pick something one-size-fits-all for base.

@blakejohnson
Copy link
Contributor

I'm with @timholy in thinking that linspace is too useful throughout numerical computing to eject it from Base.

@tkelman
Copy link
Contributor

tkelman commented Jul 25, 2016

it's pretty rarely used within base, and any adjustments to functionality would be far more flexible and less constrained by the release schedule of the language if it weren't defined here.

@gabrielgellner
Copy link
Contributor

Oh man having to do a using to get linspace would be a major wart in my opinion. It will make Julia feel less and less like a numerically convenient language. Even in python, where it is not a numerical language first, doing import numpy as np is so standard that functionally linspace is a top level api. Whereas using LinSpace feels really ugly to me to get such a basic function.

@StefanKarpinski
Copy link
Member Author

The obvious middle ground is to keep linspace in Base and have it return a plain old vector like it used to and have a LinSpaces package that does fancier things.

@timholy
Copy link
Member

timholy commented Jul 25, 2016

Just to make sure I understand the point, in terms of ulp-level behavior this allows you to both guarantee that first and last points are preserved and do fancy stuff in the middle, right? (An alternative is to add user_start and user_stop fields to the current definition, but then getindex and next get really ugly...so I prefer your solution.)

@StefanKarpinski
Copy link
Member Author

Yep, that's about the extent of it.

@timholy
Copy link
Member

timholy commented Jul 25, 2016

I'd be fine with that.

@timholy
Copy link
Member

timholy commented Jul 25, 2016

Would love it if the fancy read-your-mind stuff is restricted to AbstractFloat, and do the "obvious" thing for everything else.

@StefanKarpinski
Copy link
Member Author

Yes, it doesn't make much sense for non-floats.

@ChrisRackauckas
Copy link
Member

The other middle ground would be to try out some kind of standard library idea. Have a LinSpace.jl which defines a whole bunch of fancy LinSpace types / functions, and have it auto-installed and auto-imported (for example, by default adding using LinSpace to the default .juliarc). That way if anyone wants to get rid of it, they can. I think that solves both the problem of not wanting to bloat Base while not requiring you to do using LinSpace at the top of every script.

@DNF2
Copy link

DNF2 commented Sep 13, 2016

I use linspace all the time, in my world it's an absolutely central part of Julia.

I would also be very unhappy if it was changed to returning an ordinary vector. The current linspace behaviour fits well with the other ranges. I hope 1:n won't be changed as well. Anyway, hasn't the new way of displaying it at the REPL helped people get used to it?

I wouldn't have minded a different name, though. linrange, for example.

@ChrisRackauckas
Copy link
Member

Check out the discussion at JuliaMath/Grids.jl#3. Instead of LinSpace.jl, I called it Grids.jl since linspace is essentially for making 1D grids, and I think the issue is more about having good set of lightweight types/tools for these problems (including meshgrid and ndgrid which have been ignored in Base). For large grids, especially when nD, it's simply not possible to fit the whole array in memory, so some kind of standard tooling for this is necessary.

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.

8 participants