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

Add more functions implemented with [map]reduce and [map]reducedim #263

Merged
merged 3 commits into from
Aug 8, 2017

Conversation

wsshin
Copy link
Contributor

@wsshin wsshin commented Jul 31, 2017

This PR adds more functions implemented with [map]reduce and [map]reducedim to src/mapreduce.jl:

  • iszero
  • directional versions of sum, prod, all, any
  • mapped version of prod, count, all, any, minimum, maximum
    Note that Base already has these functions.

Additionally, this PR corrects the following typos:

  • reducedim(op, a::StaticArray, ::Val{D}) to reducedim(op, a::StaticArray, ::Type{Val{D}})
  • reducedim(op, a::StaticArray, ::Val{D}, v0) to reducedim(op, a::StaticArray, ::Type{Val{D}}, v0)

@coveralls
Copy link

Coverage Status

Coverage decreased (-0.3%) to 88.885% when pulling 8bd82c8 on wsshin:iszero-and-count into da1a371 on JuliaArrays:master.

@codecov-io
Copy link

codecov-io commented Jul 31, 2017

Codecov Report

Merging #263 into master will increase coverage by 1.15%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #263      +/-   ##
==========================================
+ Coverage   89.14%   90.29%   +1.15%     
==========================================
  Files          36       36              
  Lines        2625     2658      +33     
==========================================
+ Hits         2340     2400      +60     
+ Misses        285      258      -27
Impacted Files Coverage Δ
src/StaticArrays.jl 100% <ø> (ø) ⬆️
src/mapreduce.jl 100% <100%> (ø) ⬆️
src/traits.jl 83.78% <0%> (-2.71%) ⬇️
src/eigen.jl 91.32% <0%> (-2.29%) ⬇️
src/det.jl 100% <0%> (ø) ⬆️
src/util.jl 71.05% <0%> (+0.08%) ⬆️
src/linalg.jl 97.38% <0%> (+0.11%) ⬆️
src/MArray.jl 95.65% <0%> (+0.62%) ⬆️
src/SArray.jl 95.23% <0%> (+0.68%) ⬆️
src/MMatrix.jl 93.38% <0%> (+0.82%) ⬆️
... and 7 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update da1a371...5172c39. Read the comment docs.

@wsshin wsshin changed the title Use StaticArrays' reduce and mapreduce for iszero and count(f, a) Add more functions implemented with [map]reduce and [map]reducedim Aug 1, 2017
@coveralls
Copy link

Coverage Status

Coverage decreased (-0.03%) to 89.116% when pulling 359e347 on wsshin:iszero-and-count into da1a371 on JuliaArrays:master.

@tkoolen
Copy link
Contributor

tkoolen commented Aug 3, 2017

