I have a struct and a simple function:
struct SU2Element <: AbstractMatrix{ComplexF64}
t₁::ComplexF64
t₂::ComplexF64
function SU2Element(t₁::Number, t₂::Number)
SU2Element(ComplexF64(t₁), ComplexF64(t₂))
end
function SU2Element(t₁::ComplexF64, t₂::ComplexF64)
new(t₁, t₂)
end
end
function normalizeSU2(S::SU2Element)
sqrtΔ = √det(S)
t₁ = S.t₁ / sqrtΔ
t₂ = S.t₂ / sqrtΔ
SU2Element(t₁, t₂)
end
This basically takes an SU2Element <: AbstractMatrix{Complex} and normalizes it to have determinant 1.
In an external function, I need to construct an SU2Element and normalize it, but I also need sqrtΔ before the normalization. Since I think it is pointless to calculate sqrtΔ in normalizeSU2 just to have it dropped and recalculated outside, I though of returning sqrtΔ from normalizeSU2 in a tuple, like this:
function normalizeSU2(S::SU2Element, returndet = false)
sqrtΔ = √det(S)
t₁ = S.t₁ / sqrtΔ
t₂ = S.t₂ / sqrtΔ
if returndet
SU2Element(t₁, t₂), sqrtΔ
else
SU2Element(t₁, t₂)
end
end
The problem with this approach is that it is not type stable. I know I shouldn’t optimize prematurely, but this function gets called a lot in a hot loop, and having already recognized the type instability, I though of trying to solve it.
One solution is to always return SU2Element(t₁, t₂), sqrtΔ and just not use sqrtΔ in places I don’t need it. But this seems a bit off, I would prefer for the function to return sqrtΔ when I’m explicit about it.
Another approach is to just have two different functions with different names, which works and it is explicit, but also knowing how powerful Julia is, I would like to at least try to find a more Julian solution.
Finally, I could pass Val(true) or Val(false) and dispatch on that, but that would require me to pass Val(false) every time I don’t need sqrtΔ which is a bit annoying.
Is there a nice way of solving this, that lets me call normalizeSU2(S) and have only SU2Element returned, and be explicit when I need sqrtΔ?