// codesnip-guard: Accumulate #[cfg_attr(any(),rustfmt::skip)]pub use self::accumulate::{Accumulate,Accumulate2d,AccumulateKd};#[cfg_attr(any(),rustfmt::skip)]mod accumulate{use super::{AbelianGroup,AbelianMonoid,Group,Monoid,RangeBoundsExt};use std::{fmt::{self,Debug,Formatter},iter::FromIterator,ops::RangeBounds};#[doc=" Accumlated data"]pub struct Accumulatewhere M:Monoid{data:Vec}implDebug for Accumulatewhere M:Monoid{fn fmt(&self,f:&mut Formatter<'_>)->fmt::Result{f.debug_struct("Accumulate").field("data",&self.data).finish()}}implFromIteratorfor Accumulatewhere M:Monoid{fn from_iter(iter:T)->Self where T:IntoIterator{let iter=iter.into_iter();let(lower,_)=iter.size_hint();let mut data=Vec::with_capacity(lower.saturating_add(1));let mut acc=M::unit();for x in iter{let y=M::operate(&acc,&x);data.push(acc);acc=y;}data.push(acc);Self{data}}}implAccumulatewhere M:Monoid{pub fn from_vec(mut data:Vec)->Self{let mut acc=M::unit();for x in&mut data{let y=M::operate(&acc,x);*x=acc;acc=y;}data.push(acc);Self{data}}#[doc=" Return fold of \\[0, k\\)"]pub fn accumulate(&self,k:usize)->M::T{assert!(kAccumulatewhere M:Group{#[doc=" Return fold of range"]pub fn fold(&self,range:R)->M::T where R:RangeBounds{let n=self.data.len()-1;let range=range.to_range_bounded(0,n).expect("invalid range");let(l,r)=(range.start,range.end);assert!(l<=r,"bad range [{}, {})",l,r);M::operate(&M::inverse(unsafe{self.data.get_unchecked(l)}),unsafe{self.data.get_unchecked(r)})}}#[doc=" 2-dimensional accumlated data"]pub struct Accumulate2dwhere M:AbelianMonoid{h:usize,w:usize,data:Vec}implDebug for Accumulate2dwhere M:AbelianMonoid{fn fmt(&self,f:&mut Formatter<'_>)->fmt::Result{f.debug_struct("Accumulate2d").field("h",&self.h).field("w",&self.w).field("data",&self.data).finish()}}implAccumulate2dwhere M:AbelianMonoid{pub fn new(arr2d:&[Vec])->Self{let h=arr2d.len();assert!(h>0);let w=arr2d[0].len();assert!(w>0);let w1=w+1;let mut data=Vec::with_capacity((h+1)*w1);data.resize_with(w1,M::unit);for(i,arr)in arr2d.iter().enumerate(){assert_eq!(w,arr.len(),"expected 2d array");let mut acc=M::unit();for(j,x)in arr.iter().enumerate(){let y=M::operate(&acc,x);data.push(M::operate(&acc,unsafe{data.get_unchecked(w1*i+j)}));acc=y;}data.push(M::operate(&acc,unsafe{data.get_unchecked(w1*i+w)}));}Self{h,w,data}}pub fn from_fn(h:usize,w:usize,mut f:F)->Self where F:FnMut(usize,usize)->M::T{let w1=w+1;let mut data=Vec::with_capacity((h+1)*w1);data.resize_with(w1,M::unit);for i in 0..h{let mut acc=M::unit();for j in 0..w{let y=M::operate(&acc,&f(i,j));data.push(M::operate(&acc,unsafe{data.get_unchecked(w1*i+j)}));acc=y;}data.push(M::operate(&acc,unsafe{data.get_unchecked(w1*i+w)}));}Self{h,w,data}}#[doc=" Return fold of \\[0, x\\) × \\[0, y\\)"]pub fn accumulate(&self,x:usize,y:usize)->M::T{let h1=self.h+1;let w1=self.w+1;assert!(xAccumulate2dwhere M:AbelianGroup{#[doc=" Return fold of range"]pub fn fold(&self,range0:R0,range1:R1)->M::T where R0:RangeBounds,R1:RangeBounds{let range0=range0.to_range_bounded(0,self.h).expect("invalid range");let range1=range1.to_range_bounded(0,self.w).expect("invalid range");let(xl,xr)=(range0.start,range0.end);let(yl,yr)=(range1.start,range1.end);assert!(xl<=xr,"bad range [{}, {})",xl,xr);assert!(yl<=yr,"bad range [{}, {})",yl,yr);let w1=self.w+1;unsafe{M::rinv_operate(&M::operate(self.data.get_unchecked(w1*xl+yl),self.data.get_unchecked(w1*xr+yr)),&M::operate(self.data.get_unchecked(w1*xl+yr),self.data.get_unchecked(w1*xr+yl)))}}}pub struct AccumulateKdwhere M:AbelianMonoid{dim:[usize;K],offset:[usize;K],data:Vec}implDebug for AccumulateKdwhere M:AbelianMonoid{fn fmt(&self,f:&mut Formatter<'_>)->fmt::Result{f.debug_struct("AccumulateKd").field("dim",&self.dim).field("offset",&self.offset).field("data",&self.data).finish()}}implAccumulateKdwhere M:AbelianMonoid{pub fn from_fn(dim:[usize;K],mut f:impl FnMut([usize;K])->M::T)->Self{fn fill(dim:&[usize;K],offset:&[usize;K],data:&mut[T],f:&mut impl FnMut([usize;K])->T,mut index:[usize;K],pos:usize){if posM::T{for(d,x)in x.into_iter().enumerate(){assert!(x<=self.dim[d],"index out of range: the len is {} but the index is {}",self.dim[d]+1,x);}let p:usize=x.iter().zip(&self.offset).map(|(x,y)|x*y).sum();unsafe{self.data.get_unchecked(p)}.clone()}}implAccumulateKdwhere M:AbelianGroup{pub fn fold(&self,ranges:[R;K])->M::T where R:RangeBounds{let ranges:[_;K]=std::array::from_fn(|i|{let range=ranges[i].to_range_bounded(0,self.dim[i]).expect("invalid range");let(l,r)=(range.start,range.end);assert!(l<=r,"bad range [{}, {})",l,r);[l,r]});let mut p:usize=ranges.iter().zip(&self.offset).map(|(range,offset)|range[1]*offset).sum();let delta:[_;K]=std::array::from_fn(|d|(ranges[d][1]-ranges[d][0])*self.offset[d]);let mut acc=M::unit();let len=1usize<>1);let changed=gray^next_gray;let d=changed.trailing_zeros()as usize;if(next_gray>>d)&1==1{p-=delta[d];}else{p+=delta[d];}gray=next_gray;inv=!inv;}}acc}}} // codesnip-guard: algebra #[cfg_attr(any(),rustfmt::skip)]pub use self::magma::*;#[cfg_attr(any(),rustfmt::skip)]mod magma{#![doc=" algebraic traits"]#[doc=" binary operaion: $T \\circ T \\to T$"]pub trait Magma{#[doc=" type of operands: $T$"]type T:Clone;#[doc=" binary operaion: $\\circ$"]fn operate(x:&Self::T,y:&Self::T)->Self::T;fn reverse_operate(x:&Self::T,y:&Self::T)->Self::T{Self::operate(y,x)}fn operate_assign(x:&mut Self::T,y:&Self::T){*x=Self::operate(x,y);}}#[doc=" $\\forall a,\\forall b,\\forall c \\in T, (a \\circ b) \\circ c = a \\circ (b \\circ c)$"]pub trait Associative:Magma{}#[doc=" associative binary operation"]pub trait SemiGroup:Magma+Associative{}implSemiGroup for S where S:Magma+Associative{}#[doc=" $\\exists e \\in T, \\forall a \\in T, e \\circ a = a \\circ e = a$"]pub trait Unital:Magma{#[doc=" identity element: $e$"]fn unit()->Self::T;fn is_unit(x:&Self::T)->bool where Self::T:PartialEq{x==&Self::unit()}fn set_unit(x:&mut Self::T){*x=Self::unit();}}pub trait ExpBits{type Iter:Iterator;fn bits(self)->Self::Iter;}pub trait SignedExpBits{type T:ExpBits;fn neg_and_bits(self)->(bool,Self::T);}pub struct Bits{n:T}macro_rules!impl_exp_bits_for_uint{($($t:ty)*)=>{$(impl Iterator for Bits<$t>{type Item=bool;fn next(&mut self)->Option{if self.n==0{None}else{let bit=(self.n&1)==1;self.n>>=1;Some(bit)}}}impl ExpBits for$t{type Iter=Bits<$t>;fn bits(self)->Self::Iter{Bits{n:self}}}impl SignedExpBits for$t{type T=$t;fn neg_and_bits(self)->(bool,Self::T){(false,self)}})*};}impl_exp_bits_for_uint!(u8 u16 u32 u64 u128 usize);macro_rules!impl_signed_exp_bits_for_sint{($($s:ty,$u:ty;)*)=>{$(impl SignedExpBits for$s{type T=$u;fn neg_and_bits(self)->(bool,Self::T){(self<0,self.unsigned_abs())}})*};}impl_signed_exp_bits_for_sint!(i8,u8;i16,u16;i32,u32;i64,u64;i128,u128;isize,usize;);#[doc=" associative binary operation and an identity element"]pub trait Monoid:SemiGroup+Unital{#[doc=" binary exponentiation: $x^n = x\\circ\\ddots\\circ x$"]fn pow(mut x:Self::T,exp:E)->Self::T where E:ExpBits{let mut bits=exp.bits();let Some(first)=bits.next()else{return Self::unit();};let mut res=if first{x.clone()}else{Self::unit()};for bit in bits{x=Self::operate(&x,&x);if bit{res=Self::operate(&res,&x);}}res}fn fold(iter:I)->Self::T where I:IntoIterator{let mut iter=iter.into_iter();if let Some(item)=iter.next(){iter.fold(item,|acc,x|Self::operate(&acc,&x))}else{Self::unit()}}}implMonoid for M where M:SemiGroup+Unital{}#[doc=" $\\exists e \\in T, \\forall a \\in T, \\exists b,c \\in T, b \\circ a = a \\circ c = e$"]pub trait Invertible:Magma+Unital{#[doc=" $a$ where $a \\circ x = e$"]fn inverse(x:&Self::T)->Self::T;fn rinv_operate(x:&Self::T,y:&Self::T)->Self::T{Self::operate(x,&Self::inverse(y))}fn rinv_operate_assign(x:&mut Self::T,y:&Self::T){*x=Self::rinv_operate(x,y);}}#[doc=" associative binary operation and an identity element and inverse elements"]pub trait Group:Monoid+Invertible{fn signed_pow(x:Self::T,exp:E)->Self::T where E:SignedExpBits{let(neg,exp)=E::neg_and_bits(exp);let res=Self::pow(x,exp);if neg{Self::inverse(&res)}else{res}}}implGroup for G where G:Monoid+Invertible{}#[doc=" $\\forall a,\\forall b \\in T, a \\circ b = b \\circ a$"]pub trait Commutative:Magma{}#[doc=" commutative monoid"]pub trait AbelianMonoid:Monoid+Commutative{}implAbelianMonoid for M where M:Monoid+Commutative{}#[doc=" commutative group"]pub trait AbelianGroup:Group+Commutative{}implAbelianGroup for G where G:Group+Commutative{}#[doc=" $\\forall a \\in T, a \\circ a = a$"]pub trait Idempotent:Magma{}#[doc=" idempotent monoid"]pub trait IdempotentMonoid:Monoid+Idempotent{}implIdempotentMonoid for M where M:Monoid+Idempotent{}#[macro_export]macro_rules!monoid_fold{($m:ty)=>{<$m as Unital>::unit()};($m:ty,)=>{<$m as Unital>::unit()};($m:ty,$f:expr)=>{$f};($m:ty,$f:expr,$($ff:expr),*)=>{<$m as Magma>::operate(&($f),&monoid_fold!($m,$($ff),*))};}#[macro_export]macro_rules!define_monoid{($Name:ident,$t:ty,|$x:ident,$y:ident|$op:expr,$unit:expr)=>{struct$Name;impl Magma for$Name{type T=$t;fn operate($x:&Self::T,$y:&Self::T)->Self::T{$op}}impl Unital for$Name{fn unit()->Self::T{$unit}}impl Associative for$Name{}};}} // codesnip-guard: bounded #[cfg_attr(any(),rustfmt::skip)]pub use self::bounded::Bounded;#[cfg_attr(any(),rustfmt::skip)]mod bounded{#[doc=" Trait for max/min bounds"]pub trait Bounded:Sized+PartialOrd{fn maximum()->Self;fn minimum()->Self;fn is_maximum(&self)->bool{self==&Self::maximum()}fn is_minimum(&self)->bool{self==&Self::minimum()}fn set_maximum(&mut self){*self=Self::maximum()}fn set_minimum(&mut self){*self=Self::minimum()}}macro_rules!impl_bounded_num{($($t:ident)*)=>{$(impl Bounded for$t{fn maximum()->Self{$t::MAX}fn minimum()->Self{$t::MIN}})*};}impl_bounded_num!(u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize f32 f64);macro_rules!impl_bounded_tuple{(@impl$($T:ident)*)=>{impl<$($T:Bounded),*>Bounded for($($T,)*){fn maximum()->Self{($(<$T as Bounded>::maximum(),)*)}fn minimum()->Self{($(<$T as Bounded>::minimum(),)*)}}};(@inner$($T:ident)*,)=>{impl_bounded_tuple!(@impl$($T)*);};(@inner$($T:ident)*,$U:ident$($Rest:ident)*)=>{impl_bounded_tuple!(@impl$($T)*);impl_bounded_tuple!(@inner$($T)*$U,$($Rest)*);};($T:ident$($Rest:ident)*)=>{impl_bounded_tuple!(@inner$T,$($Rest)*);};}impl_bounded_tuple!(A B C D E F G H I J);impl Bounded for(){fn maximum()->Self{}fn minimum()->Self{}}impl Bounded for bool{fn maximum()->Self{true}fn minimum()->Self{false}}implBounded for Optionwhere T:Bounded{fn maximum()->Self{Some(::maximum())}fn minimum()->Self{None}}implBounded for std::cmp::Reversewhere T:Bounded{fn maximum()->Self{std::cmp::Reverse(::minimum())}fn minimum()->Self{std::cmp::Reverse(::maximum())}}} // codesnip-guard: discrete_steps #[cfg_attr(any(),rustfmt::skip)]pub use self::discrete_steps::{DiscreteSteps,RangeBoundsExt};#[cfg_attr(any(),rustfmt::skip)]mod discrete_steps{use super::Bounded;use std::{convert::TryFrom,ops::{Bound,Range,RangeBounds,RangeInclusive}};pub trait DiscreteSteps:Clone{fn delta()->Delta;fn steps_between(start:&Self,end:&Self)->Option;fn forward_checked(start:Self,delta:Delta)->Option;fn backward_checked(start:Self,delta:Delta)->Option;fn forward(start:Self,delta:Delta)->Self{Self::forward_checked(start,delta).expect("overflow in `DiscreteSteps::forward`")}fn backward(start:Self,delta:Delta)->Self{Self::backward_checked(start,delta).expect("overflow in `DiscreteSteps::backward`")}fn forward_delta_checked(start:Self)->Option{Self::forward_checked(start,Self::delta())}fn backward_delta_checked(start:Self)->Option{Self::backward_checked(start,Self::delta())}fn forward_delta(start:Self)->Self{Self::forward(start,Self::delta())}fn backward_delta(start:Self)->Self{Self::backward(start,Self::delta())}}macro_rules!impl_discrete_steps_integer{(@common$u_source:ident)=>{fn delta()->$u_source{1}fn forward(start:Self,delta:$u_source)->Self{assert!(Self::forward_checked(start,delta).is_some(),"attempt to add with overflow");start.wrapping_add(delta as Self)}fn backward(start:Self,delta:$u_source)->Self{assert!(Self::backward_checked(start,delta).is_some(),"attempt to subtract with overflow");start.wrapping_sub(delta as Self)}};($u_source:ident$i_source:ident;$($u_narrower:ident$i_narrower:ident),*;$($u_wider:ident$i_wider:ident),*)=>{$(impl DiscreteSteps<$u_source>for$u_narrower{impl_discrete_steps_integer!(@common$u_source);fn steps_between(start:&Self,end:&Self)->Option<$u_source>{if*start<=*end{$u_source::try_from(*end-*start).ok()}else{None}}fn forward_checked(start:Self,delta:$u_source)->Option{Self::try_from(delta).ok().and_then(|delta|start.checked_add(delta))}fn backward_checked(start:Self,delta:$u_source)->Option{Self::try_from(delta).ok().and_then(|delta|start.checked_sub(delta))}}impl DiscreteSteps<$u_source>for$i_narrower{impl_discrete_steps_integer!(@common$u_source);fn steps_between(start:&Self,end:&Self)->Option<$u_source>{if*start<=*end{$u_source::try_from(end.abs_diff(*start)).ok()}else{None}}fn forward_checked(start:Self,delta:$u_source)->Option{$u_narrower::try_from(delta).ok().and_then(|delta|{let wrapped=start.wrapping_add(delta as Self);if wrapped>=start{Some(wrapped)}else{None}})}fn backward_checked(start:Self,delta:$u_source)->Option{$u_narrower::try_from(delta).ok().and_then(|delta|{let wrapped=start.wrapping_sub(delta as Self);if wrapped<=start{Some(wrapped)}else{None}})}})*$(impl DiscreteSteps<$u_source>for$u_wider{impl_discrete_steps_integer!(@common$u_source);fn steps_between(start:&Self,end:&Self)->Option<$u_source>{if*start<=*end{$u_source::try_from(*end-*start).ok()}else{None}}fn forward_checked(start:Self,delta:$u_source)->Option{start.checked_add(delta as Self)}fn backward_checked(start:Self,delta:$u_source)->Option{start.checked_sub(delta as Self)}}impl DiscreteSteps<$u_source>for$i_wider{impl_discrete_steps_integer!(@common$u_source);fn steps_between(start:&Self,end:&Self)->Option<$u_source>{if*start<=*end{end.checked_sub(*start).and_then(|result|$u_source::try_from(result).ok())}else{None}}fn forward_checked(start:Self,delta:$u_source)->Option{start.checked_add(delta as Self)}fn backward_checked(start:Self,delta:$u_source)->Option{start.checked_sub(delta as Self)}})*};}impl_discrete_steps_integer!(u16 i16;u8 i8,u16 i16,usize isize;u32 i32,u64 i64,u128 i128);impl_discrete_steps_integer!(u32 i32;u8 i8,u16 i16,u32 i32,usize isize;u64 i64,u128 i128);impl_discrete_steps_integer!(u64 i64;u8 i8,u16 i16,u32 i32,u64 i64,usize isize;u128 i128);impl_discrete_steps_integer!(u128 i128;u8 i8,u16 i16,u32 i32,u64 i64,u128 i128,usize isize;);impl_discrete_steps_integer!(usize isize;u8 i8,u16 i16,u32 i32,u64 i64,usize isize;u128 i128);pub trait RangeBoundsExt{fn start_bound_included_checked(&self)->Option;fn start_bound_excluded_checked(&self)->Option;fn end_bound_included_checked(&self)->Option;fn end_bound_excluded_checked(&self)->Option;fn start_bound_included(&self)->T;fn start_bound_excluded(&self)->T;fn end_bound_included(&self)->T;fn end_bound_excluded(&self)->T;fn start_bound_included_bounded(&self,lb:T)->Optionwhere T:Ord;fn start_bound_excluded_bounded(&self,lb:T)->Optionwhere T:Ord;fn end_bound_included_bounded(&self,ub:T)->Optionwhere T:Ord;fn end_bound_excluded_bounded(&self,ub:T)->Optionwhere T:Ord;fn to_range_checked(&self)->Option>{match(self.start_bound_included_checked(),self.end_bound_excluded_checked()){(Some(start),Some(end))=>Some(start..end),_=>None,}}fn to_range(&self)->Range{self.start_bound_included()..self.end_bound_excluded()}fn to_range_bounded(&self,min:T,max:T)->Option>where T:Ord{Some(self.start_bound_included_bounded(min)?..self.end_bound_excluded_bounded(max)?)}fn to_range_inclusive_checked(&self)->Option>{match(self.start_bound_included_checked(),self.end_bound_included_checked()){(Some(start),Some(end))=>Some(start..=end),_=>None,}}fn to_range_inclusive(&self)->RangeInclusive{self.start_bound_included()..=self.end_bound_included()}fn to_range_inclusive_bounded(&self,min:T,max:T)->Option>where T:Ord{Some(self.start_bound_included_bounded(min)?..=self.end_bound_included_bounded(max)?)}}macro_rules!impl_range_bounds_ext{($($source:ident=>$($target:ident)+);*$(;)?)=>{$($(implRangeBoundsExt<$target>for R where R:RangeBounds<$target>,{fn start_bound_included_checked(&self)->Option<$target>{match self.start_bound(){Bound::Included(x)=>Some(*x),Bound::Excluded(x)=>DiscreteSteps::<$source>::forward_delta_checked(*x),Bound::Unbounded=>Some(Bounded::minimum()),}}fn start_bound_excluded_checked(&self)->Option<$target>{match self.start_bound(){Bound::Included(x)=>DiscreteSteps::<$source>::backward_delta_checked(*x),Bound::Excluded(x)=>Some(*x),Bound::Unbounded=>None,}}fn end_bound_included_checked(&self)->Option<$target>{match self.end_bound(){Bound::Included(x)=>Some(*x),Bound::Excluded(x)=>DiscreteSteps::<$source>::backward_delta_checked(*x),Bound::Unbounded=>Some(Bounded::maximum()),}}fn end_bound_excluded_checked(&self)->Option<$target>{match self.end_bound(){Bound::Included(x)=>DiscreteSteps::<$source>::forward_delta_checked(*x),Bound::Excluded(x)=>Some(*x),Bound::Unbounded=>None,}}fn start_bound_included(&self)->$target{match self.start_bound(){Bound::Included(x)=>*x,Bound::Excluded(x)=>DiscreteSteps::<$source>::forward_delta(*x),Bound::Unbounded=>Bounded::minimum(),}}fn start_bound_excluded(&self)->$target{match self.start_bound(){Bound::Included(x)=>DiscreteSteps::<$source>::backward_delta(*x),Bound::Excluded(x)=>*x,Bound::Unbounded=>DiscreteSteps::<$source>::backward_delta(Bounded::minimum()),}}fn end_bound_included(&self)->$target{match self.end_bound(){Bound::Included(x)=>*x,Bound::Excluded(x)=>DiscreteSteps::<$source>::backward_delta(*x),Bound::Unbounded=>Bounded::maximum(),}}fn end_bound_excluded(&self)->$target{match self.end_bound(){Bound::Included(x)=>DiscreteSteps::<$source>::forward_delta(*x),Bound::Excluded(x)=>*x,Bound::Unbounded=>DiscreteSteps::<$source>::forward_delta(Bounded::maximum()),}}fn start_bound_included_bounded(&self,lb:$target)->Option<$target>where$target:Ord{match self.start_bound(){Bound::Included(x)=>Some(*x).filter(|&x|lb<=x),Bound::Excluded(x)=>DiscreteSteps::<$source>::forward_delta_checked(*x).filter(|&x|lb<=x),Bound::Unbounded=>Some(lb),}}fn start_bound_excluded_bounded(&self,lb:$target)->Option<$target>where$target:Ord{match self.start_bound(){Bound::Included(x)=>DiscreteSteps::<$source>::backward_delta_checked(*x).filter(|&x|lb<=x),Bound::Excluded(x)=>Some(*x).filter(|&x|lb<=x),Bound::Unbounded=>Some(lb),}}fn end_bound_included_bounded(&self,ub:$target)->Option<$target>where$target:Ord{match self.end_bound(){Bound::Included(x)=>Some(*x).filter(|&x|x<=ub),Bound::Excluded(x)=>DiscreteSteps::<$source>::backward_delta_checked(*x).filter(|&x|x<=ub),Bound::Unbounded=>Some(ub),}}fn end_bound_excluded_bounded(&self,ub:$target)->Option<$target>where$target:Ord{match self.end_bound(){Bound::Included(x)=>DiscreteSteps::<$source>::forward_delta_checked(*x).filter(|&x|x<=ub),Bound::Excluded(x)=>Some(*x).filter(|&x|x<=ub),Bound::Unbounded=>Some(ub),}}})+)*};}impl_range_bounds_ext!(u16=>u8 i8 u16 i16;u32=>u32 i32;u64=>u64 i64;u128=>u128 i128;usize=>isize usize;);}