Packages
inplace
0.7.10
0.7.12
0.7.11
0.7.10
0.7.9
0.7.8
0.7.7
0.7.6
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.8
0.6.7
0.6.6
0.6.5
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.3
0.3.2
0.3.1
0.3.0
0.2.3
0.2.2
0.2.1
0.2.0
0.1.9
0.1.8
0.1.7
0.1.6
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
Mutable data structures
Current section
Files
Jump to
Current section
Files
lib/utils/bit_vector.ex
defmodule InPlace.Utils.BitVector do
@moduledoc """
Low-level operations on :atomics
"""
import Bitwise
def new(size) do
words = div(size + 63, 64)
ref = :atomics.new(words, signed: false)
{:bit_vector, ref}
end
def get({:bit_vector, ref}, idx) do
word_idx = div(idx, 64) + 1
mask = bsl(1, rem(idx, 64))
case band(mask, :atomics.get(ref, word_idx)) do
0 -> 0
^mask -> 1
end
end
def set({:bit_vector, ref}, idx) do
mask = bsl(1, rem(idx, 64))
update(ref, idx, fn word -> bor(word, mask) end)
end
def clear({:bit_vector, ref}, idx) do
mask = bnot(bsl(1, rem(idx, 64)))
update(ref, idx, fn word -> band(word, mask) end)
end
def flip({:bit_vector, ref}, idx) do
mask = bsl(1, rem(idx, 64))
update(ref, idx, fn word -> bxor(word, mask) end)
end
def update(ref, idx, update_fun) do
word_idx = div(idx, 64) + 1
update_loop(ref, word_idx, update_fun, :atomics.get(ref, word_idx))
end
defp update_loop(ref, word_idx, update_fun, current_value) do
case :atomics.compare_exchange(ref, word_idx, current_value, update_fun.(current_value)) do
:ok ->
:ok
was ->
update_loop(ref, word_idx, update_fun, was)
end
end
end