ReferenceFrameRotations.jl icon indicating copy to clipboard operation
ReferenceFrameRotations.jl copied to clipboard

Mutable quaternion?

Open mattsignorelli opened this issue 1 year ago • 10 comments

My organization has a need for a mutable quaternion. We really like this package as a lightweight, fast quaternion implementation for simulations, and we were wondering if a PR would be accepted where we implement a MQuaternion which is mutable, and have both Quaternion and MQuaternion inherit from some AbstractQuaternion, which the current function type definitions would then use. This would have no impact on current users of the package but also expand its functionality

mattsignorelli avatar Sep 17 '24 19:09 mattsignorelli

Hi @mattsignorelli !

I am glad that ReferenceFrameRotations.jl is being useful :)

One of the reasons for the speed of this package is because all the types are immutable. Can you please highlight why do you need a mutable quaternion? Furthermore, did you check Accessors.jl? Using this package, it is possible to do this:

julia> using ReferenceFrameRotations

julia> using Accessors

julia> function test()
       q = Quaternion(1, 2, 3, 4)
       @reset q.q0 = 10
       return q
       end
test (generic function with 1 method)

julia> test()
Quaternion{Int64}:
  + 10 + 2⋅i + 3⋅j + 4⋅k

It automatically creates a copy with the new field. In most of cases, it is significantly faster than using a mutable structure.

ronisbr avatar Sep 17 '24 20:09 ronisbr

Hello!

The idea is that we'd have a separate type, MQuaternion which could be used as an alternative to the primary fast Quaternion.

We are currently planning for our accelerator physics simulation API to be mutating, because instead of just simulating particles going through the accelerator (which could basically just be SVector{Float64}), we also need to simulate "truncated power series" (implemented as TPS in GTPSA.jl; the result of propagating a TPS is a Taylor map representing the particle transport to some high order.

The TPS type however is mutable, and to perform simulations without any extra allocations from each arithmetic operation including a TPS, we can instead modify in-place the result TPS which has been pre-allocated. So instead of writing separate mutating functions for TPS types, we would prefer the entire API to be mutating and have the same universally-polymorphic functions work for both immutable number types and our mutable TPSs.

mattsignorelli avatar Sep 17 '24 21:09 mattsignorelli

I see, sounds very reasonable! :)

Can you make a PR? We just need to make sure we did not decrease the performance of the previous version.

ronisbr avatar Sep 17 '24 21:09 ronisbr

Sure! I'll get started on it now

mattsignorelli avatar Sep 18 '24 12:09 mattsignorelli

Awesome!

ronisbr avatar Sep 18 '24 19:09 ronisbr

By the way! When coding, please, if possible, follow the BlueStyle: https://github.com/JuliaDiff/BlueStyle

ronisbr avatar Sep 18 '24 19:09 ronisbr

Sounds good! It might take a couple weeks to finish since I'm a bit swamped right now but it's on my to-do list

mattsignorelli avatar Sep 23 '24 17:09 mattsignorelli

OK sorry for the big delay on this, I have some time to work on this now.

I think the simplest solution would be to have an AbstractQuaternion type which Quaternion and MQuaternion both inherit, and redefine most of the routines to instead have a ::AbstractQuaternion type specification instead. And, like in static arrays where an operation including a SVector and an MVector outputs an SVector, we would make it so that the result of two operations including MQuaternion and Quaternion is a Quaternion.

What do you think? If that sounds good I can code it.

mattsignorelli avatar Feb 11 '25 18:02 mattsignorelli

Hi @mattsignorelli !

Thanks for your help! However, I already started to work on it internally. I will probably have a first version in some weeks with precisely the design you proposed.

ronisbr avatar Feb 14 '25 00:02 ronisbr

Sounds great!

mattsignorelli avatar Feb 14 '25 14:02 mattsignorelli