Skip to content

todo : change arrayof to children and arrayof(n)[end] to lastchild #58

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,9 +189,7 @@ element removed (disjoined).
#### General

- Ints vs Uints w.r.t. bitwise operations
- `children` instead of `arrayof`
- standardize "short-fn" interfaces:
- `lastchild` instead of `arrayof(node)[end]`
- `peek` should become `pop`, `pop` should become `butlast`
- What is Base doing for Arrays w.r.t. `boundscheck!`, can we drop boundcheck for iteration

Expand Down
61 changes: 32 additions & 29 deletions src/BitmappedVectorTrie.jl
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@ shift(t::BitmappedTrie) =
error("$(typeof(t)) does not implement FunctionalCollections.shift")
maxlength(t::BitmappedTrie) =
error("$(typeof(t)) does not implement FunctionalCollections.maxlength")
arrayof(t::BitmappedTrie) =
error("$(typeof(t)) does not implement FunctionalCollections.arrayof")
children(t::BitmappedTrie) =
error("$(typeof(t)) does not implement FunctionalCollections.children")

function Base.isequal(t1::BitmappedTrie, t2::BitmappedTrie)
length(t1) == length(t2) &&
shift(t1) == shift(t2) &&
maxlength(t1) == maxlength(t2) &&
arrayof(t1) == arrayof(t2)
children(t1) == children(t2)
end

==(t1::BitmappedTrie, t2::BitmappedTrie) = isequal(t1, t2)
Expand Down Expand Up @@ -80,15 +80,17 @@ struct DenseLeaf{T} <: DenseBitmappedTrie{T}
end
DenseLeaf{T}() where {T} = DenseLeaf{T}(T[])

arrayof( node::DenseNode) = node.arr
children( node::DenseNode) = node.arr
shift( node::DenseNode) = node.shift
maxlength( node::DenseNode) = node.maxlength
lastchild( node::DenseNode) = children(node)[end]
Base.length(node::DenseNode) = node.length

arrayof( leaf::DenseLeaf) = leaf.arr
children( leaf::DenseLeaf) = leaf.arr
shift( ::DenseLeaf) = shiftby
maxlength( leaf::DenseLeaf) = trielen
Base.length(leaf::DenseLeaf) = length(arrayof(leaf))
Base.length(leaf::DenseLeaf) = length(children(leaf))


