Skip to content
This repository has been archived by the owner on May 4, 2019. It is now read-only.

Commit

Permalink
Revise 0.4 compatibility
Browse files Browse the repository at this point in the history
Removes metaprogramming-heavy 0.4 map regime,
which seems to be responsible for strange
intermittent Travis failures.
  • Loading branch information
davidagold committed Jul 7, 2016
1 parent 3bc6fa2 commit 3c9ae3b
Show file tree
Hide file tree
Showing 2 changed files with 230 additions and 296 deletions.
307 changes: 162 additions & 145 deletions src/map.jl
Original file line number Diff line number Diff line change
@@ -1,178 +1,219 @@
# if VERSION < v"0.5.0-dev+3294"
# include("map0_4.jl")
# else
using Base: ith_all
if VERSION < v"0.5.0-dev+3294"
include("map0_4.jl")
else
using Base: collect_similar, Generator, ith_all
using Base: collect_similar, Generator
end

macro nullcheck(Xs, nargs)
res = :($(Xs)[1].isnull[i])
for i = 2:nargs
e = :($(Xs)[$i].isnull[i])
res = Expr(:||, res, e)
end
return res
macro nullcheck(Xs, nargs)
res = :($(Xs)[1].isnull[i])
for i = 2:nargs
e = :($(Xs)[$i].isnull[i])
res = Expr(:||, res, e)
end
return res
end

macro fcall(Xs, nargs)
res = Expr(:call, :f)
for i in 1:nargs
push!(res.args, :($(Xs)[$i].values[i]))
end
return res
macro fcall(Xs, nargs)
res = Expr(:call, :f)
for i in 1:nargs
push!(res.args, :($(Xs)[$i].values[i]))
end
return res
end

# Base.map!
# Base.map!

Base.map!{F}(f::F, X::NullableArray; lift=false) = map!(f, X, X; lift=lift)
function Base.map!{F}(f::F, dest::NullableArray, X::NullableArray; lift=false)
if lift
for (i, j) in zip(eachindex(dest), eachindex(X))
if X.isnull[j]
dest.isnull[i] = true
else
dest.isnull[i] = false
dest.values[i] = f(X.values[j])
end
Base.map!{F}(f::F, X::NullableArray; lift=false) = map!(f, X, X; lift=lift)
function Base.map!{F}(f::F, dest::NullableArray, X::NullableArray; lift=false)
if lift
for (i, j) in zip(eachindex(dest), eachindex(X))
if X.isnull[j]
dest.isnull[i] = true
else
dest.isnull[i] = false
dest.values[i] = f(X.values[j])
end
else
for (i, j) in zip(eachindex(dest), eachindex(X))
dest[i] = f(X[j])
end
else
for (i, j) in zip(eachindex(dest), eachindex(X))
dest[i] = f(X[j])
end
end
return dest
end

function Base.map!{F}(f::F, dest::NullableArray, X1::NullableArray,
X2::NullableArray; lift=false)
if lift
for (i, j, k) in zip(eachindex(dest), eachindex(X1), eachindex(X2))
if X1.isnull[j] | X2.isnull[k]
dest.isnull[i] = true
else
dest.isnull[i] = false
dest.values[i] = f(X1.values[j], X2.values[k])
end
end
return dest
else
for (i, j, k) in zip(eachindex(dest), eachindex(X1), eachindex(X2))
dest[i] = f(X1[j], X2[k])
end
end
return dest
end

function Base.map!{F}(f::F, dest::NullableArray, X1::NullableArray,
X2::NullableArray; lift=false)
function Base.map!{F}(f::F, dest::NullableArray, Xs::NullableArray...; lift=false)
_map!(f, dest, Xs, lift)
end


@generated function _map!{F, N}(f::F, dest::NullableArray, Xs::NTuple{N, NullableArray}, lift)
return quote
if lift
for (i, j, k) in zip(eachindex(dest), eachindex(X1), eachindex(X2))
if X1.isnull[j] | X2.isnull[k]
for i in linearindices(Xs[1])
if @nullcheck Xs $N
dest.isnull[i] = true
else
dest.isnull[i] = false
dest.values[i] = f(X1.values[j], X2.values[k])
dest.values[i] = @fcall Xs $N
end
end
else
for (i, j, k) in zip(eachindex(dest), eachindex(X1), eachindex(X2))
dest[i] = f(X1[j], X2[k])
for i in linearindices(Xs[1])
dest[i] = f(ith_all(i, Xs)...)
end
end
return dest
end
end

