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

Broadcast algebra

Open moble opened this issue 4 years ago • 3 comments

We should be able to broadcast-multiply floats with quaternions, but this errors out:

julia> t = collect(LinRange(-10, 10, 201));

julia> t .* imz
MethodError: no method matching Float64(::QuaternionF64)
Closest candidates are:
  (::Type{T})(::T) where T<:Number at boot.jl:760
  (::Type{T})(::AbstractChar) where T<:Union{AbstractChar, Number} at char.jl:50
  (::Type{T})(::Base.TwicePrecision) where T<:Number at twiceprecision.jl:243
  ...

Stacktrace:
  [1] convert(#unused#::Type{Float64}, x::QuaternionF64)
    @ Base ./number.jl:7
  [2] setindex!(A::Vector{Float64}, x::QuaternionF64, i1::Int64)
    @ Base ./array.jl:839
  [3] macro expansion
    @ ./broadcast.jl:984 [inlined]
  [4] macro expansion
    @ ./simdloop.jl:77 [inlined]
  [5] copyto!
    @ ./broadcast.jl:983 [inlined]
  [6] copyto!
    @ ./broadcast.jl:936 [inlined]
  [7] copy
    @ ./broadcast.jl:908 [inlined]
  [8] materialize(bc::Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1}, Nothing, typeof(*), Tuple{Vector{Float64}, Quaternion{Bool}}})
    @ Base.Broadcast ./broadcast.jl:883
  [9] top-level scope
    @ In[80]:1
 [10] eval
    @ ./boot.jl:360 [inlined]
 [11] include_string(mapexpr::typeof(REPL.softscope), mod::Module, code::String, filename::String)
    @ Base ./loading.jl:1094

moble avatar Jun 21 '21 19:06 moble

imz .* t too

moble avatar Jun 21 '21 19:06 moble

On the other hand, [imz] .* t and t .* [imz] work correctly...

moble avatar Jun 23 '21 00:06 moble

I think something like this might do what I need:

struct QuaternionStyle{T} <: Broadcast.BroadcastStyle where {T} end

function Base.BroadcastStyle(::Type{AT}) where {T, AT<:Quaternion{T}}
    QuaternionStyle{T}()
end
function Base.BroadcastStyle(::QuaternionStyle{T}, ::Base.Broadcast.DefaultArrayStyle{N}) where {T, N}
    return QuaternionStyle{T}()
end

function Base.similar(bc::Broadcast.Broadcasted{QuaternionStyle{T}}, ::Type{ElType}) where {T, ElType}
    similar(Array{Quaternion{promote_type(T, ElType)}}, axes(bc))
end

The main problem is what to do about the other subtypes with their special operations. Should I have those types broadcast to Quaternion by default, but then specialize broadcast for certain functions (*, /, +, -, exp, log, sqrt...) and combinations of subtypes?

moble avatar Jun 23 '21 04:06 moble