sparse-bin-mat 0.7.0

A sparse implementation of a binary matrix optimized for row operations
Documentation
use super::SparseBinSlice;
use crate::BinNum;
use std::cmp::Ordering;

pub(super) struct BitwiseZipIter<'a> {
    first: &'a [usize],
    second: &'a [usize],
    first_index: usize,
    second_index: usize,
}

impl<'a> Iterator for BitwiseZipIter<'a> {
    type Item = PositionAndValues;

    fn next(&mut self) -> Option<Self::Item> {
        match (
            self.next_position_in_first_row(),
            self.next_position_in_second_row(),
        ) {
            (Some(p), Some(q)) => match p.cmp(&q) {
                Ordering::Equal => {
                    self.advance_both_rows();
                    Some(PositionAndValues::both_rows_at(p))
                }
                Ordering::Less => {
                    self.advance_first_row();
                    Some(PositionAndValues::only_first_row_at(p))
                }
                Ordering::Greater => {
                    self.advance_second_row();
                    Some(PositionAndValues::only_second_row_at(q))
                }
            },
            (Some(p), None) => {
                self.advance_first_row();
                Some(PositionAndValues::only_first_row_at(p))
            }
            (None, Some(q)) => {
                self.advance_second_row();
                Some(PositionAndValues::only_second_row_at(q))
            }
            _ => None,
        }
    }
}

impl<'a> BitwiseZipIter<'a> {
    pub(super) fn new(first: SparseBinSlice<'a>, second: SparseBinSlice<'a>) -> Self {
        Self {
            first: first.positions,
            second: second.positions,
            first_index: 0,
            second_index: 0,
        }
    }

    fn next_position_in_first_row(&self) -> Option<usize> {
        self.first.get(self.first_index).cloned()
    }

    fn next_position_in_second_row(&self) -> Option<usize> {
        self.second.get(self.second_index).cloned()
    }

    fn advance_both_rows(&mut self) {
        self.advance_first_row();
        self.advance_second_row();
    }

    fn advance_first_row(&mut self) {
        self.first_index += 1;
    }

    fn advance_second_row(&mut self) {
        self.second_index += 1;
    }
}

pub(super) struct PositionAndValues {
    pub(super) position: usize,
    pub(super) first_row_value: BinNum,
    pub(super) second_row_value: BinNum,
}

impl PositionAndValues {
    fn both_rows_at(position: usize) -> Self {
        Self {
            position,
            first_row_value: 1.into(),
            second_row_value: 1.into(),
        }
    }

    fn only_first_row_at(position: usize) -> Self {
        Self {
            position,
            first_row_value: 1.into(),
            second_row_value: 0.into(),
        }
    }

    fn only_second_row_at(position: usize) -> Self {
        Self {
            position,
            first_row_value: 0.into(),
            second_row_value: 1.into(),
        }
    }
}