dataframe-core-1.0.2.0: Core data structures for the dataframe library.
Safe HaskellNone
LanguageHaskell2010

DataFrame.Internal.Hash

Description

A poor-man's hash used by Grouping to bucket rows without depending on the hashable package.

Each value is folded into an Int accumulator with an FxHash-style step (rotate, xor, multiply). It is intentionally small and not cryptographically strong — it only needs to spread group-key tuples well enough that IntMap bucketing produces sensible groups.

Synopsis

Documentation

fnvOffset :: Int Source #

FNV-1a 64-bit offset basis (used as the initial accumulator). The literal is unsigned and exceeds Int range, so we round-trip through Word64 to get the well-defined two's-complement bit pattern.

nullSalt :: Int Source #

Sentinel mixed in for a null slot of a nullable column, so that a Nothing does not hash to the same value as a present Just x that happens to store the same underlying bits (notably Just 0). A fixed distinctive constant (the 64-bit golden-ratio mix constant) keeps null hashing deterministic; a real value equal to it collides only as rarely as any other hash collision.

mixInt :: Int -> Int -> Int Source #

Mix an Int into the accumulator.

An FxHash-style step (rotate the accumulator, xor the value, multiply by a large odd constant). The rotate diffuses each value's bits across all positions before the next is folded in, so small/adjacent integers — common as group keys — do not produce the structured collisions that a plain (acc xor x) * prime does once several columns are combined. Grouping trusts hash equality, so this robustness is what keeps distinct rows in distinct groups.

mixDouble :: Int -> Double -> Int Source #

Mix a Double into the accumulator. Loses sub-millisecond precision but matches the bucketing the old hashable-based code used.

mixText :: Int -> Text -> Int Source #

Mix a Text value into the accumulator over its raw UTF-8 bytes, eight at a time. Reading a whole Word64 per step (rather than decoding and mixing one codepoint at a time) cuts the multiply count ~8x on long keys while staying collision-equivalent: UTF-8 is injective, so equal Texts mix to the same value and distinct ones almost never collide. The trailing len mod 8 bytes are folded in individually.

mixShow :: Show a => Int -> a -> Int Source #

Fallback for arbitrary Show-able values. Slower but covers types without a dedicated combinator (e.g. Day, UTCTime).