Skip to content

Do we really need normalized-flag in Quaternion? #60

@hyrodium

Description

@hyrodium

The problems

The following are what I am concerned about.

  • Someone just needs quaternion operations, without the flag.
  • Performance disadvantage
  • The flag is not well-documented, and some operations don’t work properly with the flag.

Someone just needs quaternion operations, without the flag.

See comments in Makie.jl for example.

Performance disadvantage

The following MyQuaternion is a quaternion without the flag. The benchmark shows -5.49% => improvement (5.00% tolerance).

julia> using Quaternions, BenchmarkTools

julia> struct MyQuaternion{T<:Real} <: Number
           s::T
           v1::T
           v2::T
           v3::T
       end

julia> Base.:*(q::MyQuaternion, w::MyQuaternion) = MyQuaternion(q.s * w.s - q.v1 * w.v1 - q.v2 * w.v2 - q.v3 * w.v3,
                                                      q.s * w.v1 + q.v1 * w.s + q.v2 * w.v3 - q.v3 * w.v2,
                                                      q.s * w.v2 - q.v1 * w.v3 + q.v2 * w.s + q.v3 * w.v1,
                                                      q.s * w.v3 + q.v1 * w.v2 - q.v2 * w.v1 + q.v3 * w.s)

julia> mq = MyQuaternion(1.0, 2.0, 3.0, 4.0)
MyQuaternion{Float64}(1.0, 2.0, 3.0, 4.0)

julia> q = Quaternion(1.0, 2.0, 3.0, 4.0)
Quaternion{Float64}(1.0, 2.0, 3.0, 4.0, false)

julia> a = @benchmark $mq*$mq
BenchmarkTools.Trial: 10000 samples with 1000 evaluations.
 Range (min  max):  2.793 ns  31.009 ns  ┊ GC (min  max): 0.00%  0.00%
 Time  (median):     4.260 ns              ┊ GC (median):    0.00%
 Time  (mean ± σ):   4.229 ns ±  0.486 ns  ┊ GC (mean ± σ):  0.00% ± 0.00%

                  ▁           ▃▃ ▆ ▄       ▆ █ █ ▅       ▂ ▁ ▂
  ▅▁▇▁▆▁▁▁▁▁▁▁▅▁█▁█▁▇▁▁▁▁▁▃▁▇▁██▁█▁█▁▁▁▁▁█▁█▁█▁█▁█▁▁▁▁▁█▁█▁█ █
  2.79 ns      Histogram: log(frequency) by time     4.75 ns <

 Memory estimate: 0 bytes, allocs estimate: 0.

julia> b = @benchmark $q*$q
BenchmarkTools.Trial: 10000 samples with 1000 evaluations.
 Range (min  max):  3.213 ns  18.089 ns  ┊ GC (min  max): 0.00%  0.00%
 Time  (median):     4.330 ns              ┊ GC (median):    0.00%
 Time  (mean ± σ):   4.474 ns ±  0.401 ns  ┊ GC (mean ± σ):  0.00% ± 0.00%

                                 ▅ █           ▂              
  ▂▁▂▁▂▁▂▁▁▁▁▁▁▁▂▁▂▁▂▁▂▁▁▁▁▁▂▁▄▄▁█▁█▁▅▁▁▁▁▁▃▁▇▁█▁▇▁▃▁▁▁▁▁▂▁▂ ▃
  3.21 ns        Histogram: frequency by time        5.17 ns <

 Memory estimate: 0 bytes, allocs estimate: 0.

julia> judge(mean(a),mean(b))
BenchmarkTools.TrialJudgement: 
  time:   -5.49% => improvement (5.00% tolerance)
  memory: +0.00% => invariant (1.00% tolerance)

The flag is not well-documented, and some operations don’t work properly with the flag.

See #36, #39, #51 and #59.

How to fix these problems

  • If you need unit quaternions for rotations, I think Rotations.QuatRotation would be helpful.
    • Rotations.jl package have a dependency on Quaternions.jl, and conversion Quaterion <-> QuatRotation is supported.
  • If you do not prefer the Rotations package, adding a new type Quaternions.UnitQuaternon seems better, I guess.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions