Abit lets you use :atomics as a bit array or as an array of N-bit counters.

To learn more about :atomics, see the Erlang atomics documentation.

The Abit module (this module) has functions to use :atomics as a bit array. The bit array is zero-indexed.

The Abit.Counter module has functions to use :atomics as an array of N-bit counters.

The functions in Abit.Atomics help you work with Erlang's :atomics.

The functions in Abit.Bitmask help you work with bitmasks.

Abit

iex> ref = :atomics.new(100, signed: false)
iex> Abit.bit_count(ref)
6400
iex> Abit.bit_at(ref, 0)
0
iex> Abit.set_bit_at(ref, 0, 1)
:ok
iex> Abit.bit_at(ref, 0)
1

Abit.Counter

iex> counter = %Abit.Counter{} = Abit.Counter.new(100, 16)
iex> Abit.Counter.get(counter, 0)
0
iex> Abit.Counter.put(counter, 0, 100)
{:ok, {0, 100}}
iex> Abit.Counter.add(counter, 0, 100)
{:ok, {0, 200}}
iex> Abit.Counter.member?(counter, 200)
true

Abit.Atomics

iex> ref = :atomics.new(3, signed: false)
iex> :atomics.put(ref, 1, 10)
iex> Abit.Atomics.to_list(ref)
[10, 0, 0]

Abit.Bitmask

iex> Abit.Bitmask.set_bits_count(3)
2
iex> Abit.Bitmask.bit_at(2, 0)
0
iex> Abit.Bitmask.bit_at(2, 1)
1

Summary

Functions

Returns the bit at bit_index in the atomics reference ref.

Returns the total number of bits in the atomics reference ref.

Returns the position of a bit in :atomics.

Sets all elements in the given atomics reference ref to 0.

Computes the difference between ref_a and ref_b using bitwise AND NOT.

Returns the bitwise Hamming distance between the two given :atomics references ref_l and ref_r.

Intersects the atomics references ref_a and ref_b using bitwise AND.

Inverts all bits in the signed atomics reference ref using bitwise NOT.

Sets the bit at bit_index to bit in the atomics ref.

Returns the number of bits set to 1 in the atomics array ref.

Computes the symmetric difference of ref_a and ref_b using bitwise XOR.

Converts every integer in the atomics reference ref into a flat list of bits.

Toggles the bit at bit_index in the atomics ref.

Combines the atomics references ref_a and ref_b using bitwise OR.

Functions

bit_at(ref, bit_index)

@spec bit_at(reference(), non_neg_integer()) :: 0 | 1

Returns the bit at bit_index in the atomics reference ref.

Examples

iex> ref = :atomics.new(1, signed: false)
iex> ref |> :atomics.put(1, 3)
iex> Abit.bit_at(ref, 0)
1
iex> Abit.bit_at(ref, 1)
1
iex> Abit.bit_at(ref, 2)
0

bit_count(ref)

@spec bit_count(reference()) :: pos_integer()

Returns the total number of bits in the atomics reference ref.

Each element in an atomics reference is a 64-bit integer, so the total number of bits is size * 64.

Examples

iex> ref = :atomics.new(1, signed: false)
iex> Abit.bit_count(ref)
64
iex> ref2 = :atomics.new(2, signed: false)
iex> Abit.bit_count(ref2)
128

bit_position(bit_index)

@spec bit_position(non_neg_integer()) :: {pos_integer(), non_neg_integer()}

Returns the position of a bit in :atomics.

Returns a two-element tuple containing:

  • atomics_index - the index of the integer in atomics where the bit is located
  • bit_index - the index of the bit in the integer

Examples

iex> Abit.bit_position(0)
{1, 0}
iex> Abit.bit_position(11)
{1, 11}
iex> Abit.bit_position(64)
{2, 0}

clear(ref)

(since 0.4.0)
@spec clear(reference()) :: reference()

Sets all elements in the given atomics reference ref to 0.

Returns ref.

Examples

