SimonDanisch / FixedSizeArrays.jl

Julia's generic FixedSizeArray implementation. Can be used for all kinds of Vector constructs
Other
35 stars 20 forks source link

Semantics of point + vec #102

Open c42f opened 8 years ago

c42f commented 8 years ago

Has anyone discussed the mathematical semantics of Point, and how it relates to Vec? This came up in #101, where the mathematical nature of Point might define how Point and Vec interoperate.

Is there a good reason to even have Point and Vec as different concepts? It makes sense to me if Point is meant to be something in an affine space, but as a FSA it's got a whole bunch of operations which don't make sense on points. For example, Point + Point and scalar*Point really don't make a lot of mathematical sense unless you have a blessed origin in your space. If you do have a blessed origin, you actually have a vector space, in which case we may as well be using Vec instead.

To summarize, does Point have a well defined reason for existence, or should we just replace it with Vec?

SimonDanisch commented 8 years ago

I introduced them mainly for visual debugging. The more refined the type system, the easier it is to create default visualizations. It also becomes easier to recognize intend when reading code. So I'm quite convinced of having them. I'd argue not too be that strict and don't actually remove functionality, but instead make e.g. vec+point return a point and not a stack overflow!

andyferris commented 8 years ago

How would you handle this in the general case? Users would manually define how their types promote? Is there something like promote_rule to give guidance to promote()? Or a three-argument promote() or similar? Ideally, this could be a bit easier than, e.g.:

function translate{N}(dx::Vec{N}, x::FixedVector{N})
    (x_promoted, dx_promoted) = promote(x, dx) # Force same data type
    x_promoted + (typeof(x_promoted))(dx_promoted) # Force same base type
end

But I don't have any nice design ideas here, beyond passing Val{1} or Val{2} to promote as a third argument (perhaps with a default of 1 or 2 / left or right?).

c42f commented 8 years ago

@SimonDanisch - just to check I understand you - you're saying that it all comes down to dispatch: you want the visualization of Vector{P<:Point} (for example) to dispatch differently to Vector{V<:Vec}? This seems entirely reasonable.

It leaves me a bit confused though - I still don't know exactly what kind of object Point is meant to be, and how it interacts with Vec. For example, I expect we should have point - point :: Vec, but that's clearly not the case at the moment. I think this is not just a theoretical concern - even in graphics, it's the only thing which makes sense: point - point transforms differently from a Point; it transforms like a Vec! (Come to think of it, cross(::Vec,::Vec) should return Normal, though follow this thinking far enough and you end up with the type system of a full geometric algebra. I think other people are going there)

With all the above in mind, it seems that Point is semantically an element of an affine space, with components representing standard Cartesian coordinates. (A bit less generically, it's a member of a Euclidean space I suppose, depending on whether you use the metric information for anything). @andyferris this makes it a perfect candidate for use in CoordinateTransformations.jl, just as you're doing I think...

SimonDanisch commented 8 years ago

It leaves me a bit confused though - I still don't know exactly what kind of object Point is meant to be, and how it interacts with Vec. For example, I expect we should have point - point :: Vec, but that's clearly not the case at the moment. I think this is not just a theoretical concern - even in graphics, it's the only thing which makes sense: point - point transforms differently from a Point; it transforms like a Vec! (Come to think of it, cross(::Vec,::Vec) should return Normal, though follow this thinking far enough and you end up with the type system of a full geometric algebra. I think other people are going there)

Exactly, we're not there yet ;) I'm open to PR's! I'd use something like promote_array_type like in https://github.com/JuliaLang/julia/blob/master/base/arraymath.jl#L38 In 0.5 we can also do things like:

promote_array_type(::typeof(cross), ::Type{Vec}, ::Type{Vec}) = Normal

Since Functions are Functors ;)

c42f commented 8 years ago

Right, it's easy to make the old promote_op actually good in 0.5 using the new singleton types for generic functions. In 0.4 the only mostly-equivalent option seems to be functors which are pretty clunky.

What's the plan with 0.4 compatibility for FixedSizeArrays? At work we'll probably be using 0.4 until 0.5 starts to become stableish.

Sorry for providing mostly complaints here, and not much in the way of PRs yet!

SimonDanisch commented 8 years ago

I want to keep supporting 0.4 as long as possible! We can make promote_op work with 0.4 Functors as well ;)

ScottPJones commented 8 years ago

Can you tag a version that works with v0.4.x, so that v0.4 can continue to be supported? (It looks like there are some changes coming to v0.5 that IMO will make the Tuplecalpyse seem like nothing, we've already been discussing at work the substantial work that will be needed to move to v0.5, if the string PRs are merged in) (and we've really been interested in moving to v0.5 as soon as possible, if Cxx.jl and Gallium.jl are finished for v0.5)

SimonDanisch commented 8 years ago

It's not really in sight that we stop supporting 0.4 ;) if it happens, we should sure do that!

c42f commented 8 years ago

I'm digging through the system now with the aim of upgrading the existing functors to make the type inference problems with map go away (see #63, #93, #82, etc). I'll be developing it on 0.4 - no plans to break backward compatibility.