Repository: invenia/NamedDims.jl (julia)

Issue:
Method Ambiguous Error *(::Adjoint{Float64,Array{Float64,2}}, ::NamedDimsArray
MFE:
```
d = NamedDimsArray{(:features, :observations)}(rand(4, 10))
β = rand(4, 3)
β' * d[:, 1]
MethodError: *(::Adjoint{Float64,Array{Float64,2}}, ::NamedDimsArray{(:features,),Float64,1,Array{Float64,1}}) is ambiguous. Candidates:
  *(a::AbstractArray{T,2} where T, b::NamedDimsArray{#s19,#s20,1,A} where A<:AbstractArray{#s20,1} where #s20 where #s19) in NamedDims at /Users/alexr/.julia/packages/NamedDims/MjTg0/src/functions_math.jl:74
  *(adjA::Adjoint{#s623,#s622} where #s622<:AbstractArray{T,2} where #s623, x::AbstractArray{S,1}) where {T, S} in LinearAlgebra at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.1/LinearAlgebra/src/matmul.jl:103
Possible fix, define
  *(::Adjoint{#s623,#s622} where #s622<:AbstractArray{T,2} where #s623, ::NamedDimsArray{#s19,S,1,A} where A<:AbstractArray{S,1} where #s19)
```

Where as this is fine:
```
d = NamedDimsArray{(:features, :observations)}(rand(4, 10))
β = rand(4, 3)
collect(β') * d[:, 1]
```

Pull request:
Adds tests and the two methods which resolve the ambiguities. Closes #112 and closes #60.

Patch:
diff --git a/Project.toml b/Project.toml
index 5e0bbf9..61295b0 100644
--- a/Project.toml
+++ b/Project.toml
@@ -1,7 +1,7 @@
 name = "NamedDims"
 uuid = "356022a1-0364-5f58-8944-0da4b18d706f"
 authors = ["Invenia Technical Computing Corporation"]
-version = "0.2.22"
+version = "0.2.23"
 
 [deps]
 LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
diff --git a/src/functions_math.jl b/src/functions_math.jl
index cb434bf..019c5d5 100644
--- a/src/functions_math.jl
+++ b/src/functions_math.jl
@@ -43,7 +43,7 @@ function Base.:*(a::NamedDimsArray{L,T,2,<:CoVector}, b::AbstractVector) where {
     return *(parent(a), b)
 end
 
-# Using `CovVector` results in Method ambiguities; have to define more specific methods.
+# Using `CoVector` results in Method ambiguities; have to define more specific methods.
 for A in (Adjoint{<:Any, <:AbstractVector}, Transpose{<:Real, <:AbstractVector{<:Real}})
     @eval function Base.:*(a::$A, b::NamedDimsArray{L,T,1,<:AbstractVector{T}}) where {L,T}
         return *(a, parent(b))
@@ -78,7 +78,20 @@ macro declare_matmul(MatrixT, VectorT=nothing)
     return esc(Expr(:block, codes...))
 end
 
+# The following two methods can be defined by using
+# @declare_matmul(Diagonal, AbstractVector)
+# but that overwrites existing *(1D NDA, Vector) methods
+# should improve the macro above to deal with this case
+function Base.:*(a::Diagonal, b::NamedDimsArray{<:Any, <:Any, 1})
+    return *(NamedDimsArray{dimnames(a)}(a), b)
+end
+
+function Base.:*(a::NamedDimsArray{<:Any, <:Any, 1}, b::Diagonal)
+    return *(a, NamedDimsArray{dimnames(b)}(b))
+end
+
 @declare_matmul(AbstractMatrix, AbstractVector)
+@declare_matmul(Adjoint{<:Any, <:AbstractMatrix{T1}} where T1, Adjoint{<:Any, <:AbstractVector})
 @declare_matmul(Diagonal,)
 
 function Base.inv(nda::NamedDimsArray{L, T, 2}) where {L,T}


Test patch:
diff --git a/test/functions_math.jl b/test/functions_math.jl
index 35b1404..d8d48dd 100644
--- a/test/functions_math.jl
+++ b/test/functions_math.jl
@@ -159,12 +159,33 @@ end
 
 
 @testset "Mutmul with special types" begin
-    nda = NamedDimsArray{(:a, :b)}(ones(5,5))
-    @testset "$T" for T in (Diagonal, Symmetric, Tridiagonal, SymTridiagonal, BitArray,)
-        x = T(ones(5,5))
-        @test dimnames(x * nda) == (:_, :b)
-        @test dimnames(nda * x) == (:a, :_)
+
+    special_types = (Adjoint, Diagonal, Symmetric, Tridiagonal, SymTridiagonal, BitArray,)
+
+    @testset "matrix" begin
+        ndm = NamedDimsArray{(:a, :b)}(ones(5,5))
+        @testset "$T" for T in special_types
+            x = T(ones(5,5))
+            @test dimnames(x * ndm) == (:_, :b)
+            @test dimnames(ndm * x) == (:a, :_)
+
+            @test typeof(x * ndm) <: NamedDimsArray
+            @test typeof(ndm * x) <: NamedDimsArray
+        end
     end
+
+    @testset "vector" begin
+        ndv = NamedDimsArray{(:vec,)}(ones(5))
+        @testset "$T" for T in special_types
+            x = T(ones(5,5))
+            @test dimnames(x * ndv) == (:_,)
+            @test dimnames(ndv' * x) == (:_, :_)
+
+            @test typeof(x * ndv) <: NamedDimsArray
+            @test typeof(ndv' * x) <: NamedDimsArray
+        end
+    end
+
 end