function promoted(node::DenseBitmappedTrie{T}) where T
DenseNode{T}(DenseBitmappedTrie{T}[node],
Expand All @@ -115,7 +117,7 @@ witharr(leaf::DenseLeaf{T}, arr::Array) where {T} = DenseLeaf{T}(arr)

function append(leaf::DenseLeaf, el)
if length(leaf) < maxlength(leaf)
newarr = copy_to_len(arrayof(leaf), 1 + length(leaf))
newarr = copy_to_len(children(leaf), 1 + length(leaf))
newarr[end] = el
witharr(leaf, newarr)
else
Expand All @@ -127,12 +129,12 @@ function append(node::DenseNode{T}, el) where T
child = append(demoted(node), el)
witharr(node, DenseBitmappedTrie{T}[child], 1)
elseif length(node) < maxlength(node)
if length(arrayof(node)[end]) == maxlength(arrayof(node)[end])
newarr = copy_to_len(arrayof(node), 1 + length(arrayof(node)))
if length(lastchild(node)) == maxlength(lastchild(node))
newarr = copy_to_len(children(node), 1 + length(children(node)))
newarr[end] = append(demoted(node), el)
witharr(node, newarr, 1)
else
newarr = arrayof(node)[:]
newarr = children(node)[:]
newarr[end] = append(newarr[end], el)
witharr(node, newarr, 1)
end
Expand All @@ -143,16 +145,16 @@ end
push(leaf::DenseLeaf, el) = append(leaf, el)
push(node::DenseNode, el) = append(node, el)

Base.getindex(leaf::DenseLeaf, i::Int) = arrayof(leaf)[mask(leaf, i)]
Base.getindex(node::DenseNode, i::Int) = arrayof(node)[mask(node, i)][i]
Base.getindex(leaf::DenseLeaf, i::Int) = children(leaf)[mask(leaf, i)]
Base.getindex(node::DenseNode, i::Int) = children(node)[mask(node, i)][i]

function assoc(leaf::DenseLeaf{T}, i::Int, el) where T
newarr = arrayof(leaf)[:]
newarr = children(leaf)[:]
newarr[mask(leaf, i)] = el
DenseLeaf{T}(newarr)
end
function assoc(node::DenseNode, i::Int, el)
newarr = arrayof(node)[:]
newarr = children(node)[:]
idx = mask(node, i)
newarr[idx] = assoc(newarr[idx], i, el)
witharr(node, newarr)
Expand All @@ -164,9 +166,9 @@ peek(bt::DenseBitmappedTrie) = bt[end]
# structure, so `pop` is defined to return a Trie without its last
# element. Use `peek` to access the last element.
#
pop(leaf::DenseLeaf) = witharr(leaf, arrayof(leaf)[1:end-1])
pop(leaf::DenseLeaf) = witharr(leaf, children(leaf)[1:end-1])
function pop(node::DenseNode)
newarr = arrayof(node)[:]
newarr = children(node)[:]
newarr[end] = pop(newarr[end])
witharr(node, newarr, -1)
end
Expand All @@ -191,15 +193,16 @@ struct SparseLeaf{T} <: SparseBitmappedTrie{T}
end
SparseLeaf{T}() where {T} = SparseLeaf{T}(T[], 0)

arrayof( n::SparseNode) = n.arr
children( n::SparseNode) = n.arr
shift( n::SparseNode) = n.shift
maxlength( n::SparseNode) = n.maxlength
lastchild( n::SparseNode) = children(n)[end]
Base.length(n::SparseNode) = n.length

arrayof( l::SparseLeaf) = l.arr
children( l::SparseLeaf) = l.arr
shift( ::SparseLeaf) = 0
maxlength( l::SparseLeaf) = trielen
Base.length(l::SparseLeaf) = length(arrayof(l))
Base.length(l::SparseLeaf) = length(children(l))

function demoted(n::SparseNode{T}) where T
shift(n) == shiftby ?
Expand All @@ -220,23 +223,23 @@ function update(l::SparseLeaf{T}, i::Int, el::T) where T
bitmap = bitpos(l, i) | l.bitmap
idx = index(l, i)
if hasi
newarr = arrayof(l)[:]
newarr = children(l)[:]
newarr[idx] = el
else
newarr = vcat(arrayof(l)[1:idx-1], [el], arrayof(l)[idx:end])
newarr = vcat(children(l)[1:idx-1], [el], children(l)[idx:end])
end
(SparseLeaf{T}(newarr, bitmap), !hasi)
end
function update(n::SparseNode{T}, i::Int, el::T) where T
bitmap = bitpos(n, i) | n.bitmap
idx = index(n, i)
if hasindex(n, i)
newarr = arrayof(n)[:]
newarr = children(n)[:]
updated, inc = update(newarr[idx], i, el)
newarr[idx] = updated
else
child, inc = update(demoted(n), i, el)
newarr = vcat(arrayof(n)[1:idx-1], [child], arrayof(n)[idx:end])
newarr = vcat(children(n)[1:idx-1], [child], children(n)[idx:end])
end
(SparseNode{T}(newarr,
n.shift,
Expand All @@ -246,9 +249,9 @@ function update(n::SparseNode{T}, i::Int, el::T) where T
end

Base.get(n::SparseLeaf, i::Int, default) =
hasindex(n, i) ? arrayof(n)[index(n, i)] : default
hasindex(n, i) ? children(n)[index(n, i)] : default
Base.get(n::SparseNode, i::Int, default) =
hasindex(n, i) ? get(arrayof(n)[index(n, i)], i, default) : default
hasindex(n, i) ? get(children(n)[index(n, i)], i, default) : default

function initial_state(t::SparseBitmappedTrie)
t.length == 0 && return Int[]
Expand All @@ -267,19 +270,19 @@ function Base.iterate(t::SparseBitmappedTrie, state = initial_state(t))
push!(state, index + 1)
return item, vcat(state, ones(Int, 1 + round(Int, t.shift / shiftby) -
length(state)))
elseif node === arrayof(t)
elseif node === children(t)
return item, Int[]
end
end
end
end

function directindex(t::SparseBitmappedTrie, v::Vector{Int})
isempty(v) && return arrayof(t)
local node = arrayof(t)
isempty(v) && return children(t)
local node = children(t)
for i=v
node = node[i]
node = isa(node, SparseBitmappedTrie) ? arrayof(node) : node
node = isa(node, SparseBitmappedTrie) ? children(node) : node
end
node
end
16 changes: 8 additions & 8 deletions test/SparseBitmappedTrieTest.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ using FunctionalCollections
using Test

import FunctionalCollections: SparseBitmappedTrie, SparseNode, SparseLeaf,
bitpos, index, hasindex, arrayof, update
bitpos, index, hasindex, children, update

@testset "Sparse Bitmapped Vector Tries" begin

Expand Down Expand Up @@ -32,7 +32,7 @@ import FunctionalCollections: SparseBitmappedTrie, SparseNode, SparseLeaf,

l = SparseLeaf{Int}([1, 5], 2^0 | 2^4)
l, _ = update(l, 2, 2)
@test arrayof(l) == [1, 2, 5]
@test children(l) == [1, 2, 5]
@test length(l) == 3
@test hasindex(l, 1)
@test hasindex(l, 2)
Expand All @@ -41,21 +41,21 @@ import FunctionalCollections: SparseBitmappedTrie, SparseNode, SparseLeaf,
@test hasindex(l, 5)
@test !hasindex(l, 6)

@test arrayof(update(l, 2, 100)[1]) == [1, 100, 5]
@test children(update(l, 2, 100)[1]) == [1, 100, 5]
end

@testset "SparseNode update" begin
n, _ = update(SparseNode(String), 1, "foo")
@test length(arrayof(n)) == 1
@test length(children(n)) == 1

leaf = arrayof(n)[1].arr[1].arr[1].arr[1].arr[1].arr[1].arr[1]
leaf = children(n)[1].arr[1].arr[1].arr[1].arr[1].arr[1].arr[1]
@test hasindex(leaf, 1)
@test leaf.arr[1] == "foo"

n2, _ = update(n, 33, "bar")
leaf2 = n2.arr[1].arr[1].arr[1].arr[1].arr[1].arr[1].arr[2]
@test hasindex(leaf2, 33)
@test arrayof(leaf2)[1] == "bar"
@test children(leaf2)[1] == "bar"
end

@testset "SparseBitmappedTrie get" begin
Expand All @@ -67,11 +67,11 @@ import FunctionalCollections: SparseBitmappedTrie, SparseNode, SparseLeaf,

@testset "SparseBitmappedTrie length & items" begin
n = SparseNode(Int)
for i=1:1000
for i = 1:1000
n, _ = update(n, i, i)
end
@test lastindex(n) == length(n) == 1000
@test [i for i=n] == collect(1:1000)
@test [i for i = n] == collect(1:1000)
end

end