Skip to content
New issue

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

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Named access with .{x,y,z,w} to elements of SVector and MVector #980

Merged
merged 1 commit into from
Dec 18, 2021

Conversation

c42f
Copy link
Member

@c42f c42f commented Dec 16, 2021

Having access with v.x etc makes the concrete SVector interface much
more usable for geometry; indeed, it will "just work like you expect"
without the need to resort to a custom FieldVector type.

This makes the concrete SVector/MVector interface fatter, but OTOH I
don't think it can do any harm to people who don't want to use it.

If we do this, it should be made to work at least for SVector{1}
SVector{2} and SVector{3}, but I saw no reason to disallow the use of
these in higher dimensions and overcomplicate the implementation.

Inspired by discussion at

https://discourse.julialang.org/t/ray-tracing-in-a-week-end-julia-vs-simd-optimized-c/72958

I'll add tests and some docs if we decide this is a good idea!

Copy link
Member

@andyferris andyferris left a comment

Choose a reason for hiding this comment

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

Yes, I can see how this could be convenient for using these as points, and as you say there isn’t any real downside.

src/MVector.jl Outdated

# Named field access for the first three elements with the conventional
# field names
function Base.getproperty(v::Union{MVector}, name::Symbol)
Copy link
Member

Choose a reason for hiding this comment

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

Unnecessary Union

src/SVector.jl Outdated

# Named field access for the first three elements with the conventional
# field names
function Base.getproperty(v::Union{SVector}, name::Symbol)
Copy link
Member

Choose a reason for hiding this comment

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

Unnecessary Union

Copy link
Member Author

Choose a reason for hiding this comment

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

Heh oops, thanks!

The reason this was there was that I had this defined as Union{SVector,MVector} because the implementations are the same.

But then I didn't know which file to put these in so I duplicated them instead as they're a concrete interface. Kind of a stupid reason to have duplicate code though I guess...

@c42f
Copy link
Member Author

c42f commented Dec 16, 2021

Perhaps I should also add setproperty! for MVector to go with this.

@@ -36,10 +36,6 @@ const SVector{S, T} = SArray{Tuple{S}, T, 1, S}
## SVector methods ##
#####################

@propagate_inbounds function getindex(v::SVector, i::Int)
v.data[i]
end
Copy link
Member Author

Choose a reason for hiding this comment

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

Haha, this redundant method has been in here for years. I removed it in favour of the linear getindex from SArray

@c42f
Copy link
Member Author

c42f commented Dec 16, 2021

Absent objections, I'll probably merge this some time tomorrow or so.

It's a neat little feature and should be harmless to anyone who hasn't been involved in type piracy :-)

@ffreyer
Copy link

ffreyer commented Dec 16, 2021

Perhaps this should also include p.w = p[4] to complete the set that's used in glsl?

@cdsousa
Copy link

cdsousa commented Dec 16, 2021

Perhaps this should also include p.w = p[4] to complete the set that's used in glsl?

It is also used by the Eigen C++ library.

@c42f
Copy link
Member Author

c42f commented Dec 16, 2021

I agree w is an obvious option for the forth conventional dimension name. Perhaps it's the best of the available options. If you're a physicist, the most obvious fourth dimension name might be t for time. (No it's ok, we're not doing that 😆)

I initially decided against w because it's not quite so standard — it's more a graphics (homogeneous coordinates) convention than a universal geometry thing...

@fredrikekre
Copy link
Member

Would it make sense to limit this to length-3 vectors (.x for 1D, .x, .y for 2D and .x, .y, .z for 3D)?

@claforte
Copy link

Maybe throw @inbounds in there? I think that made a significant speed-up in my toy raytracing implementation, and otherwise people might not think to add it up, i.e. might not realize that .x/.y translates into array look-up...

@c42f
Copy link
Member Author

c42f commented Dec 17, 2021

Would it make sense to limit this to length-3 vectors (.x for 1D, .x, .y for 2D and .x, .y, .z for 3D)?

I don't know! The question is, could it lead to unexpected bugs in other cases?

You know what I think I agree: let's be strict here and relax the rules later if we think it makes sense. It's much easier to add API than to remove it!

Maybe throw @inbounds in there?

Adding @inbounds here shouldn't help because any bounds check should be elided given constant propagation of the constant index into the data tuple. Though on that note, it would be better (easier on the compiler) to just implement this in terms of getfield(v,:data) rather than getindex — that avoids getproperty being recursive. I'll do that! ( turns out I already did this... duh!)

@c42f
Copy link
Member Author

c42f commented Dec 17, 2021

Ok thanks for the feedback everyone. I've now updated this as follows:

  • Restricted this to work with vectors up to dimension 4 only. We can always allow for higher dimensions later, but I doubt that'll be necessary.
  • Added the .w component. GLSL is pretty great I agree.
  • Added @inbounds to setindex usage so the compiler can elide this as early as possible. It seems nice not to rely on constant prop there.
  • Updated docs and tests accordingly

@c42f
Copy link
Member Author

c42f commented Dec 17, 2021

Side note... gosh our docs are pretty awful 😅

Not something for this PR though.

Having access with v.x etc makes the *concrete* SVector interface much
more usable for geometry; indeed, it will "just work like you expect"
without the need to resort to a custom FieldVector type.

This makes the concrete SVector/MVector interface fatter, but I don't
think it can do any harm to people who don't want to use it.
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants