diff --git a/Project.toml b/Project.toml index 6b9fe39..9220697 100644 --- a/Project.toml +++ b/Project.toml @@ -1,18 +1,18 @@ name = "Octonions" uuid = "d00ba074-1e29-4f5e-9fd4-d67071d6a14d" -version = "0.1.0" +version = "0.2.0-DEV" [deps] LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" -Quaternions = "94ee1d12-ae83-5a48-8b1c-48b8ff168ae0" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" [compat] -Quaternions = "0.5.6" +Quaternions = "0.7" julia = "1" [extras] +Quaternions = "94ee1d12-ae83-5a48-8b1c-48b8ff168ae0" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [targets] -test = ["Test"] +test = ["Quaternions", "Test"] diff --git a/src/Octonions.jl b/src/Octonions.jl index 2e144c4..70b8ad9 100644 --- a/src/Octonions.jl +++ b/src/Octonions.jl @@ -5,7 +5,6 @@ import Base: abs, abs2, conj, exp, inv, isreal, isfinite, isinf, iszero, isnan, import Base: promote_rule, float import Base: rand, randn import LinearAlgebra: normalize -using Quaternions: Quaternion using Random Base.@irrational INV_SQRT_EIGHT 0.3535533905932737622004 sqrt(big(0.125)) diff --git a/src/octonion.jl b/src/octonion.jl index 6700c98..912f365 100644 --- a/src/octonion.jl +++ b/src/octonion.jl @@ -11,16 +11,12 @@ struct Octonion{T<:Real} <: Number end Octonion{T}(x::Real) where {T<:Real} = Octonion(convert(T, x)) -Octonion{T}(x::Complex) where {T<:Real} = Octonion(convert(Complex{T}, x)) -Octonion{T}(q::Quaternion) where {T<:Real} = Octonion(convert(Quaternion{T}, q)) Octonion{T}(o::Octonion) where {T<:Real} = Octonion{T}(o.s, o.v1, o.v2, o.v3, o.v4, o.v5, o.v6, o.v7, o.norm) Octonion(s::Real, v1::Real, v2::Real, v3::Real, v4::Real, v5::Real, v6::Real, v7::Real, n::Bool = false) = Octonion(promote(s, v1, v2, v3, v4, v5, v6, v7)..., n) Octonion(x::Real) = Octonion(x, zero(x), zero(x), zero(x), zero(x), zero(x), zero(x), zero(x), abs(x) == one(x)) -Octonion(z::Complex) = Octonion(z.re, z.im, zero(z.re), zero(z.re), zero(z.re), zero(z.re), zero(z.re), zero(z.re), abs(z) == one(z.re)) -Octonion(q::Quaternion) = Octonion(q.s, q.v1, q.v2, q.v3, zero(q.s), zero(q.s), zero(q.s), zero(q.s), q.norm) Octonion(s::Real, a::Vector) = Octonion(s, a[1], a[2], a[3], a[4], a[5], a[6], a[7]) Octonion(a::Vector) = Octonion(0, a[1], a[2], a[3], a[4], a[5], a[6], a[7]) @@ -29,8 +25,6 @@ const OctonionF32 = Octonion{Float32} const OctonionF64 = Octonion{Float64} promote_rule(::Type{Octonion{T}}, ::Type{S}) where {T <: Real, S <: Real} = Octonion{promote_type(T, S)} -promote_rule(::Type{Octonion{T}}, ::Type{Complex{S}}) where {T <: Real, S <: Real} = Octonion{promote_type(T, S)} -promote_rule(::Type{Octonion{T}}, ::Type{Quaternion{S}}) where {T <: Real, S <: Real} = Octonion{promote_type(T, S)} promote_rule(::Type{Octonion{T}}, ::Type{Octonion{S}}) where {T <: Real, S <: Real} = Octonion{promote_type(T, S)} octo(p, v1, v2, v3, v4, v5, v6, v7) = Octonion(p, v1, v2, v3, v4, v5, v6, v7) @@ -148,7 +142,8 @@ function log(o::Octonion) o.v6 * M, o.v7 * M) else - return Octonion(complex(log(a), ifelse(iszero(a), zero(th), th))) + z = zero(th) + return Octonion(log(a), ifelse(iszero(a), z, th), z, z, z, z, z, z) end end diff --git a/test/octonion.jl b/test/octonion.jl index b29e925..0553327 100644 --- a/test/octonion.jl +++ b/test/octonion.jl @@ -1,9 +1,19 @@ using LinearAlgebra using Octonions -using Quaternions: Quaternion, QuaternionF64 +using Quaternions: Quaternions, Quaternion, QuaternionF64 using Random using Test +_octo(a::Real) = octo(a) +function _octo(c::Complex{T}) where T + z = zero(T) + return octo(reim(c)..., z, z, z, z, z, z) +end +function _octo(q::Quaternion{T}) where T + z = zero(T) + return octo(real(q), Quaternions.imag_part(q)..., z, z, z, z) +end + @testset "Octonion" begin @testset "type aliases" begin @test OctonionF16 === Octonion{Float16} @@ -33,26 +43,6 @@ using Test @test @inferred(Octonion(T(x))) === Octonion{T}(coef..., isone(abs(x))) end end - @testset "from complex" begin - @testset for z in (1 + 0im, -im, 1 + 2im), - T in (Float32, Float64, Int, Rational{Int}) - - coef = T.((reim(z)..., zeros(6)...)) - z2 = Complex{T}(z) - norm = isone(abs(z)) - @test Octonion{T}(z) === Octonion{T}(coef..., norm) - @test @inferred(Octonion(z2)) === Octonion{T}(coef..., norm) - end - end - @testset "from quaternion" begin - qs = (Quaternion(1, 2, 3, 4), QuaternionF64(0, 1, 0, 0, true)) - @testset for q in qs, T in (Float32, Float64) - coef = T.((q.s, q.v1, q.v2, q.v3, zeros(4)...)) - q2 = Quaternion{T}(q) - @test @inferred(Octonion{T}(q)) === Octonion{T}(coef..., q.norm) - @test @inferred(Octonion(q2)) === Octonion{T}(coef..., q.norm) - end - end @testset "from octonion" begin os = ( Octonion(1, 2, 3, 4, 5, 6, 7, 8), OctonionF64(0, 1, 0, 0, 0, 0, 0, 0, true) @@ -80,12 +70,6 @@ using Test @testset "convert" begin @test convert(Octonion{Float64}, 1) === Octonion(1.0) - @test convert(Octonion{Float64}, Complex(1, 2)) === - Octonion(1.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) - @test convert(Octonion{Float64}, Quaternion(1, 2, 3, 4)) === - Octonion(1.0, 2.0, 3.0, 4.0, 0.0, 0.0, 0.0, 0.0) - @test convert(Octonion{Float64}, Quaternion(0, 1, 0, 0, true)) === - Octonion(0.0, 1.0, 0.0, 0.0, 0, 0, 0, 0, true) @test convert(Octonion{Float64}, Octonion(1, 2, 3, 4, 5, 6, 7, 8)) === Octonion(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0) @test convert(Octonion{Float64}, Octonion(0, 0, 0, 0, 1, 0, 0, 0, true)) === @@ -96,16 +80,9 @@ using Test @test promote(Octonion(1.0, 2:8...), 1.0) === (Octonion(1.0, 2:8...), Octonion(1.0)) @test promote(Octonion(1.0f0, 2:8...), 2.0) === (Octonion(1.0, 2:8...), Octonion(2.0)) - @test promote(Octonion(1.0f0), 2 + 3im) === - (Octonion(1.0f0), Octonion(2.0f0 + 3.0f0im)) - @test promote(Octonion(1.0f0), Quaternion(1, 2, 3, 4)) === - (Octonion(1.0f0), Octonion(1.0f0:4.0f0..., fill(0, 4)...)) @test promote(Octonion(1.0f0), Octonion(2.0)) === (Octonion(1.0), Octonion(2.0)) @test Octonion(1) == 1.0 - @test Octonion(1, 2, fill(0, 6)...) == Complex(1.0, 2.0) - @test Octonion(1) == 1.0 - @test Octonion(1:4..., fill(0, 4)...) == Quaternion(1.0:4.0...) end @testset "shorthands" begin @@ -209,8 +186,8 @@ using Test test_multiplicative(q1, q2, *, norm) # complex embedding - test_multiplicative(c1, c2, *, Octonion) - test_multiplicative(c1, c2, +, Octonion) + test_multiplicative(c1, c2, *, _octo) + test_multiplicative(c1, c2, +, _octo) end end @@ -371,8 +348,7 @@ using Test @test q7 * q6 == q3 @test q7 * q7 == -q0 - @testset "* same between Quaternions and Octonion" begin - # make sure this tracks the `*` tests for Quaternions + @testset "* same between quaternion and Octonion" begin q1 = Octonion(1,0,0,0,0,0,0,0) qi = Octonion(0,1,0,0,0,0,0,0) qj = Octonion(0,0,1,0,0,0,0,0) @@ -446,8 +422,8 @@ using Test for _ in 1:100 o1, o2 = randn(OctonionF64, 2) q = randn(QuaternionF64) - o = octo(q) - @test @inferred(fun(o)) ≈ fun(q) + o = _octo(q) + @test @inferred(fun(o)) ≈ _octo(fun(q)) @test o2 * fun(o1) * inv(o2) ≈ fun(o2 * o1 * inv(o2)) end end @@ -461,8 +437,8 @@ using Test for _ in 1:100 o1, o2 = randn(OctonionF64, 2) q = randn(QuaternionF64) - o = octo(q) - @test @inferred(fun(o)) ≈ fun(q) + o = _octo(q) + @test @inferred(fun(o)) ≈ _octo(fun(q)) @test o2 * fun(o1) * inv(o2) ≈ fun(o2 * o1 * inv(o2)) end end