FillArrays.jl icon indicating copy to clipboard operation
FillArrays.jl copied to clipboard

`real(::Fill)` gives an array of arrays?

Open mcabbott opened this issue 4 years ago • 6 comments
trafficstars

This is surprising:

julia> real(Fill(1+im)) isa Array{<:AbstractArray{Int}}
true

julia> real(fill(1+im)) isa Array{Int,0}
true

(jl_AeiBcQ) pkg> st
      Status `/private/var/folders/yq/4p2zwd614y59gszh7y9ypyhh0000gn/T/jl_AeiBcQ/Project.toml`
  [1a297f60] FillArrays v0.11.7

I guess it comes from this difference, via broadcast_preserving_zero_d:

julia> Fill(1) .+ Fill(2)
0-dimensional Fill{Int64}, with entry equal to 3

julia> fill(1) .+ fill(2)
3

mcabbott avatar May 08 '21 21:05 mcabbott

This actually looks like a bug in Julia, why would 0-dimensional arrays have a different broadcasting behaviour:

julia> x + x
0-dimensional Array{Int64, 0}:
2

julia> x .+ x
2

dlfivefifty avatar May 09 '21 07:05 dlfivefifty

I do think it's the intended behaviour, although I don't see it mentioned in the manual. Maybe broadcast never produces a 0-array, e.g. sqrt.(fill(pi)) isa Float64.

mcabbott avatar May 09 '21 14:05 mcabbott

I think it’s more “unintended consequence of design: it follows because 0-dimensional arrays are treated like constants in broadcasting with vectors/matrices, but the special case where everything is 0-dimensional was probably not thought through.

I don’t think it’s going to change in Julia v1.x so yes I agree we should make Fill match. But I’ll open an issue so that perhaps this could be changed in Julia v2

dlfivefifty avatar May 09 '21 14:05 dlfivefifty

https://github.com/JuliaLang/julia/issues/28866 is the issue, it seems.

mcabbott avatar May 09 '21 14:05 mcabbott

Ah, I encountered the same issue: https://github.com/JuliaLang/julia/issues/28866#issuecomment-1143946830

GiggleLiu avatar Jun 01 '22 17:06 GiggleLiu

Can I maybe add that this still exists, and also is not consistent? It works for -(), but not for conj, real, imag.

julia> A = Fill(1im)
0-dimensional Fill{Complex{Int64}}, with entry equal to 0 + 1im

julia> conj(A), real(A), imag(A), -A
(fill(Fill(0 - 1im)), fill(Fill(0)), fill(Fill(1)), Fill(0 - 1im))

julia> B = fill(1im)
0-dimensional Array{Complex{Int64}, 0}:
0 + 1im

julia> conj(B), real(B), imag(B), -B
(fill(0 - 1im), fill(0), fill(1), fill(0 - 1im))

Would you be ok with a PR that just manually fixes this by implementing the broadcast_preserving_zero_d, at least for the case with a single argument?

# makes 0-dimensional arrays behave like Julia Base
@inline function Base.broadcast_preserving_zero_d(f, As::AbstractFill...)
    bc = broadcasted(f, As...)
    return Base.materialize(bc)
end

If we'd agree on this, I can add some tests as well.

[edit] Alternatively, I could also just add special-case versions for the zero-dimensional versions.

lkdvos avatar Jan 03 '24 17:01 lkdvos