From a04c1efa3843815e625570acb3076e66f399147c Mon Sep 17 00:00:00 2001 From: Mizar Date: Wed, 25 Jan 2023 17:25:31 +0900 Subject: [PATCH] segtree: monoid BitwiseAnd/BitwiseOr/BitwiseXor --- src/lib.rs | 4 +++- src/segtree.rs | 44 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 09cc26f..0887273 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,7 +29,9 @@ pub use modint::{ ModInt1000000007, ModInt998244353, Modulus, RemEuclidU32, StaticModInt, }; pub use scc::SccGraph; -pub use segtree::{Additive, Max, Min, Monoid, Multiplicative, Segtree}; +pub use segtree::{ + Additive, BitwiseAnd, BitwiseOr, BitwiseXor, Max, Min, Monoid, Multiplicative, Segtree, +}; pub use string::{ lcp_array, lcp_array_arbitrary, suffix_array, suffix_array_arbitrary, suffix_array_manual, z_algorithm, z_algorithm_arbitrary, diff --git a/src/segtree.rs b/src/segtree.rs index 573b9ff..e45a214 100644 --- a/src/segtree.rs +++ b/src/segtree.rs @@ -3,7 +3,7 @@ use crate::internal_type_traits::{BoundedAbove, BoundedBelow, One, Zero}; use std::cmp::{max, min}; use std::convert::Infallible; use std::marker::PhantomData; -use std::ops::{Add, Bound, Mul, RangeBounds}; +use std::ops::{Add, BitAnd, BitOr, BitXor, Bound, Mul, Not, RangeBounds}; // TODO Should I split monoid-related traits to another module? pub trait Monoid { @@ -68,6 +68,48 @@ where } } +pub struct BitwiseOr(Infallible, PhantomData S>); +impl Monoid for BitwiseOr +where + S: Copy + BitOr + Zero, +{ + type S = S; + fn identity() -> Self::S { + S::zero() + } + fn binary_operation(a: &Self::S, b: &Self::S) -> Self::S { + *a | *b + } +} + +pub struct BitwiseAnd(Infallible, PhantomData S>); +impl Monoid for BitwiseAnd +where + S: Copy + BitAnd + Not + Zero, +{ + type S = S; + fn identity() -> Self::S { + !S::zero() + } + fn binary_operation(a: &Self::S, b: &Self::S) -> Self::S { + *a & *b + } +} + +pub struct BitwiseXor(Infallible, PhantomData S>); +impl Monoid for BitwiseXor +where + S: Copy + BitXor + Zero, +{ + type S = S; + fn identity() -> Self::S { + S::zero() + } + fn binary_operation(a: &Self::S, b: &Self::S) -> Self::S { + *a ^ *b + } +} + impl Default for Segtree { fn default() -> Self { Segtree::new(0)