Yes, this seems odd.  I think it's a bug.  First, this also works:

function scale!{T<:Number}(A::Tridiagonal{T}, x::T)
           Base.scale!(A.dl, x) 
           Base.scale!(A.d,  x)
           Base.scale!(A.du, x)
           return
end

and is probably what you want as T needs to be a number for this to make
sense.  Still:

I tried reproducing this with another function, which then gives the
expected ambiguity warning:

julia> f{T,N}(X::AbstractArray{T,N},s::Number) = 1
f (generic function with 1 method)

julia> f{T}(X::Tridiagonal{T},s::T) = 1
Warning: New definition 
    f(Tridiagonal{T},T) at none:1
is ambiguous with: 
    f(AbstractArray{T,N},Number) at none:1.
To fix, define 
    f(Tridiagonal{_<:Number},_<:Number)
before the new definition.
f (generic function with 2 methods)

julia> f{T<:Number}(X::Tridiagonal{T},s::T) = 1
f (generic function with 3 methods)

I think you're right, the scale! definition as you tried should give an
ambiguity warning but it doesn't.  A bug.

Then trying changing the order of above definitions does not give an
ambiguity warning either.  I would have thought that ambiguities should
be commutative?

julia> f{T}(X::Tridiagonal{T},s::T) = 1
f (generic function with 1 method)

julia> A=Tridiagonal(rand(3),rand(4),rand(3));

julia> f(A, 1.)
1

julia> f{T,N}(X::AbstractArray{T,N},s::Number) = 2
f (generic function with 2 methods)

julia> f(A, 1.)
1

julia> f(rand(3,3), 1.)
2

julia> f{T<:Number}(X::Tridiagonal{T},s::T) = 3
f (generic function with 3 methods)

julia> f(A, 1.)
3


On Tue, 2014-07-01 at 06:46, [email protected] wrote:
> I wanted a scale! method that works for tridiagonal matrices and did the 
> following.
>
> import Base.scale!
>
> function scale!{T}(A::Tridiagonal{T}, x::T)
>     Base.scale!(A.dl, x) 
>     Base.scale!(A.d,  x)
>     Base.scale!(A.du, x)
>     return
> end
>
> Doing 
>
> methods(scale!)
>
> gives the output
>
> # 15 methods for generic function "scale!":
> scale!{T<:Union(Complex{Float64},Float32,Complex{Float32},Float64)}(X::Array{T<:Union(Complex{Float64},Float32,Complex{Float32},Float64),N},s::T<:Union(Complex{Float64},Float32,Complex{Float32},Float64))
>  
> at linalg/dense.jl:11
> ...
> scale!(X::AbstractArray{T,N},s::Number) at linalg/generic.jl:20
> ...
> (A::CholmodSparse{T<:Union(Complex{Float64},Float32,Complex{Float32},Float64),Ti<:Union(Int64,Int32)},b::Array{T<:Union(Complex{Float64},Float32,Complex{Float32},Float64),1})
>  
> at linalg/cholmod.jl:907
> scale!{T}(A::Tridiagonal{T},x::T) at none:2
>
> however
>
> A=Tridiagonal(rand(3),rand(4),rand(3))
> 4x4 Tridiagonal{Float64}:
>  0.342959   0.878001  0.0        0.0     
>  0.0359927  0.481333  0.950373   0.0     
>  0.0        0.764103  0.0200941  0.84859 
>  0.0        0.0       0.220059   0.131956
>
> scale!(A,2.0)
> ERROR: indexing not defined for Tridiagonal{Float64}
>  in generic_scale! at linalg/generic.jl:16
>  in scale! at linalg/generic.jl:20
>
> We can verify that Julia is not dispatching to the tridiagonal scale! 
> method:
>
> which(scale!, (Tridiagonal{Float64},Float64))
> scale!(X::AbstractArray{T,N},s::Number) at linalg/generic.jl:20
>
> If I change the first line of the function definition to
>
> function scale!(A::Tridiagonal,x)
>
> then I get some ambiguity warnings:
>
> Warning: New definition 
>     scale!(Tridiagonal{T},Any) at none:2
> is ambiguous with: 
>     scale!(AbstractArray{T,N},Number) at linalg/generic.jl:20.
> To fix, define 
>     scale!(Tridiagonal{T},Number)
> before the new definition.
> Warning: New definition 
>     scale!(Tridiagonal{T},Any) at none:2
> is ambiguous with: 
>     scale!(AbstractArray{T,2},AbstractArray{T,1}) at linalg/generic.jl:306.
> To fix, define 
>     scale!(Tridiagonal{T},AbstractArray{T,1})
> before the new definition.
> scale! (generic function with 15 methods)
>
> Sure enough, defining 
>
> function scale!(A::Tridiagonal, x::Number)
>     Base.scale!(A.dl, x)
>     Base.scale!(A.d,  x)
>     Base.scale!(A.du, x)
>     return
> end
>
> works fine. I am a bit mystified by this behaviour.  Why was there no 
> warning for my first attempt?
> Is there a problem in general with making a method "too specific"?


Reply via email to