use std::borrow::Cow;
#[derive(Debug, Clone, PartialEq)]
pub struct Series<'a> {
values: Cow<'a, [f64]>,
}
impl<'a> Series<'a> {
pub fn as_slice(&self) -> &[f64] {
&self.values
}
pub fn iter(&self) -> impl Iterator<Item = f64> + '_ {
self.values.iter().copied()
}
pub fn len(&self) -> usize {
self.values.len()
}
pub fn is_empty(&self) -> bool {
self.values.is_empty()
}
pub fn extent(&self) -> Option<(f64, f64)> {
let mut extent: Option<(f64, f64)> = None;
for value in self.iter().filter(|value| value.is_finite()) {
extent = match extent {
None => Some((value, value)),
Some((min, max)) => Some((min.min(value), max.max(value))),
};
}
extent
}
pub fn into_owned(self) -> Series<'static> {
Series {
values: Cow::Owned(self.values.into_owned()),
}
}
}
impl FromIterator<f64> for Series<'static> {
fn from_iter<I: IntoIterator<Item = f64>>(iter: I) -> Self {
Series {
values: Cow::Owned(iter.into_iter().collect()),
}
}
}
impl FromIterator<f32> for Series<'static> {
fn from_iter<I: IntoIterator<Item = f32>>(iter: I) -> Self {
Series {
values: Cow::Owned(iter.into_iter().map(f64::from).collect()),
}
}
}
pub trait IntoSeries<'a> {
fn into_series(self) -> Series<'a>;
}
impl<'a> IntoSeries<'a> for Series<'a> {
fn into_series(self) -> Series<'a> {
self
}
}
impl<'a> IntoSeries<'a> for &'a [f64] {
fn into_series(self) -> Series<'a> {
Series {
values: Cow::Borrowed(self),
}
}
}
impl<'a> IntoSeries<'a> for &'a Vec<f64> {
fn into_series(self) -> Series<'a> {
Series {
values: Cow::Borrowed(self),
}
}
}
impl<'a, const N: usize> IntoSeries<'a> for &'a [f64; N] {
fn into_series(self) -> Series<'a> {
Series {
values: Cow::Borrowed(self),
}
}
}
impl<'a> IntoSeries<'a> for Vec<f64> {
fn into_series(self) -> Series<'a> {
Series {
values: Cow::Owned(self),
}
}
}
impl<'a, const N: usize> IntoSeries<'a> for [f64; N] {
fn into_series(self) -> Series<'a> {
Series {
values: Cow::Owned(self.to_vec()),
}
}
}
macro_rules! converting_into_series {
($($scalar:ty),*) => {$(
impl<'a, 'b> IntoSeries<'a> for &'b [$scalar] {
fn into_series(self) -> Series<'a> {
Series {
values: Cow::Owned(self.iter().map(|&value| value as f64).collect()),
}
}
}
impl<'a, 'b> IntoSeries<'a> for &'b Vec<$scalar> {
fn into_series(self) -> Series<'a> {
self.as_slice().into_series()
}
}
impl<'a> IntoSeries<'a> for Vec<$scalar> {
fn into_series(self) -> Series<'a> {
self.as_slice().into_series()
}
}
impl<'a, 'b, const N: usize> IntoSeries<'a> for &'b [$scalar; N] {
fn into_series(self) -> Series<'a> {
self.as_slice().into_series()
}
}
impl<'a, const N: usize> IntoSeries<'a> for [$scalar; N] {
fn into_series(self) -> Series<'a> {
self.as_slice().into_series()
}
}
)*};
}
converting_into_series!(f32, i8, i16, i32, i64, isize, u8, u16, u32, u64, usize);
#[cfg(test)]
#[path = "tests/series_tests.rs"]
mod tests;