Skip to content

Rework type promotion for scalar ∘ array and array ∘ scalar #16055

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

Merged
merged 1 commit into from
Apr 29, 2016

Conversation

martinholters
Copy link
Member

The first commit is relative direct fix of #14725, rewriting ./, .\, and .^ for the mixed scalar/array case to make use of promote_eltype_op.

The second commit supersedes the first (I will squash if the end result is deemed good). It rewrites the whole promotion part for mixed scalar/array operations to have all special-casing in the promotion, not in the definition of the operation. To this end promote_array_type is rewritten to a two-step procedure. In the first step, promote_array_type is invoked with the scalar and the array type (not its element type!) in correct order. This is the interface that is used for invoking. However, it just delegates to promote_array_type giving three types: scalar, array element, and result of promote_op with the arguments in correct order. This is important because (potentially) promote_op(.^, Ta, Tb) != promote_op(.^, Tb, Ta). By default, this step returns the promoted type, but here specialization may be used to e.g. ensure that eltype([0.0f0]+1)==Float32. I am not exactly happy with both steps having the same function name, though, and wonder whether the first step should not simply replace promote_eltype_op for this case (I'm not sure about the implied contract of promote_eltype_op). Opinions?

@timholy
Copy link
Member

timholy commented Apr 27, 2016

👍

To me it seems that the main risk of using promote_array_type in both cases would be possible confusion if one wanted to extend this to deal with arrays-of-arrays. However, currently the two cases seem to be distinguished also by 3-argument and 4-argument forms; if you don't think that will change, the current naming is probably safe. If you think that the API might change someday, then indeed it's a little risky, and a different name would be preferable.

@martinholters
Copy link
Member Author

Yes, I think the number of arguments is a safe criterion for distinguishing. I'm just worried this name re-use makes the code a little harder to understand/maintain.

But then again, the whole promotion business is somewhat obscure. Which of the promote* functions are actually used for type promotion before applying an operation, and which are used to predict or enforce the return type? Furthermore, which are used in both ways, assuming that if T was the promotion result, op(::T, ::T) should return a T? (And while this assumption is perfectly reasonable, does it actually hold for all operations where promotion is performed?) My feeling is that answering these questions might lead to another promotion overhaul. But its definitely out of the scope of this PR.

And now for something completely different: @_pure_meta seems to be used a lot is type promotion code. Should I add it here as well?

@nalimilan
Copy link
Member

And now for something completely different: @_pure_meta seems to be used a lot is type promotion code. Should I add it here as well?

pure annotations imply that the compiler is free to call the function at any time, and that it will always return the same result for a set of inputs (see discussion at #14324). Since that's normally the case for promotion, sounds like a good idea to use it so that type information is propagated as much as possible. (Though I'm not sure in what cases this can happen automatically, and it which cases pure is needed.)

@martinholters
Copy link
Member Author

Updated with added @_pure_meta.

reshape([ x ^ y for y in Y ], size(Y))
.^(X::AbstractArray, y::Number ) =
reshape([ x ^ y for x in X ], size(X))
promote_array_type{S<:Number, A<:AbstractArray}(F, ::Type{S}, ::Type{A}) =
Copy link
Member

Choose a reason for hiding this comment

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

Do you have to use @_pure_meta or could you just use @pure? You have to use @_pure_meta early in the bootstrap process before the machinery to support pushmeta! is available, but I suspect by this point it's in place.

Copy link
Member Author

@martinholters martinholters Apr 29, 2016

Choose a reason for hiding this comment

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

Yes, @pure seems to do it. Thanks for the pointer.

Copy link
Member

Choose a reason for hiding this comment

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

Too bad for @pure, let's hope he doesn't mind emails from Github. (next time use ``` to wrap macros, because otherwise github pings and subscribes users named the same as our macros)

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, but dammit, ``` and ' do look similar, don't they...

Copy link
Member

Choose a reason for hiding this comment

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

Yup

@timholy
Copy link
Member

timholy commented Apr 28, 2016

LGTM. I restarted the failing builds. When you're ready to have it merged, strip off the RFC and ping again.

The new promote_array_type is flexible enough so that ./, .\, and .^ for
the mixed scalar/array case can be defined like all the other
element-wise operations (fixes JuliaLang#14725).
@martinholters martinholters changed the title RFC: Rework type promotion for scalar ∘ array and array ∘ scalar Rework type promotion for scalar ∘ array and array ∘ scalar Apr 29, 2016
@martinholters
Copy link
Member Author

Ready from my side, assuming CI passes.

@timholy timholy merged commit 52fb7cc into JuliaLang:master Apr 29, 2016
@timholy
Copy link
Member

timholy commented Apr 29, 2016

A very nice and elegantly-designed fix. Thanks so much for tackling this!

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.

4 participants