Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Empty reshapes legalization (issue #45589) #46011

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

nlw0
Copy link
Contributor

@nlw0 nlw0 commented Jul 12, 2022

In reshape, one dimension from the output can be specified as :, and then it's inferred from the input size and the remaining specified dimensions.

If any specified output dimension is zero, the function today raises a zero division error. On the case of an empty input, though, we might simply infer anything consistent with another empty matrix. It's more of a case of "0/0"... And indeed, you can do

julia> reshape(zeros(0,4), 234,:)
234×0 Matrix{Float64}

#45589 points this out, and this patch proposes a solution.

If both input and output sizes contain a 0, we compute a dimension from products of both sides ignoring zeros. This preserves the property that the input is recovered if the output contains the same values, except for one : (as long as the input has a single 0). The size of the remaining dimensions may also be relevant in applications where arrays are being concatenated, and this makes it more likely that the produced array still matches some application constraint.

@nlw0 nlw0 force-pushed the nic/issue-45589 branch from 32003d8 to 2864551 Compare July 12, 2022 22:15
@nlw0 nlw0 force-pushed the nic/issue-45589 branch from 2864551 to d8a08e7 Compare July 12, 2022 22:16
@nlw0
Copy link
Contributor Author

nlw0 commented Jul 13, 2022

I wanted to illustrate why this isn't a foolish idea, with practical code. It's not a big deal, but the new behavior can be nice in some situations.

Imagine you have an array with stacked 11x15 color images. You want to reshape them with a single image per array, each image is now a vector, what is a common operation.

reshape can recompute the vector lengths if you specify the second dimension as the number of images, or perhaps using size(A, ndims(A)). You end up with an array with the same number of images, and whatever is the appropriate shape of the vectorized images.

With the current behavior, reshape will balk at an empty array. With the new behavior, it produces an output with the "correct" dimensions. If you were concatenating multiple reshaped arrays, it would just work, and the dimension-inference feature is preserved to some extent.

julia> Nimages = 3
 rand(3, 11, 15, Nimages);
vectorized = reshape(myimages, :, Nimages);
size(vecto3r
iz
julia> myimages = rand(3,11,15,Nimages);

julia> vectorized = reshape(myimages, :,Nimages);

julia> size(vectorized)
(495, 3)

julia> Nimages = 0
0

julia> myimages = rand(3, 11, 15, Nimages);

julia> vectorized = reshape(myimages, :, Nimages);
ERROR: DivideError: integer division error
Stacktrace:
 [1] div
   @ ./int.jl:288 [inlined]
 [2] divrem
   @ ./div.jl:182 [inlined]
 [3] divrem
   @ ./div.jl:161 [inlined]
 [4] _reshape_uncolon
   @ ./reshapedarray.jl:128 [inlined]
 [5] reshape
   @ ./reshapedarray.jl:119 [inlined]
 [6] reshape(::Array{Float64, 4}, ::Colon, ::Int64)
   @ Base ./reshapedarray.jl:118
 [7] top-level scope
   @ REPL[41]:1
julia> Nimages = 3
3

julia> myimages = rand(3,11,15,Nimages);

julia> vectorized = reshape(myimages, :,Nimages);

julia> size(vectorized)
(495, 3)

julia> Nimages = 0
0

julia> myimages = rand(3, 11, 15, Nimages);

julia> vectorized = reshape(myimages, :, Nimages);

julia> size(vectorized)
(495, 0)

Strictly speaking, though, it really could be any value there. We might just infer 0 or 1, it would all be valid choices. We are making a "best effort" to find a value that might make sense. It's very much like a pseudo-inverse of an undetermined system where we choose a solution with norm 1. Any other solution would be just a good, but we pick something that we find more "sensible".

@nlw0
Copy link
Contributor Author

nlw0 commented Oct 17, 2022

Bump, how do we proceed from here? Can I get anyone to review?

@nsajko nsajko added the arrays [a, r, r, a, y, s] label Aug 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
arrays [a, r, r, a, y, s]
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants