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

Make Ref behave as a 0-dimensional array in broadcast #18965

Merged
merged 2 commits into from
Dec 21, 2016

Conversation

pabloferz
Copy link
Contributor

@pabloferz pabloferz commented Oct 16, 2016

This implements the idea #18379 (comment) proposed by @stevengj of treating Refs as 0-dimensional arrays in broadcast.

@pabloferz pabloferz changed the title Make Ref behave as a scalar wrapper for broadcast Make Ref behave as a 0-dimensional array in broadcast Oct 16, 2016
@yuyichao yuyichao added the breaking This change will break code label Oct 16, 2016
@yuyichao
Copy link
Contributor

Note that Ptr <: Ref.

@stevengj
Copy link
Member

Use ::RefValue, not Ref?

@@ -337,3 +337,9 @@ end
@test broadcast(+, 1.0, (0, -2.0)) == (1.0,-1.0)
@test broadcast(+, 1.0, (0, -2.0), [1]) == [2.0, 0.0]
@test broadcast(*, ["Hello"], ", ", ["World"], "!") == ["Hello, World!"]

# Issue #18379
@test (+).(1, Ref(2)) == fill(3)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cute, I didn't realize that fill could be used to create a 0-dimensional array like this

@pabloferz
Copy link
Contributor Author

Yeah, I guess what we need is just RefValue. If we are going to have this, should it make sense to have RefValue exported so people can access the constructor easily in case anyone want to wrap something?

@pabloferz pabloferz changed the title Make Ref behave as a 0-dimensional array in broadcast Make RefValue behave as a 0-dimensional array in broadcast Oct 16, 2016
Copy link
Member