iex> ref = :atomics.new(10, signed: false)
iex> ref |> Abit.set_bit_at(0, 1)
iex> ref |> Abit.set_bit_at(64, 1)
iex> ref |> Abit.clear()
iex> ref |> Abit.set_bits_count()
0

difference(ref_a, ref_b)

(since 0.4.0)
@spec difference(reference(), reference()) :: reference()

Computes the difference between ref_a and ref_b using bitwise AND NOT.

Clears the bits in ref_a that are set in ref_b. Mutates and returns ref_a.

Raises ArgumentError if the references have different sizes.

hamming_distance(ref_l, ref_r)

@spec hamming_distance(reference(), reference()) :: non_neg_integer()

Returns the bitwise Hamming distance between the two given :atomics references ref_l and ref_r.

Raises ArgumentError if the sizes of ref_l and ref_r are not equal.

Examples

iex> ref_l = :atomics.new(10, signed: false)
iex> ref_r = :atomics.new(10, signed: false)
iex> Abit.hamming_distance(ref_l, ref_r)
0
iex> ref_l |> :atomics.put(1, 7)
iex> Abit.hamming_distance(ref_l, ref_r)
3

intersect(ref_a, ref_b)

@spec intersect(reference(), reference()) :: reference()

Intersects the atomics references ref_a and ref_b using bitwise AND.

Mutates and returns ref_a.

Raises ArgumentError if the references have different sizes.

invert(ref)

(since 0.4.0)
@spec invert(reference()) :: reference()

Inverts all bits in the signed atomics reference ref using bitwise NOT.

Mutates and returns ref.

Raises ArgumentError if ref is unsigned.

set_bit_at(ref, bit_index, bit)

@spec set_bit_at(reference(), non_neg_integer(), 0 | 1) :: :ok

Sets the bit at bit_index to bit in the atomics ref.

Returns :ok.

Examples

iex> ref = :atomics.new(1, signed: false)
iex> ref |> Abit.set_bit_at(0, 1)
iex> ref |> :atomics.get(1)
1
iex> ref |> Abit.set_bit_at(0, 0)
:ok
iex> ref |> :atomics.get(1)
0

set_bits_count(ref)

@spec set_bits_count(reference()) :: non_neg_integer()

Returns the number of bits set to 1 in the atomics array ref.

Examples

iex> ref = :atomics.new(1, signed: false)
iex> ref |> :atomics.put(1, 3)
iex> Abit.set_bits_count(ref)
2
iex> ref2 = :atomics.new(1, signed: false)
iex> Abit.set_bits_count(ref2)
0

symmetric_difference(ref_a, ref_b)

(since 0.4.0)
@spec symmetric_difference(reference(), reference()) :: reference()

Computes the symmetric difference of ref_a and ref_b using bitwise XOR.

Mutates and returns ref_a.

Raises ArgumentError if the references have different sizes.

to_list(ref)

(since 0.2.3)
@spec to_list(reference()) :: [0 | 1]

Converts every integer in the atomics reference ref into a flat list of bits.

Examples

ref = :atomics.new(10, signed: false)
ref |> Abit.to_list
[0, 0, 0, 0, 0, ...]

toggle_bit_at(ref, bit_index)

(since 0.4.0)
@spec toggle_bit_at(reference(), non_neg_integer()) :: :ok

Toggles the bit at bit_index in the atomics ref.

Returns :ok.

Examples

iex> ref = :atomics.new(1, signed: false)
iex> ref |> :atomics.put(1, 1)
iex> ref |> Abit.toggle_bit_at(0)
:ok
iex> ref |> :atomics.get(1)
0
iex> ref |> Abit.toggle_bit_at(0)
iex> ref |> :atomics.get(1)
1

union(ref_a, ref_b)

@spec union(reference(), reference()) :: reference()

Combines the atomics references ref_a and ref_b using bitwise OR.

Mutates and returns ref_a.

Raises ArgumentError if the references have different sizes.