use core::{marker::PhantomData, ops::Add};
use crate::Augment;
#[derive(Debug)]
pub struct Unit;
impl<K, V> Augment<K, V> for Unit {
type Stats = ();
fn compute(
_key: &K,
_value: &V,
_left: Option<(&K, &V, &Self::Stats)>,
_right: Option<(&K, &V, &Self::Stats)>,
) -> Self::Stats {
}
fn identity() -> Self::Stats {}
}
#[derive(Debug, Default)]
pub struct SubtreeSize<S = usize>(PhantomData<S>);
impl<K, V, S> Augment<K, V> for SubtreeSize<S>
where
S: Add<Output = S> + From<usize> + Copy,
{
type Stats = S;
#[inline]
fn identity() -> S {
S::from(0usize)
}
fn compute(_key: &K, _value: &V, left: Option<(&K, &V, &S)>, right: Option<(&K, &V, &S)>) -> S {
S::from(1usize)
+ left.map_or(S::from(0usize), |(_, _, &c)| c)
+ right.map_or(S::from(0), |(_, _, &c)| c)
}
}
#[derive(Debug)]
pub struct SumAugmentation;
impl<K, V> Augment<K, V> for SumAugmentation
where
V: core::ops::Add<Output = V> + Copy + Default,
{
type Stats = V;
#[inline]
fn identity() -> V {
V::default()
}
fn compute(_key: &K, value: &V, left: Option<(&K, &V, &V)>, right: Option<(&K, &V, &V)>) -> V {
let left_sum = left.map(|(_, _, &s)| s).unwrap_or_default();
let right_sum = right.map(|(_, _, &s)| s).unwrap_or_default();
left_sum + *value + right_sum
}
}
#[derive(Debug)]
pub struct MaxAugmentation;
impl<K, V> Augment<K, V> for MaxAugmentation
where
V: Ord + Copy,
{
type Stats = Option<V>;
#[inline]
fn identity() -> Option<V> {
None
}
fn compute(
_key: &K,
value: &V,
left: Option<(&K, &V, &Option<V>)>,
right: Option<(&K, &V, &Option<V>)>,
) -> Option<V> {
let mut max = *value;
if let Some((_, _, Some(ls))) = left {
if *ls > max {
max = *ls;
}
}
if let Some((_, _, Some(rs))) = right {
if *rs > max {
max = *rs;
}
}
Some(max)
}
}
#[derive(Debug)]
pub struct MinAugmentation;
impl<K, V> Augment<K, V> for MinAugmentation
where
V: Ord + Copy,
{
type Stats = Option<V>;
#[inline]
fn identity() -> Option<V> {
None
}
fn compute(
_key: &K,
value: &V,
left: Option<(&K, &V, &Option<V>)>,
right: Option<(&K, &V, &Option<V>)>,
) -> Option<V> {
let mut min = *value;
if let Some((_, _, Some(ls))) = left {
if *ls < min {
min = *ls;
}
}
if let Some((_, _, Some(rs))) = right {
if *rs < min {
min = *rs;
}
}
Some(min)
}
}
#[derive(Debug)]
pub struct IntervalMaxEnd;
impl<K> Augment<K, K> for IntervalMaxEnd
where
K: Ord + Copy,
{
type Stats = Option<K>;
#[inline]
fn identity() -> Option<K> {
None
}
fn compute(
_key: &K,
value: &K,
left: Option<(&K, &K, &Option<K>)>,
right: Option<(&K, &K, &Option<K>)>,
) -> Option<K> {
let mut max_end = *value;
if let Some((_, _, Some(ls))) = left {
if *ls > max_end {
max_end = *ls;
}
}
if let Some((_, _, Some(rs))) = right {
if *rs > max_end {
max_end = *rs;
}
}
Some(max_end)
}
}
#[macro_export]
macro_rules! constant_augment {
($name:ident, $type:ty, $val:expr) => {
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct $name;
impl $crate::Augment<$type, $type> for $name {
type Stats = $type;
#[inline]
fn identity() -> Self::Stats {
$val
}
#[inline]
fn compute(
_key: &$type,
_value: &$type,
_left: Option<(&$type, &$type, &Self::Stats)>,
_right: Option<(&$type, &$type, &Self::Stats)>,
) -> Self::Stats {
$val
}
}
};
}