@vtjnash vtjnash left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the set Ref minus Ptr is a better API. The set RefArray + RefValue is rather arbitrary (it's incomplete).

@@ -127,6 +131,7 @@ dumpbitcache(Bc::Vector{UInt64}, bind::Int, C::Vector{Bool}) =
Base.copy_to_bitarray_chunks!(Bc, ((bind - 1) << 6) + 1, C, 1, min(bitcache_size, (length(Bc)-bind+1) << 6))

@inline _broadcast_getindex(A, I) = _broadcast_getindex(containertype(A), A, I)
@inline _broadcast_getindex(A::RefArrOrVal, I) = A.x
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@inline _broadcast_getindex(A::Ref, I) = A[]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking in limiting all this to RefValue. If we allow Ref and leave this definition of _broadcast_getindex as A[], then we will have

broadcast(+, [[0,2], [1,3]], Ref([1,-1])) == [[1,3], [2,4]]

where we want it to be [[1,1], [2,2]], which broadcast(+, [[0,2], [1,3]], RefValue([1,-1])) would correctly yield.

@@ -48,6 +51,7 @@ broadcast_indices(A) = broadcast_indices(containertype(A), A)
broadcast_indices(::Type{Any}, A) = ()
broadcast_indices(::Type{Tuple}, A) = (OneTo(length(A)),)
broadcast_indices(::Type{Array}, A) = indices(A)
broadcast_indices(::Type{Array}, A::RefArrOrVal) = ()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ref

@@ -30,6 +32,7 @@ end
containertype(x) = containertype(typeof(x))
containertype(::Type) = Any
containertype{T<:Tuple}(::Type{T}) = Tuple
containertype{T<:RefArrOrVal}(::Type{T}) = Array
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ref

@@ -9,6 +9,8 @@ import Base: broadcast
export broadcast!, bitbroadcast, dotview
export broadcast_getindex, broadcast_setindex!

typealias RefArrOrVal Union{Base.RefArray, Base.RefValue}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just use Ref

@pabloferz pabloferz mentioned this pull request Oct 17, 2016
@pabloferz pabloferz force-pushed the pz/broadcast-ref branch 2 times, most recently from 246ff49 to 00ef35f Compare October 22, 2016 18:28
@pabloferz pabloferz changed the title Make RefValue behave as a 0-dimensional array in broadcast Make Ref behave as a 0-dimensional array in broadcast Oct 22, 2016
pabloferz added a commit to pabloferz/julia that referenced this pull request Oct 22, 2016
@pabloferz
Copy link
Contributor Author

pabloferz commented Oct 23, 2016

I updated the PR addressing @vtjnash comments and added news and docs.

In the docs there's now an example of how to use Ref to wrap a whole array (I didn't considered that at first so that's why I thought of using RefValue, but should be better now).

@yuyichao
Copy link
Contributor

Seems that Ptr is still not handled.

@pabloferz
Copy link
Contributor Author

Well, until we have something like #18990 (comment), I'd be inclined to throw an error for Ptr. Does that seem sensible?

@yuyichao
Copy link
Contributor

yuyichao commented Oct 23, 2016

I'd be inclined to throw an error for Ptr. Does that seem sensible?

No, because using Ptr as a normal (scalar) value in broadcast should be supported.

@pabloferz
Copy link
Contributor Author

pabloferz commented Oct 23, 2016

So Ref should behave as 0-dimensional array except for Ptr which should be treated as scalar?

EDIT: NVM. Considering what Ptr is, it is clear it should be treated as scalar.

@yuyichao
Copy link
Contributor

I believe Ptr should be kept as scalar.

pabloferz added a commit to pabloferz/julia that referenced this pull request Oct 23, 2016
@pabloferz
Copy link
Contributor Author

pabloferz commented Oct 24, 2016

OK. Now it properly handles Ptr.

@stevengj
Copy link
Member

LGTM.

- If there is at least an array in the arguments, it returns an array
(and treats tuples as 1-dimensional arrays) expanding singleton dimensions.
- If there is at least an array or a `Ref` in the arguments, it returns an array
(and treats any `Ref` and tuple as 0-dimensional and 1-dimensional arrays,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ref or tuple ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"any Ref or tuple as a 0-dimensional or 1-dimensional array, respectively" would be correct, but it would perhaps be clearer to phrase it as "treats any Ref as a 0-dimensional array of its contents, and any tuple as a 1-dimensional array"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

pabloferz added a commit to pabloferz/julia that referenced this pull request Oct 27, 2016
pabloferz added a commit to pabloferz/julia that referenced this pull request Nov 4, 2016
@pabloferz pabloferz closed this Nov 4, 2016
@pabloferz pabloferz reopened this Nov 4, 2016
pabloferz added a commit to pabloferz/julia that referenced this pull request Nov 7, 2016
pabloferz added a commit to pabloferz/julia that referenced this pull request Dec 15, 2016
- If there is at least an array in the arguments, it returns an array
(and treats tuples as 1-dimensional arrays) expanding singleton dimensions.
- If there is at least an array or a `Ref` in the arguments, it returns an array
(and treats any `Ref` as a 0-dimensional array of its contents and any tuple
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing close paren?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is in the following line.

@pabloferz
Copy link
Contributor Author

Rebased in top of the recent broadcast changes. Could this go into 0.6?

@stevengj
Copy link
Member

LGTM

@stevengj stevengj merged commit 76a9180 into JuliaLang:master Dec 21, 2016
@pabloferz pabloferz deleted the pz/broadcast-ref branch December 21, 2016 15:25
@stevengj
Copy link
Member

Looks like we should define this for RefArray also. It is annoying to have to do Ref{Vector{Int}}([1,2,3]) rather than just Ref([1,2,3]).

@yuyichao
Copy link
Contributor

RefArray is a reference of the element type, not the whole array.

@stevengj
Copy link
Member

It would be nice to be able to do Ref(x) in a broadcast call and have x treated as a scalar. It is a lot less convenient if you have to do Ref{typeof(x)}(x).

RefArray contains all of the information that one needs (Ref([1,2,3]).x == [1,2,3]), so it is a bit frustrating.

@yuyichao
Copy link
Contributor

This is not what Ref is meant to be used for. If we really want to use RefValue for this we should just export that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking This change will break code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants