defmodule RoaringBitmap64 do @moduledoc """ Provides a NIF for interfacing with [Roaring Bitmaps](https://github.com/RoaringBitmap/roaring-rs) The bitsets are managed in memory by rust behind a mutex. All members are 64 bit unsigned ints Any method on an existing bitset ref may return {:error, :lock_fail} if the method is unable to obtain mutex access """ alias RoaringBitmap.NifBridge @doc """ Return a reference to a new roaring bitset ## Examples iex> RoaringBitmap.new() {:ok, bitset_ref} """ def new() do NifBridge.new_64() end @doc """ Create a new bitset from the list of `members`. Can take any enumerable as input, but may not be performant, particularly for large lists. Prefer RoaringBitmap.deserialize/1 if performance is critical ## Examples iex> RoaringBitmap.from_list([1, 2, 22]) {:ok, bitset_ref} """ def from_list(members) do # TODO: implement this within the NIF {:ok, set} = new() Enum.each(members, &NifBridge.insert_64(set, &1)) {:ok, set} end @doc """ Export this bitset to a list. Leaves the `bitset_ref` still valid. May not be performant particularly for large lists. Prefer RoaringBitmap.serialize/1 if performance is critical ## Examples iex> RoaringBitmap.to_list(bitset_ref) {:ok, [1, 2, 22]} """ def to_list(set) do NifBridge.to_list_64(set) end @doc """ Inserts a `member` into the referenced set ## Examples iex> RoaringBitmap.insert(bitset_ref, 15) :ok """ def insert(set, member) do {:ok, :ok} = NifBridge.insert_64(set, member) :ok end @doc """ Removes a `member` from the referenced set ## Examples iex> RoaringBitmap.remove(bitset_ref, 15) :ok """ def remove(set, member) do {:ok, :ok} = NifBridge.remove_64(set, member) :ok end @doc """ Checks for set membership. ## Examples iex> RoaringBitmap.insert(bitset_ref, 15) {:ok, false} """ def contains?(set, index) do NifBridge.contains_64(set, index) end @doc """ Returns a reference to a new set representing the intersection of all supplied sets ## Examples iex> RoaringBitmap.intersection([bitset_ref, bitset_ref, ...]) {:ok, new_bitset_ref} """ def intersection([set1 | rest]) do # TODO: Ideally we'd push down all the sets at once into the NIF new_set = Enum.reduce(rest, set1, fn next_set, result -> {:ok, updated} = NifBridge.intersection_64(result, next_set) updated end) {:ok, new_set} end def intersection(set1, set2), do: intersection([set1, set2]) @doc """ Returns a reference to a new set representing the union of all supplied sets ## Examples iex> RoaringBitmap.union([bitset_ref, bitset_ref, ...]) {:ok, new_bitset_ref} """ def union([set1 | rest]) do # TODO: Ideally we'd push down all the sets at once into the NIF new_set = Enum.reduce(rest, set1, fn next_set, result -> {:ok, updated} = NifBridge.union_64(result, next_set) updated end) {:ok, new_set} end def union(set1, set2), do: union([set1, set2]) @doc """ Returns a reference to a new set representing the xor of two sets ## Examples iex> RoaringBitmap.xor(bitset_ref, bitset_ref) {:ok, new_bitset_ref} """ def xor(set1, set2) do NifBridge.xor_64(set1, set2) end @doc """ Returns a reference to a new set representing the difference of two sets ## Examples iex> RoaringBitmap.difference(bitset_ref, bitset_ref) {:ok, new_bitset_ref} """ def difference(set1, set2) do NifBridge.difference_64(set1, set2) end @doc """ Serializes the bitset to the [cross platform serialization format](https://github.com/RoaringBitmap/RoaringFormatSpec/) in binary form. (64-bit) ## Examples iex> RoaringBitmap.serialize(bitset_ref) {:ok, <<...>>} """ def serialize(set) do NifBridge.serialize_64(set) end @doc """ Deserializes a binary into a new bitset ref Uses the [cross platform serialization format](https://github.com/RoaringBitmap/RoaringFormatSpec/) in binary form. (64-bit) ## Examples iex> RoaringBitmap.deserialize(binary) {:ok, bitset_ref} """ def deserialize(binary) do NifBridge.deserialize_64(binary) end @doc """ Check for the equality of two sets """ def equal?(set1, set2) do NifBridge.equal_64(set1, set2) end @doc """ Returns the number of members within the set """ def size(set) do NifBridge.size_64(set) end end