rs_poker 5.0.0

A library to help with any Rust code dealing with poker. This includes card values, suits, hands, hand ranks, 5 card hand strength calculation, 7 card hand strength calulcation, and monte carlo game simulation helpers.
Documentation
//! Perfect-hash hand evaluation core.
//!
//! Tables are generated by `build.rs` (see the spec). Each card adds a fixed
//! `u64` key contribution; ranking is a branchless flush test plus one masked
//! table load. All indices are masked to power-of-two table lengths so safe
//! indexing carries no bounds-check branch. No `unsafe`.

include!(concat!(env!("OUT_DIR"), "/eval_tables.rs"));

/// Bit mask selecting each suit nibble's `0x8` flush bit (suit count reached 5,
/// given the +3 bias baked into [`DEFAULT_KEY`]).
const FLUSH_BITS: u64 = 0x8888u64 << 48;

/// Raw score for an accumulated `(key, mask)` pair. Higher = better. The score
/// is `(category << 12) | subrank`; see [`crate::core::Rank`].
#[inline]
pub(crate) fn evaluate_key(key: u64, mask: u64) -> u16 {
    let flush = key & FLUSH_BITS;
    if flush != 0 {
        // The lowest set flush bit identifies the flush suit nibble.
        let suit = (flush.trailing_zeros() - 51) / 4;
        let pattern = (mask >> (13 * suit)) & 0x1FFF;
        return FLUSH_LOOKUP[(pattern as usize) & (FLUSH_LEN - 1)];
    }
    let rank_key = (key & 0xFFFF_FFFF) as usize;
    let offset = ROW_OFFSETS[(rank_key >> ROW_SHIFT) & (ROW_OFFSETS_LEN - 1)] as usize;
    LOOKUP[rank_key.wrapping_add(offset) & (LOOKUP_LEN - 1)]
}

/// Fold one card (index `suit*13 + value`, 0..51) into a `(key, mask)` pair.
#[inline]
pub(crate) fn add_card(key: &mut u64, mask: &mut u64, card_index: u8) {
    let i = (card_index as usize) & 63;
    *key = key.wrapping_add(CARDS_KEY[i]);
    *mask |= CARDS_MASK[i];
}