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

Should reshape() accept Integer as dims rather than only Int? #17372

Open
davidavdav opened this issue Jul 11, 2016 · 17 comments
Open

Should reshape() accept Integer as dims rather than only Int? #17372

davidavdav opened this issue Jul 11, 2016 · 17 comments
Labels
arrays [a, r, r, a, y, s] help wanted Indicates that a maintainer wants help on an issue or pull request

Comments

@davidavdav
Copy link
Contributor

Currently, reshape requires the dimension parameters to be Int

reshape(parent::AbstractArray, dims::Int...) = reshape(parent, dims)

I am not sure if this is required for efficiency reasons, but I wonder if this could be changed to Integer?

In reading binary formatted data I often come across the situation where dimensions of an array are specified as Int32, and then the matrix data that follows has to be reshaped accordingly. Currently I have to escape the dimension specification using Int(), a small effort, but it would be slightly cleaner if that would not be required.

@timholy
Copy link
Member

timholy commented Jul 11, 2016

There's a sense in which this is already fixed on julia-0.5:

julia> a = rand(3,4)
3×4 Array{Float64,2}:
 0.835471  0.0993574  0.678461  0.456434
 0.952059  0.217379   0.533439  0.576274
 0.231707  0.4597     0.574938  0.780569

julia> b = reshape(a, 4, 3)
4×3 Array{Float64,2}:
 0.835471   0.217379  0.574938
 0.952059   0.4597    0.456434
 0.231707   0.678461  0.576274
 0.0993574  0.533439  0.780569

julia> b = reshape(a, Int32(4), Int32(3))
4×3 Base.ReshapedArray{Float64,2,Array{Float64,2},Tuple{}}:
 0.835471   0.217379  0.574938
 0.952059   0.4597    0.456434
 0.231707   0.678461  0.576274
 0.0993574  0.533439  0.780569

julia> b.parent === a
true

Of course, it's giving you a ReshapedArray rather than an Array. Probably adding a fallback that does map(Int, dims) would do the trick? Want to give it a whirl?

@davidavdav
Copy link
Contributor Author

Is this a very recent fix, or a different branch? On Commit f53b00e (5 days old master) I still get an error.

I guess a fallback is always an option, but I understand you'd want that for 0.4 then, right?

@stevengj
Copy link
Member

I feel like this has been discussed in another issue, but I can't find it at the moment. Look at all of the uses of the Dims type (== Int...) in Base … if these were changed to Integer... you'd get a huge proliferation of methods.

@stevengj
Copy link
Member

See #7956

@stevengj
Copy link
Member

On the other hand, #13739 was merged

@tkelman tkelman added the needs decision A decision on this change is needed label Jul 12, 2016
@martinholters
Copy link
Member

If we generally employ the pattern

foo(whatever, dims::Dims) = ... # does the actual work
@inline foo(whatever, dims::Integer...) = foo(whatever, convert(Dims, dims))

would there be the feared huge number of specializations or would they be inlined away? (Or at worst lead to a huge number of specializations of convert only?)

@davidavdav
Copy link
Contributor Author

Updating to today's master, I can reproduce @timholy's answer. But is it in any way desirable that the type returned by reshape() depends on its second+ argument? reshape(::Array, ::Int, ...) => ::Array, whereas reshape(::Array, ::Int32, ...) => ::ReshapedArray? That sounds a bit hairy to me.

@timholy
Copy link
Member

timholy commented Jul 12, 2016

Not desirable, so I support changing it.

@timholy
Copy link
Member

timholy commented Jul 12, 2016

@martinholters, that would indeed be the right kind of specialization: you'd get a "short" specialization of foo, along with convert. That would reduce the number of times you need to compile that 100-line version of foo.

@martinholters
Copy link
Member

So would there be any harm in using this pattern throughout? (Whether it's worthwhile changing all of Base accordingly is another question, but maybe we could adopt it on a "while you're at it, do this too"-basis, similarly to moving docstrings inline.)

@alanedelman
Copy link
Contributor

This may be another issue, but what is the thinking on dims giving the right answer
if it is a float that happens to equal an integer?

@davidavdav
Copy link
Contributor Author

Should that be interpreted as a special case of FractalArrays?

@stevengj
Copy link
Member

@alanedelman, see #1972, #2293, #4275, #5868, #9776, #10154 for discussion of floating-point dimensions.

JeffBezanson added a commit that referenced this issue Jul 22, 2016
Before, the definition of `reshape` that returns a `ReshapedArray` accepted
any integer, but the Array->Array definition only accepted `Int`, so passing a
different type of integer strangely resulted in a different type of array.
JeffBezanson added a commit that referenced this issue Jul 22, 2016
Before, the definition of `reshape` that returns a `ReshapedArray` accepted
any integer, but the Array->Array definition only accepted `Int`, so passing a
different type of integer strangely resulted in a different type of array.
JeffBezanson added a commit that referenced this issue Jul 23, 2016
Before, the definition of `reshape` that returns a `ReshapedArray` accepted
any integer, but the Array->Array definition only accepted `Int`, so passing a
different type of integer strangely resulted in a different type of array.
This behavior was observed as part of #17372.
mfasi pushed a commit to mfasi/julia that referenced this issue Sep 5, 2016
Before, the definition of `reshape` that returns a `ReshapedArray` accepted
any integer, but the Array->Array definition only accepted `Int`, so passing a
different type of integer strangely resulted in a different type of array.
This behavior was observed as part of JuliaLang#17372.
@dlfivefifty
Copy link
Contributor

I think converting to Int is not a good idea: for example, one may want to do

julia> reshape(BigInt(1):BigInt(100)^2, BigInt(100), BigInt(100))
ERROR: MethodError: no method matching reshape(::UnitRange{BigInt}, ::BigInt, ::BigInt)
Closest candidates are:
  reshape(::AbstractArray, ::Int64...) at reshapedarray.jl:95
  reshape(::AbstractArray, ::Union{Int64, AbstractUnitRange}...) at reshapedarray.jl:90
  reshape(::AbstractArray, ::Tuple{Vararg{Int64,N}} where N) at reshapedarray.jl:92
  ...

Or in the case of InfiniteArrays.jl, I want to be able to do reshape(1:∞, 1, ∞).

@machakann
Copy link
Contributor

I came across the same problem on Julia 1.0.2. It seems Integer dims parameter other than Int got invalid again. Though this is avoidable if using Tuple, I feel it a little inconsistent.

a = zeros(100);

reshape(a, 10, 10)  # OK

reshape(a, UInt(10), UInt(10))  # MethodError
reshape(a, (UInt(10), UInt(10)))  # OK

reshape(a, Int128(10), Int128(10))  # MethodError
reshape(a, (Int128(10), Int128(10)))  # OK

@StefanKarpinski
Copy link
Member

It does seem like we should be more consistent here.

@mbauman
Copy link
Member

mbauman commented Dec 3, 2018

I think it's fine to be more relaxed here, but we just need to be careful how these methods all layer atop one another so we don't hit #17567 again.

@mbauman mbauman added help wanted Indicates that a maintainer wants help on an issue or pull request and removed needs decision A decision on this change is needed labels Dec 3, 2018
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] help wanted Indicates that a maintainer wants help on an issue or pull request
Projects
None yet
Development

No branches or pull requests