Code specialization on literals for addition and multiplication operators

Hi !

This code is working:

struct MP v::Float64 end
Base.:(*)(x::MP, y::MP) = MP(x.v + y.v)
Base.:(*)(x::MP, y::Real) = MP(x.v + y)
Base.:(*)(x::Real, y::MP) = MP(x + y.v)

But on a corner case, this is giving me correct result point of view a computer science :

julia> MP(-Inf) * MP(Inf)
MP(NaN)

But I want to force it to return a different result in accordance to my algebra => MP(-Inf). I tried to follow the idea base on literal_pow but without success:

@inline Base.:(*)(::Val{MP(Inf)}, ::Val{MP(-Inf)}) = MP(-Inf)
@inline Base.:(*)(::Val{MP(-Inf)}, ::Val{MP(Inf)}) = MP(-Inf)

Still returning me NaN. I succeeded with literal_pow but for operators + and * seems the compiler is not working in the same manner. How to reach the same result without adding an if-then-else in my function ?

Thanks in advance !

You can’t. You can only dispatch on types, not on values. literal_pow is a special case in lowering, so there is no way to extend it to other functions or non-literals. Using an if condition should be just as fast though.

2 Likes

Thanks ! Bad news :frowning:

This is working Val(MP(Inf)) * Val(MP(-Inf)) so maybe I’ll have to create a special type.