function Base.map!{F}(f::F, dest::NullableArray, Xs::NullableArray...; lift=false)
_map!(f, dest, Xs, lift)
end
# Base.map

@generated function _map!{F, N}(f::F, dest::NullableArray, Xs::Tuple{Vararg{NullableArray, N}}, lift)
return quote
if lift
for i in linearindices(Xs[1])
if @nullcheck Xs $N
dest.isnull[i] = true
else
dest.isnull[i] = false
dest.values[i] = @fcall Xs $N
end
end
else
for i in linearindices(Xs[1])
dest[i] = f(ith_all(i, Xs)...)
end
end
return dest
end
if VERSION < v"0.5.0-dev+3294"
function Base.map(f, X::NullableArray; lift=false)
lift ? _liftedmap(f, X) : _map(f, X)
end

# Base.map

function Base.map(f, X1::NullableArray, X2::NullableArray; lift=false)
lift ? _liftedmap(f, X1, X2) : _map(f, X1, X2)
end
function Base.map(f, Xs::NullableArray...; lift=false)
lift ? _liftedmap(f, Xs...) : _map(f, Xs...)
end
else
function Base.map(f, X::NullableArray; lift=false)
lift ? _liftedmap(f, X) : collect_similar(X, Generator(f, X))
end
function Base.map(f, X1::NullableArray, X2::NullableArray; lift=false)
lift ? _liftedmap(f, X1, X2) : collect(Generator(f, X1, X2))
end
function Base.map(f, Xs::NullableArray...; lift=false)
lift ? _liftedmap(f, Xs...) : collect(Generator(f, Xs...))
lift ? _liftedmap(f, Xs) : collect(Generator(f, Xs...))
end
end

function _liftedmap(f, X::NullableArray)
len = length(X)
# if X is empty, fall back on type inference
len > 0 || return NullableArray{Base.return_types(f, (eltype(X),))[1], 1}()
i = 1
while X.isnull[i]
i += 1
end
# if X is all null, fall back on type inference
i <= len || return similar(X, Base.return_types(f, (eltype(X),))[1])
v = f(X.values[i])
dest = similar(X, typeof(v))
dest[i] = v
_liftedmap_to!(f, dest, X, i+1, len)
end

function _liftedmap(f, X::NullableArray)
len = length(X)
# if X is empty, fall back on type inference
len > 0 || return NullableArray{Base.return_types(f, (eltype(X),)), 0}()
i = 1
while X.isnull[i]
i += 1
end
# if X is all null, fall back on type inference
i <= len || return similar(X, Base.return_types(f, (eltype(X),)))
v = f(X.values[i])
dest = similar(X, typeof(v))
dest[i] = v
map_to!(f, dest, X, i+1, len)
function _liftedmap(f, X1::NullableArray, X2::NullableArray)
len = prod(promote_shape(X1, X2))
len > 0 || return NullableArray{Base.return_types(f, (eltype(X1), eltype(X2))), 0}()
i = 1
while X1.isnull[i] | X2.isnull[i]
i += 1
end
i <= len || return similar(X1, Base.return_types(f, (eltype(X1), eltype(X2))))
v = f(X1.values[i], X2.values[i])
dest = similar(X1, typeof(v))
dest[i] = v
_liftedmap_to!(f, dest, X1, X2, i+1, len)
end

function _liftedmap(f, X1::NullableArray, X2::NullableArray)
len = prod(promote_shape(X1, X2))
len > 0 || return NullableArray{Base.return_types(f, (eltype(X1), eltype(X2))), 0}()
@generated function _liftedmap{N}(f, Xs::NTuple{N, NullableArray})
return quote
shp = size(zip(Xs...))
len = prod(shp)
i = 1
while X1.isnull[i] | X2.isnull[i]
while @nullcheck Xs $N
i += 1
end
i <= len || return similar(X1, Base.return_types(f, (eltype(X1), eltype(X2))))
v = f(X1.values[i], X2.values[i])
dest = similar(X1, typeof(v))
i <= len || return similar(X1, Base.return_types(f, tuple([ eltype(X) for X in Xs ])))
v = @fcall Xs $N
dest = similar(Xs[1], typeof(v))
dest[i] = v
map_to!(f, dest, X1, X2, i+1, len)
_liftedmap_to!(f, dest, Xs, i+1, len)
end
end

