Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 41 additions & 36 deletions bitgauss/src/bitmatrix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ impl BitMatrix {
}

/// Creates a new `BitMatrix` from a vector of bool vectors
pub fn from_bool_vec(data: &Vec<Vec<bool>>) -> Self {
pub fn from_bool_vec(data: &[Vec<bool>]) -> Self {
Self::build(
data.len(),
if data.is_empty() { 0 } else { data[0].len() },
Expand All @@ -91,7 +91,7 @@ impl BitMatrix {
}

/// Creates a new `BitMatrix` from a vector of integer vectors
pub fn from_int_vec(data: &Vec<Vec<usize>>) -> Self {
pub fn from_int_vec(data: &[Vec<usize>]) -> Self {
Self::build(
data.len(),
if data.is_empty() { 0 } else { data[0].len() },
Expand Down Expand Up @@ -457,27 +457,32 @@ impl BitMatrix {
/// If `full` is true, then perform full Gauss-Jordan to produce reduced echelon form, otherwise
/// just returns echelon form.
#[inline]
pub fn gauss(&mut self, full: bool) {
self.gauss_helper(full, 1, &mut ());
pub fn gauss(&mut self, full: bool) -> Vec<usize> {
self.gauss_helper(full, 1, &mut ())
}

/// Performs gaussian elimination with a `chunksize` and a `proxy`
///
/// # Arguments
/// - `full`: if this is true, compute reduced echelon form
/// - `blocksize`: a Patel-Markov-Hayes blocksize. This can be set to reduce the total number of
/// row operations
/// row operations
/// - `proxy`: a struct that implements [`RowOps`] and receives the same row operations as the
/// matrix being reduced. This can be used e.g. for reversible logic circuit synthesis
#[inline]
pub fn gauss_with_proxy(&mut self, full: bool, chunksize: usize, proxy: &mut impl RowOps) {
self.gauss_helper(full, chunksize, proxy);
pub fn gauss_with_proxy(
&mut self,
full: bool,
chunksize: usize,
proxy: &mut impl RowOps,
) -> Vec<usize> {
self.gauss_helper(full, chunksize, proxy)
}

/// Performs gaussian elimination using the Patel-Markov-Hayes algorithm with the given `chunksize`
#[inline]
pub fn gauss_with_chunksize(&mut self, full: bool, chunksize: usize) {
self.gauss_helper(full, chunksize, &mut ());
pub fn gauss_with_chunksize(&mut self, full: bool, chunksize: usize) -> Vec<usize> {
self.gauss_helper(full, chunksize, &mut ())
}

/// Computes the rank of the matrix using gaussian elimination
Expand Down Expand Up @@ -829,12 +834,12 @@ mod test {
let m = BitMatrix::from_bool_vec(&data);
assert_eq!(m.rows(), 2);
assert_eq!(m.cols(), 3);
assert_eq!(m.bit(0, 0), true);
assert_eq!(m.bit(0, 1), false);
assert_eq!(m.bit(0, 2), true);
assert_eq!(m.bit(1, 0), false);
assert_eq!(m.bit(1, 1), true);
assert_eq!(m.bit(1, 2), false);
assert!(m.bit(0, 0));
assert!(!m.bit(0, 1));
assert!(m.bit(0, 2));
assert!(!m.bit(1, 0));
assert!(m.bit(1, 1));
assert!(!m.bit(1, 2));
}

// test from_int_vec
Expand All @@ -844,12 +849,12 @@ mod test {
let m = BitMatrix::from_int_vec(&data);
assert_eq!(m.rows(), 2);
assert_eq!(m.cols(), 3);
assert_eq!(m.bit(0, 0), true);
assert_eq!(m.bit(0, 1), false);
assert_eq!(m.bit(0, 2), true);
assert_eq!(m.bit(1, 0), false);
assert_eq!(m.bit(1, 1), true);
assert_eq!(m.bit(1, 2), false);
assert!(m.bit(0, 0));
assert!(!m.bit(0, 1));
assert!(m.bit(0, 2));
assert!(!m.bit(1, 0));
assert!(m.bit(1, 1));
assert!(!m.bit(1, 2));
}

// test construction from empty vectors
Expand Down Expand Up @@ -1188,10 +1193,10 @@ mod test {
assert_eq!(result.cols(), 2);

// Check that the stacking worked correctly
assert_eq!(result[(0, 0)], true); // From identity
assert_eq!(result[(1, 1)], true); // From identity
assert_eq!(result[(2, 0)], false); // From zeros
assert_eq!(result[(5, 1)], true); // From all-ones row
assert!(result[(0, 0)]); // From identity
assert!(result[(1, 1)]); // From identity
assert!(!result[(2, 0)]); // From zeros
assert!(result[(5, 1)]); // From all-ones row
}

#[test]
Expand All @@ -1205,10 +1210,10 @@ mod test {
assert_eq!(result.cols(), 6);

// Check that the stacking worked correctly
assert_eq!(result[(0, 0)], true); // From identity
assert_eq!(result[(1, 1)], true); // From identity
assert_eq!(result[(0, 2)], false); // From zeros
assert_eq!(result[(0, 5)], true); // From all-ones column
assert!(result[(0, 0)]); // From identity
assert!(result[(1, 1)]); // From identity
assert!(!result[(0, 2)]); // From zeros
assert!(result[(0, 5)]); // From all-ones column
}

#[test]
Expand Down Expand Up @@ -1264,19 +1269,19 @@ mod test {

// Test row swap
m.swap_rows(0, 2);
assert_eq!(m[(0, 0)], false);
assert_eq!(m[(2, 2)], false);
assert_eq!(m[(0, 2)], true);
assert_eq!(m[(2, 0)], true);
assert!(!m[(0, 0)]);
assert!(!m[(2, 2)]);
assert!(m[(0, 2)]);
assert!(m[(2, 0)]);

// Swap back
m.swap_rows(0, 2);
assert_eq!(m, original);

// Test row addition (XOR)
m.add_row(0, 1); // Add row 0 to row 1
assert_eq!(m[(1, 0)], true); // XOR of 0 and 1
assert_eq!(m[(1, 1)], true); // XOR of 1 and 0
assert!(m[(1, 0)]); // XOR of 0 and 1
assert!(m[(1, 1)]); // XOR of 1 and 0
}

#[test]
Expand Down Expand Up @@ -1305,7 +1310,7 @@ mod test {
{
let row1 = m_mut.row_mut(1);
// Modify the row (this is at the BitVec level)
if row1.len() > 0 {
if !row1.is_empty() {
row1[0] ^= MSB_ON; // Flip the first bit
}
}
Expand Down
18 changes: 9 additions & 9 deletions bitgauss/src/bitvector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ impl BitVector {
}

/// Creates a new `BitVector` from a vector of bool vectors
pub fn from_bool_vec(data: &Vec<bool>) -> Self {
pub fn from_bool_vec(data: &[bool]) -> Self {
Self::build(data.len(), |i| data[i])
}

/// Creates a new `BitVector` from a vector of integer vectors
pub fn from_int_vec(data: &Vec<usize>) -> Self {
pub fn from_int_vec(data: &[usize]) -> Self {
Self::build(data.len(), |i| data[i] != 0)
}

Expand Down Expand Up @@ -239,12 +239,12 @@ mod tests {
// Row 0: 1*1 + 0*1 + 1*0 = 1 + 0 + 0 = 1 (in GF(2))
// Row 1: 0*1 + 1*1 + 1*0 = 0 + 1 + 0 = 1 (in GF(2))
// Row 2: 1*1 + 1*1 + 0*0 = 1 + 1 + 0 = 0 (in GF(2), since 1⊕1=0)
let matrix = BitMatrix::from_bool_vec(&vec![
let matrix = BitMatrix::from_bool_vec(&[
vec![true, false, true],
vec![false, true, true],
vec![true, true, false],
]);
let vector = BitVector::from_bool_vec(&vec![true, true, false]);
let vector = BitVector::from_bool_vec(&[true, true, false]);

let result = &matrix * &vector;
assert_eq!(result.len(), 3);
Expand All @@ -257,20 +257,20 @@ mod tests {
fn test_matrix_vector_multiplication_identity() {
// Test multiplication with identity matrix
let identity = BitMatrix::identity(3);
let vector = BitVector::from_bool_vec(&vec![true, false, true]);
let vector = BitVector::from_bool_vec(&[true, false, true]);

let result = &identity * &vector;
assert_eq!(result.len(), 3);
assert_eq!(result[0], true);
assert_eq!(result[1], false);
assert_eq!(result[2], true);
assert!(result[0]);
assert!(!result[1]);
assert!(result[2]);
}

#[test]
fn test_matrix_vector_multiplication_zeros() {
// Test multiplication with zero matrix
let zero_matrix = BitMatrix::zeros(2, 3);
let vector = BitVector::from_bool_vec(&vec![true, true, true]);
let vector = BitVector::from_bool_vec(&[true, true, true]);

let result = &zero_matrix * &vector;
assert_eq!(result.len(), 2);
Expand Down
19 changes: 12 additions & 7 deletions bitgauss/src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ pub fn min_blocks(bits: usize) -> usize {
///
/// Many methods are implemented via dereferencing to [`BitSlice`], which provides
/// additional bitwise and range operations.
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Default)]
pub struct BitData(Vec<BitBlock>);

/// A range of bits, represented as a slice of [`BitBlock`]s.
Expand Down Expand Up @@ -107,7 +107,7 @@ impl BitSlice {

/// Returns an iterator over all bits in this range as `bool`s.
#[inline]
pub fn iter(&self) -> BitIter {
pub fn iter(&self) -> BitIter<'_> {
BitIter {
inner: self.0.iter(),
c: BLOCKSIZE,
Expand Down Expand Up @@ -309,7 +309,7 @@ impl BitData {

/// Returns an iterator over all bits in this vector as `bool`s.
#[inline]
pub fn iter(&self) -> BitIter {
pub fn iter(&self) -> BitIter<'_> {
self.deref().iter()
}

Expand Down Expand Up @@ -375,7 +375,7 @@ impl BitData {

/// Constructs a new empty [`BitData`].
pub fn new() -> Self {
BitData(Vec::new())
Self::default()
}

/// Constructs a new [`BitData`] with the specified capacity in blocks
Expand Down Expand Up @@ -588,9 +588,14 @@ mod test {

// ...so the remaining bits should be 0
assert_eq!(vec.num_bits(), bool_vec1.len());
for i in bool_vec.len()..vec.len() {
for (i, &x) in bool_vec1
.iter()
.enumerate()
.take(vec.len())
.skip(bool_vec.len())
{
assert_eq!((i, vec.bit(i)), (i, false));
assert_eq!((i, bool_vec1[i]), (i, false));
assert_eq!((i, x), (i, false));
}
}

Expand Down Expand Up @@ -642,7 +647,7 @@ mod test {
} else if i < 20 * BLOCKSIZE - shift {
assert_eq!(v3.bit(i), v2.bit(i - (10 * BLOCKSIZE - shift)));
} else {
assert_eq!(v3.bit(i), false);
assert!(!v3.bit(i));
}
}
}
Expand Down