Just browsing, but FYI for the Val change: the Base convention that methods should take ::Type{Val{T}} is going to be changed to ::Val{T} in 1.0 (see latest docs vs. 0.6 docs and JuliaLang/julia#22475.

@wsshin
Copy link
Contributor Author

wsshin commented Aug 3, 2017

Didn't know about the discussion. Good to know. Thanks!

@@ -160,25 +160,76 @@ end
## reducedim ##
###############

@inline reducedim(op, a::StaticArray, ::Val{D}) where {D} = mapreducedim(identity, op, a, Val{D})
@inline reducedim(op, a::StaticArray, ::Val{D}, v0) where {D} = mapreducedim(identity, op, a, Val{D}, v0)
@inline reducedim(op, a::StaticArray, ::Type{Val{D}}) where {D} = mapreducedim(identity, op, a, Val{D})
Copy link
Member

@andyferris andyferris Aug 6, 2017

Choose a reason for hiding this comment

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

FYI: This possibly wasn't a typo. I had been thinking about this PR for a long time :)

However, we should probably add a if VERSION < v"0.7" to support both versions of Julia, or something (or simply support both syntaxes?)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

But having to use Val(D) in reducedim and Val{D} in mapreducedim seems confusing and inconsistent. I don't see the use of Val(D) and ::Val{D} anywhere else in StaticArrays, either. Wouldn't it be better to handle this in a separate PR collectively?

Copy link
Member

@andyferris andyferris Aug 6, 2017

Choose a reason for hiding this comment

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

OK, so what I would like is if StaticArrays used Val{D} everywhere in v0.6 and Val(D) everywhere in v0.7. (I suppose it's OK if the v0.6 version also supports Val{D}(), partly to avoid this being a breaking change)

If you were to implement that here, that would be awesome (as it seems pertinent to the change already done on this line) - however, let me know if you'd prefer to not do that at the moment, and I'll get to it later.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

When making this change, I would like to have things like

default_similar_type{T,S,D}(::Type{T}, s::Size{S}, ::Type{Val{D}})

in abstractarray.jl change to

default_similar_type{T,S,D}(::Type{T}, s::Size{S}, ::Val{D})

as well. Because such a change is outside mapreduce.jl, I think creating a separate PR dedicated to ::Type{Val{D}} -> ::Val{D} would be cleaner... So yes, I would prefer not to make this change at the moment.

Copy link
Member

Choose a reason for hiding this comment

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

Fair enough

src/mapreduce.jl Outdated
# with an initial value v0 = true and false.
#
# 4. Some implementations (e.g., count(a, Val{D})) are commented out because corresponding
# Base functions (e.g., count(a, D)) do not exist yet.
Copy link
Member

Choose a reason for hiding this comment

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

Yet? Meaning they are mooted for v0.7?

(We are allowed to be a bit more agile and move a bit beyond Base wherever it makes sense, so long as we don't break anything that tends to work for AbstractArray)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

5172c39 uncomments these functions!

@andyferris
Copy link
Member

Basically looks good to me. Thanks @wsshin.

I guess we may as well try and support the syntax for v0.6 and v1.0? (Ideally, I'd like to support multiple versions of Julia - in the past we've been hampered by internal compiler changes meaning different approaches are valid/optimal, but so far I am not really expecting this for v0.7/v1.0).

@wsshin
Copy link
Contributor Author

wsshin commented Aug 6, 2017

Wait. While trying to uncomment count(a, Val{D}), I found some bugs. I will report it back later.

@andyferris
Copy link
Member

OK

@wsshin
Copy link
Contributor Author

wsshin commented Aug 7, 2017

The bug I was referring to was ignorance of the possibility of element type change in mapreducedim. Because of this, count(f::Function, a::StaticArray, ::Type{Val{D}}) was returning an array of Float64, rather than Int64, when eltype(a) was Float64. Now properly promoted element types are used in mapreducedim and its friends.

One question, though. I used Base.promote_op to deduce the proper element types after mapping and operation, but in _map I find that Core.Inference.return_type is used for the same purpose. I find that Base.promote_op wraps around Core.Inference.return_type (https://github.com/JuliaLang/julia/blob/master/base/promotion.jl#L321), so I guessed that promote_op takes care of some difficult situations better than return_type, but I'm not sure which one of the two is better. Any suggestions?

@coveralls
Copy link

Coverage Status

Coverage increased (+1.2%) to 90.293% when pulling 5172c39 on wsshin:iszero-and-count into da1a371 on JuliaArrays:master.

@andyferris
Copy link
Member

Feel free to use either. I think there are historic reasons surrounding this... something about one being inferable and the other not (but these days they should both be fine).

BTW, I'd be most happy with the idea of just letting the natural types fall out, rather than using inference. At the moment we can't do this everywhere since we'd need a "eltypeless" constructor for every StaticArray, but unlike Base.Array, we can construct the result before wrapping it in an array so technically we don't need eltype prediction (in such a system, inference will still work to make everything fast, but only in the background).

@wsshin
Copy link
Contributor Author

wsshin commented Aug 8, 2017

I think I know what you mean by "letting the natural types fall out", but just in case, could you point me to a couple of examples of this practice in StaticArrays, if any?

@andyferris
Copy link
Member

Constructors are one case, things get promoted to a common type and an output is generated.

I think complete reductions also might do this?

@wsshin
Copy link
Contributor Author

wsshin commented Aug 8, 2017

Hmmm... Not sure if I understood what you meant. Could you be more specific about how to apply your idea in _mapreducedim?

@andyferris
Copy link
Member

I don't think you can implement this idea (at this stage) for partial reductions because the infrastructure isn't available. I was just expressing an idea of where I'd like to get to.

@wsshin
Copy link
Contributor Author

wsshin commented Aug 8, 2017

I see. Then can we merge this now?

@andyferris andyferris merged commit 7d711ab into JuliaArrays:master Aug 8, 2017
@andyferris
Copy link
Member

Done!

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.

5 participants