@generated function _liftedmap{N}(f, Xs::Vararg{NullableArray, N})
return quote
shp = size(zip(Xs...))
len = prod(shp)
i = 1
while @nullcheck Xs $N
i += 1
end
i <= len || return similar(X1, Base.return_types(f, tuple([ eltype(X) for X in Xs ])))
v = @fcall Xs $N
dest = similar(Xs[1], typeof(v))
dest[i] = v
map_to!(f, dest, Xs, i+1, len)
function _liftedmap_to!{T}(f, dest::NullableArray{T}, X, offs, len)
# map to dest array, checking the type of each result. if a result does not
# match, widen the result type and re-dispatch.
i = offs
while i <= len
@inbounds if X.isnull[i]
i += 1; continue
end
@inbounds el = f(X.values[i])
S = typeof(el)
if S === T || S <: T
@inbounds dest[i] = el::T
i += 1
else
R = typejoin(T, S)
new = similar(dest, R)
copy!(new, 1, dest, 1, i-1)
@inbounds new[i] = el
return map_to!(f, new, X, i+1, len)
end
end
return dest
end

function map_to!{T}(f, dest::NullableArray{T}, X, offs, len)
# map to dest array, checking the type of each result. if a result does not
# match, widen the result type and re-dispatch.
i = offs
while i <= len
@inbounds if X.isnull[i]
i += 1; continue
end
@inbounds el = f(X.values[i])
S = typeof(el)
if S === T || S <: T
@inbounds dest[i] = el::T
i += 1
else
R = typejoin(T, S)
new = similar(dest, R)
copy!(new, 1, dest, 1, i-1)
@inbounds new[i] = el
return map_to!(f, new, X, i+1, len)
end
function _liftedmap_to!{T}(f, dest::NullableArray{T}, X1, X2, offs, len)
i = offs
while i <= len
@inbounds if X1.isnull[i] | X2.isnull[i]
i += 1; continue
end
@inbounds el = f(X1.values[i], X2.values[i])
S = typeof(el)
if S === T || S <: T
@inbounds dest[i] = el::T
i += 1
else
R = typejoin(T, S)
new = similar(dest, R)
copy!(new, 1, dest, 1, i-1)
@inbounds new[i] = el
return map_to!(f, new, X1, X2, i+1, len)
end
return dest
end
return dest
end

function map_to!{T}(f, dest::NullableArray{T}, X1, X2, offs, len)
@generated function _liftedmap_to!{T, N}(f, dest::NullableArray{T}, Xs::NTuple{N,NullableArray}, offs, len)
return quote
i = offs
while i <= len
@inbounds if X1.isnull[i] | X2.isnull[i]
@inbounds if @nullcheck Xs $N
i += 1; continue
end
@inbounds el = f(X1.values[i], X2.values[i])
@inbounds el = @fcall Xs $N
S = typeof(el)
if S === T || S <: T
@inbounds dest[i] = el::T
Expand All @@ -182,33 +223,9 @@ else
new = similar(dest, R)
copy!(new, 1, dest, 1, i-1)
@inbounds new[i] = el
return map_to!(f, new, X1, X2, i+1, len)
return map_to!(f, new, Xs, i+1, len)
end
end
return dest
end

@generated function map_to!{T, N}(f, dest::NullableArray{T}, Xs::Tuple{Vararg{NullableArray, N}}, offs, len)
return quote
i = offs
while i <= len
@inbounds if @nullcheck Xs $N
i += 1; continue
end
@inbounds el = @fcall Xs $N
S = typeof(el)
if S === T || S <: T
@inbounds dest[i] = el::T
i += 1
else
R = typejoin(T, S)
new = similar(dest, R)
copy!(new, 1, dest, 1, i-1)
@inbounds new[i] = el
return map_to!(f, new, Xs, i+1, len)
end
end
return dest
end
end
end
Loading

0 comments on commit 3c9ae3b

Please sign in to comment.