51 size_t num_uint64_limbs)
noexcept
53 constexpr size_t LIMB_BITS = 64;
55 if (bit_offset == 0) {
64 sp.lo_off = LIMB_BITS - 1;
67 sp.hi_mask = (uint32_t{ 1 } << window_bits) - 1;
68 sp.slice_localised_to_one_u64 =
false;
70 const size_t lookback_bit = bit_offset - 1;
71 const size_t bits_to_read = window_bits + 1;
72 sp.lo_limb =
static_cast<uint32_t
>(lookback_bit / LIMB_BITS);
73 sp.lo_off =
static_cast<uint32_t
>(lookback_bit & (LIMB_BITS - 1));
74 sp.lo_bits =
static_cast<uint32_t
>(LIMB_BITS - sp.lo_off < bits_to_read ? LIMB_BITS - sp.lo_off : bits_to_read);
75 const uint32_t hi_bits =
static_cast<uint32_t
>(bits_to_read) - sp.lo_bits;
77 sp.lo_mask = (uint32_t{ 1 } << sp.lo_bits) - 1;
83 if (
static_cast<size_t>(sp.lo_limb) + 1 >= num_uint64_limbs) {
84 sp.hi_limb = sp.lo_limb;
87 sp.hi_limb = sp.lo_limb + 1;
88 sp.hi_mask = (uint32_t{ 1 } << hi_bits) - 1;
93 sp.slice_localised_to_one_u64 = (hi_bits == 0);
148 size_t window_bits)
noexcept
150 const uint64_t s_lo = s[sp.lo_limb];
151 const uint64_t s_hi = s[sp.hi_limb];
152 const uint64_t lo_part = (s_lo >> sp.lo_off) & sp.lo_mask;
153 const uint64_t hi_part = (s_hi & sp.hi_mask) << sp.lo_bits;
155 const uint32_t raw =
static_cast<uint32_t
>(lo_part | hi_part);
156 const uint32_t neg = (raw >> window_bits) & uint32_t{ 1 };
157 const uint32_t neg_mask = uint32_t{ 0 } - neg;
158 const uint32_t val_mask = (uint32_t{ 1 } << window_bits) - 1;
159 const uint32_t encode = (raw + 1) >> 1;
160 const uint32_t magnitude = ((encode + neg_mask) ^ neg_mask) & val_mask;
161 return (neg << 31) | magnitude;