use crate::PointRef;
use std::convert::{TryFrom, TryInto};
use std::marker::PhantomData;
use std::ops::Deref;
impl<'a> PointRef for &'a [f32] {
type DenseIter = std::iter::Copied<std::slice::Iter<'a, f32>>;
fn dense(&self) -> Vec<f32> {
Vec::from(*self)
}
fn dense_iter(&self) -> Self::DenseIter {
self.iter().copied()
}
}
macro_rules! make_misc_point {
($base:ident, $iter_name:ident) => {
pub struct $iter_name<'a> {
iter: std::slice::Iter<'a, $base>,
}
impl<'a> Iterator for $iter_name<'a> {
type Item = f32;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|u| *u as f32)
}
}
impl<'a> PointRef for &'a [$base] {
type DenseIter = $iter_name<'a>;
fn dense(&self) -> Vec<f32> {
self.iter().map(|i| *i as f32).collect()
}
fn dense_iter(&self) -> Self::DenseIter {
$iter_name { iter: self.iter() }
}
}
};
}
make_misc_point!(i8, Converteri8);
make_misc_point!(u8, Converteru8);
make_misc_point!(i16, Converteri16);
make_misc_point!(u16, Converteru16);
make_misc_point!(i32, Converteri32);
make_misc_point!(u32, Converteru32);
#[derive(Debug)]
pub struct SparseDenseIter<'a, T: std::fmt::Debug, S: std::fmt::Debug> {
raw: RawSparse<T, S>,
index: usize,
sparse_index: usize,
lifetime: PhantomData<&'a T>,
}
impl<'a, T, S> Iterator for SparseDenseIter<'a, T, S>
where
T: std::fmt::Debug + Copy + Into<f32>,
S: Ord + TryInto<usize> + std::fmt::Debug + Copy,
{
type Item = f32;
fn next(&mut self) -> Option<Self::Item> {
let dim = self.raw.dim();
if self.index < dim && self.sparse_index < self.raw.len {
let raw_si = unsafe { *self.raw.indexes_ptr.add(self.sparse_index) };
let si: usize = match raw_si.try_into() {
Ok(si) => si,
Err(_) => panic!("Could not covert a sparse index into a usize"),
};
if si == self.index {
let val = unsafe { *self.raw.values_ptr.add(self.sparse_index) };
self.sparse_index += 1;
self.index += 1;
Some(val.into())
} else if self.index < dim {
self.index += 1;
Some(0.0)
} else {
None
}
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let dim = self.raw.dim();
(dim, Some(dim))
}
}
#[derive(Debug)]
pub struct RawSparse<T, S> {
dim: usize,
values_ptr: *const T,
indexes_ptr: *const S,
len: usize,
}
#[derive(Debug)]
pub struct SparseRef<'a, T, S> {
raw: RawSparse<T, S>,
lifetime: PhantomData<&'a T>,
}
unsafe impl<T: Send, S: Send> Send for RawSparse<T, S> {}
unsafe impl<T: Sync, S: Sync> Sync for RawSparse<T, S> {}
impl<T: std::fmt::Debug, S: std::fmt::Debug + TryInto<usize>> RawSparse<T, S> {
pub(crate) fn indexes<'a>(&'a self) -> &'a [S] {
unsafe { std::slice::from_raw_parts::<'a>(self.indexes_ptr, self.len) }
}
pub(crate) fn values<'a>(&'a self) -> &'a [T] {
unsafe { std::slice::from_raw_parts::<'a>(self.values_ptr, self.len) }
}
pub(crate) fn dim(&self) -> usize {
self.dim
}
}
impl<'a, T, S: TryInto<usize>> SparseRef<'a, T, S> {
pub fn new<'b>(dim: usize, values: &'b [T], indexes: &'b [S]) -> SparseRef<'b, T, S> {
let len = values.len();
assert_eq!(
indexes.len(),
len,
"Need the indexes and values to be of identical len"
);
let indexes_ptr: *const S = indexes.as_ptr();
let values_ptr: *const T = values.as_ptr();
let raw = RawSparse {
indexes_ptr,
values_ptr,
dim,
len,
};
SparseRef {
raw,
lifetime: PhantomData,
}
}
pub fn indexes(&self) -> &'a [S] {
unsafe { std::slice::from_raw_parts::<'a>(self.raw.indexes_ptr, self.raw.len) }
}
pub fn values(&self) -> &'a [T] {
unsafe { std::slice::from_raw_parts::<'a>(self.raw.values_ptr, self.raw.len) }
}
pub fn dim(&self) -> usize {
self.raw.dim
}
}
impl<'a, T, S> Deref for SparseRef<'a, T, S> {
type Target = RawSparse<T, S>;
fn deref(&self) -> &Self::Target {
&self.raw
}
}
impl<'a, T, S> PointRef for SparseRef<'a, T, S>
where
T: std::fmt::Debug + Copy + Into<f32> + Send + Sync,
S: TryInto<usize> + Ord + TryFrom<usize> + std::fmt::Debug + Copy + Send + Sync + 'static,
{
type DenseIter = SparseDenseIter<'a, T, S>;
fn dense(&self) -> Vec<f32> {
let dim = self.dim();
let mut v = vec![0.0; dim];
for (xi, i) in self.values().iter().zip(self.indexes()) {
match (*i).try_into() {
Ok(i) => {
let _index: usize = i;
v[i] = (*xi).into();
}
Err(_) => panic!("Could not covert a sparse index into a usize"),
}
}
v
}
fn dense_iter(&self) -> SparseDenseIter<'a, T, S> {
let raw = RawSparse {
dim: self.raw.dim,
values_ptr: self.raw.values_ptr,
indexes_ptr: self.raw.indexes_ptr,
len: self.raw.len,
};
SparseDenseIter {
raw,
index: 0,
sparse_index: 0,
lifetime: PhantomData,
}
}
}