Expand description
Bit-packed GF(2) buffers: one element per bit.
GF(2) is the one field whose natural element width is sub-byte, so it does
not fit the byte-per-element crate::ops surface. Instead, elements are
packed eight per byte and the operations here are whole-buffer or masked
bit ranges over plain &[u8]:
- element
ilives in biti % 8(LSB-first) of bytei / 8; - a word is the little-endian
u64assembly of eight bytes, so elementiis biti % 64of wordi / 64; - bits past the logical length are padding. The invariant is that they are zero; it is caller-maintained. Range operations leave bits outside their range untouched. Whole-buffer operations also process padding and preserve zero padding when their inputs satisfy the invariant. No operation promises to sanitize nonzero padding.
Because a byte holds eight elements and the last byte may be partial, the
element count is not recoverable from the byte length: operations whose
meaning depends on the exact bit count take an explicit bits, and every
range operation checks from <= to <= bits. Buffers may be longer than
bytes_for(bits) — a consumer with word-aligned storage passes its
whole row and the surplus bits are padding like any other.
Multiplying by a coefficient is masked out of the API on purpose: the
coefficient of GF(2) is a bit — multiply by zero is “skip”, by one is
“XOR” — so there is no prepared-coefficient form and no crate::ops
counterpart. What is prepared is geometry: a XorRange derives a
bit range’s window and masks once for xor_range_with to apply to
many buffer pairs. The scalar oracle for this surface is
crate::gf2::Elem.
use fgf::bits;
use fgf::field::Elem;
// Seven elements: 1,0,0,1,1,1,1 -> LSB-first byte 0b0111_1001.
let mut a = [0u8; 1];
bits::set_range(&mut a, 7, 0, 7);
bits::clear_range(&mut a, 7, 1, 3);
assert_eq!(a[0], 0b0111_1001);
assert_eq!(bits::weight(&a, 7), 5);
// The GF(2) inner product of a vector with itself is its weight mod 2.
let parity = bits::dot_product(&a, &a, 7);
assert!(parity.is_one());
// Whole-buffer addition is XOR of equal-length buffers.
let b = [0xff];
bits::xor_assign(&mut a, &b);
assert_eq!(bits::weight(&a, 7), 2);Structs§
- XorRange
- A prepared bit range for repeated
dst ^= src: the window and end masks of[from, to)derived once, applied to many buffer pairs.
Functions§
- and_
assign dst &= src: in-place elementwise GF(2) multiplication.- and_
into dst = a & b: elementwise GF(2) multiplication.- andnot_
assign dst &= !mask: clears every bit ofdstwheremaskhas a 1.- bytes_
for - Number of bytes needed to hold
bitspacked elements. - clear_
range - Zeros the bit range
[from, to)ofdst. - dot_
product - The GF(2) inner product of two packed vectors: the parity of
popcount(a & b)over the live bits. - set_
range - Sets the bit range
[from, to)ofdstto one. - weight
- Hamming weight of the live bits
[0, bits). - xor_
assign dst ^= src: GF(2) addition over whole buffers.- xor_
gather dst ^= srcs[i]for every set bitiofselector: the combination step of subset-XOR over a dense row set.- xor_
range dst ^= srcover the bit range[from, to).- xor_
range_ with dst ^= srcover a preparedXorRange: the per-row apply of the split form ofxor_range.