# `ExDataSketch.Hash.Murmur3`
[🔗](https://github.com/thanos/ex_data_sketch/blob/main/lib/ex_data_sketch/hash/murmur3.ex#L1)

MurmurHash3_x64_128 (64-bit output).

This module implements the full MurmurHash3_x64_128 algorithm and returns
the high 64 bits of the 128-bit output. This matches the convention used
by Apache DataSketches when a 64-bit hash is needed.

Murmur3 is **not the default** for ExDataSketch (XXHash3 is faster and the
default), but it is provided for interoperability with the Apache DataSketches
ecosystem and as a portable BEAM-side reference implementation.

## Properties

| Property            | Value                                          |
|---------------------|------------------------------------------------|
| Output bits         | 64 (high half of x64_128)                      |
| Seedable            | Yes (`u32`)                                    |
| Cross-platform      | Yes                                            |
| Cross-OTP stable    | Yes — pure Elixir, no `:erlang.phash2`         |
| Rust acceleration   | Yes (internal NIF, see `hash/2`)               |

When the Rust NIF is available, `hash/2` dispatches to it. When it is not,
the pure Elixir implementation is used. Both implementations are
**byte-identical** on every input (verified by parity tests).

## Examples

    iex> ExDataSketch.Hash.Murmur3.hash("hello") == ExDataSketch.Hash.Murmur3.hash("hello")
    true

    iex> ExDataSketch.Hash.Murmur3.hash("hello", 0) != ExDataSketch.Hash.Murmur3.hash("hello", 1)
    true

    iex> ExDataSketch.Hash.Murmur3.hash("", 0) >= 0
    true

## Reference

- Austin Appleby's reference implementation: <https://github.com/aappleby/smhasher>
- Apache DataSketches Java: `org.apache.datasketches.hash.MurmurHash3`

# `available?`

```elixir
@spec available?() :: true
```

Returns whether this algorithm is available in the current runtime.

Murmur3 is always available because a pure-Elixir implementation is bundled.

## Examples

    iex> ExDataSketch.Hash.Murmur3.available?()
    true

# `hash128`

```elixir
@spec hash128(binary(), non_neg_integer()) :: {non_neg_integer(), non_neg_integer()}
```

Returns the full 128-bit MurmurHash3_x64_128 as a `{h1, h2}` pair.

Provided for interop scenarios where the full 128-bit hash is required
(e.g., computing Apache DataSketches seed_hash, or other Murmur3-based
fingerprints).

## Examples

    iex> {h1, h2} = ExDataSketch.Hash.Murmur3.hash128("hello", 0)
    iex> is_integer(h1) and is_integer(h2)
    true

# `hash`

```elixir
@spec hash(binary(), non_neg_integer()) :: ExDataSketch.Hash.hash64()
```

Computes the high 64 bits of MurmurHash3_x64_128 over the given binary.

The seed is the standard Murmur3 `u32` seed; values above `2^32 - 1`
are masked to 32 bits.

## Examples

    iex> h = ExDataSketch.Hash.Murmur3.hash("hello", 0)
    iex> is_integer(h) and h >= 0 and h <= 0xFFFFFFFFFFFFFFFF
    true

# `id`

```elixir
@spec id() :: :murmur3
```

Returns the algorithm identifier `:murmur3`.

## Examples

    iex> ExDataSketch.Hash.Murmur3.id()
    :murmur3

# `pure_hash`

```elixir
@spec pure_hash(binary(), non_neg_integer()) :: ExDataSketch.Hash.hash64()
```

Pure Elixir implementation of MurmurHash3_x64_128 returning the high 64 bits.

This function never calls the NIF. It is used by the parity tests and as
the fallback when the NIF is unavailable. Keep this function deterministic
across all OTP versions — it must not depend on `:erlang.phash2/1,2`.

## Examples

    iex> ExDataSketch.Hash.Murmur3.pure_hash("hello", 0) == ExDataSketch.Hash.Murmur3.hash("hello", 0)
    true

---

*Consult [api-reference.md](api-reference.md) for complete listing*
