Skip to content

Commit

Permalink
Add more methods to quat (#132)
Browse files Browse the repository at this point in the history
* add more methods to `quat`

* fix typo

* Fix docstring in `src/Quaternion.jl`

Co-authored-by: Seth Axen <seth@sethaxen.com>

* avoid tests on unbound_args

* add more tests on `quat`

* add more tests on `quat`

* replace `function quat end` with `quat`

---------

Co-authored-by: Seth Axen <seth@sethaxen.com>
  • Loading branch information
hyrodium and sethaxen authored Nov 25, 2023
1 parent 0877cfd commit bf3803b
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 5 deletions.
38 changes: 34 additions & 4 deletions src/Quaternion.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ Base.promote_rule(::Type{Quaternion{T}}, ::Type{S}) where {T <: Real, S <: Real}
Base.promote_rule(::Type{Quaternion{T}}, ::Type{Quaternion{S}}) where {T <: Real, S <: Real} = Quaternion{promote_type(T, S)}

"""
quat(r, [i, j, k])
quat(w, [x, y, z])
Convert real numbers or arrays to quaternion. `i, j, k` defaults to zero.
Convert real numbers or arrays to quaternion. `x, y, z` defaults to zero.
# Examples
```jldoctest
Expand All @@ -49,15 +49,45 @@ julia> quat([1, 2, 3])
"""
quat

quat(p, v1, v2, v3) = Quaternion(p, v1, v2, v3)
quat(x) = Quaternion(x)
quat(q::Quaternion) = q
quat(s::Real) = Quaternion(s)
quat(s::Real, v1::Real, v2::Real, v3::Real) = Quaternion(s, v1, v2, v3)

## Array operations on quaternions ##
quat(A::AbstractArray{<:Quaternion}) = A
function quat(A::AbstractArray{T}) where T
if !isconcretetype(T)
error("`quat` not defined on abstractly-typed arrays; please convert to a more specific type")
end
convert(AbstractArray{typeof(quat(zero(T)))}, A)
end

"""
quat(T::Type)
Return an appropriate type that can represent a value of type `T` as a quaternion.
Equivalent to `typeof(quat(zero(T)))`.
# Examples
```jldoctest
julia> quat(Quaternion{Int})
Quaternion{Int64}
julia> quat(Int)
Quaternion{Int64}
```
"""
quat(::Type{T}) where {T<:Real} = Quaternion{T}
quat(::Type{Quaternion{T}}) where {T<:Real} = Quaternion{T}

quat(::Missing) = missing
# Same definitioin as in Base: https://github.com/JuliaLang/julia/blob/v1.9.3/base/missing.jl#L111-L115
quat(::Type{Missing}) = Missing
function quat(::Type{Union{T, Missing}}) where T
T === Any && throw(MethodError(quat, (Any,))) # To prevent StackOverflowError
Union{quat(T), Missing}
end

"""
real(T::Type{<:Quaternion})
Expand Down
12 changes: 12 additions & 0 deletions test/Quaternion.jl
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,18 @@ end
@test quat(Quaternion(1, 2, 3, 4)) === Quaternion(1, 2, 3, 4)
@test quat([2, 3, 4]) == Quaternion{Int}[2, 3, 4]
@test_throws ErrorException quat(Real[1,2,3])
@test quat(Quaternion[1,2]) == Quaternion[1,2]

@test quat(Int) === Quaternion{Int}
@test quat(Float32) === Quaternion{Float32}
@test quat(Quaternion{Int}) === Quaternion{Int}
@test quat(Quaternion{Float32}) === Quaternion{Float32}

# Note that `quat(1,missing,0,0)` throws an error.
# This is the same behavior as `complex(1,missing)`.
@test quat(missing) === missing
@test quat(Missing) === Missing
@test quat(Union{Missing, Int}) === Union{Missing, Quaternion{Int}}
end

@testset "random generation" begin
Expand Down
4 changes: 3 additions & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ using Quaternions
using Aqua
using RealDot

Aqua.test_all(Quaternions)
# Avoid tests on unbound_args.
# https://github.com/JuliaGeometry/Quaternions.jl/pull/132#discussion_r1383817950
Aqua.test_all(Quaternions, unbound_args=false)

include("helpers.jl")
include("Quaternion.jl")

0 comments on commit bf3803b

Please sign in to comment.