#[cfg(feature = "alloc")]
use alloc::vec::Vec;
use core::{
iter::{Cloned, Copied},
ops::Range,
};
#[cfg(feature = "arbitrary")]
use arbitrary::{Arbitrary, Unstructured};
use crate::{prelude::*, traits::Symbol};
impl<V: Symbol> Vocabulary for Vec<V> {
type SourceSymbol = usize;
type DestinationSymbol = V;
type Sources<'a>
= Range<usize>
where
Self: 'a;
type Destinations<'a>
= Cloned<core::slice::Iter<'a, Self::DestinationSymbol>>
where
Self: 'a;
#[inline]
fn convert(&self, source: &Self::SourceSymbol) -> Option<Self::DestinationSymbol> {
self.get(*source).cloned()
}
#[inline]
fn len(&self) -> usize {
self.len()
}
#[inline]
fn sources(&self) -> Self::Sources<'_> {
0..self.len()
}
#[inline]
fn destinations(&self) -> Self::Destinations<'_> {
self.iter().cloned()
}
}
impl<V: Symbol> VocabularyRef for Vec<V> {
type DestinationRefs<'a>
= core::slice::Iter<'a, Self::DestinationSymbol>
where
Self: 'a;
#[inline]
fn convert_ref(&self, source: &Self::SourceSymbol) -> Option<&Self::DestinationSymbol> {
self.get(*source)
}
#[inline]
fn destination_refs(&self) -> Self::DestinationRefs<'_> {
self.iter()
}
}
impl<V: Symbol> BidirectionalVocabulary for Vec<V> {
#[inline]
fn invert(&self, destination: &Self::DestinationSymbol) -> Option<Self::SourceSymbol> {
self.iter().position(|v| v == destination)
}
}
impl<V: Symbol + Ord> GrowableVocabulary for Vec<V> {
#[inline]
fn new() -> Self {
Vec::new()
}
#[inline]
fn with_capacity(capacity: usize) -> Self {
Vec::with_capacity(capacity)
}
#[inline]
fn add(
&mut self,
source: Self::SourceSymbol,
destination: Self::DestinationSymbol,
) -> Result<(), crate::errors::builder::vocabulary::VocabularyBuilderError<Self>> {
if source != self.len() {
return Err(
crate::errors::builder::vocabulary::VocabularyBuilderError::SparseSourceNode(
source,
),
);
}
if self.invert(&destination).is_some() {
return Err(crate::errors::builder::vocabulary::VocabularyBuilderError::RepeatedDestinationSymbol(destination));
}
self.push(destination);
Ok(())
}
}
use crate::traits::{
DenseMatrix, DenseMatrix2D, DenseValuedMatrix, DenseValuedMatrix2D, Matrix, Matrix2D,
ValuedMatrix, ValuedMatrix2D,
};
#[cfg_attr(feature = "mem_size", derive(mem_dbg::MemSize))]
#[cfg_attr(feature = "mem_size", mem_size(rec))]
#[cfg_attr(feature = "mem_dbg", derive(mem_dbg::MemDbg))]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct VecMatrix2D<V> {
data: Vec<V>,
number_of_rows: usize,
}
impl<V> VecMatrix2D<V> {
#[must_use]
pub fn new(number_of_rows: usize, number_of_columns: usize, data: Vec<V>) -> Self {
assert_eq!(number_of_rows * number_of_columns, data.len());
Self { data, number_of_rows }
}
}
impl<V> Matrix for VecMatrix2D<V> {
type Coordinates = (usize, usize);
#[inline]
fn shape(&self) -> Vec<usize> {
vec![self.number_of_rows(), self.number_of_columns()]
}
}
impl<V> Matrix2D for VecMatrix2D<V> {
type RowIndex = usize;
type ColumnIndex = usize;
#[inline]
fn number_of_rows(&self) -> usize {
self.number_of_rows
}
#[inline]
fn number_of_columns(&self) -> usize {
self.data.len().checked_div(self.number_of_rows).unwrap_or(0)
}
}
impl<V: Copy> ValuedMatrix for VecMatrix2D<V> {
type Value = V;
}
impl<V: Copy> ValuedMatrix2D for VecMatrix2D<V> {}
impl<V: Copy> DenseMatrix for VecMatrix2D<V> {}
impl<V: Copy> DenseMatrix2D for VecMatrix2D<V> {}
impl<V: Copy> DenseValuedMatrix for VecMatrix2D<V> {
type Values<'a>
= Copied<core::slice::Iter<'a, V>>
where
Self: 'a;
#[inline]
fn value(&self, (row, col): Self::Coordinates) -> Self::Value {
self.data[row * self.number_of_columns() + col]
}
#[inline]
fn values(&self) -> Self::Values<'_> {
self.data.iter().copied()
}
}
impl<V: Copy> DenseValuedMatrix2D for VecMatrix2D<V> {
type RowValues<'a>
= Copied<core::slice::Iter<'a, V>>
where
Self: 'a;
#[inline]
fn row_values(&self, row: Self::RowIndex) -> Self::RowValues<'_> {
let cols = self.number_of_columns();
let start = row * cols;
self.data[start..start + cols].iter().copied()
}
}
impl<V, const COLS: usize, const ROWS: usize> From<[[V; COLS]; ROWS]> for VecMatrix2D<V> {
#[inline]
fn from(value: [[V; COLS]; ROWS]) -> Self {
let data: Vec<V> = value.into_iter().flat_map(IntoIterator::into_iter).collect();
Self { data, number_of_rows: ROWS }
}
}
#[cfg(feature = "arbitrary")]
impl<'a, V> Arbitrary<'a> for VecMatrix2D<V>
where
V: Arbitrary<'a>,
{
#[inline]
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
let number_of_rows = usize::from(u.int_in_range::<u8>(0..=32)?);
let number_of_columns =
if number_of_rows == 0 { 0 } else { usize::from(u.int_in_range::<u8>(0..=32)?) };
let number_of_values = number_of_rows * number_of_columns;
let mut data = Vec::with_capacity(number_of_values);
for _ in 0..number_of_values {
data.push(V::arbitrary(u)?);
}
Ok(Self::new(number_of_rows, number_of_columns, data))
}
}
#[cfg(all(test, feature = "alloc"))]
mod tests {
use alloc::{vec, vec::Vec};
use super::*;
use crate::traits::{BidirectionalVocabulary, GrowableVocabulary, Vocabulary, VocabularyRef};
#[test]
fn test_vec_vocabulary_len() {
let v: Vec<i32> = vec![10, 20, 30];
assert_eq!(Vocabulary::len(&v), 3);
}
#[test]
fn test_vec_vocabulary_convert() {
let v: Vec<&str> = vec!["a", "b", "c"];
assert_eq!(v.convert(&0), Some("a"));
assert_eq!(v.convert(&1), Some("b"));
assert_eq!(v.convert(&2), Some("c"));
assert_eq!(v.convert(&3), None);
}
#[test]
fn test_vec_vocabulary_sources() {
let v: Vec<i32> = vec![1, 2, 3];
let sources: Vec<usize> = v.sources().collect();
assert_eq!(sources, vec![0, 1, 2]);
}
#[test]
fn test_vec_vocabulary_destinations() {
let v: Vec<i32> = vec![10, 20, 30];
let destinations: Vec<i32> = v.destinations().collect();
assert_eq!(destinations, vec![10, 20, 30]);
}
#[test]
fn test_vec_vocabulary_ref_convert_ref() {
let v: Vec<i32> = vec![100, 200];
assert_eq!(v.convert_ref(&0), Some(&100));
assert_eq!(v.convert_ref(&1), Some(&200));
assert_eq!(v.convert_ref(&2), None);
}
#[test]
fn test_vec_vocabulary_ref_destination_refs() {
let v: Vec<i32> = vec![1, 2];
let refs: Vec<&i32> = v.destination_refs().collect();
assert_eq!(refs, vec![&1, &2]);
}
#[test]
fn test_vec_bidirectional_vocabulary_invert() {
let v: Vec<&str> = vec!["x", "y", "z"];
assert_eq!(v.invert(&"x"), Some(0));
assert_eq!(v.invert(&"y"), Some(1));
assert_eq!(v.invert(&"z"), Some(2));
assert_eq!(v.invert(&"w"), None);
}
#[test]
fn test_vec_growable_vocabulary_new() {
let v: Vec<i32> = GrowableVocabulary::new();
assert_eq!(v, [] as [i32; 0]);
}
#[test]
fn test_vec_growable_vocabulary_with_capacity() {
let v: Vec<i32> = GrowableVocabulary::with_capacity(10);
assert_eq!(v, [] as [i32; 0]);
}
#[test]
fn test_vec_growable_vocabulary_add() {
let mut v: Vec<i32> = GrowableVocabulary::new();
assert!(v.add(0, 10).is_ok());
assert!(v.add(1, 20).is_ok());
assert!(v.add(2, 30).is_ok());
assert_eq!(v.len(), 3);
}
#[test]
fn test_vec_growable_vocabulary_add_sparse_error() {
let mut v: Vec<i32> = GrowableVocabulary::new();
assert!(v.add(1, 10).is_err());
}
#[test]
fn test_vec_growable_vocabulary_add_duplicate_error() {
let mut v: Vec<i32> = GrowableVocabulary::new();
assert!(v.add(0, 10).is_ok());
assert!(v.add(1, 10).is_err());
}
#[test]
fn test_vec_matrix2d_shape() {
let matrix = VecMatrix2D { data: vec![1, 2, 3, 4, 5, 6], number_of_rows: 2 };
assert_eq!(matrix.number_of_rows(), 2);
assert_eq!(matrix.number_of_columns(), 3);
assert_eq!(matrix.shape(), vec![2, 3]);
}
}