// codesnip-guard: area_of_union_of_rectangles #[cfg_attr(any(),rustfmt::skip)]pub use self::area_of_union_of_rectangles::area_of_union_of_rectangles;#[cfg_attr(any(),rustfmt::skip)]mod area_of_union_of_rectangles{use super::{LazySegmentTree,RangeMinCountRangeAdd,SliceSortExt,StaticSearch};#[doc=" Rectangles are `(left, bottom, right, top)`."]pub fn area_of_union_of_rectangles(rectangles:&[(u32,u32,u32,u32)])->u64{let endpoints:Vec<_>=rectangles.iter().flat_map(|&(_,d,_,u)|[d,u]).collect();let mut ys=endpoints.clone();ys.radix_sort_by_key(|&y|y);ys.dedup();if ys.len()<2{return 0;}let search=StaticSearch::from_sorted(&ys);let mut positions=vec![0;endpoints.len()];search.lower_bound_batch(&endpoints,&mut positions);let mut events:Vec<_>=rectangles.iter().zip(positions.as_chunks().0).flat_map(|(&(l,_,r,_),&[d,u])|{let d=d as u32;let u=u as u32;[(l,d,u,1),(r,d,u,-1)]}).collect();events.radix_sort_by_key(|&(x,..)|x);let mut seg=LazySegmentTree::>::from_vec(ys.windows(2).map(|w|(0,(w[1]-w[0])as usize)).collect());let height=(ys[ys.len()-1]-ys[0])as usize;let mut prev_x=0;let mut area=0;for(x,d,u,delta)in events{let(minimum,count)=seg.fold_all();let covered=height-if minimum==0{count}else{0};area+=(x-prev_x)as u64*covered as u64;seg.update(d as usize..u as usize,delta);prev_x=x;}area}} // codesnip-guard: AdditiveOperation #[cfg_attr(any(),rustfmt::skip)]pub use self::additive_operation_impl::AdditiveOperation;#[cfg_attr(any(),rustfmt::skip)]mod additive_operation_impl{use super::*;use std::{marker::PhantomData,ops::{Add,Neg,Sub}};#[doc=" $+$"]pub struct AdditiveOperationwhere T:Clone+Zero+Add{_marker:PhantomDataT>}implMagma for AdditiveOperationwhere T:Clone+Zero+Add{type T=T;#[inline]fn operate(x:&Self::T,y:&Self::T)->Self::T{x.clone()+y.clone()}}implUnital for AdditiveOperationwhere T:Clone+Zero+Add{#[inline]fn unit()->Self::T{Zero::zero()}}implAssociative for AdditiveOperationwhere T:Clone+Zero+Add{}implCommutative for AdditiveOperationwhere T:Clone+Zero+Add{}implInvertible for AdditiveOperationwhere T:Clone+Zero+Add+Sub+Neg{#[inline]fn inverse(x:&Self::T)->Self::T{-x.clone()}#[inline]fn rinv_operate(x:&Self::T,y:&Self::T)->Self::T{x.clone()-y.clone()}}} // codesnip-guard: ArrayOperation #[cfg_attr(any(),rustfmt::skip)]pub use self::array_operation_impl::ArrayOperation;#[cfg_attr(any(),rustfmt::skip)]mod array_operation_impl{use super::*;use crate::array;use std::marker::PhantomData;pub struct ArrayOperation{_marker:PhantomDataM>}implMagma for ArrayOperationwhere M:Magma{type T=[M::T;N];#[inline]fn operate(x:&Self::T,y:&Self::T)->Self::T{array!(|i|M::operate(&x[i],&y[i]);N)}}implUnital for ArrayOperationwhere M:Unital{#[inline]fn unit()->Self::T{array!(||M::unit();N)}}implAssociative for ArrayOperationwhere M:Associative{}implCommutative for ArrayOperationwhere M:Commutative{}implIdempotent for ArrayOperationwhere M:Idempotent{}implInvertible for ArrayOperationwhere M:Invertible{#[inline]fn inverse(x:&Self::T)->Self::T{array!(|i|M::inverse(&x[i]);N)}}} // codesnip-guard: CountingOperation #[cfg_attr(any(),rustfmt::skip)]pub use self::counting_operation_impl::CountingOperation;#[cfg_attr(any(),rustfmt::skip)]mod counting_operation_impl{use super::*;use std::marker::PhantomData;pub struct CountingOperation{_marker:PhantomDataM>}implMagma for CountingOperationwhere M:Magma+Idempotent{type T=(M::T,usize);#[inline]fn operate(x:&Self::T,y:&Self::T)->Self::T{let z=M::operate(&x.0,&y.0);match(z==x.0,z==y.0){(true,true)=>(z,x.1+y.1),(true,false)=>(z,x.1),(false,true)=>(z,y.1),(false,false)=>(z,1),}}}implUnital for CountingOperationwhere M:Unital+Idempotent{#[inline]fn unit()->Self::T{(M::unit(),0)}}implAssociative for CountingOperationwhere M:Associative+Idempotent{}implCommutative for CountingOperationwhere M:Commutative+Idempotent{}} // codesnip-guard: LastOperation #[cfg_attr(any(),rustfmt::skip)]pub use self::last_operation_impl::LastOperation;#[cfg_attr(any(),rustfmt::skip)]mod last_operation_impl{use super::*;use std::marker::PhantomData;#[doc=" retain the last element"]pub struct LastOperationwhere T:Clone{_marker:PhantomDataT>}implMagma for LastOperationwhere T:Clone{type T=Option;#[inline]fn operate(x:&Self::T,y:&Self::T)->Self::T{y.as_ref().or(x.as_ref()).cloned()}}implUnital for LastOperationwhere T:Clone{#[inline]fn unit()->Self::T{None}}implAssociative for LastOperationwhere T:Clone{}implIdempotent for LastOperationwhere T:Clone{}} // codesnip-guard: LazyMapMonoid #[cfg_attr(any(),rustfmt::skip)]pub use self::lazy_map::*;#[cfg_attr(any(),rustfmt::skip)]mod lazy_map{use super::*;use std::{cmp::Ordering,marker::PhantomData,ops::{Add,Mul,Sub}};pub type LazyMapAgg=<::AggMonoid as Magma>::T;pub type LazyMapAct=<::ActMonoid as Magma>::T;pub trait LazyMapMonoid{type Key;type AggMonoid:Monoid;type ActMonoid:Monoid;fn single_agg(key:&Self::Key)->LazyMapAgg;fn toggle(_x:&mut LazyMapAgg){}#[inline]fn is_act_unit(act:&LazyMapAct)->bool{::is_unit(act)}#[doc=" Returns `None` when descent is needed; must succeed on single-key aggregates."]fn act_agg(x:&LazyMapAgg,a:&LazyMapAct)->Option>;#[inline]fn agg_unit()->LazyMapAgg{::unit()}#[inline]fn act_unit()->LazyMapAct{::unit()}#[inline]fn agg_operate(x:&LazyMapAgg,y:&LazyMapAgg)->LazyMapAgg{::operate(x,y)}#[inline]fn act_operate(x:&LazyMapAct,y:&LazyMapAct)->LazyMapAct{::operate(x,y)}#[inline]fn agg_operate_assign(x:&mut LazyMapAgg,y:&LazyMapAgg){*x=::operate(x,y);}#[inline]fn act_operate_assign(x:&mut LazyMapAct,y:&LazyMapAct){*x=::operate(x,y);}}pub trait LazyMapMonoidWithKeyAct:LazyMapMonoid{fn act_key(key:&Self::Key,act:&LazyMapAct)->Self::Key;}pub struct EmptyActLazy{_marker:PhantomDataM>}implLazyMapMonoid for EmptyActLazywhere M:Monoid{type Key=M::T;type AggMonoid=M;type ActMonoid=();fn single_agg(key:&Self::Key)->LazyMapAgg{key.clone()}fn act_agg(x:&LazyMapAgg,_a:&LazyMapAct)->Option>{Some(x.clone())}}implLazyMapMonoidWithKeyAct for EmptyActLazywhere M:Monoid{fn act_key(key:&Self::Key,act:&LazyMapAct)->Self::Key{EmptyAct::act(key,act)}}pub struct EmptyAggActLazy{_marker:PhantomDataT>}implLazyMapMonoid for EmptyAggActLazy{type Key=T;type AggMonoid=();type ActMonoid=();fn single_agg(_key:&Self::Key)->LazyMapAgg{}fn act_agg(_x:&LazyMapAgg,_a:&LazyMapAct)->Option>{Some(())}}implLazyMapMonoidWithKeyAct for EmptyAggActLazywhere T:Clone{fn act_key(key:&Self::Key,act:&LazyMapAct)->Self::Key{EmptyAct::act(key,act)}}pub struct FlattenLazy{_marker:PhantomDataM>}implLazyMapMonoid for FlattenLazywhere M:Monoid,M::T:PartialEq{type Key=M::T;type AggMonoid=M;type ActMonoid=M;fn single_agg(key:&Self::Key)->LazyMapAgg{key.clone()}fn act_agg(x:&LazyMapAgg,a:&LazyMapAct)->Option>{Some(M::operate(x,a))}}implLazyMapMonoidWithKeyAct for FlattenLazywhere M:Monoid,M::T:PartialEq{fn act_key(key:&Self::Key,act:&LazyMapAct)->Self::Key{FlattenAct::::act(key,act)}}pub struct RangeSumRangeAdd{_marker:PhantomDataT>}implLazyMapMonoid for RangeSumRangeAddwhere T:Copy+Zero+One+Add+Mul+PartialEq{type Key=T;type AggMonoid=(AdditiveOperation,AdditiveOperation);type ActMonoid=AdditiveOperation;fn single_agg(key:&Self::Key)->LazyMapAgg{(*key,T::one())}fn act_agg(&(x,y):&LazyMapAgg,a:&LazyMapAct)->Option>{Some(if Self::is_act_unit(a){(x,y)}else{let a=*a;(x+a*y,y)})}}implLazyMapMonoidWithKeyAct for RangeSumRangeAddwhere T:Copy+Zero+One+Add+Mul+PartialEq{fn act_key(key:&Self::Key,act:&LazyMapAct)->Self::Key{FlattenAct::::act(key,act)}}pub struct RangeSumRangeLinear{_marker:PhantomDataT>}implLazyMapMonoid for RangeSumRangeLinearwhere T:Copy+Zero+One+Add+Mul+PartialEq{type Key=T;type AggMonoid=(AdditiveOperation,AdditiveOperation);type ActMonoid=LinearOperation;fn single_agg(key:&Self::Key)->LazyMapAgg{(*key,T::one())}fn act_agg(&(x,y):&LazyMapAgg,&(a,b):&LazyMapAct)->Option>{Some((a*x+b*y,y))}}implLazyMapMonoidWithKeyAct for RangeSumRangeLinearwhere T:Copy+Zero+One+Add+Mul+PartialEq{fn act_key(key:&Self::Key,act:&LazyMapAct)->Self::Key{LinearAct::act(key,act)}}pub struct RangePowerSumRangeLinear{_marker:PhantomDataT>}implLazyMapMonoid for RangePowerSumRangeLinearwhere T:Copy+Zero+One+Add+Mul+PartialEq{type Key=T;type AggMonoid=ArrayOperation,K>;type ActMonoid=LinearOperation;fn single_agg(key:&Self::Key)->LazyMapAgg{let mut power=T::one();std::array::from_fn(|k|{if k!=0{power=power**key;}power})}fn act_agg(x:&LazyMapAgg,&(a,b):&LazyMapAct)->Option>{let mut coefficients=[T::one();K];let mut result=*x;for k in 1..K{coefficients[k]=a*coefficients[k-1];for j in(1..k).rev(){coefficients[j]=b*coefficients[j]+a*coefficients[j-1];}coefficients[0]=b*coefficients[0];result[k]=coefficients[..=k].iter().zip(x).fold(T::zero(),|sum,(&c,&p)|sum+c*p);}Some(result)}}implLazyMapMonoidWithKeyAct for RangePowerSumRangeLinearwhere T:Copy+Zero+One+Add+Mul+PartialEq{fn act_key(key:&Self::Key,act:&LazyMapAct)->Self::Key{LinearAct::act(key,act)}}pub struct RangeSumRangeUpdate{_marker:PhantomDataT>}implLazyMapMonoid for RangeSumRangeUpdatewhere T:Copy+Zero+One+Add+Mul+PartialEq{type Key=T;type AggMonoid=(AdditiveOperation,AdditiveOperation);type ActMonoid=LastOperation;fn single_agg(key:&Self::Key)->LazyMapAgg{(*key,T::one())}fn act_agg(&(x,y):&LazyMapAgg,a:&LazyMapAct)->Option>{Some((a.map(|a|a*y).unwrap_or(x),y))}}implLazyMapMonoidWithKeyAct for RangeSumRangeUpdatewhere T:Copy+Zero+One+Add+Mul+PartialEq{fn act_key(key:&Self::Key,act:&LazyMapAct)->Self::Key{UpdateAct::act(key,act)}}pub struct RangeMaxRangeUpdate{_marker:PhantomDataT>}implLazyMapMonoid for RangeMaxRangeUpdatewhere T:Clone+PartialEq+Ord+Bounded{type Key=T;type AggMonoid=MaxOperation;type ActMonoid=LastOperation;fn single_agg(key:&Self::Key)->LazyMapAgg{key.clone()}fn act_agg(x:&LazyMapAgg,a:&LazyMapAct)->Option>{Some(a.as_ref().unwrap_or(x).clone())}}implLazyMapMonoidWithKeyAct for RangeMaxRangeUpdatewhere T:Clone+PartialEq+Ord+Bounded{fn act_key(key:&Self::Key,act:&LazyMapAct)->Self::Key{UpdateAct::act(key,act)}}pub struct RangeMinRangeUpdate{_marker:PhantomDataT>}implLazyMapMonoid for RangeMinRangeUpdatewhere T:Clone+PartialEq+Ord+Bounded{type Key=T;type AggMonoid=MinOperation;type ActMonoid=LastOperation;fn single_agg(key:&Self::Key)->LazyMapAgg{key.clone()}fn act_agg(x:&LazyMapAgg,a:&LazyMapAct)->Option>{Some(a.as_ref().unwrap_or(x).clone())}}implLazyMapMonoidWithKeyAct for RangeMinRangeUpdatewhere T:Clone+PartialEq+Ord+Bounded{fn act_key(key:&Self::Key,act:&LazyMapAct)->Self::Key{UpdateAct::act(key,act)}}pub struct RangeMaxRangeAdd{_marker:PhantomDataT>}implLazyMapMonoid for RangeMaxRangeAddwhere T:Clone+Ord+Bounded+Zero+Add{type Key=T;type AggMonoid=MaxOperation;type ActMonoid=AdditiveOperation;fn single_agg(key:&Self::Key)->LazyMapAgg{key.clone()}fn act_agg(x:&LazyMapAgg,a:&LazyMapAct)->Option>{Some(if Self::is_act_unit(a){x.clone()}else{x.clone()+a.clone()})}}implLazyMapMonoidWithKeyAct for RangeMaxRangeAddwhere T:Clone+Ord+Bounded+Zero+Add{fn act_key(key:&Self::Key,act:&LazyMapAct)->Self::Key{FlattenAct::::act(key,act)}}pub struct RangeMinRangeAdd{_marker:PhantomDataT>}implLazyMapMonoid for RangeMinRangeAddwhere T:Clone+Ord+Bounded+Zero+Add{type Key=T;type AggMonoid=MinOperation;type ActMonoid=AdditiveOperation;fn single_agg(key:&Self::Key)->LazyMapAgg{key.clone()}fn act_agg(x:&LazyMapAgg,a:&LazyMapAct)->Option>{Some(if Self::is_act_unit(a){x.clone()}else{x.clone()+a.clone()})}}implLazyMapMonoidWithKeyAct for RangeMinRangeAddwhere T:Clone+Ord+Bounded+Zero+Add{fn act_key(key:&Self::Key,act:&LazyMapAct)->Self::Key{FlattenAct::::act(key,act)}}pub struct RangeMinCountRangeAdd{_marker:PhantomDataT>}implLazyMapMonoid for RangeMinCountRangeAddwhere T:Clone+Ord+Bounded+Zero+Add{type Key=T;type AggMonoid=CountingOperation>;type ActMonoid=AdditiveOperation;fn single_agg(key:&Self::Key)->LazyMapAgg{(key.clone(),1)}fn act_agg(x:&LazyMapAgg,a:&LazyMapAct)->Option>{Some(if x.1==0{x.clone()}else{(x.0 .clone()+a.clone(),x.1)})}}implLazyMapMonoidWithKeyAct for RangeMinCountRangeAddwhere T:Clone+Ord+Bounded+Zero+Add{fn act_key(key:&Self::Key,act:&LazyMapAct)->Self::Key{FlattenAct::::act(key,act)}}#[derive(Debug,Clone,Copy,PartialEq,Eq)]pub struct RangeChminChmaxAdd{lb:T,ub:T,bias:T}implRangeChminChmaxAddwhere T:Zero+Bounded{pub fn chmin(x:T)->Self{Self{lb:T::minimum(),ub:x,bias:T::zero()}}pub fn chmax(x:T)->Self{Self{lb:x,ub:T::maximum(),bias:T::zero()}}pub fn add(x:T)->Self where T:Copy+Ord+Add{Self{lb:T::minimum()+x.max(T::zero()),ub:T::maximum()+x.min(T::zero()),bias:x}}}implMagma for RangeChminChmaxAddwhere T:Copy+Zero+Ord+Bounded+Add{type T=Self;fn operate(x:&Self::T,y:&Self::T)->Self::T{Self{lb:(x.lb+y.bias).max(y.lb).min(y.ub),ub:(x.ub+y.bias).max(y.lb).min(y.ub),bias:x.bias+y.bias}}}implAssociative for RangeChminChmaxAddwhere T:Copy+Zero+Ord+Bounded+Add{}implUnital for RangeChminChmaxAddwhere T:Copy+Zero+Ord+Bounded+Add{fn unit()->Self::T{Self{lb:T::minimum(),ub:T::maximum(),bias:T::zero()}}}#[derive(Debug,Clone,PartialEq,Eq)]pub struct RangeSumRangeChminChmaxAdd{min:T,max:T,min2:T,max2:T,pub sum:T,size:T,n_min:T,n_max:T}implRangeSumRangeChminChmaxAddwhere T:Copy+Zero+One+Ord+Bounded+Add+Sub+Mul+PartialEq{pub fn single(key:T,size:T)->Self{Self{min:key,max:key,min2:T::maximum(),max2:T::minimum(),sum:key*size,size,n_min:size,n_max:size}}}implMagma for RangeSumRangeChminChmaxAddwhere T:Copy+Zero+One+Ord+Bounded+Add+Sub+Mul+PartialEq{type T=Self;fn operate(x:&Self::T,y:&Self::T)->Self::T{Self{min:x.min.min(y.min),max:x.max.max(y.max),min2:if x.min==y.min{x.min2.min(y.min2)}else if x.min2<=y.min{x.min2}else if y.min2<=x.min{y.min2}else{x.min.max(y.min)},max2:if x.max==y.max{x.max2.max(y.max2)}else if x.max2>=y.max{x.max2}else if y.max2>=x.max{y.max2}else{x.max.min(y.max)},sum:x.sum+y.sum,size:x.size+y.size,n_min:match x.min.cmp(&y.min){Ordering::Less=>x.n_min,Ordering::Equal=>x.n_min+y.n_min,Ordering::Greater=>y.n_min,},n_max:match x.max.cmp(&y.max){Ordering::Less=>y.n_max,Ordering::Equal=>x.n_max+y.n_max,Ordering::Greater=>x.n_max,}}}}implAssociative for RangeSumRangeChminChmaxAddwhere T:Copy+Zero+One+Ord+Bounded+Add+Sub+Mul+PartialEq{}implUnital for RangeSumRangeChminChmaxAddwhere T:Copy+Zero+One+Ord+Bounded+Add+Sub+Mul+PartialEq{fn unit()->Self::T{Self{min:T::maximum(),max:T::minimum(),min2:T::maximum(),max2:T::minimum(),sum:T::zero(),size:T::zero(),n_min:T::zero(),n_max:T::zero()}}}implMonoidAct for RangeChminChmaxAddwhere T:Copy+Zero+Ord+Bounded+Add{type Key=T;type Act=RangeChminChmaxAdd;type ActMonoid=RangeChminChmaxAdd;fn act(x:&Self::Key,a:&Self::Act)->Self::Key{(*x+a.bias).max(a.lb).min(a.ub)}}implLazyMapMonoid for RangeSumRangeChminChmaxAddwhere T:Copy+Zero+One+Ord+Bounded+Add+Sub+Mul+PartialEq{type Key=T;type AggMonoid=Self;type ActMonoid=RangeChminChmaxAdd;fn single_agg(&key:&Self::Key)->LazyMapAgg{Self::single(key,T::one())}fn act_agg(x:&LazyMapAgg,a:&LazyMapAct)->Option>{if Self::is_act_unit(a){return Some(x.clone());}if x.size.is_zero(){return Some(Self::unit());}let lb=a.lb-a.bias;let ub=a.ub-a.bias;let min=x.min.max(lb);let max=x.max.min(ub);Some(if min>=max{Self::single(RangeChminChmaxAdd::act(&x.min,a),x.size)}else if x.min2==x.max{let mut x=x.clone();let min=min+a.bias;let max=max+a.bias;x.min=min;x.max2=min;x.max=max;x.min2=max;x.sum=min*x.n_min+max*x.n_max;x}else if lbLazyMapMonoidWithKeyAct for RangeSumRangeChminChmaxAddwhere T:Copy+Zero+One+Ord+Bounded+Add+Sub+Mul+PartialEq{fn act_key(key:&Self::Key,act:&LazyMapAct)->Self::Key{RangeChminChmaxAdd::act(key,act)}}} // codesnip-guard: LazySegmentTree #[cfg_attr(any(),rustfmt::skip)]pub use self::lazy_segment_tree::LazySegmentTree;#[cfg_attr(any(),rustfmt::skip)]mod lazy_segment_tree{use super::{LazyMapAct,LazyMapAgg,LazyMapMonoid,RangeBoundsExt};use std::{fmt::{self,Debug,Formatter},mem::replace,ops::RangeBounds};pub struct LazySegmentTreewhere M:LazyMapMonoid{len:usize,n:usize,seg:Vec>,lazy:Vec>}implClone for LazySegmentTreewhere M:LazyMapMonoid{fn clone(&self)->Self{Self{len:self.len,n:self.n,seg:self.seg.clone(),lazy:self.lazy.clone()}}}implDebug for LazySegmentTreewhere M:LazyMapMonoid,LazyMapAgg:Debug,LazyMapAct:Debug{fn fmt(&self,f:&mut Formatter<'_>)->fmt::Result{f.debug_struct("LazySegmentTree").field("len",&self.len).field("n",&self.n).field("seg",&self.seg).field("lazy",&self.lazy).finish()}}implLazySegmentTreewhere M:LazyMapMonoid{pub fn new(len:usize)->Self{let n=len.next_power_of_two();let seg=vec![M::agg_unit();2*n];let lazy=vec![M::act_unit();n];Self{len,n,seg,lazy}}pub fn from_vec(v:Vec>)->Self{let len=v.len();let n=len.next_power_of_two();let mut seg=vec![M::agg_unit();2*n];for(i,x)in v.into_iter().enumerate(){seg[i+n]=x;}for i in(1..n).rev(){seg[i]=M::agg_operate(&seg[2*i],&seg[2*i+1]);}let lazy=vec![M::act_unit();n];Self{len,n,seg,lazy}}pub fn from_keys(keys:impl ExactSizeIterator)->Self{let len=keys.len();let n=len.next_power_of_two();let mut seg=vec![M::agg_unit();2*n];for(i,key)in keys.enumerate(){seg[i+n]=M::single_agg(&key);}for i in(1..n).rev(){seg[i]=M::agg_operate(&seg[2*i],&seg[2*i+1]);}let lazy=vec![M::act_unit();n];Self{len,n,seg,lazy}}#[inline]fn update_at(&mut self,k:usize,x:&LazyMapAct){if M::is_act_unit(x){return;}let nx=M::act_agg(&self.seg[k],x);if k>i);}}#[inline]fn recalc(&mut self,mut k:usize){while k>1{k>>=1;self.recalc_at(k);}}pub fn update(&mut self,range:R,x:LazyMapAct)where R:RangeBounds{let range=range.to_range_bounded(0,self.len).expect("invalid range");if range.is_empty()||M::is_act_unit(&x){return;}let mut a=range.start+self.n;let mut b=range.end+self.n;for i in(1..=self.n.trailing_zeros()).rev(){if(a>>i)<>i);}if(b>>i)<>i);}}while a>i)<>i);}if(b>>i)<>i);}}}pub fn fold(&mut self,range:R)->LazyMapAggwhere R:RangeBounds{let range=range.to_range_bounded(0,self.len).expect("invalid range");if range.is_empty(){return M::agg_unit();}if let Some(result)=(| |{let mut left_index=range.start+self.n-1;let mut right_index=range.end+self.n;let mut left=M::agg_unit();let mut right=M::agg_unit();let mut has_left=false;let mut has_right=false;for _ in 0..(left_index^right_index).ilog2(){if left_index&1==0{left=M::agg_operate(&left,&self.seg[left_index^1]);has_left=true;}if right_index&1!=0{right=M::agg_operate(&self.seg[right_index^1],&right);has_right=true;}left_index>>=1;right_index>>=1;if has_left{left=M::act_agg(&left,&self.lazy[left_index])?;}if has_right&&right_index1{left_index>>=1;result=M::act_agg(&result,&self.lazy[left_index])?;}Some(result)})(){return result;}let mut l=range.start+self.n;let mut r=range.end+self.n;self.propagate(l);self.propagate(r-1);let mut vl=M::agg_unit();let mut vr=M::agg_unit();while l){assert!(kLazyMapAgg{self.fold(k..k+1)}pub fn fold_all(&self)->LazyMapAgg{self.seg[1].clone()}pub fn partition_point_acc

