Skip to content

Commit

Permalink
Deprecate unary functors
Browse files Browse the repository at this point in the history
The following functors are deprecated: IdFun, AbsFun, Abs2Fun, ExpFun,
LogFun, and ConjFun.

Specialization for BitArray map! is done by dispatching on function
type instead of using helper type BitFunctorUnary. Also a add a few
tests for those.
  • Loading branch information
martinholters committed Apr 21, 2016
1 parent 1d0fa8a commit 0a72958
Show file tree
Hide file tree
Showing 13 changed files with 90 additions and 126 deletions.
9 changes: 5 additions & 4 deletions base/bitarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1711,19 +1711,20 @@ maximum(B::BitArray) = isempty(B) ? throw(ArgumentError("argument must be non-em
# arrays since there can be a 64x speedup by working at the level of Int64
# instead of looping bit-by-bit.

map(f::Function, A::BitArray) = map(specialized_bitwise_unary(f), A)
map(f::Function, A::BitArray, B::BitArray) = map(specialized_bitwise_binary(f), A, B)
map(f::BitFunctorUnary, A::BitArray) = map!(f, similar(A), A)
map(f::Function, A::BitArray) = map!(f, similar(A), A)
map(f::BitFunctorBinary, A::BitArray, B::BitArray) = map!(f, similar(A), A, B)

map!(f, A::BitArray) = map!(f, A, A)
map!(f::Function, dest::BitArray, A::BitArray) = map!(specialized_bitwise_unary(f), dest, A)
map!(f::typeof(!), dest::BitArray, A::BitArray) = map!(~, dest, A)
map!(f::typeof(zero), dest::BitArray, A::BitArray) = fill!(dest, false)
map!(f::typeof(one), dest::BitArray, A::BitArray) = fill!(dest, true)
map!(f::Function, dest::BitArray, A::BitArray, B::BitArray) = map!(specialized_bitwise_binary(f), dest, A, B)

# If we were able to specialize the function to a known bitwise operation,
# map across the chunks. Otherwise, fall-back to the AbstractArray method that
# iterates bit-by-bit.
function map!(f::BitFunctorUnary, dest::BitArray, A::BitArray)
function map!(f::Union{typeof(identity), typeof(~)}, dest::BitArray, A::BitArray)
size(A) == size(dest) || throw(DimensionMismatch("sizes of dest and A must match"))
isempty(A) && return dest
for i=1:length(A.chunks)-1
Expand Down
16 changes: 16 additions & 0 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1020,6 +1020,22 @@ function pmap(f, c...; err_retry=nothing, err_stop=nothing, pids=nothing)
return pmap(p, f, c...)
end

# 15692
for (Fun, func) in [(:IdFun, :identity),
(:AbsFun, :abs),
(:Abs2Fun, :abs2),
(:ExpFun, :exp),
(:LogFun, :log),
(:ConjFun, :conj),
]
@eval begin
@deprecate_binding $(Fun) typeof($(func))
(::Type{typeof($(func))})() = $(func)
end
end
@deprecate specialized_unary(f::Function) f
@deprecate specialized_bitwise_unary(f::Function) f


# During the 0.5 development cycle, do not add any deprecations below this line
# To be deprecated in 0.6
Expand Down
40 changes: 0 additions & 40 deletions base/functors.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,6 @@

abstract Func{N}

immutable IdFun <: Func{1} end
(::IdFun)(x) = x

immutable AbsFun <: Func{1} end
(::AbsFun)(x) = abs(x)

immutable Abs2Fun <: Func{1} end
(::Abs2Fun)(x) = abs2(x)

immutable ExpFun <: Func{1} end
(::ExpFun)(x) = exp(x)

immutable LogFun <: Func{1} end
(::LogFun)(x) = log(x)

immutable ConjFun <: Func{1} end
(::ConjFun)(x) = conj(x)

immutable AndFun <: Func{2} end
(::AndFun)(x, y) = x & y

Expand Down Expand Up @@ -106,7 +88,6 @@ immutable DotRSFun <: Func{2} end
immutable UnspecializedFun{N} <: Func{N}
f::Function
end
(f::UnspecializedFun{1})(x) = f.f(x)
(f::UnspecializedFun{2})(x, y) = f.f(x,y)

# Special purpose functors
Expand Down Expand Up @@ -148,12 +129,6 @@ promote_op{T<:Integer}(::PowFun, ::Type{Bool}, ::Type{T}) = Bool
##############################################################################


immutable BitFunctorUnary{T,F} <: Func{1} end
(::BitFunctorUnary{true, true})( p) = p | ~p # Must work for bits and ints
(::BitFunctorUnary{false, false})(p) = p & ~p # LLVM figures them out nicely
(::BitFunctorUnary{true, false})(p) = p
(::BitFunctorUnary{false, true})( p) = ~p

immutable BitFunctorBinary{TT,TF,FT,FF} <: Func{2} end
(::BitFunctorBinary{true, true, true, true })(p, q) = p | ~p
(::BitFunctorBinary{true, true, true, false})(p, q) = p | q
Expand All @@ -175,14 +150,6 @@ immutable BitFunctorBinary{TT,TF,FT,FF} <: Func{2} end

# Specializations by value

function specialized_unary(f::Function)
is(f, identity) ? IdFun() :
is(f, abs) ? AbsFun() :
is(f, abs2) ? Abs2Fun() :
is(f, exp) ? ExpFun() :
is(f, log) ? LogFun() :
UnspecializedFun{1}(f)
end
function specialized_binary(f::Function)
is(f, +) ? AddFun() :
is(f, -) ? SubFun() :
Expand All @@ -199,13 +166,6 @@ function specialized_binary(f::Function)
UnspecializedFun{2}(f)
end

function specialized_bitwise_unary(f::Function)
is(f, identity) ? BitFunctorUnary{true, false}() :
is(f, !) | is(f, ~) ? BitFunctorUnary{false, true }() :
is(f, one) ? BitFunctorUnary{true, true }() :
is(f, zero) ? BitFunctorUnary{false, false}() :
UnspecializedFun{1}(f)
end
function specialized_bitwise_binary(f::Function)
is(f, &) | is(f, *) | is(f, min) ? BitFunctorBinary{true, false, false, false}() :
is(f, |) | is(f, max) ? BitFunctorBinary{true, true, true, false}() :
Expand Down
8 changes: 4 additions & 4 deletions base/linalg/dense.jl
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,19 @@ isposdef(x::Number) = imag(x)==0 && real(x) > 0
stride1(x::Array) = 1
stride1(x::StridedVector) = stride(x, 1)::Int

import Base: mapreduce_seq_impl, AbsFun, Abs2Fun, AddFun
import Base: mapreduce_seq_impl, AddFun

mapreduce_seq_impl{T<:BlasReal}(::AbsFun, ::AddFun, a::Union{Array{T},StridedVector{T}}, ifirst::Int, ilast::Int) =
mapreduce_seq_impl{T<:BlasReal}(::typeof(abs), ::AddFun, a::Union{Array{T},StridedVector{T}}, ifirst::Int, ilast::Int) =
BLAS.asum(ilast-ifirst+1, pointer(a, ifirst), stride1(a))

function mapreduce_seq_impl{T<:BlasReal}(::Abs2Fun, ::AddFun, a::Union{Array{T},StridedVector{T}}, ifirst::Int, ilast::Int)
function mapreduce_seq_impl{T<:BlasReal}(::typeof(abs2), ::AddFun, a::Union{Array{T},StridedVector{T}}, ifirst::Int, ilast::Int)
n = ilast-ifirst+1
px = pointer(a, ifirst)
incx = stride1(a)
BLAS.dot(n, px, incx, px, incx)
end

function mapreduce_seq_impl{T<:BlasComplex}(::Abs2Fun, ::AddFun, a::Union{Array{T},StridedVector{T}}, ifirst::Int, ilast::Int)
function mapreduce_seq_impl{T<:BlasComplex}(::typeof(abs2), ::AddFun, a::Union{Array{T},StridedVector{T}}, ifirst::Int, ilast::Int)
n = ilast-ifirst+1
px = pointer(a, ifirst)
incx = stride1(a)
Expand Down
55 changes: 27 additions & 28 deletions base/reduce.jl
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ function mapfoldl(f, op, itr)
mapfoldl_impl(f, op, v0, itr, i)
end

foldl(op, v0, itr) = mapfoldl(IdFun(), op, v0, itr)
foldl(op, itr) = mapfoldl(IdFun(), op, itr)
foldl(op, v0, itr) = mapfoldl(identity, op, v0, itr)
foldl(op, itr) = mapfoldl(identity, op, itr)

## foldr & mapfoldr

Expand All @@ -86,8 +86,8 @@ end
mapfoldr(f, op, v0, itr) = mapfoldr_impl(f, op, v0, itr, endof(itr))
mapfoldr(f, op, itr) = (i = endof(itr); mapfoldr_impl(f, op, f(itr[i]), itr, i-1))

foldr(op, v0, itr) = mapfoldr(IdFun(), op, v0, itr)
foldr(op, itr) = mapfoldr(IdFun(), op, itr)
foldr(op, v0, itr) = mapfoldr(identity, op, v0, itr)
foldr(op, itr) = mapfoldr(identity, op, itr)

## reduce & mapreduce

Expand Down Expand Up @@ -122,12 +122,12 @@ mapreduce_impl(f, op, A::AbstractArray, ifirst::Int, ilast::Int) =
# handling empty arrays
mr_empty(f, op, T) = throw(ArgumentError("reducing over an empty collection is not allowed"))
# use zero(T)::T to improve type information when zero(T) is not defined
mr_empty(::IdFun, op::AddFun, T) = r_promote(op, zero(T)::T)
mr_empty(::AbsFun, op::AddFun, T) = r_promote(op, abs(zero(T)::T))
mr_empty(::Abs2Fun, op::AddFun, T) = r_promote(op, abs2(zero(T)::T))
mr_empty(::IdFun, op::MulFun, T) = r_promote(op, one(T)::T)
mr_empty(::AbsFun, op::MaxFun, T) = abs(zero(T)::T)
mr_empty(::Abs2Fun, op::MaxFun, T) = abs2(zero(T)::T)
mr_empty(::typeof(identity), op::AddFun, T) = r_promote(op, zero(T)::T)
mr_empty(::typeof(abs), op::AddFun, T) = r_promote(op, abs(zero(T)::T))
mr_empty(::typeof(abs2), op::AddFun, T) = r_promote(op, abs2(zero(T)::T))
mr_empty(::typeof(identity), op::MulFun, T) = r_promote(op, one(T)::T)
mr_empty(::typeof(abs), op::MaxFun, T) = abs(zero(T)::T)
mr_empty(::typeof(abs2), op::MaxFun, T) = abs2(zero(T)::T)
mr_empty(f, op::AndFun, T) = true
mr_empty(f, op::OrFun, T) = false

Expand Down Expand Up @@ -161,8 +161,8 @@ mapreduce(f, op, a::Number) = f(a)

mapreduce(f, op::Function, A::AbstractArray) = mapreduce(f, specialized_binary(op), A)

reduce(op, v0, itr) = mapreduce(IdFun(), op, v0, itr)
reduce(op, itr) = mapreduce(IdFun(), op, itr)
reduce(op, v0, itr) = mapreduce(identity, op, v0, itr)
reduce(op, itr) = mapreduce(identity, op, itr)
reduce(op, a::Number) = a

### short-circuiting specializations of mapreduce
Expand Down Expand Up @@ -205,11 +205,10 @@ end
mapreduce_no_sc(f, op, itr::Any) = mapfoldl(f, op, itr)
mapreduce_no_sc(f, op, itr::AbstractArray) = _mapreduce(f, op, itr)

mapreduce_sc(f::Function, op, itr) = mapreduce_sc(specialized_unary(f), op, itr)
mapreduce_sc(f::Function, op, itr) = mapreduce_no_sc(f, op, itr)
mapreduce_sc(f::ReturnsBool, op, itr) = mapreduce_sc_impl(f, op, itr)
mapreduce_sc(f::Func{1}, op, itr) = mapreduce_no_sc(f, op, itr)

mapreduce_sc(f::IdFun, op, itr) =
mapreduce_sc(f::typeof(identity), op, itr) =
eltype(itr) <: Bool ?
mapreduce_sc_impl(f, op, itr) :
mapreduce_no_sc(f, op, itr)
Expand Down Expand Up @@ -237,16 +236,16 @@ end
sum_pairwise_blocksize(f) = 1024

# This appears to show a benefit from a larger block size
sum_pairwise_blocksize(::Abs2Fun) = 4096
sum_pairwise_blocksize(::typeof(abs2)) = 4096

mapreduce_impl(f, op::AddFun, A::AbstractArray, ifirst::Int, ilast::Int) =
mapreduce_pairwise_impl(f, op, A, ifirst, ilast, sum_pairwise_blocksize(f))

sum(f::Union{Callable,Func{1}}, a) = mapreduce(f, AddFun(), a)
sum(a) = mapreduce(IdFun(), AddFun(), a)
sum(a) = mapreduce(identity, AddFun(), a)
sum(a::AbstractArray{Bool}) = countnz(a)
sumabs(a) = mapreduce(AbsFun(), AddFun(), a)
sumabs2(a) = mapreduce(Abs2Fun(), AddFun(), a)
sumabs(a) = mapreduce(abs, AddFun(), a)
sumabs2(a) = mapreduce(abs2, AddFun(), a)

# Kahan (compensated) summation: O(1) error growth, at the expense
# of a considerable increase in computational expense.
Expand Down Expand Up @@ -274,7 +273,7 @@ end
## prod

prod(f::Union{Callable,Func{1}}, a) = mapreduce(f, MulFun(), a)
prod(a) = mapreduce(IdFun(), MulFun(), a)
prod(a) = mapreduce(identity, MulFun(), a)

## maximum & minimum

Expand Down Expand Up @@ -321,11 +320,11 @@ end
maximum(f::Union{Callable,Func{1}}, a) = mapreduce(f, MaxFun(), a)
minimum(f::Union{Callable,Func{1}}, a) = mapreduce(f, MinFun(), a)

maximum(a) = mapreduce(IdFun(), MaxFun(), a)
minimum(a) = mapreduce(IdFun(), MinFun(), a)
maximum(a) = mapreduce(identity, MaxFun(), a)
minimum(a) = mapreduce(identity, MinFun(), a)

maxabs(a) = mapreduce(AbsFun(), MaxFun(), a)
minabs(a) = mapreduce(AbsFun(), MinFun(), a)
maxabs(a) = mapreduce(abs, MaxFun(), a)
minabs(a) = mapreduce(abs, MinFun(), a)

## extrema

Expand Down Expand Up @@ -397,19 +396,19 @@ end

## all & any

any(itr) = any(IdFun(), itr)
all(itr) = all(IdFun(), itr)
any(itr) = any(identity, itr)
all(itr) = all(identity, itr)

any(f::Any, itr) = any(Predicate(f), itr)
any(f::Predicate, itr) = mapreduce_sc_impl(f, OrFun(), itr)
any(f::IdFun, itr) =
any(f::typeof(identity), itr) =
eltype(itr) <: Bool ?
mapreduce_sc_impl(f, OrFun(), itr) :
reduce(or_bool_only, itr)

all(f::Any, itr) = all(Predicate(f), itr)
all(f::Predicate, itr) = mapreduce_sc_impl(f, AndFun(), itr)
all(f::IdFun, itr) =
all(f::typeof(identity), itr) =
eltype(itr) <: Bool ?
mapreduce_sc_impl(f, AndFun(), itr) :
reduce(and_bool_only, itr)
Expand Down
34 changes: 17 additions & 17 deletions base/reducedim.jl
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ end

reducedim_init{T}(f, op::MaxFun, A::AbstractArray{T}, region) = reducedim_initarray0(A, region, typemin(f(zero(T))))
reducedim_init{T}(f, op::MinFun, A::AbstractArray{T}, region) = reducedim_initarray0(A, region, typemax(f(zero(T))))
reducedim_init{T}(f::Union{AbsFun,Abs2Fun}, op::MaxFun, A::AbstractArray{T}, region) =
reducedim_init{T}(f::Union{typeof(abs),typeof(abs2)}, op::MaxFun, A::AbstractArray{T}, region) =
reducedim_initarray(A, region, zero(f(zero(T))))

reducedim_init(f, op::AndFun, A::AbstractArray, region) = reducedim_initarray(A, region, true)
Expand All @@ -133,17 +133,17 @@ reducedim_init(f, op::OrFun, A::AbstractArray, region) = reducedim_initarray(A,
for (IT, RT) in ((CommonReduceResult, :(eltype(A))), (SmallSigned, :Int), (SmallUnsigned, :UInt))
T = Union{[AbstractArray{t} for t in IT.types]..., [AbstractArray{Complex{t}} for t in IT.types]...}
@eval begin
reducedim_init(f::IdFun, op::AddFun, A::$T, region) =
reducedim_init(f::typeof(identity), op::AddFun, A::$T, region) =
reducedim_initarray(A, region, zero($RT))
reducedim_init(f::IdFun, op::MulFun, A::$T, region) =
reducedim_init(f::typeof(identity), op::MulFun, A::$T, region) =
reducedim_initarray(A, region, one($RT))
reducedim_init(f::Union{AbsFun,Abs2Fun}, op::AddFun, A::$T, region) =
reducedim_init(f::Union{typeof(abs),typeof(abs2)}, op::AddFun, A::$T, region) =
reducedim_initarray(A, region, real(zero($RT)))
reducedim_init(f::Union{AbsFun,Abs2Fun}, op::MulFun, A::$T, region) =
reducedim_init(f::Union{typeof(abs),typeof(abs2)}, op::MulFun, A::$T, region) =
reducedim_initarray(A, region, real(one($RT)))
end
end
reducedim_init(f::Union{IdFun,AbsFun,Abs2Fun}, op::AddFun, A::AbstractArray{Bool}, region) =
reducedim_init(f::Union{typeof(identity),typeof(abs),typeof(abs2)}, op::AddFun, A::AbstractArray{Bool}, region) =
reducedim_initarray(A, region, 0)


Expand Down Expand Up @@ -234,15 +234,15 @@ mapreducedim!(f, op, R::AbstractArray, A::AbstractArray) =
(_mapreducedim!(f, to_op(op), R, A); R)

reducedim!{RT}(op, R::AbstractArray{RT}, A::AbstractArray) =
mapreducedim!(IdFun(), op, R, A, zero(RT))
mapreducedim!(identity, op, R, A, zero(RT))

mapreducedim(f, op, A::AbstractArray, region, v0) =
mapreducedim!(f, op, reducedim_initarray(A, region, v0), A)
mapreducedim{T}(f, op, A::AbstractArray{T}, region) =
mapreducedim!(f, op, reducedim_init(f, to_op(op), A, region), A)

reducedim(op, A::AbstractArray, region, v0) = mapreducedim(IdFun(), op, A, region, v0)
reducedim(op, A::AbstractArray, region) = mapreducedim(IdFun(), op, A, region)
reducedim(op, A::AbstractArray, region, v0) = mapreducedim(identity, op, A, region, v0)
reducedim(op, A::AbstractArray, region) = mapreducedim(identity, op, A, region)


##### Specific reduction functions #####
Expand All @@ -255,24 +255,24 @@ for (fname, Op) in [(:sum, :AddFun), (:prod, :MulFun),
@eval begin
$(fname!)(f::Union{Function,Func{1}}, r::AbstractArray, A::AbstractArray; init::Bool=true) =
mapreducedim!(f, $(Op)(), initarray!(r, $(Op)(), init), A)
$(fname!)(r::AbstractArray, A::AbstractArray; init::Bool=true) = $(fname!)(IdFun(), r, A; init=init)
$(fname!)(r::AbstractArray, A::AbstractArray; init::Bool=true) = $(fname!)(identity, r, A; init=init)

$(fname)(f::Union{Function,Func{1}}, A::AbstractArray, region) =
mapreducedim(f, $(Op)(), A, region)
$(fname)(A::AbstractArray, region) = $(fname)(IdFun(), A, region)
$(fname)(A::AbstractArray, region) = $(fname)(identity, A, region)
end
end

for (fname, fbase, Fun) in [(:sumabs, :sum, :AbsFun),
(:sumabs2, :sum, :Abs2Fun),
(:maxabs, :maximum, :AbsFun),
(:minabs, :minimum, :AbsFun)]
for (fname, fbase, fun) in [(:sumabs, :sum, :abs),
(:sumabs2, :sum, :abs2),
(:maxabs, :maximum, :abs),
(:minabs, :minimum, :abs)]
fname! = symbol(fname, '!')
fbase! = symbol(fbase, '!')
@eval begin
$(fname!)(r::AbstractArray, A::AbstractArray; init::Bool=true) =
$(fbase!)($(Fun)(), r, A; init=init)
$(fname)(A::AbstractArray, region) = $(fbase)($(Fun)(), A, region)
$(fbase!)($(fun), r, A; init=init)
$(fname)(A::AbstractArray, region) = $(fbase)($(fun), A, region)
end
end

Expand Down
2 changes: 1 addition & 1 deletion base/sparse.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

module SparseArrays

using Base: Func, AddFun, OrFun, ConjFun, IdFun
using Base: Func, AddFun, OrFun
using Base: ReshapedArray
using Base.Sort: Forward
using Base.LinAlg: AbstractTriangular, PosDefException
Expand Down
Loading

0 comments on commit 0a72958

Please sign in to comment.