Skip to content

Commit

Permalink
Make indcopy() type-stable
Browse files Browse the repository at this point in the history
This yields major performance improvements for any function using
the output for indexing.
  • Loading branch information
timholy committed Aug 16, 2013
1 parent 5994263 commit beee4e2
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 11 deletions.
23 changes: 13 additions & 10 deletions base/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1394,22 +1394,25 @@ function findin(a, b)
end

# Copying subregions
function indcopy(sz::Dims, I::RangeVecIntList)
function indcopy(sz::Dims, I::Vector)
n = length(I)
dst = Array(AbstractVector{Int}, n)
src = Array(AbstractVector{Int}, n)
for dim = 1:(n-1)
tmp = findin(I[dim], 1:sz[dim])
dst[dim] = tmp
src[dim] = I[dim][tmp]
s = sz[n]
for i = n+1:length(sz)
s *= sz[i]
end
dst = eltype(I)[findin(I[i], i < n ? (1:sz[i]) : (1:s)) for i = 1:n]
src = eltype(I)[I[i][findin(I[i], i < n ? (1:sz[i]) : (1:s))] for i = 1:n]
dst, src
end

function indcopy(sz::Dims, I::(RangeIndex...))
n = length(I)
s = sz[n]
for i = n+1:length(sz)
s *= sz[i]
end
tmp = findin(I[n], 1:s)
dst[n] = tmp
src[n] = I[n][tmp]
dst::typeof(I) = ntuple(n, i-> findin(I[i], i < n ? (1:sz[i]) : (1:s)))::typeof(I)
src::typeof(I) = ntuple(n, i-> I[i][findin(I[i], i < n ? (1:sz[i]) : (1:s))])::typeof(I)
dst, src
end

Expand Down
12 changes: 11 additions & 1 deletion base/range.jl
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ function intersect(r::Ranges, s::Ranges...)
end

# findin (the index of intersection)
function findin{T1<:Integer, T2<:Integer}(r::Ranges{T1}, span::Range1{T2})
function _findin{T1<:Integer, T2<:Integer}(r::Ranges{T1}, span::Range1{T2})
local ifirst
local ilast
fspan = first(span)
Expand All @@ -265,9 +265,19 @@ function findin{T1<:Integer, T2<:Integer}(r::Ranges{T1}, span::Range1{T2})
ifirst = fr >= fspan ? 1 : length(r)+1
ilast = fr <= lspan ? length(r) : 0
end
ifirst, ilast
end

function findin{T1<:Integer, T2<:Integer}(r::Range1{T1}, span::Range1{T2})
ifirst, ilast = _findin(r, span)
ifirst:ilast
end

function findin{T1<:Integer, T2<:Integer}(r::Range{T1}, span::Range1{T2})
ifirst, ilast = _findin(r, span)
ifirst:1:ilast
end

## linear operations on ranges ##

-(r::Ranges) = Range(-r.start, -step(r), r.len)
Expand Down

0 comments on commit beee4e2

Please sign in to comment.