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Δ
?