use std::fmt::{Debug, Display};
use relp_num::NonZero;
use crate::data::linear_algebra::SparseTuple;
pub mod identity;
pub trait Column: ColumnIntoIterator<Self::F> + Debug {
type F: ColumnNumber;
type Iter<'a>: ColumnIterator<'a, F=Self::F> where Self: 'a;
fn iter(&self) -> Self::Iter<'_>;
fn index_to_string(&self, i: usize) -> String;
}
pub trait ColumnIterator<'a>: Iterator<Item=SparseTuple<&'a Self::F>> + Clone {
type F: 'a + ColumnNumber;
}
impl<'a, F: 'a + ColumnNumber, T: Iterator<Item=SparseTuple<&'a F>> + Clone> ColumnIterator<'a> for T {
type F = F;
}
pub trait ColumnIntoIterator<F> = IntoIterator<Item=SparseTuple<F>>;
pub trait ColumnNumber =
NonZero +
Eq +
PartialEq +
Display +
Clone +
Debug +
;
#[derive(Debug, Clone)]
pub struct SparseColumn<F> {
inner: Vec<SparseTuple<F>>
}
impl<F> SparseColumn<F> {
pub fn new(data: Vec<SparseTuple<F>>) -> Self {
Self {
inner: data,
}
}
}
impl<F: 'static + ColumnNumber> Column for SparseColumn<F> {
type F = F;
type Iter<'a> = impl ColumnIterator<'a, F=Self::F>;
fn iter(&self) -> Self::Iter<'_> {
SparseSliceIterator::new(&self.inner)
}
fn index_to_string(&self, i: usize) -> String {
match self.inner.iter().find(|&&(ii, _)| ii == i) {
None => "0".to_string(),
Some((_, v)) => v.to_string(),
}
}
}
impl<F> IntoIterator for SparseColumn<F> {
type Item = SparseTuple<F>;
type IntoIter = impl Iterator<Item=Self::Item>;
fn into_iter(self) -> Self::IntoIter {
self.inner.into_iter()
}
}
#[derive(Clone)]
pub struct SparseSliceIterator<'a, F> {
creator: &'a [SparseTuple<F>],
data_index: usize,
}
impl<'a, F: ColumnNumber> SparseSliceIterator<'a, F> {
pub fn new(slice: &'a [SparseTuple<F>]) -> Self {
debug_assert!(slice.iter().all(|(_, v)| v.is_not_zero()));
Self {
creator: slice,
data_index: 0,
}
}
}
impl<'a, F> Iterator for SparseSliceIterator<'a, F> {
type Item = SparseTuple<&'a F>;
fn next(&mut self) -> Option<Self::Item> {
if self.data_index < self.creator.len() {
let (index, value) = &self.creator[self.data_index];
self.data_index += 1;
Some((*index, value))
} else {
None
}
}
}
#[derive(Clone)]
pub struct SparseOptionIterator<'a, F> {
creator: Option<SparseTuple<&'a F>>,
}
impl<'a, F: ColumnNumber> SparseOptionIterator<'a, F> {
pub fn new(option: &'a Option<SparseTuple<F>>) -> Self {
debug_assert!(option.iter().all(|(_, v)| v.is_not_zero()));
Self {
creator: match option {
None => None,
Some((index, value)) => Some((*index, value)),
},
}
}
}
impl<'a, F> Iterator for SparseOptionIterator<'a, F> {
type Item = SparseTuple<&'a F>;
fn next(&mut self) -> Option<Self::Item> {
self.creator.take()
}
}
#[derive(Debug, Clone)]
struct DenseColumn<F> {
inner: Vec<F>,
}
impl<F> IntoIterator for DenseColumn<F> {
type Item = SparseTuple<F>;
type IntoIter = impl Iterator<Item=Self::Item>;
fn into_iter(self) -> Self::IntoIter {
self.inner.into_iter().enumerate()
}
}
impl<F: ColumnNumber> DenseColumn<F> {
pub fn new(data: Vec<F>) -> Self {
debug_assert!(data.iter().any(|v| v.is_not_zero()));
Self {
inner: data,
}
}
}
impl<F: 'static + ColumnNumber> Column for DenseColumn<F> {
type F = F;
type Iter<'a> = impl ColumnIterator<'a, F=Self::F>;
fn iter(&self) -> Self::Iter<'_> {
DenseSliceIterator::new(&self.inner)
}
fn index_to_string(&self, i: usize) -> String {
debug_assert!(i < self.inner.len());
self.inner[i].to_string()
}
}
#[derive(Clone)]
pub struct DenseSliceIterator<'a, F> {
creator: &'a [F],
data_index: usize,
}
impl<'a, F> DenseSliceIterator<'a, F> {
pub fn new(slice: &'a [F]) -> Self {
Self {
creator: slice,
data_index: 0,
}
}
}
impl<'a, F: ColumnNumber> Iterator for DenseSliceIterator<'a, F> {
type Item = SparseTuple<&'a F>;
fn next(&mut self) -> Option<Self::Item> {
while self.data_index < self.creator.len() {
let value = &self.creator[self.data_index];
if value.is_not_zero() {
let index = self.data_index;
self.data_index += 1;
return Some((index, value));
}
self.data_index += 1;
}
None
}
}
#[cfg(test)]
mod test {
use crate::algorithm::two_phase::matrix_provider::column::{Column, DenseColumn};
#[test]
fn test_dense() {
let data = vec![1, 2, 3, 0, 5];
let column = DenseColumn::new(data);
let mut column_iter = column.iter();
assert_eq!(column_iter.next(), Some((0, &1)));
assert_eq!(column_iter.next(), Some((1, &2)));
assert_eq!(column_iter.next(), Some((2, &3)));
assert_eq!(column_iter.next(), Some((4, &5)));
assert_eq!(column_iter.next(), None);
}
}