(&mut self,left:usize,mut pred:P)->usize where P:FnMut(&LazyMapAgg)->bool{let mut acc=M::agg_unit();if left==self.len{return self.len;}let mut k=left+self.n;self.propagate(k);loop{while k&1==0{k>>=1;}let nacc=M::agg_operate(&acc,&self.seg[k]);if!pred(&nacc){while k(&mut self,right:usize,mut pred:P)->usize where P:FnMut(&LazyMapAgg)->bool{let mut acc=M::agg_unit();if right==0{return 0;}let mut k=right+self.n;self.propagate(k-1);loop{k-=1;while k>1&&k&1!=0{k>>=1;}let nacc=M::agg_operate(&self.seg[k],&acc);if!pred(&nacc){while kwhere T:Clone+Zero+Add+One+Mul{_marker:PhantomDataT>}implLinearOperationwhere T:Clone+Zero+Add+One+Mul{pub fn apply(f:&(T,T),x:&T)->T{f.0 .clone()*x.clone()+f.1 .clone()}}implMagma for LinearOperationwhere T:Clone+Zero+One+Add+Mul{type T=(T,T);#[inline]fn operate(x:&Self::T,y:&Self::T)->Self::T{(y.0 .clone()*x.0 .clone(),y.0 .clone()*x.1 .clone()+y.1 .clone())}}implUnital for LinearOperationwhere T:Clone+Zero+One+Add+Mul{#[inline]fn unit()->Self::T{(One::one(),Zero::zero())}}implAssociative for LinearOperationwhere T:Clone+Zero+One+Add+Mul{}implInvertible for LinearOperationwhere T:Clone+Zero+One+Add+Sub+Neg+Mul+Div{fn inverse(x:&Self::T)->Self::T{let y=::one().div(x.0 .clone());(y.clone(),-y.mul(x.1 .clone()))}}} // codesnip-guard: MaxOperation #[cfg_attr(any(),rustfmt::skip)]pub use self::max_operation_impl::MaxOperation;#[cfg_attr(any(),rustfmt::skip)]mod max_operation_impl{use super::*;use std::marker::PhantomData;#[doc=" binary operation to select larger element"]pub struct MaxOperationwhere T:Clone+Ord+Bounded{_marker:PhantomDataT>}implMagma for MaxOperationwhere T:Clone+Ord+Bounded{type T=T;#[inline]fn operate(x:&Self::T,y:&Self::T)->Self::T{x.max(y).clone()}}implUnital for MaxOperationwhere T:Clone+Ord+Bounded{#[inline]fn unit()->Self::T{::minimum()}}implAssociative for MaxOperationwhere T:Clone+Ord+Bounded{}implCommutative for MaxOperationwhere T:Clone+Ord+Bounded{}implIdempotent for MaxOperationwhere T:Clone+Ord+Bounded{}} // codesnip-guard: MinOperation #[cfg_attr(any(),rustfmt::skip)]pub use self::min_operation_impl::MinOperation;#[cfg_attr(any(),rustfmt::skip)]mod min_operation_impl{use super::*;use std::marker::PhantomData;#[doc=" binary operation to select smaller element"]pub struct MinOperationwhere T:Clone+Ord+Bounded{_marker:PhantomDataT>}implMagma for MinOperationwhere T:Clone+Ord+Bounded{type T=T;#[inline]fn operate(x:&Self::T,y:&Self::T)->Self::T{x.min(y).clone()}}implUnital for MinOperationwhere T:Clone+Ord+Bounded{#[inline]fn unit()->Self::T{::maximum()}}implAssociative for MinOperationwhere T:Clone+Ord+Bounded{}implCommutative for MinOperationwhere T:Clone+Ord+Bounded{}implIdempotent for MinOperationwhere T:Clone+Ord+Bounded{}} // codesnip-guard: MonoidAct #[cfg_attr(any(),rustfmt::skip)]pub use self::action::*;#[cfg_attr(any(),rustfmt::skip)]mod action{use super::*;use std::{marker::PhantomData,ops::{Add,Mul}};pub trait MonoidAct{type Key;type Act:Clone;type ActMonoid:Monoid;fn act(x:&Self::Key,a:&Self::Act)->Self::Key;fn act_assign(x:&mut Self::Key,a:&Self::Act){*x=Self::act(x,a);}fn unit()->Self::Act{::unit()}fn operate(x:&Self::Act,y:&Self::Act)->Self::Act{::operate(x,y)}fn operate_assign(x:&mut Self::Act,y:&Self::Act){*x=::operate(x,y);}}pub struct EmptyAct{_marker:PhantomDataT>}implMonoidAct for EmptyActwhere T:Clone{type Key=T;type Act=();type ActMonoid=();fn act(x:&Self::Key,_a:&Self::Act)->Self::Key{x.clone()}}pub struct FlattenAct{_marker:PhantomDataM>}implMonoidAct for FlattenActwhere M:Monoid{type Key=M::T;type Act=M::T;type ActMonoid=M;fn act(x:&Self::Key,a:&Self::Act)->Self::Key{M::operate(x,a)}}pub struct LinearAct{_marker:PhantomDataT>}implMonoidAct for LinearActwhere T:Clone+Zero+One+Add+Mul{type Key=T;type Act=(T,T);type ActMonoid=LinearOperation;fn act(x:&Self::Key,(a,b):&Self::Act)->Self::Key{a.clone()*x.clone()+b.clone()}}pub struct UpdateAct{_marker:PhantomDataT>}implMonoidAct for UpdateActwhere T:Clone{type Key=T;type Act=Option;type ActMonoid=LastOperation;fn act(x:&Self::Key,a:&Self::Act)->Self::Key{a.as_ref().unwrap_or(x).clone()}}} // codesnip-guard: StaticSearch #[cfg_attr(any(),rustfmt::skip)]pub use self::static_search::{SimdKey,StaticSearch};#[cfg_attr(any(),rustfmt::skip)]mod static_search{use super::SimdBackend;#[cfg(target_arch="x86_64")]use super::{avx512_enabled,simd};use std::{marker::PhantomData,ops::Range};#[inline]fn static_search_backend(bits:u32)->SimdBackend{#[cfg(target_arch="x86_64")]{if avx512_enabled()&&is_x86_feature_detected!("avx512f")&&(bits!=16||is_x86_feature_detected!("avx512bw")){return SimdBackend::Avx512;}if is_x86_feature_detected!("avx2"){return SimdBackend::Avx2;}}let _=bits;SimdBackend::Scalar}#[doc=" Maps a key to an unsigned integer with exactly the same ordering."]#[doc=""]#[doc=" `BITS` must be 8, 16, 32, 64, or 128. `encode` must be deterministic, fit in"]#[doc=" `BITS`, and satisfy `a.cmp(&b) == a.encode().cmp(&b.encode())`."]pub trait SimdKey:Copy+Ord{const BITS:u32;fn encode(self)->u128;}macro_rules!impl_unsigned_simd_key{($($value:ty),*$(,)?)=>{$(impl SimdKey for$value{const BITS:u32=<$value>::BITS;#[inline(always)]fn encode(self)->u128{self as u128}})*};}macro_rules!impl_signed_simd_key{($(($signed:ty,$unsigned:ty)),*$(,)?)=>{$(impl SimdKey for$signed{const BITS:u32=<$signed>::BITS;#[inline(always)]fn encode(self)->u128{((self as$unsigned)^((1 as$unsigned)<<(<$signed>::BITS-1)))as u128}})*};}impl_unsigned_simd_key!(u8,u16,u32,u64,u128,usize);impl_signed_simd_key!((i8,u8),(i16,u16),(i32,u32),(i64,u64),(i128,u128),(isize,usize),);#[derive(Clone,Debug)]enum DirectStaticSearch{U16(Vec),U32(Vec)}impl DirectStaticSearch{fn build(values:&[K],bits:u32)->Self{assert!(values.len()<=u32::MAX as usize);if values.len()<=u16::MAX as usize{Self::U16(build_direct_positions(values,bits,|position|{position as u16}))}else{Self::U32(build_direct_positions(values,bits,|position|{position as u32}))}}#[inline(always)]fn lower_bound(&self,value:u128)->usize{let value=usize::try_from(value).expect("SimdKey::encode exceeds usize");match self{Self::U16(positions)=>positions[value]as usize,Self::U32(positions)=>positions[value]as usize,}}#[inline(always)]fn upper_bound(&self,value:u128)->usize{let value=usize::try_from(value).ok().and_then(|value|value.checked_add(1)).expect("SimdKey::encode exceeds usize");match self{Self::U16(positions)=>positions[value]as usize,Self::U32(positions)=>positions[value]as usize,}}#[inline(always)]fn contains(&self,value:u128)->bool{let value=usize::try_from(value).ok().and_then(|value|value.checked_add(1).map(|next|(value,next))).expect("SimdKey::encode exceeds usize");match self{Self::U16(positions)=>positions[value.0]!=positions[value.1],Self::U32(positions)=>positions[value.0]!=positions[value.1],}}}fn build_direct_positions(values:&[K],bits:u32,position:impl Fn(usize)->P)->Vec

where K:SimdKey,P:Copy{let len=(1<=None;for(index,&value)in values.iter().enumerate(){let encoded=value.encode();assert!(encoded<=maximum,"SimdKey::encode exceeds its declared width");if let Some((previous_value,previous_encoded))=previous{assert_eq!(previous_value.cmp(&value),previous_encoded.cmp(&encoded),"SimdKey::encode does not preserve order");}if previous.is_none_or(|(_,previous)|previous!=encoded){positions.resize(encoded as usize+1,position(index));}previous=Some((value,encoded));}positions.resize(len,position(values.len()));positions}macro_rules!bound_batch{(lower,$this:ident,$values:ident,$search:expr)=>{{if$this.len==0{return[0;16];}let mut$values=*$values;let mut beyond=[false;16];for index in 0..16{beyond[index]=$values[index]>$this.maximum;$values[index]=$values[index].min($this.maximum);}let mut result=$search;for index in 0..16{if beyond[index]{result[index]=$this.len;}}result}};(upper,$this:ident,$values:ident,$search:expr)=>{{if$this.len==0{return[0;16];}let mut$values=*$values;let mut beyond=[false;16];for index in 0..16{beyond[index]=$values[index]>=$this.maximum;}let Some(value)=$values.iter().copied().find(|&value|value<$this.maximum)else{return[$this.len;16];};for index in 0..16{if beyond[index]{$values[index]=value;}}let mut result=$search;for index in 0..16{if beyond[index]{result[index]=$this.len;}}result}};}#[repr(C,align(64))]#[derive(Clone,Debug)]struct SearchBlock([T;B]);#[derive(Clone,Debug)]struct StaticSearchTree{values:Vec>,len:usize,maximum:T,levels:Vec>>,#[cfg(target_arch="x86_64")]backend:SimdBackend}implStaticSearchTree{fn build(values:&[K],sentinel:T,maximum_encoded:u128,convert:impl Fn(u128)->T,backend:SimdBackend)->Self where K:SimdKey{let _=&backend;let len=values.len();let mut previous:Option<(K,T)>=None;let mut separators=Vec::with_capacity(values.len().div_ceil(B));let mut blocks=Vec::with_capacity(separators.capacity());for chunk in values.chunks(B){let mut block=[sentinel;B];for(index,&value)in chunk.iter().enumerate(){let encoded=value.encode();assert!(encoded<=maximum_encoded,"SimdKey::encode exceeds its declared width");let encoded=convert(encoded);if let Some((previous_value,previous_encoded))=previous{assert!(previous_value.cmp(&value)==previous_encoded.cmp(&encoded),"SimdKey::encode does not preserve order");}previous=Some((value,encoded));block[index]=encoded;}separators.push(block[chunk.len()-1]);blocks.push(SearchBlock(block));}let maximum=separators.last().copied().unwrap_or(sentinel);let mut levels=Vec::new();while separators.len()>1{let mut blocks=Vec::with_capacity(separators.len().div_ceil(B));let mut next=Vec::with_capacity(blocks.capacity());for chunk in separators.chunks(B){let mut block=[sentinel;B];block[..chunk.len()].copy_from_slice(chunk);blocks.push(SearchBlock(block));next.push(chunk[chunk.len()-1]);}levels.push(blocks);separators=next;}Self{values:blocks,len,maximum,levels,#[cfg(target_arch="x86_64")]backend}}#[inline(always)]fn descend(&self,value:T,mut position:F)->usize where F:FnMut(&[T;B],T)->usize{let mut block=0;for level in self.levels.iter().rev(){let values=&unsafe{level.get_unchecked(block)}.0;block=block*B+position(values,value);}let values=&unsafe{self.values.get_unchecked(block)}.0;(block*B+position(values,value)).min(self.len)}#[inline(always)]fn get(&self,index:usize)->T{unsafe{*self.values.get_unchecked(index/B).0 .get_unchecked(index%B)}}#[inline(always)]fn descend_batch(&self,values:&[T;16],mut position:F)->[usize;16]where F:FnMut(&[T;B],T)->usize{let mut blocks=[0;16];for level in self.levels.iter().rev(){for index in 0..16{let block_values=&unsafe{level.get_unchecked(blocks[index])}.0;blocks[index]=blocks[index]*B+position(block_values,values[index]);}}for index in 0..16{let block=blocks[index];let block_values=&unsafe{self.values.get_unchecked(block)}.0;blocks[index]=(block*B+position(block_values,values[index])).min(self.len);}blocks}#[inline(always)]fn lower_bound_scalar(&self,value:T)->usize{self.descend(value,|values,value|{values.partition_point(|¤t|currentusize{self.descend(value,|values,value|{values.partition_point(|¤t|current<=value)})}#[inline(always)]fn lower_bound_batch_scalar(&self,values:&[T;16])->[usize;16]{self.descend_batch(values,|values,value|{values.partition_point(|¤t|current[usize;16]{self.descend_batch(values,|values,value|{values.partition_point(|¤t|current<=value)})}}macro_rules!impl_static_search_tree{($value:ty,$branch:expr,$first_ge_avx2:ident,$first_gt_avx2:ident,$first_ge_avx512:ident,$first_gt_avx512:ident,$avx512_features:literal)=>{impl StaticSearchTree<$value,$branch>{#[inline]fn lower_bound(&self,value:$value)->usize{if self.len==0||value>self.maximum{return self.len;}#[cfg(target_arch="x86_64")]return match self.backend{SimdBackend::Scalar=>self.lower_bound_scalar(value),SimdBackend::Avx2=>unsafe{self.lower_bound_avx2(value)},SimdBackend::Avx512=>unsafe{self.lower_bound_avx512(value)},};#[cfg(not(target_arch="x86_64"))]self.lower_bound_scalar(value)}#[inline]fn upper_bound(&self,value:$value)->usize{if self.len==0{return 0;}if value>=self.maximum{return self.len;}#[cfg(target_arch="x86_64")]return match self.backend{SimdBackend::Scalar=>self.upper_bound_scalar(value),SimdBackend::Avx2=>unsafe{self.upper_bound_avx2(value)},SimdBackend::Avx512=>unsafe{self.upper_bound_avx512(value)},};#[cfg(not(target_arch="x86_64"))]self.upper_bound_scalar(value)}#[inline]fn contains(&self,value:$value)->bool{let index=self.lower_bound(value);index[usize;16]{#[cfg(target_arch="x86_64")]if self.backend==SimdBackend::Avx512{return unsafe{self.lower_bound_batch_avx512(values)};}bound_batch!(lower,self,values,{#[cfg(target_arch="x86_64")]let result=if self.backend==SimdBackend::Avx2{unsafe{self.lower_bound_batch_avx2(&values)}}else{self.lower_bound_batch_scalar(&values)};#[cfg(not(target_arch="x86_64"))]let result=self.lower_bound_batch_scalar(&values);result})}#[inline]fn upper_bound_batch(&self,values:&[$value;16])->[usize;16]{#[cfg(target_arch="x86_64")]if self.backend==SimdBackend::Avx512{return unsafe{self.upper_bound_batch_avx512(values)};}bound_batch!(upper,self,values,{#[cfg(target_arch="x86_64")]let result=if self.backend==SimdBackend::Avx2{unsafe{self.upper_bound_batch_avx2(&values)}}else{self.upper_bound_batch_scalar(&values)};#[cfg(not(target_arch="x86_64"))]let result=self.upper_bound_batch_scalar(&values);result})}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx2")]unsafe fn lower_bound_avx2(&self,value:$value)->usize{self.descend(value,|values,value|unsafe{simd::$first_ge_avx2(values,value)})}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx2")]unsafe fn upper_bound_avx2(&self,value:$value)->usize{self.descend(value,|values,value|unsafe{simd::$first_gt_avx2(values,value)})}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx2")]unsafe fn lower_bound_batch_avx2(&self,values:&[$value;16])->[usize;16]{self.descend_batch(values,|values,value|unsafe{simd::$first_ge_avx2(values,value)})}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx2")]unsafe fn upper_bound_batch_avx2(&self,values:&[$value;16])->[usize;16]{self.descend_batch(values,|values,value|unsafe{simd::$first_gt_avx2(values,value)})}#[cfg(target_arch="x86_64")]#[target_feature(enable=$avx512_features)]unsafe fn lower_bound_avx512(&self,value:$value)->usize{self.descend(value,|values,value|unsafe{simd::$first_ge_avx512(values,value)})}#[cfg(target_arch="x86_64")]#[target_feature(enable=$avx512_features)]unsafe fn upper_bound_avx512(&self,value:$value)->usize{self.descend(value,|values,value|unsafe{simd::$first_gt_avx512(values,value)})}#[cfg(target_arch="x86_64")]#[target_feature(enable=$avx512_features)]unsafe fn lower_bound_batch_avx512(&self,values:&[$value;16])->[usize;16]{bound_batch!(lower,self,values,self.descend_batch(&values,|values,value|unsafe{simd::$first_ge_avx512(values,value)}))}#[cfg(target_arch="x86_64")]#[target_feature(enable=$avx512_features)]unsafe fn upper_bound_batch_avx512(&self,values:&[$value;16])->[usize;16]{bound_batch!(upper,self,values,self.descend_batch(&values,|values,value|unsafe{simd::$first_gt_avx512(values,value)}))}}};}impl_static_search_tree!(u16,32,first_ge_u16x32_avx2,first_gt_u16x32_avx2,first_ge_u16x32_avx512,first_gt_u16x32_avx512,"avx512f,avx512bw");impl_static_search_tree!(u32,16,first_ge_u32x16_avx2,first_gt_u32x16_avx2,first_ge_u32x16_avx512,first_gt_u32x16_avx512,"avx512f");impl_static_search_tree!(u64,8,first_ge_u64x8_avx2,first_gt_u64x8_avx2,first_ge_u64x8_avx512,first_gt_u64x8_avx512,"avx512f");impl StaticSearchTree{#[inline]fn lower_bound(&self,value:u128)->usize{if self.len==0||value>self.maximum{self.len}else{self.descend(value,|values,value|{(values[0]usize{if self.len==0||value>=self.maximum{self.len}else{self.descend(value,|values,value|{(values[0]<=value)as usize+(values[1]<=value)as usize+(values[2]<=value)as usize+(values[3]<=value)as usize})}}#[inline]fn contains(&self,value:u128)->bool{let index=self.lower_bound(value);index[usize;16]{bound_batch!(lower,self,values,self.descend_batch(&values,|values,value|{(values[0][usize;16]{bound_batch!(upper,self,values,self.descend_batch(&values,|values,value|{(values[0]<=value)as usize+(values[1]<=value)as usize+(values[2]<=value)as usize+(values[3]<=value)as usize}))}}fn search_batch(values:&[K],output:&mut[usize],convert:impl Fn(u128)->T,single:impl Fn(T)->usize,batch:impl Fn(&[T;16])->[usize;16])where K:SimdKey,T:Copy{let mut offset=0;while offset+16<=values.len(){let values=std::array::from_fn(|index|convert(values[offset+index].encode()));output[offset..offset+16].copy_from_slice(&batch(&values));offset+=16;}let remaining=values.len()-offset;if remaining>=8{let mut encoded=[convert(values[offset].encode());16];for index in 1..remaining{encoded[index]=convert(values[offset+index].encode());}let positions=batch(&encoded);output[offset..].copy_from_slice(&positions[..remaining]);}else{for(&value,position)in values[offset..].iter().zip(&mut output[offset..]){*position=single(convert(value.encode()));}}}#[derive(Clone,Debug)]enum StaticSearchStorage{Direct(DirectStaticSearch),U16(StaticSearchTree),U32(StaticSearchTree),U64(StaticSearchTree),U128(StaticSearchTree)}impl StaticSearchStorage{#[inline(always)]fn lower_bound(&self,value:u128)->usize{match self{Self::Direct(search)=>search.lower_bound(value),Self::U16(search)=>search.lower_bound(u16::try_from(value).expect("SimdKey::encode exceeds its declared width")),Self::U32(search)=>search.lower_bound(u32::try_from(value).expect("SimdKey::encode exceeds its declared width")),Self::U64(search)=>search.lower_bound(u64::try_from(value).expect("SimdKey::encode exceeds its declared width")),Self::U128(search)=>search.lower_bound(value),}}#[inline(always)]fn upper_bound(&self,value:u128)->usize{match self{Self::Direct(search)=>search.upper_bound(value),Self::U16(search)=>search.upper_bound(u16::try_from(value).expect("SimdKey::encode exceeds its declared width")),Self::U32(search)=>search.upper_bound(u32::try_from(value).expect("SimdKey::encode exceeds its declared width")),Self::U64(search)=>search.upper_bound(u64::try_from(value).expect("SimdKey::encode exceeds its declared width")),Self::U128(search)=>search.upper_bound(value),}}#[inline(always)]fn contains(&self,value:u128)->bool{match self{Self::Direct(search)=>search.contains(value),Self::U16(search)=>search.contains(u16::try_from(value).expect("SimdKey::encode exceeds its declared width")),Self::U32(search)=>search.contains(u32::try_from(value).expect("SimdKey::encode exceeds its declared width")),Self::U64(search)=>search.contains(u64::try_from(value).expect("SimdKey::encode exceeds its declared width")),Self::U128(search)=>search.contains(value),}}fn lower_bound_batch(&self,values:&[K],output:&mut[usize]){match self{Self::Direct(search)=>{for(&value,position)in values.iter().zip(output){*position=search.lower_bound(value.encode());}}Self::U16(search)=>search_batch(values,output,|value|u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),|value|search.lower_bound(value),|values|search.lower_bound_batch(values)),Self::U32(search)=>search_batch(values,output,|value|u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),|value|search.lower_bound(value),|values|search.lower_bound_batch(values)),Self::U64(search)=>search_batch(values,output,|value|u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),|value|search.lower_bound(value),|values|search.lower_bound_batch(values)),Self::U128(search)=>search_batch(values,output,|value|value,|value|search.lower_bound(value),|values|search.lower_bound_batch(values)),}}fn upper_bound_batch(&self,values:&[K],output:&mut[usize]){match self{Self::Direct(search)=>{for(&value,position)in values.iter().zip(output){*position=search.upper_bound(value.encode());}}Self::U16(search)=>search_batch(values,output,|value|u16::try_from(value).expect("SimdKey::encode exceeds its declared width"),|value|search.upper_bound(value),|values|search.upper_bound_batch(values)),Self::U32(search)=>search_batch(values,output,|value|u32::try_from(value).expect("SimdKey::encode exceeds its declared width"),|value|search.upper_bound(value),|values|search.upper_bound_batch(values)),Self::U64(search)=>search_batch(values,output,|value|u64::try_from(value).expect("SimdKey::encode exceeds its declared width"),|value|search.upper_bound(value),|values|search.upper_bound_batch(values)),Self::U128(search)=>search_batch(values,output,|value|value,|value|search.upper_bound(value),|values|search.upper_bound_batch(values)),}}}#[doc=" A static search index over sorted integer or integer-encoded keys."]#[doc=""]#[doc=" The index adds build time and storage. For a small number of searches, search the sorted slice"]#[doc=" directly instead."]#[derive(Clone,Debug)]pub struct StaticSearch{storage:StaticSearchStorage,len:usize,marker:PhantomDataK>}implStaticSearch{#[doc=" Builds an index over sorted `values`."]#[doc=""]#[doc=" # Panics"]#[doc=""]#[doc=" Panics if `values` is not sorted or `SimdKey` does not satisfy its contract."]pub fn from_sorted(values:&[K])->Self{Self::build(values,static_search_backend(K::BITS),false)}#[doc=" Builds a direct lookup table over sorted 8-bit or 16-bit `values`."]#[doc=""]#[doc=" This layout uses a fixed table of 257 or 65,537 positions and is intended"]#[doc=" for query-heavy workloads."]#[doc=""]#[doc=" # Panics"]#[doc=""]#[doc=" Panics if `K::BITS` is neither 8 nor 16, or if `values` is not sorted."]pub fn from_sorted_direct(values:&[K])->Self{assert!(matches!(K::BITS,8|16));Self::build(values,static_search_backend(K::BITS),true)}#[inline]pub fn len(&self)->usize{self.len}#[inline]pub fn is_empty(&self)->bool{self.len==0}#[doc=" Returns the first index whose value is greater than or equal to `value`."]#[inline]pub fn lower_bound(&self,value:K)->usize{self.storage.lower_bound(value.encode())}#[doc=" Returns one past the last index whose value is less than or equal to `value`."]#[inline]pub fn upper_bound(&self,value:K)->usize{self.storage.upper_bound(value.encode())}#[doc=" Writes the first index greater than or equal to each value into `output`."]#[doc=""]#[doc=" # Panics"]#[doc=""]#[doc=" Panics if `values` and `output` have different lengths."]pub fn lower_bound_batch(&self,values:&[K],output:&mut[usize]){assert_eq!(values.len(),output.len());self.storage.lower_bound_batch(values,output);}#[doc=" Writes one past the last index less than or equal to each value into `output`."]#[doc=""]#[doc=" # Panics"]#[doc=""]#[doc=" Panics if `values` and `output` have different lengths."]pub fn upper_bound_batch(&self,values:&[K],output:&mut[usize]){assert_eq!(values.len(),output.len());self.storage.upper_bound_batch(values,output);}#[inline]pub fn range(&self,value:K)->Range{let value=value.encode();self.storage.lower_bound(value)..self.storage.upper_bound(value)}#[inline]pub fn contains(&self,value:K)->bool{self.storage.contains(value.encode())}fn build(values:&[K],backend:SimdBackend,direct:bool)->Self{assert!(matches!(K::BITS,8|16|32|64|128));assert!(values.windows(2).all(|pair|pair[0]<=pair[1]));let len=values.len();let storage=match K::BITS{8=>StaticSearchStorage::Direct(DirectStaticSearch::build(values,K::BITS)),16=>{if direct{StaticSearchStorage::Direct(DirectStaticSearch::build(values,K::BITS))}else{StaticSearchStorage::U16(StaticSearchTree::build(values,u16::MAX,u16::MAX as u128,|value|value as u16,backend))}}32=>StaticSearchStorage::U32(StaticSearchTree::build(values,u32::MAX,u32::MAX as u128,|value|value as u32,backend)),64=>StaticSearchStorage::U64(StaticSearchTree::build(values,u64::MAX,u64::MAX as u128,|value|value as u64,backend)),128=>StaticSearchStorage::U128(StaticSearchTree::build(values,u128::MAX,u128::MAX,|value|value,backend)),_=>unreachable!(),};Self{storage,len,marker:PhantomData}}}} // codesnip-guard: TupleOperation #[cfg_attr(any(),rustfmt::skip)]mod tuple_operation_impl{use super::*;macro_rules!impl_tuple_operation{(@impl)=>{impl Magma for(){type T=();fn operate(_x:&Self::T,_y:&Self::T)->Self::T{}}impl Unital for(){fn unit()->Self::T{}}impl Associative for(){}impl Commutative for(){}impl Idempotent for(){}impl Invertible for(){fn inverse(_x:&Self::T)->Self::T{}}};(@impl$($T:ident$i:tt)*)=>{impl<$($T:Magma),*>Magma for($($T,)*){type T=($(<$T as Magma>::T,)*);fn operate(x:&Self::T,y:&Self::T)->Self::T{($(<$T as Magma>::operate(&x.$i,&y.$i),)*)}}impl<$($T:Unital),*>Unital for($($T,)*){fn unit()->Self::T{($(<$T as Unital>::unit(),)*)}}impl<$($T:Associative),*>Associative for($($T,)*){}impl<$($T:Commutative),*>Commutative for($($T,)*){}impl<$($T:Idempotent),*>Idempotent for($($T,)*){}impl<$($T:Invertible),*>Invertible for($($T,)*){fn inverse(x:&Self::T)->Self::T{($(<$T as Invertible>::inverse(&x.$i),)*)}}};(@inner$($T:ident$i:tt)*;$U:ident$j:tt$($t:tt)*)=>{impl_tuple_operation!(@impl$($T$i)*);impl_tuple_operation!(@inner$($T$i)*$U$j;$($t)*);};(@inner$($T:ident$i:tt)*;)=>{impl_tuple_operation!(@impl$($T$i)*);};($($t:tt)*)=>{impl_tuple_operation!(@inner;$($t)*);};}impl_tuple_operation!(A 0 B 1 C 2 D 3 E 4 F 5 G 6 H 7 I 8 J 9);} // codesnip-guard: _simd #[cfg_attr(any(),rustfmt::skip)]pub mod simd{#![allow(unsafe_op_in_unsafe_fn)]#[cfg(target_arch="x86_64")]use std::arch::x86_64::*;#[cfg(target_arch="x86_64")]#[target_feature(enable="avx2")]#[inline]pub unsafe fn first_ge_u16x32_avx2(values:&[u16;32],key:u16)->usize{let sign=_mm256_set1_epi16(i16::MIN);let key=_mm256_xor_si256(_mm256_set1_epi16(key as i16),sign);let low=_mm256_xor_si256(_mm256_loadu_si256(values.as_ptr().cast()),sign);let high=_mm256_xor_si256(_mm256_loadu_si256(values.as_ptr().add(16).cast()),sign);let low=_mm256_movemask_epi8(_mm256_cmpgt_epi16(key,low))as u32 as u64;let high=_mm256_movemask_epi8(_mm256_cmpgt_epi16(key,high))as u32 as u64;(!(low|high<<32)).trailing_zeros()as usize/2}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx2")]#[inline]pub unsafe fn first_gt_u16x32_avx2(values:&[u16;32],key:u16)->usize{let sign=_mm256_set1_epi16(i16::MIN);let key=_mm256_xor_si256(_mm256_set1_epi16(key as i16),sign);let low=_mm256_xor_si256(_mm256_loadu_si256(values.as_ptr().cast()),sign);let high=_mm256_xor_si256(_mm256_loadu_si256(values.as_ptr().add(16).cast()),sign);let low=_mm256_movemask_epi8(_mm256_cmpgt_epi16(low,key))as u32 as u64;let high=_mm256_movemask_epi8(_mm256_cmpgt_epi16(high,key))as u32 as u64;(low|high<<32).trailing_zeros()as usize/2}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx2")]#[inline]pub unsafe fn first_ge_u32x16_avx2(values:&[u32;16],key:u32)->usize{let sign=_mm256_set1_epi32(i32::MIN);let key=_mm256_xor_si256(_mm256_set1_epi32(key as i32),sign);let low=_mm256_xor_si256(_mm256_loadu_si256(values.as_ptr().cast()),sign);let high=_mm256_xor_si256(_mm256_loadu_si256(values.as_ptr().add(8).cast()),sign);let low=_mm256_movemask_ps(_mm256_castsi256_ps(_mm256_cmpgt_epi32(key,low)));let high=_mm256_movemask_ps(_mm256_castsi256_ps(_mm256_cmpgt_epi32(key,high)));let mask=((!low as u32)&0xff)|(((!high as u32)&0xff)<<8);(mask as u16).trailing_zeros()as usize}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx2")]#[inline]pub unsafe fn first_gt_u32x16_avx2(values:&[u32;16],key:u32)->usize{let sign=_mm256_set1_epi32(i32::MIN);let key=_mm256_xor_si256(_mm256_set1_epi32(key as i32),sign);let low=_mm256_xor_si256(_mm256_loadu_si256(values.as_ptr().cast()),sign);let high=_mm256_xor_si256(_mm256_loadu_si256(values.as_ptr().add(8).cast()),sign);let low=_mm256_movemask_ps(_mm256_castsi256_ps(_mm256_cmpgt_epi32(low,key)));let high=_mm256_movemask_ps(_mm256_castsi256_ps(_mm256_cmpgt_epi32(high,key)));let mask=low as u32|((high as u32)<<8);(mask as u16).trailing_zeros()as usize}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx2")]#[inline]pub unsafe fn first_ge_u64x8_avx2(values:&[u64;8],key:u64)->usize{let sign=_mm256_set1_epi64x(i64::MIN);let key=_mm256_xor_si256(_mm256_set1_epi64x(key as i64),sign);let low=_mm256_xor_si256(_mm256_loadu_si256(values.as_ptr().cast()),sign);let high=_mm256_xor_si256(_mm256_loadu_si256(values.as_ptr().add(4).cast()),sign);let low=_mm256_movemask_pd(_mm256_castsi256_pd(_mm256_cmpgt_epi64(key,low)));let high=_mm256_movemask_pd(_mm256_castsi256_pd(_mm256_cmpgt_epi64(key,high)));let mask=((!low as u32)&0x0f)|(((!high as u32)&0x0f)<<4);(mask as u8).trailing_zeros()as usize}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx2")]#[inline]pub unsafe fn first_gt_u64x8_avx2(values:&[u64;8],key:u64)->usize{let sign=_mm256_set1_epi64x(i64::MIN);let key=_mm256_xor_si256(_mm256_set1_epi64x(key as i64),sign);let low=_mm256_xor_si256(_mm256_loadu_si256(values.as_ptr().cast()),sign);let high=_mm256_xor_si256(_mm256_loadu_si256(values.as_ptr().add(4).cast()),sign);let low=_mm256_movemask_pd(_mm256_castsi256_pd(_mm256_cmpgt_epi64(low,key)));let high=_mm256_movemask_pd(_mm256_castsi256_pd(_mm256_cmpgt_epi64(high,key)));let mask=low as u32|((high as u32)<<4);(mask as u8).trailing_zeros()as usize}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx512f,avx512bw")]#[inline]pub unsafe fn first_ge_u16x32_avx512(values:&[u16;32],key:u16)->usize{let values=_mm512_loadu_si512(values.as_ptr().cast());let key=_mm512_set1_epi16(key as i16);(!_mm512_cmplt_epu16_mask(values,key)).trailing_zeros()as usize}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx512f,avx512bw")]#[inline]pub unsafe fn first_gt_u16x32_avx512(values:&[u16;32],key:u16)->usize{let values=_mm512_loadu_si512(values.as_ptr().cast());let key=_mm512_set1_epi16(key as i16);_mm512_cmpgt_epu16_mask(values,key).trailing_zeros()as usize}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx512f")]#[inline]pub unsafe fn first_ge_u32x16_avx512(values:&[u32;16],key:u32)->usize{let values=_mm512_loadu_si512(values.as_ptr().cast());let key=_mm512_set1_epi32(key as i32);(!_mm512_cmplt_epu32_mask(values,key)).trailing_zeros()as usize}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx512f")]#[inline]pub unsafe fn first_gt_u32x16_avx512(values:&[u32;16],key:u32)->usize{let values=_mm512_loadu_si512(values.as_ptr().cast());let key=_mm512_set1_epi32(key as i32);_mm512_cmpgt_epu32_mask(values,key).trailing_zeros()as usize}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx512f")]#[inline]pub unsafe fn first_ge_u64x8_avx512(values:&[u64;8],key:u64)->usize{let values=_mm512_loadu_si512(values.as_ptr().cast());let key=_mm512_set1_epi64(key as i64);(!_mm512_cmplt_epu64_mask(values,key)).trailing_zeros()as usize}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx512f")]#[inline]pub unsafe fn first_gt_u64x8_avx512(values:&[u64;8],key:u64)->usize{let values=_mm512_loadu_si512(values.as_ptr().cast());let key=_mm512_set1_epi64(key as i64);_mm512_cmpgt_epu64_mask(values,key).trailing_zeros()as usize}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx2")]#[inline]pub unsafe fn add_suffix_u32x16_avx2(values:&mut[u32;16],index:usize,delta:u32){let index=_mm256_set1_epi32(index as i32-1);let delta=_mm256_set1_epi32(delta as i32);let low_mask=_mm256_cmpgt_epi32(_mm256_setr_epi32(0,1,2,3,4,5,6,7),index);let high_mask=_mm256_cmpgt_epi32(_mm256_setr_epi32(8,9,10,11,12,13,14,15),index);let low=_mm256_add_epi32(_mm256_loadu_si256(values.as_ptr().cast()),_mm256_and_si256(delta,low_mask));let high=_mm256_add_epi32(_mm256_loadu_si256(values.as_ptr().add(8).cast()),_mm256_and_si256(delta,high_mask));_mm256_storeu_si256(values.as_mut_ptr().cast(),low);_mm256_storeu_si256(values.as_mut_ptr().add(8).cast(),high);}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx2")]#[inline]pub unsafe fn add_suffix_u64x8_avx2(values:&mut[u64;8],index:usize,delta:u64){let index=_mm256_set1_epi64x(index as i64-1);let delta=_mm256_set1_epi64x(delta as i64);let low_mask=_mm256_cmpgt_epi64(_mm256_setr_epi64x(0,1,2,3),index);let high_mask=_mm256_cmpgt_epi64(_mm256_setr_epi64x(4,5,6,7),index);let low=_mm256_add_epi64(_mm256_loadu_si256(values.as_ptr().cast()),_mm256_and_si256(delta,low_mask));let high=_mm256_add_epi64(_mm256_loadu_si256(values.as_ptr().add(4).cast()),_mm256_and_si256(delta,high_mask));_mm256_storeu_si256(values.as_mut_ptr().cast(),low);_mm256_storeu_si256(values.as_mut_ptr().add(4).cast(),high);}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx512f")]#[inline]pub unsafe fn add_suffix_u32x16_avx512(values:&mut[u32;16],index:usize,delta:u32){let values_vector=_mm512_loadu_si512(values.as_ptr().cast());let values_vector=_mm512_mask_add_epi32(values_vector,u16::MAX<usize{let low=_mm256_loadu_si256(values.as_ptr().cast());let high=_mm256_loadu_si256(values.as_ptr().add(8).cast());let mut maximum=_mm256_max_epu32(low,high);maximum=_mm256_max_epu32(maximum,_mm256_permute2x128_si256::<0x01>(maximum,maximum));maximum=_mm256_max_epu32(maximum,_mm256_shuffle_epi32::<0x4e>(maximum));maximum=_mm256_max_epu32(maximum,_mm256_shuffle_epi32::<0xb1>(maximum));let maximum=_mm256_set1_epi32(_mm256_extract_epi32::<0>(maximum));let low=_mm256_movemask_ps(_mm256_castsi256_ps(_mm256_cmpeq_epi32(low,maximum)));let high=_mm256_movemask_ps(_mm256_castsi256_ps(_mm256_cmpeq_epi32(high,maximum)));((low as u32|((high as u32)<<8))as u16).trailing_zeros()as usize}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx512f")]#[inline]pub unsafe fn max_index_u32x16_avx512(values:&[u32;16])->usize{let values=_mm512_loadu_si512(values.as_ptr().cast());let maximum=_mm512_set1_epi32(_mm512_reduce_max_epu32(values)as i32);_mm512_cmpeq_epi32_mask(values,maximum).trailing_zeros()as usize}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx2")]#[inline]unsafe fn max_epu64(left:__m256i,right:__m256i)->__m256i{let sign=_mm256_set1_epi64x(i64::MIN);let greater=_mm256_cmpgt_epi64(_mm256_xor_si256(left,sign),_mm256_xor_si256(right,sign));_mm256_blendv_epi8(right,left,greater)}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx2")]#[inline]pub unsafe fn max_index_u64x8_avx2(values:&[u64;8])->usize{let sign=_mm256_set1_epi64x(i64::MIN);let low=_mm256_xor_si256(_mm256_loadu_si256(values.as_ptr().cast()),sign);let high=_mm256_xor_si256(_mm256_loadu_si256(values.as_ptr().add(4).cast()),sign);let mut maximum=max_i64x4(low,high);maximum=max_i64x4(maximum,_mm256_permute4x64_epi64::<0x4e>(maximum));maximum=max_i64x4(maximum,_mm256_permute4x64_epi64::<0xb1>(maximum));let low=_mm256_movemask_pd(_mm256_castsi256_pd(_mm256_cmpeq_epi64(low,maximum)));let high=_mm256_movemask_pd(_mm256_castsi256_pd(_mm256_cmpeq_epi64(high,maximum)));((low as u32|((high as u32)<<4))as u8).trailing_zeros()as usize}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx512f")]#[inline]pub unsafe fn max_index_u64x8_avx512(values:&[u64;8])->usize{let values=_mm512_loadu_si512(values.as_ptr().cast());let maximum=_mm512_set1_epi64(_mm512_reduce_max_epu64(values)as i64);_mm512_cmpeq_epi64_mask(values,maximum).trailing_zeros()as usize}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx2")]#[inline]pub unsafe fn max_index_u128x4_avx2(low:&[u64;4],high:&[u64;4])->usize{let low=_mm256_loadu_si256(low.as_ptr().cast());let high=_mm256_loadu_si256(high.as_ptr().cast());let mut maximum_high=high;maximum_high=max_epu64(maximum_high,_mm256_permute4x64_epi64::<0x4e>(maximum_high));maximum_high=max_epu64(maximum_high,_mm256_permute4x64_epi64::<0xb1>(maximum_high));let high_equal=_mm256_cmpeq_epi64(high,maximum_high);let high_mask=_mm256_movemask_pd(_mm256_castsi256_pd(high_equal))as u32&15;if high_mask.is_power_of_two(){return high_mask.trailing_zeros()as usize;}let mut maximum_low=_mm256_and_si256(low,high_equal);maximum_low=max_epu64(maximum_low,_mm256_permute4x64_epi64::<0x4e>(maximum_low));maximum_low=max_epu64(maximum_low,_mm256_permute4x64_epi64::<0xb1>(maximum_low));let both=_mm256_and_si256(high_equal,_mm256_cmpeq_epi64(low,maximum_low));(_mm256_movemask_pd(_mm256_castsi256_pd(both))as u32&15).trailing_zeros()as usize}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx2,avx512f,avx512vl")]#[inline]pub unsafe fn max_index_u128x4_avx512(low:&[u64;4],high:&[u64;4])->usize{let low=_mm256_loadu_si256(low.as_ptr().cast());let high=_mm256_loadu_si256(high.as_ptr().cast());let mut maximum_high=high;maximum_high=_mm256_max_epu64(maximum_high,_mm256_permute4x64_epi64::<0x4e>(maximum_high));maximum_high=_mm256_max_epu64(maximum_high,_mm256_permute4x64_epi64::<0xb1>(maximum_high));let high_equal=_mm256_cmpeq_epi64(high,maximum_high);let high_mask=_mm256_movemask_pd(_mm256_castsi256_pd(high_equal))as u32&15;if high_mask.is_power_of_two(){return high_mask.trailing_zeros()as usize;}let mut maximum_low=_mm256_and_si256(low,high_equal);maximum_low=_mm256_max_epu64(maximum_low,_mm256_permute4x64_epi64::<0x4e>(maximum_low));maximum_low=_mm256_max_epu64(maximum_low,_mm256_permute4x64_epi64::<0xb1>(maximum_low));let both=_mm256_and_si256(high_equal,_mm256_cmpeq_epi64(low,maximum_low));(_mm256_movemask_pd(_mm256_castsi256_pd(both))as u32&15).trailing_zeros()as usize}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx2")]#[inline]unsafe fn reduce_min_i32x8(mut values:__m256i)->i32{values=_mm256_min_epi32(values,_mm256_permute2x128_si256::<0x01>(values,values));values=_mm256_min_epi32(values,_mm256_shuffle_epi32::<0x4e>(values));values=_mm256_min_epi32(values,_mm256_shuffle_epi32::<0xb1>(values));_mm256_extract_epi32::<0>(values)}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx2")]#[inline]unsafe fn reduce_max_i32x8(mut values:__m256i)->i32{values=_mm256_max_epi32(values,_mm256_permute2x128_si256::<0x01>(values,values));values=_mm256_max_epi32(values,_mm256_shuffle_epi32::<0x4e>(values));values=_mm256_max_epi32(values,_mm256_shuffle_epi32::<0xb1>(values));_mm256_extract_epi32::<0>(values)}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx2")]#[inline]unsafe fn reduce_sum_i32x8(mut values:__m256i)->i32{values=_mm256_add_epi32(values,_mm256_permute2x128_si256::<0x01>(values,values));values=_mm256_add_epi32(values,_mm256_shuffle_epi32::<0x4e>(values));values=_mm256_add_epi32(values,_mm256_shuffle_epi32::<0xb1>(values));_mm256_extract_epi32::<0>(values)}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx2")]#[inline]pub unsafe fn minimum_i32x16_avx2(values:&[i32;16])->i32{let low=_mm256_loadu_si256(values.as_ptr().cast());let high=_mm256_loadu_si256(values.as_ptr().add(8).cast());reduce_min_i32x8(_mm256_min_epi32(low,high))}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx2")]#[inline]pub unsafe fn maximum_i32x16_avx2(values:&[i32;16])->i32{let low=_mm256_loadu_si256(values.as_ptr().cast());let high=_mm256_loadu_si256(values.as_ptr().add(8).cast());reduce_max_i32x8(_mm256_max_epi32(low,high))}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx2")]#[inline]pub unsafe fn sum_i32x16_avx2(values:&[i32;16])->i32{let low=_mm256_loadu_si256(values.as_ptr().cast());let high=_mm256_loadu_si256(values.as_ptr().add(8).cast());reduce_sum_i32x8(_mm256_add_epi32(low,high))}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx2")]#[inline]unsafe fn range_mask_i32x8(start:usize,end:usize,offset:i32)->__m256i{let lanes=_mm256_setr_epi32(offset,offset+1,offset+2,offset+3,offset+4,offset+5,offset+6,offset+7);_mm256_and_si256(_mm256_cmpgt_epi32(lanes,_mm256_set1_epi32(start as i32-1)),_mm256_cmpgt_epi32(_mm256_set1_epi32(end as i32),lanes))}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx2")]#[inline]pub unsafe fn minimum_range_i32x16_avx2(values:&[i32;16],start:usize,end:usize)->i32{let unit=_mm256_set1_epi32(i32::MAX);let low=_mm256_blendv_epi8(unit,_mm256_loadu_si256(values.as_ptr().cast()),range_mask_i32x8(start,end,0));let high=_mm256_blendv_epi8(unit,_mm256_loadu_si256(values.as_ptr().add(8).cast()),range_mask_i32x8(start,end,8));reduce_min_i32x8(_mm256_min_epi32(low,high))}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx2")]#[inline]pub unsafe fn maximum_range_i32x16_avx2(values:&[i32;16],start:usize,end:usize)->i32{let unit=_mm256_set1_epi32(i32::MIN);let low=_mm256_blendv_epi8(unit,_mm256_loadu_si256(values.as_ptr().cast()),range_mask_i32x8(start,end,0));let high=_mm256_blendv_epi8(unit,_mm256_loadu_si256(values.as_ptr().add(8).cast()),range_mask_i32x8(start,end,8));reduce_max_i32x8(_mm256_max_epi32(low,high))}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx2")]#[inline]pub unsafe fn sum_range_i32x16_avx2(values:&[i32;16],start:usize,end:usize)->i32{let low=_mm256_and_si256(_mm256_loadu_si256(values.as_ptr().cast()),range_mask_i32x8(start,end,0));let high=_mm256_and_si256(_mm256_loadu_si256(values.as_ptr().add(8).cast()),range_mask_i32x8(start,end,8));reduce_sum_i32x8(_mm256_add_epi32(low,high))}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx512f")]#[inline]pub unsafe fn minimum_i32x16_avx512(values:&[i32;16])->i32{_mm512_reduce_min_epi32(_mm512_loadu_si512(values.as_ptr().cast()))}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx512f")]#[inline]pub unsafe fn maximum_i32x16_avx512(values:&[i32;16])->i32{_mm512_reduce_max_epi32(_mm512_loadu_si512(values.as_ptr().cast()))}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx512f")]#[inline]pub unsafe fn sum_i32x16_avx512(values:&[i32;16])->i32{_mm512_reduce_add_epi32(_mm512_loadu_si512(values.as_ptr().cast()))}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx512f")]#[inline]pub unsafe fn minimum_range_i32x16_avx512(values:&[i32;16],start:usize,end:usize)->i32{let mask=(u16::MAX<>(16-end));_mm512_mask_reduce_min_epi32(mask,_mm512_loadu_si512(values.as_ptr().cast()))}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx512f")]#[inline]pub unsafe fn maximum_range_i32x16_avx512(values:&[i32;16],start:usize,end:usize)->i32{let mask=(u16::MAX<>(16-end));_mm512_mask_reduce_max_epi32(mask,_mm512_loadu_si512(values.as_ptr().cast()))}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx512f")]#[inline]pub unsafe fn sum_range_i32x16_avx512(values:&[i32;16],start:usize,end:usize)->i32{let mask=(u16::MAX<>(16-end));_mm512_mask_reduce_add_epi32(mask,_mm512_loadu_si512(values.as_ptr().cast()))}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx2")]#[inline]unsafe fn min_i64x4(left:__m256i,right:__m256i)->__m256i{_mm256_blendv_epi8(left,right,_mm256_cmpgt_epi64(left,right))}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx2")]#[inline]unsafe fn max_i64x4(left:__m256i,right:__m256i)->__m256i{_mm256_blendv_epi8(right,left,_mm256_cmpgt_epi64(left,right))}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx2")]#[inline]unsafe fn reduce_min_i64x4(mut values:__m256i)->i64{values=min_i64x4(values,_mm256_permute4x64_epi64::<0x4e>(values));values=min_i64x4(values,_mm256_permute4x64_epi64::<0xb1>(values));_mm256_extract_epi64::<0>(values)}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx2")]#[inline]unsafe fn reduce_max_i64x4(mut values:__m256i)->i64{values=max_i64x4(values,_mm256_permute4x64_epi64::<0x4e>(values));values=max_i64x4(values,_mm256_permute4x64_epi64::<0xb1>(values));_mm256_extract_epi64::<0>(values)}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx2")]#[inline]unsafe fn reduce_sum_i64x4(mut values:__m256i)->i64{values=_mm256_add_epi64(values,_mm256_permute4x64_epi64::<0x4e>(values));values=_mm256_add_epi64(values,_mm256_permute4x64_epi64::<0xb1>(values));_mm256_extract_epi64::<0>(values)}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx2")]#[inline]pub unsafe fn minimum_i64x8_avx2(values:&[i64;8])->i64{let low=_mm256_loadu_si256(values.as_ptr().cast());let high=_mm256_loadu_si256(values.as_ptr().add(4).cast());reduce_min_i64x4(min_i64x4(low,high))}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx2")]#[inline]pub unsafe fn maximum_i64x8_avx2(values:&[i64;8])->i64{let low=_mm256_loadu_si256(values.as_ptr().cast());let high=_mm256_loadu_si256(values.as_ptr().add(4).cast());reduce_max_i64x4(max_i64x4(low,high))}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx2")]#[inline]pub unsafe fn sum_i64x8_avx2(values:&[i64;8])->i64{let low=_mm256_loadu_si256(values.as_ptr().cast());let high=_mm256_loadu_si256(values.as_ptr().add(4).cast());reduce_sum_i64x4(_mm256_add_epi64(low,high))}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx2")]#[inline]unsafe fn range_mask_i64x4(start:usize,end:usize,offset:i64)->__m256i{let lanes=_mm256_setr_epi64x(offset,offset+1,offset+2,offset+3);_mm256_and_si256(_mm256_cmpgt_epi64(lanes,_mm256_set1_epi64x(start as i64-1)),_mm256_cmpgt_epi64(_mm256_set1_epi64x(end as i64),lanes))}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx2")]#[inline]pub unsafe fn minimum_range_i64x8_avx2(values:&[i64;8],start:usize,end:usize)->i64{let unit=_mm256_set1_epi64x(i64::MAX);let low=_mm256_blendv_epi8(unit,_mm256_loadu_si256(values.as_ptr().cast()),range_mask_i64x4(start,end,0));let high=_mm256_blendv_epi8(unit,_mm256_loadu_si256(values.as_ptr().add(4).cast()),range_mask_i64x4(start,end,4));reduce_min_i64x4(min_i64x4(low,high))}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx2")]#[inline]pub unsafe fn maximum_range_i64x8_avx2(values:&[i64;8],start:usize,end:usize)->i64{let unit=_mm256_set1_epi64x(i64::MIN);let low=_mm256_blendv_epi8(unit,_mm256_loadu_si256(values.as_ptr().cast()),range_mask_i64x4(start,end,0));let high=_mm256_blendv_epi8(unit,_mm256_loadu_si256(values.as_ptr().add(4).cast()),range_mask_i64x4(start,end,4));reduce_max_i64x4(max_i64x4(low,high))}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx2")]#[inline]pub unsafe fn sum_range_i64x8_avx2(values:&[i64;8],start:usize,end:usize)->i64{let low=_mm256_and_si256(_mm256_loadu_si256(values.as_ptr().cast()),range_mask_i64x4(start,end,0));let high=_mm256_and_si256(_mm256_loadu_si256(values.as_ptr().add(4).cast()),range_mask_i64x4(start,end,4));reduce_sum_i64x4(_mm256_add_epi64(low,high))}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx512f")]#[inline]pub unsafe fn minimum_i64x8_avx512(values:&[i64;8])->i64{_mm512_reduce_min_epi64(_mm512_loadu_si512(values.as_ptr().cast()))}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx512f")]#[inline]pub unsafe fn maximum_i64x8_avx512(values:&[i64;8])->i64{_mm512_reduce_max_epi64(_mm512_loadu_si512(values.as_ptr().cast()))}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx512f")]#[inline]pub unsafe fn sum_i64x8_avx512(values:&[i64;8])->i64{_mm512_reduce_add_epi64(_mm512_loadu_si512(values.as_ptr().cast()))}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx512f")]#[inline]pub unsafe fn minimum_range_i64x8_avx512(values:&[i64;8],start:usize,end:usize)->i64{let mask=(u8::MAX<>(8-end));_mm512_mask_reduce_min_epi64(mask,_mm512_loadu_si512(values.as_ptr().cast()))}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx512f")]#[inline]pub unsafe fn maximum_range_i64x8_avx512(values:&[i64;8],start:usize,end:usize)->i64{let mask=(u8::MAX<>(8-end));_mm512_mask_reduce_max_epi64(mask,_mm512_loadu_si512(values.as_ptr().cast()))}#[cfg(target_arch="x86_64")]#[target_feature(enable="avx512f")]#[inline]pub unsafe fn sum_range_i64x8_avx512(values:&[i64;8],start:usize,end:usize)->i64{let mask=(u8::MAX<>(8-end));_mm512_mask_reduce_add_epi64(mask,_mm512_loadu_si512(values.as_ptr().cast()))}} // 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: array #[cfg_attr(any(),rustfmt::skip)]mod array{#[macro_export]macro_rules!array{[@inner$data:ident=[$init:expr;$len:expr]]=>{{use::std::mem::{ManuallyDrop,MaybeUninit};let mut$data:[MaybeUninit<_>;$len]=unsafe{MaybeUninit::uninit().assume_init()};$init;#[repr(C)]union __Transmuter{src:ManuallyDrop<[MaybeUninit;N]>,dst:ManuallyDrop<[T;N]>,}ManuallyDrop::into_inner(unsafe{__Transmuter{src:ManuallyDrop::new($data)}.dst})}};[||$e:expr;$len:expr]=>{$crate::array![@inner data=[data.iter_mut().for_each(|item|*item=MaybeUninit::new($e));$len]]};[|$i:pat_param|$e:expr;$len:expr]=>{$crate::array![@inner data=[data.iter_mut().enumerate().for_each(|($i,item)|*item=MaybeUninit::new($e));$len]]};[$e:expr;$len:expr]=>{{let e=$e;$crate::array![||Clone::clone(&e);$len]}};}} // codesnip-guard: avx_helper #[cfg_attr(any(),rustfmt::skip)]pub use self::avx_helper::{SimdBackend,avx512_enabled,avx512_supported,disable_avx512,enable_avx512,simd_backend};#[cfg_attr(any(),rustfmt::skip)]mod avx_helper{use std::sync::atomic::{AtomicBool,Ordering};#[derive(Copy,Clone,Debug,Eq,PartialEq)]pub enum SimdBackend{Scalar,Avx2,Avx512}static AVX512_ENABLED:AtomicBool=AtomicBool::new(true);#[inline]pub fn disable_avx512(){AVX512_ENABLED.store(false,Ordering::Relaxed);}#[inline]pub fn enable_avx512(){AVX512_ENABLED.store(true,Ordering::Relaxed);}#[inline]pub fn avx512_enabled()->bool{AVX512_ENABLED.load(Ordering::Relaxed)}#[inline]pub fn avx512_supported()->bool{#[cfg(any(target_arch="x86",target_arch="x86_64"))]return is_x86_feature_detected!("avx512f")&&is_x86_feature_detected!("avx512dq")&&is_x86_feature_detected!("avx512cd")&&is_x86_feature_detected!("avx512bw")&&is_x86_feature_detected!("avx512vl");#[cfg(not(any(target_arch="x86",target_arch="x86_64")))]false}#[inline]pub fn simd_backend()->SimdBackend{#[cfg(any(target_arch="x86",target_arch="x86_64"))]{if avx512_enabled()&&avx512_supported(){return SimdBackend::Avx512;}if is_x86_feature_detected!("avx2"){return SimdBackend::Avx2;}}SimdBackend::Scalar}#[macro_export]macro_rules!avx_helper{(@dispatch$backend:path,$kind:ident;$avx512:expr,$avx2:expr,$scalar:expr)=>{{#[cfg(target_arch="x86_64")]{match$backend(){$kind::Avx512=>$avx512,$kind::Avx2=>$avx2,$kind::Scalar=>$scalar,}}#[cfg(not(target_arch="x86_64"))]$scalar}};(@dispatch_avx2_fma$avx2:expr,$scalar:expr)=>{{#[cfg(target_arch="x86_64")]{if is_x86_feature_detected!("avx2")&&is_x86_feature_detected!("fma"){$avx2}else{$scalar}}#[cfg(not(target_arch="x86_64"))]$scalar}};(@avx512$(#[$meta:meta])*$vis:vis fn$name:ident$(<$($T:ident),+>)?($($i:ident:$t:ty),*)->$ret:ty where[$($clauses:tt)*]$body:block)=>{$(#[$meta])*$vis fn$name$(<$($T)*>)?($($i:$t),*)->$ret where$($clauses)*{if$crate::avx512_supported(){$crate::avx_helper!(@def_avx512 fn avx512$(<$($T)*>)?($($i:$t),*)->$ret where[$($clauses)*]$body);unsafe{avx512$(::<$($T),*>)?($($i),*)}}else if is_x86_feature_detected!("avx2"){$crate::avx_helper!(@def_avx2 fn avx2$(<$($T)*>)?($($i:$t),*)->$ret where[$($clauses)*]$body);unsafe{avx2$(::<$($T),*>)?($($i),*)}}else{$body}}};(@avx2$(#[$meta:meta])*$vis:vis fn$name:ident$(<$($T:ident),+>)?($($i:ident:$t:ty),*)->$ret:ty where[$($clauses:tt)*]$body:block)=>{$(#[$meta])*$vis fn$name$(<$($T)*>)?($($i:$t),*)->$ret where$($clauses)*{if is_x86_feature_detected!("avx2"){$crate::avx_helper!(@def_avx2 fn avx2$(<$($T)*>)?($($i:$t),*)->$ret where[$($clauses)*]$body);unsafe{avx2$(::<$($T),*>)?($($i),*)}}else{$body}}};(@def_avx512 fn$name:ident$(<$($T:ident),+>)?($($args:tt)*)->$ret:ty where[$($clauses:tt)*]$body:block)=>{#[target_feature(enable="avx512f,avx512dq,avx512cd,avx512bw,avx512vl")]unsafe fn$name$(<$($T)*>)?($($args)*)->$ret where$($clauses)*$body};(@def_avx2 fn$name:ident$(<$($T:ident),+>)?($($args:tt)*)->$ret:ty where[$($clauses:tt)*]$body:block)=>{#[target_feature(enable="avx2")]unsafe fn$name$(<$($T)*>)?($($args)*)->$ret where$($clauses)*$body};(@$tag:ident$(#[$meta:meta])*$vis:vis fn$name:ident$(<$($T:ident),+>)?($($args:tt)*)->$ret:ty$body:block)=>{$crate::avx_helper!(@$tag$(#[$meta])*$vis fn$name$(<$($T)*>)?($($args)*)->$ret where[]$body);};(@$tag:ident$(#[$meta:meta])*$vis:vis fn$name:ident$(<$($T:ident),+>)?($($args:tt)*)$($t:tt)*)=>{$crate::avx_helper!(@$tag$(#[$meta])*$vis fn$name$(<$($T)*>)?($($args)*)->()$($t)*);};($($t:tt)*)=>{::std::compile_error!($($t)*);}}} // 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;);} // codesnip-guard: sort #[cfg_attr(any(),rustfmt::skip)]pub use self::sort::{RadixSortKey,SliceSortExt};#[cfg_attr(any(),rustfmt::skip)]mod sort{use std::{cmp::Ordering,ptr::copy_nonoverlapping};pub trait RadixSortKey:Copy{const BYTES:usize;fn radix_byte(self,byte:usize)->usize;}macro_rules!unsigned_radix_sort_key{($($t:ty),*$(,)?)=>{$(impl RadixSortKey for$t{const BYTES:usize=(<$t>::BITS/8)as usize;fn radix_byte(self,byte:usize)->usize{((self>>(byte*8))&0xff)as usize}})*};}macro_rules!signed_radix_sort_key{($($t:ty=>$u:ty),*$(,)?)=>{$(impl RadixSortKey for$t{const BYTES:usize=(<$t>::BITS/8)as usize;fn radix_byte(self,byte:usize)->usize{let key=self as$u^(1<<(<$t>::BITS-1));((key>>(byte*8))&0xff)as usize}})*};}unsigned_radix_sort_key!(u8,u16,u32,u64,u128,usize);signed_radix_sort_key!(i8=>u8,i16=>u16,i32=>u32,i64=>u64,i128=>u128,isize=>usize,);pub trait SliceSortExt{fn bubble_sort(&mut self)where T:Ord;fn bubble_sort_by(&mut self,compare:F)where F:FnMut(&T,&T)->Ordering;fn merge_sort(&mut self)where T:Ord;fn merge_sort_by(&mut self,compare:F)where F:FnMut(&T,&T)->Ordering;fn insertion_sort(&mut self)where T:Ord;fn insertion_sort_by(&mut self,compare:F)where F:FnMut(&T,&T)->Ordering;fn radix_sort_by_key(&mut self,key:impl FnMut(&T)->K)where T:Clone,K:RadixSortKey;}implSliceSortExtfor[T]{fn bubble_sort(&mut self)where T:Ord{bubble_sort(self,|a,b|a.lt(b));}fn bubble_sort_by(&mut self,mut compare:F)where F:FnMut(&T,&T)->Ordering{bubble_sort(self,|a,b|compare(a,b)==Ordering::Less);}fn merge_sort(&mut self)where T:Ord{merge_sort(self,|a,b|a.lt(b));}fn merge_sort_by(&mut self,mut compare:F)where F:FnMut(&T,&T)->Ordering{merge_sort(self,|a,b|compare(a,b)==Ordering::Less);}fn insertion_sort(&mut self)where T:Ord{insertion_sort(self,|a,b|a.lt(b));}fn insertion_sort_by(&mut self,mut compare:F)where F:FnMut(&T,&T)->Ordering{insertion_sort(self,|a,b|compare(a,b)==Ordering::Less);}fn radix_sort_by_key(&mut self,key:impl FnMut(&T)->K)where T:Clone,K:RadixSortKey{radix_sort_by_key(self,key);}}fn radix_sort_by_key(values:&mut[T],mut key:impl FnMut(&T)->K)where T:Clone,K:RadixSortKey{if values.len()<=1{return;}let mut histograms=vec![[0usize;256];K::BYTES];for value in values.iter(){let key=key(value);for(byte,histogram)in histograms.iter_mut().enumerate(){histogram[key.radix_byte(byte)]+=1;}}for histogram in histograms.iter_mut(){let mut position=0;for count in histogram.iter_mut(){let next=position+*count;*count=position;position=next;}}let mut ends=[values.len();256];ends[..255].copy_from_slice(&histograms[0][1..]);let mut buffer=Vec::with_capacity(values.len());{let spare=buffer.spare_capacity_mut();let positions=&mut histograms[0];for value in values.iter(){let bucket=key(value).radix_byte(0);let position=&mut positions[bucket];assert!(*position{{let source=$source;let destination=$destination;for value in source{let bucket=key(value).radix_byte(byte);let position=&mut positions[bucket];destination[*position].clone_from(value);*position+=1;}}};}if byte%2==0{distribute!(&*values,&mut buffer);}else{distribute!(&buffer,&mut*values);}}if K::BYTES%2==1{values.clone_from_slice(&buffer);}}fn bubble_sort(v:&mut[T],mut is_less:F)where F:FnMut(&T,&T)->bool{let len=v.len();if len<=1{return;}for i in 0..len-1{for j in 0..len-i-1{unsafe{if is_less(v.get_unchecked(j+1),v.get_unchecked(j)){v.swap(j,j+1);}}}}}unsafe fn merge(v:&mut[T],mid:usize,buf:*mut T,is_less:&mut F)where F:FnMut(&T,&T)->bool{unsafe{let len=v.len();let v=v.as_mut_ptr();let(v_mid,v_end)=(v.add(mid),v.add(len));copy_nonoverlapping(v,buf,mid);let mut guard=MergeGuard{start:buf,dest:v,len:mid};let mut right=v_mid;while guard.len!=0&&right{start:*mut T,dest:*mut T,len:usize}implDrop for MergeGuard{fn drop(&mut self){unsafe{copy_nonoverlapping(self.start,self.dest,self.len)};}}unsafe fn get_and_increment(ptr:&mut*mut T)->*mut T{let old=*ptr;*ptr=unsafe{ptr.offset(1)};old}}fn merge_sort(v:&mut[T],mut is_less:F)where F:FnMut(&T,&T)->bool{let len=v.len();if len<=1{return;}let mut buf=Vec::with_capacity(len/2);let mut runs:Vec=vec![];let mut end=len;while end>0{let start=end-1;let mut left=Run{start,len:end-start};end=start;while let Some(right)=runs.pop_if(|right|left.start==0||right.len<=left.len){unsafe{merge(&mut v[left.start..right.start+right.len],left.len,buf.as_mut_ptr(),&mut is_less);}left=Run{start:left.start,len:left.len+right.len};}runs.push(left);}debug_assert!(runs.len()==1&&runs[0].start==0&&runs[0].len==len);#[derive(Clone,Copy)]struct Run{start:usize,len:usize}}fn insertion_sort(v:&mut[T],mut is_less:F)where F:FnMut(&T,&T)->bool{for i in 1..v.len(){let x=&v[i];let p=v[..i].partition_point(|y|is_less(y,x));v[p..=i].rotate_right(1);}}} // codesnip-guard: zero_one #[cfg_attr(any(),rustfmt::skip)]pub use self::zero_one::{One,Zero};#[cfg_attr(any(),rustfmt::skip)]mod zero_one{pub trait Zero:Sized{fn zero()->Self;#[inline]fn is_zero(&self)->bool where Self:PartialEq{self==&Self::zero()}#[inline]fn set_zero(&mut self){*self=Self::zero();}}pub trait One:Sized{fn one()->Self;#[inline]fn is_one(&self)->bool where Self:PartialEq{self==&Self::one()}#[inline]fn set_one(&mut self){*self=Self::one();}}macro_rules!impl_zero_one{($({$(<$T:ident:$Bound:ident>)?$Trait:ident$method:ident$($t:ty)*,$e:expr})*)=>{$(impl_zero_one!(@impl[$(<$T:$Bound>)?]$Trait$method[$($t)*],$e);)*};(@impl[<$T:ident:$Bound:ident>]$Trait:ident$method:ident[$($t:ty)*],$e:expr)=>{$(impl<$T:$Bound>$Trait for$t{fn$method()->Self{$e}})*};(@impl[]$Trait:ident$method:ident[$($t:ty)*],$e:expr)=>{$(impl$Trait for$t{fn$method()->Self{$e}})*};}impl_zero_one!({Zero zero u8 u16 u32 u64 usize i8 i16 i32 i64 isize u128 i128,0}{Zero zero f32 f64,0.}{One one u8 u16 u32 u64 usize i8 i16 i32 i64 isize u128 i128,1}{One one f32 f64,1.}{Zero zero std::num::Wrapping,Self(T::zero())}{One one std::num::Wrapping,Self(T::one())});}