reliq 0.3.6

A portable library of primitive-like constructs.
Documentation
use super::*;

#[repr(transparent)]
#[derive(Clone)]
pub struct Set<const A: u8, const B: usize, C, D>
where
    C: ops::Int,
    C: ops::Prim,
    D: q::Engine,
    (): q::SupportedPrecision<A>,
    (): q::SupportedInt<C>,
    (): q::Supported<A, C> {
    pub(crate) points: array::Array<B, Point<A, B, C, D>>
}

impl<const A: u8, const B: usize, C, D> Set<A, B, C, D>
where
    C: ops::Int,
    C: ops::Prim,
    D: q::Engine,
    (): q::SupportedPrecision<A>,
    (): q::SupportedInt<C>,
    (): q::Supported<A, C> {
    pub fn next_weighted(&self) -> Result<Point<A, B, C, D>> {
        let len: usize = self.points.len();
        if len < 3 {
            return self.next_linear()
        }
        let mut dimensions: array::Array<B, Q<A, C, D>> = array::Array::default();
        let l: &Point<A, B, C, D> = self.points.get(len - 1)?;
        let m: &Point<A, B, C, D> = self.points.get(len - 2)?;
        let p: &Point<A, B, C, D> = self.points.get(len - 3)?;
        for i in 0..B {
            let p: Q<A, C, D> = *p.dimension(i).unwrap();
            let m: Q<A, C, D> = *m.dimension(i).unwrap();
            let l: Q<A, C, D> = *l.dimension(i).unwrap();
            let a: Q<A, C, D> = (m - p)?;
            let b: Q<A, C, D> = (l - m)?;
            let c: Q<A, C, D> = C::AS_2.into();
            let d: Q<A, C, D> = C::AS_3.into();
            let next: Q<A, C, D> = ((l + ((a + (b * c)?)?))? / d)?;
            dimensions.push(next).ok();
        }
        let ret: Point<A, B, C, D> = dimensions.into();
        Ok(ret)
    }

    #[inline]
    pub fn next_k_step(&self) -> Result<Point<A, B, C, D>> {
        let len: usize = self.points.len();
        let mut arr: array::Array<B, Q<A, C, D>> = array::Array::default();
        for dimension in 0..B {
            let mut magnitude_sum: Q<A, C, D> = C::AS_0.into();
            for i in (len - B)..len {
                let prev: Point<A, B, C, D> = *self.points.get(i - 1)?;
                let prev: Q<A, C, D> = *prev.dimension(dimension).expect("Point dimension is not out of bounds.");
                let curr: Point<A, B, C, D> = *self.points.get(i)?;
                let curr: Q<A, C, D> = *curr.dimension(dimension).expect("Point dimension is not out of bounds.");
                magnitude_sum = (magnitude_sum + (curr - prev)?)?;
            }
            let len: usize = B;
            let len: C = len
                .try_into()
                .ok()
                .expect("???");
            let len: Q<A, C, D> = len.into();
            let magnitude_average: Q<A, C, D> = (magnitude_sum / len)?;
            let k: C = len.as_int();
            let k: C = k - C::AS_1;
            let k: usize = k
                .try_into()
                .ok()
                .expect("???");
            let last: Point<A, B, C, D> = *self.points.get(k).unwrap();
            let last: Q<A, C, D> = *last.dimension(dimension).unwrap();
            arr.push((last + magnitude_average)?).ok();
        }
        let ret: Point<A, B, C, D> = Point {
            dimensions: arr
        };
        Ok(ret)
    }

    #[inline]
    pub fn next_linear(&self) -> Result<Point<A, B, C, D>> {
        let len: usize = self.points.len();
        if len < 2 {
            return Err(Error::InsufficientSetSize)
        }
        let prev: &Point<A, B, C, D> = self.points.get(len - 2)?;
        let last: &Point<A, B, C, D> = self.points.get(len - 1)?;
        let mut arr: array::Array<B, Q<A, C, D>> = array::Array::default();
        for i in 0..B {
            let prev_x: Q<A, C, D> = *prev.dimension(i).expect("Point dimension is not out of bounds.");
            let last_x: Q<A, C, D> = *last.dimension(i).expect("Point dimension is not out of bounds.");
            let magnitude: Q<A, C, D> = (last_x - prev_x)?;
            let next_x: Q<A, C, D> = (last_x + magnitude)?;
            arr.push(next_x).ok();
        }
        let ret: Point<A, B, C, D> = arr.into();
        Ok(ret)
    }
}

impl<const A: u8, const B: usize, C, D, E> From<array::Array<B, E>> for Set<A, B, C, D>
where
    C: ops::Int,
    C: ops::Prim,
    D: q::Engine,
    E: Into<Point<A, B, C, D>>,
    E: Copy,
    (): q::SupportedPrecision<A>,
    (): q::SupportedInt<C>,
    (): q::Supported<A, C> {
    fn from(value: array::Array<B, E>) -> Self {
        let mut points: array::Array<B, Point<A, B, C, D>> = array::Array::default();
        for item in value {
            let item: Point<A, B, C, D> = item.into();
            points.push(item).ok();
        }
        Self {
            points
        }
    }
}

impl<const A: u8, const B: usize, C, D, E> From<[E; B]> for Set<A, B, C, D>
where
    C: ops::Int,
    C: ops::Prim,
    D: q::Engine,
    E: Into<Point<A, B, C, D>>,
    (): q::SupportedPrecision<A>,
    (): q::SupportedInt<C>,
    (): q::Supported<A, C> {
    fn from(value: [E; B]) -> Self {
        let value: [Point<A, B, C, D>; B] = value.map(|item| {
            let item: Point<A, B, C, D> = item.into();
            item
        });
        let points: array::Array<B, Point<A, B, C, D>> = value.into();
        Self {
            points
        }
    }
}

impl<const A: u8, const B: usize, C, D> ::core::ops::Deref for Set<A, B, C, D> 
where
    C: ops::Int,
    C: ops::Prim,
    D: q::Engine,
    (): q::SupportedPrecision<A>,
    (): q::SupportedInt<C>,
    (): q::Supported<A, C> {
    type Target = array::Array<B, Point<A, B, C, D>>;

    fn deref(&self) -> &Self::Target {
        &self.points
    }
}

impl<const A: u8, const B: usize, C, D> ::core::ops::DerefMut for Set<A, B, C, D> 
where
    C: ops::Int,
    C: ops::Prim,
    D: q::Engine,
    (): q::SupportedPrecision<A>,
    (): q::SupportedInt<C>,
    (): q::Supported<A, C> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.points
    }
}

#[test]
fn test_next_linear() {
    let mut set: Set<2, 2, u128, q::DefaultEngine> = [[
        0_00, 
        0_00
    ], [
        0_00, 
        0_00
    ]].into();
    set.push(
        [
            1_00,
            2_00
        ].into()
    ).ok();
    let predicted_point: Point<2, 2, u128> = set.next_linear().unwrap();
    let expected_predicted_point: Point<2, 2, u128> = [
        0_00,
        0_00
    ].into();
    assert_eq!(predicted_point, expected_predicted_point);
}