Skip to content

Commit

Permalink
Fix bug in Vector.concat/2
Browse files Browse the repository at this point in the history
Close #6
  • Loading branch information
sabiwara committed Oct 14, 2024
1 parent 6bc88f7 commit 8225669
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 24 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Dev

### Bug fixes

- Fix bug in `Aja.Vector.concat/2`

## v0.7.0 (2024-08-28)

### Enhancements
Expand Down
43 changes: 20 additions & 23 deletions lib/vector/builder.ex
Original file line number Diff line number Diff line change
Expand Up @@ -115,26 +115,30 @@ defmodule Aja.Vector.Builder do
end
end

def from_trie(trie, level, index) do
case :erlang.bsr(index, level) do
def from_trie(trie, level, amount) do
do_from_trie(trie, level, amount, [])
end

def do_from_trie(_trie, _level, 0, acc), do: [[] | acc]

def do_from_trie(trie, level, amount, acc) do
case :erlang.bsr(amount, level) do
C.branch_factor() ->
prepend_single_builder([[trie]], level)
prepend_single_builder([[trie] | acc], level)

_ ->
do_from_trie(trie, level, index, [])
end
end
full_nodes_count ->
reverse_full_nodes = Node.take_reverse(trie, full_nodes_count)
acc = [reverse_full_nodes | acc]

defp do_from_trie(trie, level = C.bits(), index, acc) do
current_index = C.radix_search(index, level)
[subtries_list(trie, 1, current_index + 1, []) | acc]
end
case amount - :erlang.bsl(full_nodes_count, level) do
0 ->
prepend_single_builder(acc, C.decr_level(level))

defp do_from_trie(trie, level, index, acc) do
current_index = C.radix_search(index, level)
child = elem(trie, current_index)
new_acc = [subtries_list(trie, 1, current_index + 1, []) | acc]
do_from_trie(child, C.decr_level(level), index, new_acc)
remaining ->
:erlang.element(full_nodes_count + 1, trie)
|> do_from_trie(C.decr_level(level), remaining, acc)
end
end
end

defp prepend_single_builder(list, _level = 0), do: list
Expand All @@ -143,13 +147,6 @@ defmodule Aja.Vector.Builder do
prepend_single_builder([[] | list], C.decr_level(level))
end

defp subtries_list(_trie, _index = until, until, acc), do: acc

defp subtries_list(trie, index, until, acc) do
new_acc = [:erlang.element(index, trie) | acc]
subtries_list(trie, index + 1, until, new_acc)
end

@compile {:inline, tail_offset: 3}
def tail_offset([], _level, acc), do: acc

Expand Down
12 changes: 12 additions & 0 deletions lib/vector/node.ex
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,16 @@ defmodule Aja.Vector.Node do
unquote(C.array_with_nils(i))
end
end

def take_reverse(node, amount)
def take_reverse(_node, 0), do: []

for i <- C.range() do
# def take({arg1, arg2, _arg3, _arg4}, _amount = 2) do
# [arg2, arg1]
# end
def take_reverse(unquote(C.array_with_wildcards(i)), _amount = unquote(i)) do
unquote(C.reversed_arguments(i))
end
end
end
2 changes: 1 addition & 1 deletion lib/vector/raw.ex
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ defmodule Aja.Vector.Raw do
end

def concat_vector(left = small(_, _, _), right) do
# can probably fo better
# can probably do better
left |> to_list(to_list(right)) |> from_list()
end

Expand Down
11 changes: 11 additions & 0 deletions test/vector_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,17 @@ defmodule Aja.VectorTest do
assert Aja.Vector.new(1..20) == Aja.Vector.new(1..10) |> Aja.Vector.concat(11..20)
assert Aja.Vector.new(1..100) == Aja.Vector.new(1..50) |> Aja.Vector.concat(51..100)
assert Aja.Vector.new(1..1000) == Aja.Vector.new(1..500) |> Aja.Vector.concat(501..1000)

right_list = List.duplicate(0, 16)
right_vec = Aja.Vector.duplicate(0, 16)

# an attempt at finding concat edge cases near "interesting" sizes,
# when tries are full or partially full
for n <- 2..11, p <- [4 ** n, 4 ** n * 2], i <- (p - 16)..(p + 16) do
expected = Aja.Vector.duplicate(0, i + 16)
assert Aja.Vector.duplicate(0, i) |> Aja.Vector.concat(right_list) == expected
assert Aja.Vector.duplicate(0, i) |> Aja.Vector.concat(right_vec) == expected
end
end

test "pop_last!/1" do
Expand Down

0 comments on commit 8225669

Please sign in to comment.