Skip to content

Conversation

FelixBenning
Copy link

Spin-off from #49965. The goal is to enable users to do

julia> vec(PermutedDimsArray(Iterators.product(rand(3), 1:4), (2,1)))
12-element reshape(PermutedDimsArray(::Matrix{Tuple{Float64, Int64}}, (2, 1)), 12) with eltype Tuple{Float64, Int64}:
 (0.39059299961662275, 1)
 (0.39059299961662275, 2)
 (0.39059299961662275, 3)
 (0.39059299961662275, 4)
 (0.1864604429198029, 1)
 (0.1864604429198029, 2)
 (0.1864604429198029, 3)
 (0.1864604429198029, 4)
 (0.3248860864098778, 1)
 (0.3248860864098778, 2)
 (0.3248860864098778, 3)
 (0.3248860864098778, 4)

for this ProductIterator would need to be a subtype of AbstractArray, which it can not be in general. This Pull request introduces the ProductArray as a complement to the ProductIterator and uses traits to decide which to use when product is called. This decision might be possible to generalize further. Using a type union the existing implementations for ProductIterator are then all reused for ProductArray (only that it also inherits functionality from AbstractArray.

I am not very familiar with the internals of juila, so my usage of Unions might not be performance optimal.

The same idea could in principle also be applied to Flatten with the same goal.

@MasonProtter
Copy link
Contributor

I wonder if the best solution for this is to just use https://github.com/JuliaArrays/MappedArrays.jl instead of adding another iterator type to julia. E.g.

julia> using MappedArrays

julia> m_prod = let v1 = rand(3), v2= 1:4
           Is = CartesianIndices((axes(v1)..., axes(v2)...))
           mappedarray(I ->(v1[I[1]], v2[I[2]]), Is)
       end
3×4 mappedarray(var"#12#13"{Vector{Float64}, UnitRange{Int64}}([0.7870192228323807, 0.49428680787475354, 0.7833575043171959], 1:4), ::CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}) with eltype Tuple{Float64, Int64}:
 (0.787019, 1)  (0.787019, 2)  (0.787019, 3)  (0.787019, 4)
 (0.494287, 1)  (0.494287, 2)  (0.494287, 3)  (0.494287, 4)
 (0.783358, 1)  (0.783358, 2)  (0.783358, 3)  (0.783358, 4)

julia> vec(PermutedDimsArray(m_prod, (2,1)))
12-element reshape(PermutedDimsArray(mappedarray(var"#12#13"{Vector{Float64}, UnitRange{Int64}}([0.7870192228323807, 0.49428680787475354, 0.7833575043171959], 1:4), ::CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}), (2, 1)), 12) with eltype Tuple{Float64, Int64}:
 (0.7870192228323807, 1)
 (0.7870192228323807, 2)
 (0.7870192228323807, 3)
 (0.7870192228323807, 4)
 (0.49428680787475354, 1)
 (0.49428680787475354, 2)
 (0.49428680787475354, 3)
 (0.49428680787475354, 4)
 (0.7833575043171959, 1)
 (0.7833575043171959, 2)
 (0.7833575043171959, 3)
 (0.7833575043171959, 4)

@FelixBenning
Copy link
Author

The compiler neither likes

const Product{T} where {T<:Tuple} = Union{ProductIterator{T}, ProductArray{T}}

Nor likes

IteratorSize(::Type{PT{Tuple{}}}) where {PT<:Product} = HasShape{0}()

and I am too tired to find a solution right now.

@FelixBenning
Copy link
Author

@MasonProtter you are probably right about the mapped arrays being a good solution - you don't happen to know a good way to simplify the output? A wrapper would take away functionality so I want to avoid that

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants