# Qr of custom number type works but svd fails to find a method

**URL:** <https://discourse.julialang.org/t/qr-of-custom-number-type-works-but-svd-fails-to-find-a-method/43226>\
**Category:** General Usage\
**Tags:** type\
**Created:** [July 17, 2020, 9:44am UTC](https://discourse.julialang.org/t/qr-of-custom-number-type-works-but-svd-fails-to-find-a-method/43226 "2020-07-17T09:44:47Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![tomohiro\_soejima](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomohiro_soejima/32/8056_2.png) [@tomohiro\_soejima](https://discourse.julialang.org/u/tomohiro_soejima)\
**Post date:** [July 17, 2020, 9:44am UTC](https://discourse.julialang.org/t/qr-of-custom-number-type-works-but-svd-fails-to-find-a-method/43226/1 "2020-07-17T09:44:47Z")

</div>

Hi,

I’ve been playing around with implementing `MyQuaternion` type to demonstrate versatility of Julia’s type system to newcomers. I managed to get QR to work, but svd fails for some reason. Here is my implementation:

```julia
using Random
using LinearAlgebra
struct MyQuaternion{T} <: Number
    a :: T
    b :: T
    c :: T
    d :: T
end

Base.conj(a :: MyQuaternion{T}) where T = MyQuaternion{T}(a.a, -a.b, -a.c, -a.d)
Base.:+(a :: MyQuaternion{T}, b :: MyQuaternion{T}) where {T} = MyQuaternion{T}( a.a + b.a, a.b + b.b, a.c + b.c, a.d + b.d)
Base.:-(a :: MyQuaternion{T}) where {T} = MyQuaternion{T}(-a.a, -a.b, -a.c, -a.d)
Base.:-(a :: MyQuaternion{T}, b :: MyQuaternion{T}) where {T} = MyQuaternion{T}( a.a - b.a, a.b - b.b, a.c - b.c, a.d - b.d)
Base.:*(a :: MyQuaternion{T}, b :: MyQuaternion{T}) where {T} = MyQuaternion{T}( a.a * b.a - a.b * b.b - a.c * b.c - a.d * b.d,
                                                                                     a.a * b.b + a.b * b.a + a.c * b.d - a.d * b.c,
                                                                                     a.a * b.c + a.c * b.a + a.d * b.b - a.b * b.d,
                                                                                     a.a * b.d + a.d * b.a + a.b * b.c - a.c * b.b)
Base.:/(a :: MyQuaternion{T}, b :: T) where {T<:Number} = a * inv(b)
Base.:/(a :: MyQuaternion{T}, b :: MyQuaternion{T}) where {T} = a * inv(b)
Base.inv(a :: MyQuaternion{T}) where T = conj(a) / (a.a^2 + a.b^2 + a.c^2 + a.d^2)

Base.zero(::Type{MyQuaternion{T}}) where {T} = MyQuaternion{T}(zero(T),zero(T),zero(T),zero(T))
Random.rand(rng::AbstractRNG, ::Random.SamplerType{MyQuaternion{T}}) where T = MyQuaternion{T}(rand(T), rand(T), rand(T), rand(T))
Base.promote_rule(::Type{S}, ::Type{MyQuaternion{T}}) where {T, S} = MyQuaternion{promote_type(T, S)}
Base.convert(::Type{MyQuaternion{T}}, x::S) where {T, S<:Real} = MyQuaternion{promote_type(T, S)}(x, zero(promote_type(T, S)), zero(promote_type(T, S)), zero(promote_type(T, S)))
Base.real(x::MyQuaternion) = x.a
Base.abs2(x::MyQuaternion) = x.a^2 + x.b^2 + x.c^2 + x.d^2
Base.promote_rule(::Type{Bool}, ::Type{MyQuaternion{T}}) where T = MyQuaternion{T}

```

QR works just fine

```julia
A = rand(MyQuaternion{Float64}, 100, 100)
Q, R = qr(A)
Q * R == A # this is approximately true

```

However, svd `F = svd(A)` fails with the following error.

```julia
MethodError: no method matching svd!(::Array{MyQuaternion{Float64},2}; full=false, alg=LinearAlgebra.DivideAndConquer())
Closest candidates are:
  svd!(!Matched::LinearAlgebra.AbstractTriangular; kwargs...) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.4/LinearAlgebra/src/triangular.jl:2631
  svd!(!Matched::Union{DenseArray{T,2}, Base.ReinterpretArray{T,2,S,A} where S where A<:Union{SubArray{T,N,A,I,true} where I<:Union{Tuple{Vararg{Real,N} where N}, Tuple{AbstractUnitRange,Vararg{Any,N} where N}} where A<:DenseArray where N where T, DenseArray}, Base.ReshapedArray{T,2,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:Union{Base.ReinterpretArray{T,N,S,A} where S where A<:Union{SubArray{T,N,A,I,true} where I<:Union{Tuple{Vararg{Real,N} where N}, Tuple{AbstractUnitRange,Vararg{Any,N} where N}} where A<:DenseArray where N where T, DenseArray} where N where T, SubArray{T,N,A,I,true} where I<:Union{Tuple{Vararg{Real,N} where N}, Tuple{AbstractUnitRange,Vararg{Any,N} where N}} where A<:DenseArray where N where T, DenseArray}, SubArray{T,2,A,I,L} where L where I<:Tuple{Vararg{Union{Int64, AbstractRange{Int64}, Base.AbstractCartesianIndex},N} where N} where A<:Union{Base.ReinterpretArray{T,N,S,A} where S where A<:Union{SubArray{T,N,A,I,true} where I<:Union{Tuple{Vararg{Real,N} where N}, Tuple{AbstractUnitRange,Vararg{Any,N} where N}} where A<:DenseArray where N where T, DenseArray} where N where T, Base.ReshapedArray{T,N,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:Union{Base.ReinterpretArray{T,N,S,A} where S where A<:Union{SubArray{T,N,A,I,true} where I<:Union{Tuple{Vararg{Real,N} where N}, Tuple{AbstractUnitRange,Vararg{Any,N} where N}} where A<:DenseArray where N where T, DenseArray} where N where T, SubArray{T,N,A,I,true} where I<:Union{Tuple{Vararg{Real,N} where N}, Tuple{AbstractUnitRange,Vararg{Any,N} where N}} where A<:DenseArray where N where T, DenseArray} where N where T, DenseArray}}; full, alg) where T<:Union{Complex{Float32}, Complex{Float64}, Float32, Float64} at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.4/LinearAlgebra/src/svd.jl:94
  svd!(!Matched::Union{DenseArray{T,2}, Base.ReinterpretArray{T,2,S,A} where S where A<:Union{SubArray{T,N,A,I,true} where I<:Union{Tuple{Vararg{Real,N} where N}, Tuple{AbstractUnitRange,Vararg{Any,N} where N}} where A<:DenseArray where N where T, DenseArray}, Base.ReshapedArray{T,2,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:Union{Base.ReinterpretArray{T,N,S,A} where S where A<:Union{SubArray{T,N,A,I,true} where I<:Union{Tuple{Vararg{Real,N} where N}, Tuple{AbstractUnitRange,Vararg{Any,N} where N}} where A<:DenseArray where N where T, DenseArray} where N where T, SubArray{T,N,A,I,true} where I<:Union{Tuple{Vararg{Real,N} where N}, Tuple{AbstractUnitRange,Vararg{Any,N} where N}} where A<:DenseArray where N where T, DenseArray}, SubArray{T,2,A,I,L} where L where I<:Tuple{Vararg{Union{Int64, AbstractRange{Int64}, Base.AbstractCartesianIndex},N} where N} where A<:Union{Base.ReinterpretArray{T,N,S,A} where S where A<:Union{SubArray{T,N,A,I,true} where I<:Union{Tuple{Vararg{Real,N} where N}, Tuple{AbstractUnitRange,Vararg{Any,N} where N}} where A<:DenseArray where N where T, DenseArray} where N where T, Base.ReshapedArray{T,N,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:Union{Base.ReinterpretArray{T,N,S,A} where S where A<:Union{SubArray{T,N,A,I,true} where I<:Union{Tuple{Vararg{Real,N} where N}, Tuple{AbstractUnitRange,Vararg{Any,N} where N}} where A<:DenseArray where N where T, DenseArray} where N where T, SubArray{T,N,A,I,true} where I<:Union{Tuple{Vararg{Real,N} where N}, Tuple{AbstractUnitRange,Vararg{Any,N} where N}} where A<:DenseArray where N where T, DenseArray} where N where T, DenseArray}}, !Matched::Union{DenseArray{T,2}, Base.ReinterpretArray{T,2,S,A} where S where A<:Union{SubArray{T,N,A,I,true} where I<:Union{Tuple{Vararg{Real,N} where N}, Tuple{AbstractUnitRange,Vararg{Any,N} where N}} where A<:DenseArray where N where T, DenseArray}, Base.ReshapedArray{T,2,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:Union{Base.ReinterpretArray{T,N,S,A} where S where A<:Union{SubArray{T,N,A,I,true} where I<:Union{Tuple{Vararg{Real,N} where N}, Tuple{AbstractUnitRange,Vararg{Any,N} where N}} where A<:DenseArray where N where T, DenseArray} where N where T, SubArray{T,N,A,I,true} where I<:Union{Tuple{Vararg{Real,N} where N}, Tuple{AbstractUnitRange,Vararg{Any,N} where N}} where A<:DenseArray where N where T, DenseArray}, SubArray{T,2,A,I,L} where L where I<:Tuple{Vararg{Union{Int64, AbstractRange{Int64}, Base.AbstractCartesianIndex},N} where N} where A<:Union{Base.ReinterpretArray{T,N,S,A} where S where A<:Union{SubArray{T,N,A,I,true} where I<:Union{Tuple{Vararg{Real,N} where N}, Tuple{AbstractUnitRange,Vararg{Any,N} where N}} where A<:DenseArray where N where T, DenseArray} where N where T, Base.ReshapedArray{T,N,A,MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64},N} where N} where A<:Union{Base.ReinterpretArray{T,N,S,A} where S where A<:Union{SubArray{T,N,A,I,true} where I<:Union{Tuple{Vararg{Real,N} where N}, Tuple{AbstractUnitRange,Vararg{Any,N} where N}} where A<:DenseArray where N where T, DenseArray} where N where T, SubArray{T,N,A,I,true} where I<:Union{Tuple{Vararg{Real,N} where N}, Tuple{AbstractUnitRange,Vararg{Any,N} where N}} where A<:DenseArray where N where T, DenseArray} where N where T, DenseArray}}) where T<:Union{Complex{Float32}, Complex{Float64}, Float32, Float64} at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.4/LinearAlgebra/src/svd.jl:365 got unsupported keyword arguments "full", "alg"
  ...

Stacktrace:
 [1] svd(::Array{MyQuaternion{Float64},2}; full::Bool, alg::LinearAlgebra.DivideAndConquer) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.4/LinearAlgebra/src/svd.jl:158
 [2] svd(::Array{MyQuaternion{Float64},2}) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.4/LinearAlgebra/src/svd.jl:158
 [3] top-level scope at In[20]:1

```

Any idea why svd fails? It’s weird to me that it seems to be failing at method lookup. I’m using version 1.4.2.

Thanks in advance!

---

<div class="post-metadata">

**Author:** ![tomohiro\_soejima](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomohiro_soejima/32/8056_2.png) [@tomohiro\_soejima](https://discourse.julialang.org/u/tomohiro_soejima)\
**Post date:** [July 17, 2020, 9:46am UTC](https://discourse.julialang.org/t/qr-of-custom-number-type-works-but-svd-fails-to-find-a-method/43226/2 "2020-07-17T09:46:35Z")

</div>

I should add that when I was prototyping it, I got it to work a couple of times, during which `svd` printed something like “ignoring `alg` for generic SVD”. However, I have not been able to reproduce it since.

---

<div class="post-metadata">

**Author:** ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)\
**Post date:** [July 17, 2020, 12:08pm UTC](https://discourse.julialang.org/t/qr-of-custom-number-type-works-but-svd-fails-to-find-a-method/43226/3 "2020-07-17T12:08:06Z")

</div>

Try loading either GenericLinearAlgebra or GenericSVD
