Skip to content

Instantly share code, notes, and snippets.

@AndyGreenwell
Last active December 4, 2015 18:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AndyGreenwell/197fea6cf2c0ff601e30 to your computer and use it in GitHub Desktop.
Save AndyGreenwell/197fea6cf2c0ff601e30 to your computer and use it in GitHub Desktop.
Proposal 1 for alternative uniqueslices function signatures (but with fake names)
@generated function foo{T,N}(A::AbstractArray{T,N}, dim::Int)
quote
1 <= dim <= $N || return copy(A)
hashes = zeros(UInt, size(A, dim))
# Compute hash for each row
k = 0
@nloops $N i A d->(if d == dim; k = i_d; end) begin
@inbounds hashes[k] = hash(hashes[k], hash((@nref $N A i)))
end
# Collect index of first row for each hash
uniquerow = Array(Int, size(A, dim))
ic = Array(Int, size(A, dim))
ia = Int[]
firstrow = Dict{Prehashed,Int}()
icdict = Dict{Int,Int}()
iadict = Dict{UInt,Int}()
h = 0
for k = 1:size(A, dim)
tmp = get!(firstrow, Prehashed(hashes[k]), k)
uniquerow[k] = tmp
if !haskey(icdict,tmp)
h += 1
icdict[tmp] = h
ic[k] = h
else
ic[k] = icdict[tmp]
end
if !haskey(iadict,hashes[k])
iadict[hashes[k]] = k
push!(ia,k)
end
end
uniquerows = collect(values(firstrow))
# Check for collisions
collided = falses(size(A, dim))
@inbounds begin
@nloops $N i A d->(if d == dim
k = i_d
j_d = uniquerow[k]
else
j_d = i_d
end) begin
if (@nref $N A j) != (@nref $N A i)
collided[k] = true
end
end
end
if any(collided)
nowcollided = BitArray(size(A, dim))
while any(collided)
# Collect index of first row for each collided hash
empty!(firstrow)
for j = 1:size(A, dim)
collided[j] || continue
uniquerow[j] = get!(firstrow, Prehashed(hashes[j]), j)
end
for v in values(firstrow)
push!(uniquerows, v)
end
# Check for collisions
fill!(nowcollided, false)
@nloops $N i A d->begin
if d == dim
k = i_d
j_d = uniquerow[k]
(!collided[k] || j_d == k) && continue
else
j_d = i_d
end
end begin
if (@nref $N A j) != (@nref $N A i)
nowcollided[k] = true
end
end
(collided, nowcollided) = (nowcollided, collided)
end
end
ib = Array(Vector{Int},length(ia))
for k = 1:length(ia)
ib[k] = Int[]
end
for h = 1:length(ic)
push!(ib[ic[h]], h)
end
return ib
end
end
# Signature for core of uniqueind/uniqueslices/whatevever
# ib = foo(A, dim)
function bar(A, dim::Int; selection::Function=first)
# selection is first, last, or something else
ib = foo(A, dim)
ia = map(selection, ib)
l = length(size(A))
s = Array(Any,l)
for k = 1:l
s[k] = k == dim ? ia : Colon()
end
C = A[s...]
return C, ia, ib
end
function baz(A, dim::Int)
C, ia, ib = bar(A, dim)
return C, ib
end
function qux(A, dim::Int) #Just returns the same output as the current unique(A, dim)
C, ia, ib = bar(A, dim)
return C
end
function norf(ib)
n = 0
for i = 1:length(ib)
n += length(ib[i])
end
ic = Array(Int,n)
for i = 1:length(ib)
for k = 1:length(ib[i])
ic[ib[i][k]] = i
end
end
return ic
end
function bletch(A, dim::Int; selection::Function=first)
C, ia, ib = bar(A, dim, selection)
ic = norf(ib)
return C, ia, ib, ic
end
function grunt(A, dim::Int; selection::Function=first)
ib = foo(A, dim)
ia = map(selection, ib)
ic = norf(ib)
return ia, ib, ic
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment