The following is taken from statistics.jl line 428 

    function cor(x::AbstractVector, y::AbstractVector; mean=nothing)
        mean == 0 ? corzm(x, y) :
        mean == nothing ? corm(x, Base.mean(x), y, Base.mean(y)) :
        isa(mean, (Number,Number)) ? corm(x, mean[1], y, mean[2]) :
        error("Invalid value of mean.")
    end

due to the 'mean' initially having a type of 'Nothing' I am unable to 
inference the return type of the function - the following will return Any 
for the return type.

    rt = {}
    for x in Base._methods(f,types,-1)
        linfo = x[3].func.code
        (tree, ty) = Base.typeinf(linfo, x[1], x[2])
        push!(rt, ty)
    end

Each of the underlying functions are type stable when called directly. 

Code lowered doesn't give much of a pointer to what will actually happen 
here, 

julia> code_lowered( cor, ( Vector{Float64}, Vector{Float64} ) )
1-element Array{Any,1}:
 :($(Expr(:lambda, {:x,:y}, {{},{{:x,:Any,0},{:y,:Any,0}},{}}, :(begin $(
Expr(:line, 429, symbol("statistics.jl"), symbol("")))
        return __cor#195__(nothing,x,y)
    end))))


If I re-write with a regular optional arg for the mean 

code_lowered( cordf, ( Vector{Float64}, Vector{Float64}, Nothing ) )
1-element Array{Any,1}:
 :($(Expr(:lambda, {:x,:y,:mean}, {{},{{:x,:Any,0},{:y,:Any,0},{:mean,:Any,0
}},{}}, :(begin  # none, line 2:
        unless mean == 0 goto 0
        return corzm(x,y)
        0: 
        unless mean == nothing goto 1
        return corm(x,((top(getfield))(Base,:mean))(x),y,((top(getfield))(
Base,:mean))(y))
        1: 
        unless isa(mean,(top(tuple))(Number,Number)) goto 2
        return corm(x,getindex(mean,1),y,getindex(mean,2))
        2: 
        return error("Invalid value of mean.")
    end))))

The LLVM code does not look very clean, If I have a real type for the mean 
(say Float64 ) it looks better  88 lines vs 140 

julia> code_llvm( cor, ( Vector{Float64}, Vector{Float64}, Nothing ) )


define %jl_value_t* @julia_cordf_20322(%jl_value_t*, %jl_value_t*, %
jl_value_t*) {
top:
  %3 = alloca [7 x %jl_value_t*], align 8
  %.sub = getelementptr inbounds [7 x %jl_value_t*]* %3, i64 0, i64 0
  %4 = getelementptr [7 x %jl_value_t*]* %3, i64 0, i64 2, !dbg !949
  store %jl_value_t* inttoptr (i64 10 to %jl_value_t*), %jl_value_t** %.sub, 
align 8
  %5 = getelementptr [7 x %jl_value_t*]* %3, i64 0, i64 1, !dbg !949
  %6 = load %jl_value_t*** @jl_pgcstack, align 8, !dbg !949
  %.c = bitcast %jl_value_t** %6 to %jl_value_t*, !dbg !949
  store %jl_value_t* %.c, %jl_value_t** %5, align 8, !dbg !949
  store %jl_value_t** %.sub, %jl_value_t*** @jl_pgcstack, align 8, !dbg !949
  store %jl_value_t* null, %jl_value_t** %4, align 8
  %7 = getelementptr [7 x %jl_value_t*]* %3, i64 0, i64 3
  store %jl_value_t* null, %jl_value_t** %7, align 8
  %8 = getelementptr [7 x %jl_value_t*]* %3, i64 0, i64 4
  store %jl_value_t* null, %jl_value_t** %8, align 8
  %9 = getelementptr [7 x %jl_value_t*]* %3, i64 0, i64 5
  store %jl_value_t* null, %jl_value_t** %9, align 8
  %10 = getelementptr [7 x %jl_value_t*]* %3, i64 0, i64 6
  store %jl_value_t* null, %jl_value_t** %10, align 8
  %11 = load %jl_value_t** inttoptr (i64 52494032 to %jl_value_t**), align 
16, !dbg !950
  %12 = call i32 @jl_egal(%jl_value_t* %2, %jl_value_t* %11), !dbg !950
  %13 = and i32 %12, 1, !dbg !950
  %14 = icmp eq i32 %13, 0, !dbg !950
  br i1 %14, label %L7, label %if1, !dbg !950


if1:                                              ; preds = %top
  %15 = load %jl_value_t** inttoptr (i64 116157440 to %jl_value_t**), align 
1024, !dbg !950
  %16 = icmp eq %jl_value_t* %15, null, !dbg !950
  br i1 %16, label %err2, label %ok3, !dbg !950


err2:                                             ; preds = %if1
  call void @jl_undefined_var_error(%jl_value_t* inttoptr (i64 
140022028478128 to %jl_value_t*)), !dbg !950
  unreachable


ok3:                                              ; preds = %if1
  %17 = getelementptr inbounds %jl_value_t* %15, i64 0, i32 0, !dbg !950
  %18 = load %jl_value_t** %17, align 8, !dbg !950
  %magicptr = ptrtoint %jl_value_t* %18 to i64, !dbg !950
  switch i64 %magicptr, label %notf4 [
    i64 23428288, label %isf5
    i64 23296304, label %isf5
  ], !dbg !950
....

lots more removed


You can resolve this by writing something like the below, but this doesn't 
handle the case where the two vectors are of different types. Just making 
two versions of the function one with mean and one without would almost 
certainly be cleaner. 

function cor{T<:Number}(x::Vector{T}, y::Vector{T}; corrected::Bool=true, 
mean=nothing)    
    if( mean == nothing )
        covnomean( x,y,corrected )
    else
        mymean::T = convert( T, mean )
        covmean( x, y, corrected, mymean )
    end    
end

Is this intended behavior, how concerned should I be? 



Reply via email to