Dear julia users,

When looking at e.g. BLAS functions, they have a general format of adding a 
scaled result array to an existing array, which itself can also be scaled; 
e.g. AB could be the result of a matrix multiplication of matrices A and B, 
and the BLAS gemm! function (using Julia's name) allows to store 
alpha*AB+beta*C into C. Looking at the high-performant microkernels of 
BLAS, they specialize on the different possibilities for alpha and beta 
using if constructions:

if beta == 0
 # do not actually compute C*0 since that could produce NaN if C was not 
initialized and contains NaN or infinity
 # instead set C to zero
elseif beta != 1
 # only scale C if beta is not 1
end
if alpha == 1
 # immediately add AB, do not scale with alpha
else
 # C+=alpha * AB
end

In writing something related in Julia, I thought this would be a perfect 
case for dispatch. The high performant low level function could just 
contain the general statement C=beta*C+alpha*AB and it would be called in a 
high level function as (note that I am not actually trying to reimplement 
gemm!, this is just as an example)

gemm!((beta == 1 ? _one : (beta == 0 ?_zero : beta)) , C, (alpha == 1 ?_one 
: alpha), A,B)


in combination with the following definitions

immutable Zero <: Integer
end
immutable One <: Integer
end

const _zero = Zero()
const _one = One()

Base.promote_rule{T<:Number}(::Type{Zero}, ::Type{T}) = T
Base.promote_rule{T<:Number}(::Type{One}, ::Type{T}) = T

Base.convert{T<:Number}(::Type{T}, ::Zero) = zero(T)
Base.convert{T<:Number}(::Type{T}, ::One) = one(T)

# add special rules, the most essential of which are:
+(::Zero, a::Number) = a
+(::Number, a::Zero) = a
*(::Zero, a::Number) = _zero
*(a::Number, ::Zero) = _zero

*(::One, a::Number) = a
*(a::Number, ::One) = a


Unfortunately this produces a lot of ambiguity warnings. Of course I need 
to add the rules for +(::Zero,::Zero) etc, i.e. the interaction of my newly 
defined types with themselves. But this is not sufficient. The remaining 
addition and multiplication ambiguities can be avoided by defining them 
separately for a::Real and a::Complex. But the most difficult one is the 
convert definition, which is ambiguous with almost any other number type 
out there.

I am aware of the many ambiguity related issues and the proposal to make 
those runtime errors instead of warnings, but I have the feeling that there 
might be a more specific solution for what I am trying to accomplish and 
that I am missing something trivial. I know there are several other number 
types defined in packages, and I assume the corresponding authors must have 
faced similar problems? So I appreciate any tips or input.

Reply via email to