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

convenience variables for quaternions friendly suggestion #148

Open
alanedelman opened this issue Dec 17, 2024 · 2 comments
Open

convenience variables for quaternions friendly suggestion #148

alanedelman opened this issue Dec 17, 2024 · 2 comments

Comments

@alanedelman
Copy link

iq = Quaternion(0,1,0,0)
jq = Quaternion(0,0,1,0)
kq = Quaternion(0,0,0,1)
@hyrodium
Copy link
Collaborator

hyrodium commented Jan 7, 2025

Thank you for the suggestion! There was a related issue (#50).

I also think the constants add convenience.
To implement the constants, we need to decide the following:

@sethaxen
Copy link
Collaborator

sethaxen commented Jan 8, 2025

I agree that most of the arguments against including these convenience variables no longer apply, so it's worth reconsidering this.

From https://docs.julialang.org/en/v1/manual/complex-and-rational-numbers/#Complex-Numbers:

The [literal numeric coefficient notation](@ref man-numeric-literal-coefficients) does not work when constructing a complex number
from variables. Instead, the multiplication must be explicitly written out:

```jldoctest
julia> a = 1; b = 2; a + b*im
1 + 2im
```

However, this is *not* recommended. Instead, use the more efficient [`complex`](@ref) function to construct
a complex value directly from its real and imaginary parts:

```jldoctest
julia> a = 1; b = 2; complex(a, b)
1 + 2im
```

This construction avoids the multiplication and addition operations.

i.e. it's safe to use im when a and b are constants, e.g. in the REPL or when defining a constant within a function. But otherwise complex should be used.

Which symbols should we use?

* `iq, jq, kq`

* [`im_i, im_j, im_k`](https://github.com/JuliaGeometry/Quaternions.jl/issues/50#issuecomment-1045786440)

* [`imx, imy, imz`](https://moble.github.io/Quaternionic.jl/stable/manual/#Quaternionic.imx)

* etc.

I don't have a strong preference here. Base uses im instead of i, since i is commonly an index. So I don't think we need to use a variant of im, just something that is unlikely to clash with another namespace. We don't use xyz anywhere else, and this is uncommon with quaternions, so I'd say no. Underscores are insufficiently compact. iq, jq, etc is fine. My only annoyance is that we use v1, v2, etc in the fields of Quaternion. I wouldn't like iq1, iq2, etc though.

The following show implementation is based on Complex's. Because the strings are much longer than Complex's, I think it looks nicer to render the bases as bold (while still keeping the unicode as non-bold):

# use Bool to avoid promoting integer types e.g. Int16 to Int64
const iq = Quaternion(false, true, false, false)
const jq = Quaternion(false, false, true, false)
const kq = Quaternion(false, false, false, true)

function Base.show(io::IO, q::Quaternion)
    compact = get(io, :compact, false)::Bool
    show(io, q.s)
    for (v, sym) in zip((q.v1, q.v2, q.v3), (:iq, :jq, :kq))
        if signbit(v) && !isnan(v)
            print(io, compact ? "-" : " - ")
            if isa(v, Signed) && !isa(v, BigInt) && v == typemin(typeof(v))
                show(io, -widen(v))
            else
                show(io, -v)
            end
        else
            print(io, compact ? "+" : " + ")
            show(io, v)
        end
        printstyled(io, sym; bold=true)
    end
end

function  Base.show(io::IO, q::Quaternion{Bool})
    name = findfirst(Base.Fix2(===, q), (; iq, jq, kq))
    if name === nothing
        print(io, "Quaternion(", q.s, ',', q.v1, ',', q.v2, ',', q.v3, ")")
    else
        printstyled(io, name; bold=true)
    end
end
julia> iq
iq

julia> jq
jq

julia> kq
kq

julia> 1+3jq
1 + 0iq + 3jq + 0kq

julia> Quaternion(true, true, false, false)
Quaternion(true,true,false,false)

julia> randn(QuaternionF64, 3)
3-element Vector{QuaternionF64}:
 0.14029180109916273 - 1.1540872532752005iq + 0.1906721473746647jq + 1.2743183122684032kq
  -1.030315293683978 + 0.2523419854373315iq - 0.38537355553418795jq - 1.089803948247486kq
 -1.1036492479688396 - 0.3894607415241461iq - 0.1328394303475304jq - 0.5361253909830082kq

julia> randn(QuaternionF64, 3, 2)
3×2 Matrix{QuaternionF64}:
   0.389246-0.606827iq+0.704692jq+0.205152kq  0.346844+0.412816iq-0.409325jq+0.0666423kq
   0.796425-0.147743iq+0.495668jq-0.237316kq   -1.03524+0.672756iq-0.149115jq-0.199047kq
 -0.326256+0.346335iq-0.165236jq-0.0462912kq  -0.432593+0.138248iq-0.400217jq-0.221615kq

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

No branches or pull requests

3 participants