How to best program this function with cases?

I have this function that depends on cases i. I programmed it this way, but I am wondering if there is a better way of achieving the same result and with better performance.

using ComponentArrays

θ = ComponentArray(one=(α=0.1, γ=[0.2, 0.3]), two=(α=1.0, γ=[2.0, 3.0]))

function Zi(i, si; θ=θ)
    if i == 1
        α = θ.one.α
        γ = copy(θ.one.γ)
    elseif i == 2
        α = θ.two.α
        γ = copy(θ.two.γ)
    end
    α = exp(α)
    γ .= exp.(γ)
    abs(si)^α + sum(γ)
end

I also tried using value types, with a half the performance:

function _Zi(si, α, γ)
    α = exp(α)
    γ .= exp.(γ)
    abs(si)^α + sum(γ)
end

function Zi(::Val{1}, si; θ=θ)
    α = θ.one.α
    γ = copy(θ.one.γ)
    _Zi(si, α, γ)
end

function Zi(::Val{2}, si; θ=θ)
    α = θ.two.α
    γ = copy(θ.two.γ)
    _Zi(si, α, γ)
end

Why not just

α = [0.1, 1,0]
γ = [[0.2, 0.3], [2.0, 3.0]]

function Zi(i, si; α=α, γ=γ)
    α = exp(α[i])
    γ .= exp.(copy(γ[i]))
    abs(si)^α + sum(γ)
end
2 Likes

Creating value types from values not known at compile time forces dynamic dispatch. The situations for using them are very rare.

4 Likes

I guess I have a problem of trying to use ComponentArrays too early into basic functions.

The way I look at it is that if you want your components to be numbers, you should just be using numbers instead of components. Components are useful for things like dimension names, but if you only want numbers, just use those.

1 Like

I use it for separating components of complex models. For example:

You could do it this way, although the inner-arrays-of-components thing is not quite as performant or flexible as I’d like it to be. The performance is more tuned for looping over inner arrays of components rather than indexing into them. And as for the limitations on flexibility: each component in the array must be the same size/type/layout. In this case it looks like you’re fine there, though.

using ComponentArrays

θ = ComponentArray(θ=[(α=0.1, γ=[0.2, 0.3]), (α=1.0, γ=[2.0, 3.0])])

function Zi(i, si; θ=θ)
    θ = θ.θ
    α = θ[i].α
    γ = copy(θ[i].γ)
    α = exp(α)
    γ .= exp.(γ)
    abs(si)^α + sum(γ)
end
1 Like