pub trait ExtMonoid {
type X: Clone + PartialEq;
type F: Clone + PartialEq;
fn id_x() -> Self::X;
fn id_f() -> Self::F;
fn op(x: &Self::X, y: &Self::X) -> Self::X;
fn mapping(x: &Self::X, y: &Self::F) -> Self::X;
fn composition(x: &Self::F, y: &Self::F) -> Self::F;
fn aggregate(x: &Self::F, p: usize) -> Self::F;
}
pub mod examples {
use super::ExtMonoid;
#[derive(Debug)]
pub struct AddSum;
impl ExtMonoid for AddSum {
type X = isize;
type F = isize;
fn id_x() -> Self::X {
0
}
fn id_f() -> Self::F {
0
}
fn op(x: &Self::X, y: &Self::X) -> Self::X {
x + y
}
fn mapping(x: &Self::X, y: &Self::F) -> Self::X {
x + y
}
fn composition(x: &Self::F, y: &Self::F) -> Self::F {
x + y
}
fn aggregate(x: &Self::F, p: usize) -> Self::F {
x * p as isize
}
}
#[derive(Debug)]
pub struct UpdateMin;
impl ExtMonoid for UpdateMin {
type X = isize;
type F = isize;
fn id_x() -> Self::X {
isize::MAX
}
fn id_f() -> Self::F {
isize::MAX
}
fn op(x: &Self::X, y: &Self::X) -> Self::X {
*x.min(y)
}
fn mapping(_x: &Self::X, y: &Self::F) -> Self::X {
*y
}
fn composition(_x: &Self::F, y: &Self::F) -> Self::F {
*y
}
fn aggregate(x: &Self::F, _p: usize) -> Self::F {
*x
}
}
#[derive(Debug)]
pub struct UpdateMax;
impl ExtMonoid for UpdateMax {
type X = isize;
type F = isize;
fn id_x() -> Self::X {
isize::MIN
}
fn id_f() -> Self::F {
isize::MIN
}
fn op(x: &Self::X, y: &Self::X) -> Self::X {
*x.max(y)
}
fn mapping(_x: &Self::X, y: &Self::F) -> Self::X {
*y
}
fn composition(_x: &Self::F, y: &Self::F) -> Self::F {
*y
}
fn aggregate(x: &Self::F, _p: usize) -> Self::F {
*x
}
}
#[derive(Debug)]
pub struct AddMin;
impl ExtMonoid for AddMin {
type X = isize;
type F = isize;
fn id_x() -> Self::X {
isize::MAX
}
fn id_f() -> Self::F {
0
}
fn op(x: &Self::X, y: &Self::X) -> Self::X {
*x.min(y)
}
fn mapping(x: &Self::X, y: &Self::F) -> Self::X {
x + y
}
fn composition(x: &Self::F, y: &Self::F) -> Self::F {
x + y
}
fn aggregate(x: &Self::F, _p: usize) -> Self::F {
*x
}
}
#[derive(Debug)]
pub struct UpdateSum;
impl ExtMonoid for UpdateSum {
type X = isize;
type F = Option<isize>;
fn id_x() -> Self::X {
0
}
fn id_f() -> Self::F {
None
}
fn op(x: &Self::X, y: &Self::X) -> Self::X {
x + y
}
fn mapping(_x: &Self::X, y: &Self::F) -> Self::X {
y.unwrap()
}
fn composition(_x: &Self::F, y: &Self::F) -> Self::F {
*y
}
fn aggregate(x: &Self::F, p: usize) -> Self::F {
x.map(|x| x * p as isize)
}
}
}