Skip to main content

competitive/algebra/
operations.rs

1//! binary operaions
2
3use super::{Bounded, One, Zero, magma::*};
4
5#[codesnip::entry("MaxOperation")]
6pub use self::max_operation_impl::MaxOperation;
7#[codesnip::entry("MaxOperation", include("algebra", "bounded"))]
8mod max_operation_impl {
9    use super::*;
10    use std::marker::PhantomData;
11    /// binary operation to select larger element
12    pub struct MaxOperation<T>
13    where
14        T: Clone + Ord + Bounded,
15    {
16        _marker: PhantomData<fn() -> T>,
17    }
18    impl<T> Magma for MaxOperation<T>
19    where
20        T: Clone + Ord + Bounded,
21    {
22        type T = T;
23        #[inline]
24        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
25            x.max(y).clone()
26        }
27    }
28    impl<T> Unital for MaxOperation<T>
29    where
30        T: Clone + Ord + Bounded,
31    {
32        #[inline]
33        fn unit() -> Self::T {
34            <T as Bounded>::minimum()
35        }
36    }
37    impl<T> Associative for MaxOperation<T> where T: Clone + Ord + Bounded {}
38    impl<T> Commutative for MaxOperation<T> where T: Clone + Ord + Bounded {}
39    impl<T> Idempotent for MaxOperation<T> where T: Clone + Ord + Bounded {}
40
41    #[cfg(test)]
42    mod tests {
43        use super::*;
44
45        #[test]
46        fn test_max_operation() {
47            type M = MaxOperation<i32>;
48            for a in -10..=10 {
49                assert!(M::check_unital(&a));
50                assert!(M::check_idempotent(&a));
51                for b in -10..=10 {
52                    assert!(M::check_commutative(&a, &b));
53                    for c in -10..=10 {
54                        assert!(M::check_associative(&a, &b, &c));
55                    }
56                }
57            }
58        }
59    }
60}
61
62#[codesnip::entry("MinOperation")]
63pub use self::min_operation_impl::MinOperation;
64#[codesnip::entry("MinOperation", include("algebra", "bounded"))]
65mod min_operation_impl {
66    use super::*;
67    use std::marker::PhantomData;
68    /// binary operation to select smaller element
69    pub struct MinOperation<T>
70    where
71        T: Clone + Ord + Bounded,
72    {
73        _marker: PhantomData<fn() -> T>,
74    }
75    impl<T> Magma for MinOperation<T>
76    where
77        T: Clone + Ord + Bounded,
78    {
79        type T = T;
80        #[inline]
81        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
82            x.min(y).clone()
83        }
84    }
85    impl<T> Unital for MinOperation<T>
86    where
87        T: Clone + Ord + Bounded,
88    {
89        #[inline]
90        fn unit() -> Self::T {
91            <T as Bounded>::maximum()
92        }
93    }
94    impl<T> Associative for MinOperation<T> where T: Clone + Ord + Bounded {}
95    impl<T> Commutative for MinOperation<T> where T: Clone + Ord + Bounded {}
96    impl<T> Idempotent for MinOperation<T> where T: Clone + Ord + Bounded {}
97
98    #[cfg(test)]
99    mod tests {
100        use super::*;
101
102        #[test]
103        fn test_min_operation() {
104            type M = MinOperation<i32>;
105            for a in -10..=10 {
106                assert!(M::check_unital(&a));
107                assert!(M::check_idempotent(&a));
108                for b in -10..=10 {
109                    assert!(M::check_commutative(&a, &b));
110                    for c in -10..=10 {
111                        assert!(M::check_associative(&a, &b, &c));
112                    }
113                }
114            }
115        }
116    }
117}
118
119#[codesnip::entry("FirstOperation")]
120pub use self::first_operation_impl::FirstOperation;
121#[codesnip::entry("FirstOperation", include("algebra"))]
122mod first_operation_impl {
123    use super::*;
124    use std::marker::PhantomData;
125    /// retain the first element
126    pub struct FirstOperation<T>
127    where
128        T: Clone,
129    {
130        _marker: PhantomData<fn() -> T>,
131    }
132    impl<T> Magma for FirstOperation<T>
133    where
134        T: Clone,
135    {
136        type T = Option<T>;
137        #[inline]
138        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
139            x.as_ref().or(y.as_ref()).cloned()
140        }
141    }
142    impl<T> Unital for FirstOperation<T>
143    where
144        T: Clone,
145    {
146        #[inline]
147        fn unit() -> Self::T {
148            None
149        }
150    }
151    impl<T> Associative for FirstOperation<T> where T: Clone {}
152    impl<T> Idempotent for FirstOperation<T> where T: Clone {}
153
154    #[cfg(test)]
155    mod tests {
156        use super::*;
157
158        #[test]
159        fn test_first_operation() {
160            type M = FirstOperation<i32>;
161            let iter = [Some(1), Some(2), Some(3), None];
162            for a in iter {
163                assert!(M::check_unital(&a));
164                assert!(M::check_idempotent(&a));
165                for b in iter {
166                    assert_eq!(M::operate(&a, &b), [a, b].into_iter().flatten().next());
167                    for c in iter {
168                        assert!(M::check_associative(&a, &b, &c));
169                    }
170                }
171            }
172        }
173    }
174}
175
176#[codesnip::entry("LastOperation")]
177pub use self::last_operation_impl::LastOperation;
178#[codesnip::entry("LastOperation", include("algebra"))]
179mod last_operation_impl {
180    use super::*;
181    use std::marker::PhantomData;
182    /// retain the last element
183    pub struct LastOperation<T>
184    where
185        T: Clone,
186    {
187        _marker: PhantomData<fn() -> T>,
188    }
189    impl<T> Magma for LastOperation<T>
190    where
191        T: Clone,
192    {
193        type T = Option<T>;
194        #[inline]
195        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
196            y.as_ref().or(x.as_ref()).cloned()
197        }
198    }
199    impl<T> Unital for LastOperation<T>
200    where
201        T: Clone,
202    {
203        #[inline]
204        fn unit() -> Self::T {
205            None
206        }
207    }
208    impl<T> Associative for LastOperation<T> where T: Clone {}
209    impl<T> Idempotent for LastOperation<T> where T: Clone {}
210
211    #[cfg(test)]
212    mod tests {
213        use super::*;
214
215        #[test]
216        fn test_last_operation() {
217            type M = LastOperation<i32>;
218            let iter = [Some(1), Some(2), Some(3), None];
219            for a in iter {
220                assert!(M::check_unital(&a));
221                assert!(M::check_idempotent(&a));
222                for b in iter {
223                    assert_eq!(M::operate(&a, &b), [a, b].into_iter().flatten().next_back());
224                    for c in iter {
225                        assert!(M::check_associative(&a, &b, &c));
226                    }
227                }
228            }
229        }
230    }
231}
232
233#[codesnip::entry("AdditiveOperation")]
234pub use self::additive_operation_impl::AdditiveOperation;
235#[codesnip::entry("AdditiveOperation", include("algebra", "zero_one"))]
236mod additive_operation_impl {
237    use super::*;
238    use std::{
239        marker::PhantomData,
240        ops::{Add, Neg, Sub},
241    };
242    /// $+$
243    pub struct AdditiveOperation<T>
244    where
245        T: Clone + Zero + Add<Output = T>,
246    {
247        _marker: PhantomData<fn() -> T>,
248    }
249    impl<T> Magma for AdditiveOperation<T>
250    where
251        T: Clone + Zero + Add<Output = T>,
252    {
253        type T = T;
254        #[inline]
255        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
256            x.clone() + y.clone()
257        }
258    }
259    impl<T> Unital for AdditiveOperation<T>
260    where
261        T: Clone + Zero + Add<Output = T>,
262    {
263        #[inline]
264        fn unit() -> Self::T {
265            Zero::zero()
266        }
267    }
268    impl<T> Associative for AdditiveOperation<T> where T: Clone + Zero + Add<Output = T> {}
269    impl<T> Commutative for AdditiveOperation<T> where T: Clone + Zero + Add<Output = T> {}
270    impl<T> Invertible for AdditiveOperation<T>
271    where
272        T: Clone + Zero + Add<Output = T> + Sub<Output = T> + Neg<Output = T>,
273    {
274        #[inline]
275        fn inverse(x: &Self::T) -> Self::T {
276            -x.clone()
277        }
278        #[inline]
279        fn rinv_operate(x: &Self::T, y: &Self::T) -> Self::T {
280            x.clone() - y.clone()
281        }
282    }
283
284    #[cfg(test)]
285    mod tests {
286        use super::*;
287
288        #[test]
289        fn test_additive_operation() {
290            type M = AdditiveOperation<i32>;
291            for a in -10..=10 {
292                assert!(M::check_unital(&a));
293                assert!(M::check_invertible(&a));
294                for b in -10..=10 {
295                    assert!(M::check_commutative(&a, &b));
296                    for c in -10..=10 {
297                        assert!(M::check_associative(&a, &b, &c));
298                    }
299                }
300            }
301        }
302    }
303}
304
305#[codesnip::entry("MultiplicativeOperation")]
306pub use self::multiplicative_operation_impl::MultiplicativeOperation;
307#[codesnip::entry("MultiplicativeOperation", include("algebra", "zero_one"))]
308mod multiplicative_operation_impl {
309    use super::*;
310    use std::{
311        marker::PhantomData,
312        ops::{Div, Mul},
313    };
314    /// $\times$
315    pub struct MultiplicativeOperation<T>
316    where
317        T: Clone + One + Mul<Output = T>,
318    {
319        _marker: PhantomData<fn() -> T>,
320    }
321    impl<T> Magma for MultiplicativeOperation<T>
322    where
323        T: Clone + One + Mul<Output = T>,
324    {
325        type T = T;
326        #[inline]
327        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
328            x.clone() * y.clone()
329        }
330    }
331    impl<T> Unital for MultiplicativeOperation<T>
332    where
333        T: Clone + One + Mul<Output = T>,
334    {
335        #[inline]
336        fn unit() -> Self::T {
337            One::one()
338        }
339    }
340    impl<T> Associative for MultiplicativeOperation<T> where T: Clone + One + Mul<Output = T> {}
341    impl<T> Commutative for MultiplicativeOperation<T> where T: Clone + One + Mul<Output = T> {}
342    impl<T> Invertible for MultiplicativeOperation<T>
343    where
344        T: Clone + One + Mul<Output = T> + Div<Output = T>,
345    {
346        #[inline]
347        fn inverse(x: &Self::T) -> Self::T {
348            Self::unit().div(x.clone())
349        }
350        #[inline]
351        fn rinv_operate(x: &Self::T, y: &Self::T) -> Self::T {
352            (x.clone()).div(y.clone())
353        }
354    }
355
356    #[cfg(test)]
357    mod tests {
358        use super::*;
359        use crate::num::mint_basic::MInt998244353;
360
361        #[test]
362        fn test_multiplicative_operation() {
363            type MInt = MInt998244353;
364            type M = MultiplicativeOperation<MInt>;
365            let iter = (-10..=10).map(MInt::from);
366            for a in iter.clone() {
367                assert!(M::check_unital(&a));
368                if !a.is_zero() {
369                    assert!(M::check_invertible(&a));
370                }
371                for b in iter.clone() {
372                    assert!(M::check_commutative(&a, &b));
373                    for c in iter.clone() {
374                        assert!(M::check_associative(&a, &b, &c));
375                    }
376                }
377            }
378        }
379    }
380}
381
382#[codesnip::entry("LinearOperation")]
383pub use self::linear_operation_impl::LinearOperation;
384#[codesnip::entry("LinearOperation", include("algebra", "zero_one"))]
385mod linear_operation_impl {
386    use super::*;
387    use std::{
388        marker::PhantomData,
389        ops::{Add, Div, Mul, Neg, Sub},
390    };
391    /// $(a, b) \circ (c, d) = \lambda x. c \times (a \times x + b) + d$
392    pub struct LinearOperation<T>
393    where
394        T: Clone + Zero + Add<Output = T> + One + Mul<Output = T>,
395    {
396        _marker: PhantomData<fn() -> T>,
397    }
398    impl<T> LinearOperation<T>
399    where
400        T: Clone + Zero + Add<Output = T> + One + Mul<Output = T>,
401    {
402        pub fn apply(f: &(T, T), x: &T) -> T {
403            f.0.clone() * x.clone() + f.1.clone()
404        }
405    }
406    impl<T> Magma for LinearOperation<T>
407    where
408        T: Clone + Zero + One + Add<Output = T> + Mul<Output = T>,
409    {
410        type T = (T, T);
411        #[inline]
412        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
413            (
414                y.0.clone() * x.0.clone(),
415                y.0.clone() * x.1.clone() + y.1.clone(),
416            )
417        }
418    }
419    impl<T> Unital for LinearOperation<T>
420    where
421        T: Clone + Zero + One + Add<Output = T> + Mul<Output = T>,
422    {
423        #[inline]
424        fn unit() -> Self::T {
425            (One::one(), Zero::zero())
426        }
427    }
428    impl<T> Associative for LinearOperation<T> where
429        T: Clone + Zero + One + Add<Output = T> + Mul<Output = T>
430    {
431    }
432    impl<T> Invertible for LinearOperation<T>
433    where
434        T: Clone
435            + Zero
436            + One
437            + Add<Output = T>
438            + Sub<Output = T>
439            + Neg<Output = T>
440            + Mul<Output = T>
441            + Div<Output = T>,
442    {
443        fn inverse(x: &Self::T) -> Self::T {
444            let y = <T as One>::one().div(x.0.clone());
445            (y.clone(), -y.mul(x.1.clone()))
446        }
447    }
448
449    #[cfg(test)]
450    mod tests {
451        use super::*;
452        use crate::num::mint_basic::MInt998244353;
453
454        #[test]
455        fn test_linear_operation() {
456            type MInt = MInt998244353;
457            type M = LinearOperation<MInt>;
458            let iter = (-5..=5).flat_map(|x| (-5..=5).map(move |y| (MInt::from(x), MInt::from(y))));
459            for a in iter.clone() {
460                assert!(M::check_unital(&a));
461                if !a.0.is_zero() {
462                    assert!(M::check_invertible(&a));
463                }
464                for b in iter.clone() {
465                    for c in iter.clone() {
466                        assert!(M::check_associative(&a, &b, &c));
467                    }
468                    for x in (-5..=5).map(MInt::from) {
469                        assert_eq!(
470                            M::apply(&M::operate(&a, &b), &x),
471                            M::apply(&b, &M::apply(&a, &x))
472                        );
473                    }
474                }
475            }
476        }
477    }
478}
479
480#[codesnip::entry("BitAndOperation")]
481pub use self::bitand_operation_impl::{BitAndIdentity, BitAndOperation};
482#[codesnip::entry("BitAndOperation", include("algebra"))]
483mod bitand_operation_impl {
484    use super::*;
485    use std::{marker::PhantomData, ops::BitAnd};
486    /// &
487    pub struct BitAndOperation<T>
488    where
489        T: Clone + BitAndIdentity,
490    {
491        _marker: PhantomData<fn() -> T>,
492    }
493    pub trait BitAndIdentity: Sized + BitAnd<Output = Self> {
494        fn all_one() -> Self;
495    }
496    #[macro_export]
497    macro_rules! impl_bitand_identity {
498        ([$($wh:tt)*], $t:ty, $all_one:expr) => {
499            impl<$($wh)*> BitAndIdentity for $t {
500                #[inline]
501                fn all_one() -> Self {
502                    $all_one
503                }
504            }
505        };
506        ($t:ty, $all_one:expr) => {
507            impl BitAndIdentity for $t {
508                #[inline]
509                fn all_one() -> Self {
510                    $all_one
511                }
512            }
513        };
514    }
515    impl_bitand_identity!(bool, true);
516    impl_bitand_identity!(usize, usize::MAX);
517    impl_bitand_identity!(u8, u8::MAX);
518    impl_bitand_identity!(u16, u16::MAX);
519    impl_bitand_identity!(u32, u32::MAX);
520    impl_bitand_identity!(u64, u64::MAX);
521    impl_bitand_identity!(u128, u128::MAX);
522    impl_bitand_identity!(isize, -1);
523    impl_bitand_identity!(i8, -1);
524    impl_bitand_identity!(i16, -1);
525    impl_bitand_identity!(i32, -1);
526    impl_bitand_identity!(i64, -1);
527    impl_bitand_identity!(i128, -1);
528    impl<T> Magma for BitAndOperation<T>
529    where
530        T: Clone + BitAndIdentity,
531    {
532        type T = T;
533        #[inline]
534        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
535            x.clone() & y.clone()
536        }
537    }
538    impl<T> Unital for BitAndOperation<T>
539    where
540        T: Clone + BitAndIdentity,
541    {
542        #[inline]
543        fn unit() -> Self::T {
544            BitAndIdentity::all_one()
545        }
546    }
547    impl<T> Associative for BitAndOperation<T> where T: Clone + BitAndIdentity {}
548    impl<T> Commutative for BitAndOperation<T> where T: Clone + BitAndIdentity {}
549    impl<T> Idempotent for BitAndOperation<T> where T: Clone + BitAndIdentity {}
550
551    #[cfg(test)]
552    mod tests {
553        use super::*;
554
555        #[test]
556        fn test_bitand_operation() {
557            let mut rng = crate::tools::Xorshift::default();
558            macro_rules! check {
559                ($ty:ty, $value:expr, $small:expr) => {{
560                    type M = BitAndOperation<$ty>;
561                    let alphabet: Vec<$ty> = $small;
562                    let alphabet = alphabet.as_slice();
563                    let triples: Vec<_> = alphabet
564                        .iter()
565                        .flat_map(|&a| {
566                            alphabet
567                                .iter()
568                                .flat_map(move |&b| alphabet.iter().map(move |&c| (a, b, c)))
569                        })
570                        .chain((0..1000).map(|_| ($value, $value, $value)))
571                        .collect();
572                    for (a, b, c) in triples {
573                        assert_eq!(M::operate(&a, &b), a & b);
574                        assert!(M::check_unital(&a));
575                        assert!(M::check_idempotent(&a));
576                        assert!(M::check_commutative(&a, &b));
577                        assert!(M::check_associative(&a, &b, &c));
578                    }
579                }};
580            }
581            check!(bool, rng.random(0..2) == 0, vec![false, true]);
582            check!(
583                u8,
584                rng.random(..),
585                (0..=7).chain([u8::MIN, u8::MAX]).collect()
586            );
587            check!(
588                i8,
589                rng.random(..),
590                (0..=7).chain([i8::MIN, i8::MAX]).collect()
591            );
592            check!(
593                u16,
594                rng.random(..),
595                (0..=7).chain([u16::MIN, u16::MAX]).collect()
596            );
597            check!(
598                i16,
599                rng.random(..),
600                (0..=7).chain([i16::MIN, i16::MAX]).collect()
601            );
602            check!(
603                u32,
604                rng.random(..),
605                (0..=7).chain([u32::MIN, u32::MAX]).collect()
606            );
607            check!(
608                i32,
609                rng.random(..),
610                (0..=7).chain([i32::MIN, i32::MAX]).collect()
611            );
612            check!(
613                u64,
614                rng.random(..),
615                (0..=7).chain([u64::MIN, u64::MAX]).collect()
616            );
617            check!(
618                i64,
619                rng.random(..),
620                (0..=7).chain([i64::MIN, i64::MAX]).collect()
621            );
622            check!(
623                u128,
624                rng.random(..),
625                (0..=7).chain([u128::MIN, u128::MAX]).collect()
626            );
627            check!(
628                i128,
629                rng.random(..),
630                (0..=7).chain([i128::MIN, i128::MAX]).collect()
631            );
632            check!(
633                usize,
634                rng.random(..),
635                (0..=7).chain([usize::MIN, usize::MAX]).collect()
636            );
637            check!(
638                isize,
639                rng.random(..),
640                (0..=7).chain([isize::MIN, isize::MAX]).collect()
641            );
642        }
643    }
644}
645
646#[codesnip::entry("BitOrOperation")]
647pub use self::bitor_operation_impl::{BitOrIdentity, BitOrOperation};
648#[codesnip::entry("BitOrOperation", include("algebra"))]
649mod bitor_operation_impl {
650    use super::*;
651    use std::{marker::PhantomData, ops::BitOr};
652    /// |
653    pub struct BitOrOperation<T>
654    where
655        T: Clone + BitOrIdentity,
656    {
657        _marker: PhantomData<fn() -> T>,
658    }
659    pub trait BitOrIdentity: Sized + BitOr<Output = Self> {
660        fn all_zero() -> Self;
661    }
662    #[macro_export]
663    macro_rules! impl_bitor_identity {
664        ([$($wh:tt)*], $t:ty, $all_zero:expr) => {
665            impl<$($wh)*> BitOrIdentity for $t {
666                #[inline]
667                fn all_zero() -> Self {
668                    $all_zero
669                }
670            }
671        };
672        ($t:ty, $all_zero:expr) => {
673            impl BitOrIdentity for $t {
674                #[inline]
675                fn all_zero() -> Self {
676                    $all_zero
677                }
678            }
679        };
680    }
681    impl_bitor_identity!(bool, false);
682    impl_bitor_identity!(usize, 0);
683    impl_bitor_identity!(u8, 0);
684    impl_bitor_identity!(u16, 0);
685    impl_bitor_identity!(u32, 0);
686    impl_bitor_identity!(u64, 0);
687    impl_bitor_identity!(u128, 0);
688    impl_bitor_identity!(isize, 0);
689    impl_bitor_identity!(i8, 0);
690    impl_bitor_identity!(i16, 0);
691    impl_bitor_identity!(i32, 0);
692    impl_bitor_identity!(i64, 0);
693    impl_bitor_identity!(i128, 0);
694    impl<T> Magma for BitOrOperation<T>
695    where
696        T: Clone + BitOrIdentity,
697    {
698        type T = T;
699        #[inline]
700        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
701            x.clone() | y.clone()
702        }
703    }
704    impl<T> Unital for BitOrOperation<T>
705    where
706        T: Clone + BitOrIdentity,
707    {
708        #[inline]
709        fn unit() -> Self::T {
710            BitOrIdentity::all_zero()
711        }
712    }
713    impl<T> Associative for BitOrOperation<T> where T: Clone + BitOrIdentity {}
714    impl<T> Commutative for BitOrOperation<T> where T: Clone + BitOrIdentity {}
715    impl<T> Idempotent for BitOrOperation<T> where T: Clone + BitOrIdentity {}
716
717    #[cfg(test)]
718    mod tests {
719        use super::*;
720
721        #[test]
722        fn test_bitor_operation() {
723            let mut rng = crate::tools::Xorshift::default();
724            macro_rules! check {
725                ($ty:ty, $value:expr, $small:expr) => {{
726                    type M = BitOrOperation<$ty>;
727                    let alphabet: Vec<$ty> = $small;
728                    let alphabet = alphabet.as_slice();
729                    let triples: Vec<_> = alphabet
730                        .iter()
731                        .flat_map(|&a| {
732                            alphabet
733                                .iter()
734                                .flat_map(move |&b| alphabet.iter().map(move |&c| (a, b, c)))
735                        })
736                        .chain((0..1000).map(|_| ($value, $value, $value)))
737                        .collect();
738                    for (a, b, c) in triples {
739                        assert_eq!(M::operate(&a, &b), a | b);
740                        assert!(M::check_unital(&a));
741                        assert!(M::check_idempotent(&a));
742                        assert!(M::check_commutative(&a, &b));
743                        assert!(M::check_associative(&a, &b, &c));
744                    }
745                }};
746            }
747            check!(bool, rng.random(0..2) == 0, vec![false, true]);
748            check!(
749                u8,
750                rng.random(..),
751                (0..=7).chain([u8::MIN, u8::MAX]).collect()
752            );
753            check!(
754                i8,
755                rng.random(..),
756                (0..=7).chain([i8::MIN, i8::MAX]).collect()
757            );
758            check!(
759                u16,
760                rng.random(..),
761                (0..=7).chain([u16::MIN, u16::MAX]).collect()
762            );
763            check!(
764                i16,
765                rng.random(..),
766                (0..=7).chain([i16::MIN, i16::MAX]).collect()
767            );
768            check!(
769                u32,
770                rng.random(..),
771                (0..=7).chain([u32::MIN, u32::MAX]).collect()
772            );
773            check!(
774                i32,
775                rng.random(..),
776                (0..=7).chain([i32::MIN, i32::MAX]).collect()
777            );
778            check!(
779                u64,
780                rng.random(..),
781                (0..=7).chain([u64::MIN, u64::MAX]).collect()
782            );
783            check!(
784                i64,
785                rng.random(..),
786                (0..=7).chain([i64::MIN, i64::MAX]).collect()
787            );
788            check!(
789                u128,
790                rng.random(..),
791                (0..=7).chain([u128::MIN, u128::MAX]).collect()
792            );
793            check!(
794                i128,
795                rng.random(..),
796                (0..=7).chain([i128::MIN, i128::MAX]).collect()
797            );
798            check!(
799                usize,
800                rng.random(..),
801                (0..=7).chain([usize::MIN, usize::MAX]).collect()
802            );
803            check!(
804                isize,
805                rng.random(..),
806                (0..=7).chain([isize::MIN, isize::MAX]).collect()
807            );
808        }
809    }
810}
811
812#[codesnip::entry("BitXorOperation")]
813pub use self::bitxor_operation_impl::{BitXorIdentity, BitXorOperation};
814#[codesnip::entry("BitXorOperation", include("algebra"))]
815mod bitxor_operation_impl {
816    use super::*;
817    use std::{marker::PhantomData, ops::BitXor};
818    /// ^
819    pub struct BitXorOperation<T>
820    where
821        T: Clone + BitXorIdentity,
822    {
823        _marker: PhantomData<fn() -> T>,
824    }
825    pub trait BitXorIdentity: Sized + BitXor<Output = Self> {
826        fn xor_zero() -> Self;
827    }
828    #[macro_export]
829    macro_rules! impl_bitxor_identity {
830        ([$($wh:tt)*], $t:ty, $xor_zero:expr) => {
831            impl<$($wh)*> BitXorIdentity for $t {
832                #[inline]
833                fn xor_zero() -> Self { $xor_zero }
834            }
835        };
836        ($t:ty, $xor_zero:expr) =>{
837            impl BitXorIdentity for $t {
838                #[inline]
839                fn xor_zero() -> Self { $xor_zero }
840            }
841        };
842    }
843    impl_bitxor_identity!(bool, false);
844    impl_bitxor_identity!(usize, 0);
845    impl_bitxor_identity!(u8, 0);
846    impl_bitxor_identity!(u16, 0);
847    impl_bitxor_identity!(u32, 0);
848    impl_bitxor_identity!(u64, 0);
849    impl_bitxor_identity!(u128, 0);
850    impl_bitxor_identity!(isize, 0);
851    impl_bitxor_identity!(i8, 0);
852    impl_bitxor_identity!(i16, 0);
853    impl_bitxor_identity!(i32, 0);
854    impl_bitxor_identity!(i64, 0);
855    impl_bitxor_identity!(i128, 0);
856    impl<T> Magma for BitXorOperation<T>
857    where
858        T: Clone + BitXorIdentity,
859    {
860        type T = T;
861        #[inline]
862        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
863            x.clone() ^ y.clone()
864        }
865    }
866    impl<T> Unital for BitXorOperation<T>
867    where
868        T: Clone + BitXorIdentity,
869    {
870        #[inline]
871        fn unit() -> Self::T {
872            BitXorIdentity::xor_zero()
873        }
874    }
875    impl<T> Associative for BitXorOperation<T> where T: Clone + BitXorIdentity {}
876    impl<T> Commutative for BitXorOperation<T> where T: Clone + BitXorIdentity {}
877    impl<T> Invertible for BitXorOperation<T>
878    where
879        T: Clone + BitXorIdentity,
880    {
881        fn inverse(x: &Self::T) -> Self::T {
882            x.clone()
883        }
884    }
885
886    #[cfg(test)]
887    mod tests {
888        use super::*;
889
890        #[test]
891        fn test_bitxor_operation() {
892            let mut rng = crate::tools::Xorshift::default();
893            macro_rules! check {
894                ($ty:ty, $value:expr, $small:expr) => {{
895                    type M = BitXorOperation<$ty>;
896                    let alphabet: Vec<$ty> = $small;
897                    let alphabet = alphabet.as_slice();
898                    let triples: Vec<_> = alphabet
899                        .iter()
900                        .flat_map(|&a| {
901                            alphabet
902                                .iter()
903                                .flat_map(move |&b| alphabet.iter().map(move |&c| (a, b, c)))
904                        })
905                        .chain((0..1000).map(|_| ($value, $value, $value)))
906                        .collect();
907                    for (a, b, c) in triples {
908                        assert_eq!(M::operate(&a, &b), a ^ b);
909                        assert!(M::check_unital(&a));
910                        assert!(M::check_invertible(&a));
911                        assert!(M::check_commutative(&a, &b));
912                        assert!(M::check_associative(&a, &b, &c));
913                    }
914                }};
915            }
916            check!(bool, rng.random(0..2) == 0, vec![false, true]);
917            check!(
918                u8,
919                rng.random(..),
920                (0..=7).chain([u8::MIN, u8::MAX]).collect()
921            );
922            check!(
923                i8,
924                rng.random(..),
925                (0..=7).chain([i8::MIN, i8::MAX]).collect()
926            );
927            check!(
928                u16,
929                rng.random(..),
930                (0..=7).chain([u16::MIN, u16::MAX]).collect()
931            );
932            check!(
933                i16,
934                rng.random(..),
935                (0..=7).chain([i16::MIN, i16::MAX]).collect()
936            );
937            check!(
938                u32,
939                rng.random(..),
940                (0..=7).chain([u32::MIN, u32::MAX]).collect()
941            );
942            check!(
943                i32,
944                rng.random(..),
945                (0..=7).chain([i32::MIN, i32::MAX]).collect()
946            );
947            check!(
948                u64,
949                rng.random(..),
950                (0..=7).chain([u64::MIN, u64::MAX]).collect()
951            );
952            check!(
953                i64,
954                rng.random(..),
955                (0..=7).chain([i64::MIN, i64::MAX]).collect()
956            );
957            check!(
958                u128,
959                rng.random(..),
960                (0..=7).chain([u128::MIN, u128::MAX]).collect()
961            );
962            check!(
963                i128,
964                rng.random(..),
965                (0..=7).chain([i128::MIN, i128::MAX]).collect()
966            );
967            check!(
968                usize,
969                rng.random(..),
970                (0..=7).chain([usize::MIN, usize::MAX]).collect()
971            );
972            check!(
973                isize,
974                rng.random(..),
975                (0..=7).chain([isize::MIN, isize::MAX]).collect()
976            );
977        }
978    }
979}
980
981#[codesnip::entry("LogicalLinearOperation")]
982pub use self::logical_linear_operation_impl::LogicalLinearOperation;
983#[codesnip::entry(
984    "LogicalLinearOperation",
985    include("algebra", "BitXorOperation", "BitAndOperation")
986)]
987mod logical_linear_operation_impl {
988    use super::*;
989    use std::{
990        marker::PhantomData,
991        ops::{BitAnd, BitXor},
992    };
993    /// $(a, b) \circ (c, d) = \lambda x. c \wedge (a \wedge x \oplus b) \oplus d$
994    pub struct LogicalLinearOperation<T>
995    where
996        T: Clone + BitXorIdentity + BitAndIdentity + BitXor<Output = T> + BitAnd<Output = T>,
997    {
998        _marker: PhantomData<fn() -> T>,
999    }
1000    impl<T> LogicalLinearOperation<T>
1001    where
1002        T: Clone + BitXorIdentity + BitAndIdentity + BitXor<Output = T> + BitAnd<Output = T>,
1003    {
1004        pub fn eval((a, b): &<Self as Magma>::T, x: &T) -> T {
1005            a.clone() & x.clone() ^ b.clone()
1006        }
1007    }
1008    impl<T> Magma for LogicalLinearOperation<T>
1009    where
1010        T: Clone + BitXorIdentity + BitAndIdentity + BitXor<Output = T> + BitAnd<Output = T>,
1011    {
1012        type T = (T, T);
1013        #[inline]
1014        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
1015            (
1016                y.0.clone() & x.0.clone(),
1017                y.0.clone() & x.1.clone() ^ y.1.clone(),
1018            )
1019        }
1020    }
1021    impl<T> Unital for LogicalLinearOperation<T>
1022    where
1023        T: Clone + BitXorIdentity + BitAndIdentity + BitXor<Output = T> + BitAnd<Output = T>,
1024    {
1025        #[inline]
1026        fn unit() -> Self::T {
1027            (BitAndIdentity::all_one(), BitXorIdentity::xor_zero())
1028        }
1029    }
1030    impl<T> Associative for LogicalLinearOperation<T> where
1031        T: Clone + BitXorIdentity + BitAndIdentity + BitXor<Output = T> + BitAnd<Output = T>
1032    {
1033    }
1034
1035    #[cfg(test)]
1036    mod tests {
1037        use super::*;
1038
1039        #[test]
1040        fn test_logical_linear_operation() {
1041            type M = LogicalLinearOperation<i32>;
1042            let iter = (-3..=3).flat_map(|x| (-3..=3).map(move |y| (x, y)));
1043            for a in iter.clone() {
1044                assert!(M::check_unital(&a));
1045                for b in iter.clone() {
1046                    for c in iter.clone() {
1047                        assert!(M::check_associative(&a, &b, &c));
1048                    }
1049                    for x in -3..=3 {
1050                        assert_eq!(
1051                            M::eval(&M::operate(&a, &b), &x),
1052                            M::eval(&b, &M::eval(&a, &x))
1053                        );
1054                    }
1055                }
1056            }
1057        }
1058    }
1059}
1060
1061#[codesnip::entry("TupleOperation", include("algebra"))]
1062mod tuple_operation_impl {
1063    use super::*;
1064    macro_rules! impl_tuple_operation {
1065        (@impl) => {
1066            impl Magma for () {
1067                type T = ();
1068                fn operate(_x: &Self::T, _y: &Self::T) -> Self::T {}
1069            }
1070            impl Unital for () {
1071                fn unit() -> Self::T {}
1072            }
1073            impl Associative for () {}
1074            impl Commutative for () {}
1075            impl Idempotent for () {}
1076            impl Invertible for () {
1077                fn inverse(_x: &Self::T) -> Self::T {}
1078            }
1079        };
1080        (@impl $($T:ident $i:tt)*) => {
1081            impl<$($T: Magma),*> Magma for ($($T,)*) {
1082                type T = ($(<$T as Magma>::T,)*);
1083                fn operate(x: &Self::T, y: &Self::T) -> Self::T {
1084                    ($(<$T as Magma>::operate(&x.$i, &y.$i),)*)
1085                }
1086            }
1087            impl<$($T: Unital),*> Unital for ($($T,)*) {
1088                fn unit() -> Self::T {
1089                    ($(<$T as Unital>::unit(),)*)
1090                }
1091            }
1092            impl<$($T: Associative),*> Associative for ($($T,)*) {}
1093            impl<$($T: Commutative),*> Commutative for ($($T,)*) {}
1094            impl<$($T: Idempotent),*> Idempotent for ($($T,)*) {}
1095            impl<$($T: Invertible),*> Invertible for ($($T,)*) {
1096                fn inverse(x: &Self::T) -> Self::T {
1097                    ($(<$T as Invertible>::inverse(&x.$i),)*)
1098                }
1099            }
1100        };
1101        (@inner $($T:ident $i:tt)*; $U:ident $j:tt $($t:tt)*) => {
1102            impl_tuple_operation!(@impl $($T $i)*);
1103            impl_tuple_operation!(@inner $($T $i)* $U $j; $($t)*);
1104        };
1105        (@inner $($T:ident $i:tt)*;) => {
1106            impl_tuple_operation!(@impl $($T $i)*);
1107        };
1108        ($($t:tt)*) => {
1109            impl_tuple_operation!(@inner ; $($t)*);
1110        };
1111    }
1112    impl_tuple_operation!(A 0 B 1 C 2 D 3 E 4 F 5 G 6 H 7 I 8 J 9);
1113
1114    #[cfg(test)]
1115    mod tests {
1116        use super::*;
1117        use crate::num::mint_basic::MInt998244353;
1118
1119        #[test]
1120        fn test_tuple_operation() {
1121            type MInt = MInt998244353;
1122            type M = (AdditiveOperation<MInt>, MultiplicativeOperation<MInt>);
1123            let iter = (-5..=5).flat_map(|x| (-5..=5).map(move |y| (MInt::from(x), MInt::from(y))));
1124            for a in iter.clone() {
1125                assert!(M::check_unital(&a));
1126                if !a.1.is_zero() {
1127                    assert!(M::check_invertible(&a));
1128                }
1129                for b in iter.clone() {
1130                    assert!(M::check_commutative(&a, &b));
1131                    for c in iter.clone() {
1132                        assert!(M::check_associative(&a, &b, &c));
1133                    }
1134                }
1135            }
1136        }
1137    }
1138}
1139
1140#[codesnip::entry("ArrayOperation")]
1141pub use self::array_operation_impl::ArrayOperation;
1142#[codesnip::entry("ArrayOperation", include("algebra", "array"))]
1143mod array_operation_impl {
1144    use super::*;
1145    use crate::array;
1146    use std::marker::PhantomData;
1147    pub struct ArrayOperation<M, const N: usize> {
1148        _marker: PhantomData<fn() -> M>,
1149    }
1150    impl<M, const N: usize> Magma for ArrayOperation<M, N>
1151    where
1152        M: Magma,
1153    {
1154        type T = [M::T; N];
1155        #[inline]
1156        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
1157            array!(|i| M::operate(&x[i], &y[i]); N)
1158        }
1159    }
1160    impl<M, const N: usize> Unital for ArrayOperation<M, N>
1161    where
1162        M: Unital,
1163    {
1164        #[inline]
1165        fn unit() -> Self::T {
1166            array!(|| M::unit(); N)
1167        }
1168    }
1169    impl<M, const N: usize> Associative for ArrayOperation<M, N> where M: Associative {}
1170    impl<M, const N: usize> Commutative for ArrayOperation<M, N> where M: Commutative {}
1171    impl<M, const N: usize> Idempotent for ArrayOperation<M, N> where M: Idempotent {}
1172    impl<M, const N: usize> Invertible for ArrayOperation<M, N>
1173    where
1174        M: Invertible,
1175    {
1176        #[inline]
1177        fn inverse(x: &Self::T) -> Self::T {
1178            array!(|i| M::inverse(&x[i]); N)
1179        }
1180    }
1181
1182    #[cfg(test)]
1183    mod tests {
1184        use super::*;
1185
1186        #[test]
1187        fn test_array_operation() {
1188            type M = ArrayOperation<AdditiveOperation<i32>, 2>;
1189
1190            let iter = (-5..=5).flat_map(|x| (-5..=5).map(move |y| [x, y]));
1191            for a in iter.clone() {
1192                assert!(M::check_unital(&a));
1193                assert!(M::check_invertible(&a));
1194                for b in iter.clone() {
1195                    assert!(M::check_commutative(&a, &b));
1196                    for c in iter.clone() {
1197                        assert!(M::check_associative(&a, &b, &c));
1198                    }
1199                }
1200            }
1201        }
1202    }
1203}
1204
1205#[codesnip::entry("CountingOperation")]
1206pub use self::counting_operation_impl::CountingOperation;
1207#[codesnip::entry("CountingOperation", include("algebra"))]
1208mod counting_operation_impl {
1209    use super::*;
1210    use std::marker::PhantomData;
1211    pub struct CountingOperation<M> {
1212        _marker: PhantomData<fn() -> M>,
1213    }
1214    impl<M> Magma for CountingOperation<M>
1215    where
1216        M: Magma<T: PartialEq> + Idempotent,
1217    {
1218        type T = (M::T, usize);
1219        #[inline]
1220        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
1221            let z = M::operate(&x.0, &y.0);
1222            match (z == x.0, z == y.0) {
1223                (true, true) => (z, x.1 + y.1),
1224                (true, false) => (z, x.1),
1225                (false, true) => (z, y.1),
1226                (false, false) => (z, 1),
1227            }
1228        }
1229    }
1230    impl<M> Unital for CountingOperation<M>
1231    where
1232        M: Unital<T: PartialEq> + Idempotent,
1233    {
1234        #[inline]
1235        fn unit() -> Self::T {
1236            (M::unit(), 0)
1237        }
1238    }
1239    impl<M> Associative for CountingOperation<M> where M: Associative<T: PartialEq> + Idempotent {}
1240    impl<M> Commutative for CountingOperation<M> where M: Commutative<T: PartialEq> + Idempotent {}
1241
1242    #[cfg(test)]
1243    mod tests {
1244        use super::*;
1245
1246        #[test]
1247        fn test_counting_operation() {
1248            type M = CountingOperation<MaxOperation<i32>>;
1249            let iter = (-5..=5).flat_map(|x| (1..=5).map(move |y| (x, y)));
1250            for a in iter.clone() {
1251                assert!(M::check_unital(&a));
1252                for b in iter.clone() {
1253                    assert!(M::check_commutative(&a, &b));
1254                    for c in iter.clone() {
1255                        assert!(M::check_associative(&a, &b, &c));
1256                    }
1257                }
1258            }
1259        }
1260    }
1261}
1262
1263#[codesnip::entry("ReverseOperation")]
1264pub use self::reverse_operation_impl::ReverseOperation;
1265#[codesnip::entry("ReverseOperation", include("algebra"))]
1266mod reverse_operation_impl {
1267    use super::*;
1268    use std::marker::PhantomData;
1269    pub struct ReverseOperation<M> {
1270        _marker: PhantomData<fn() -> M>,
1271    }
1272    impl<M> Magma for ReverseOperation<M>
1273    where
1274        M: Magma,
1275    {
1276        type T = M::T;
1277        #[inline]
1278        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
1279            M::operate(y, x)
1280        }
1281    }
1282    impl<M> Unital for ReverseOperation<M>
1283    where
1284        M: Unital,
1285    {
1286        #[inline]
1287        fn unit() -> Self::T {
1288            M::unit()
1289        }
1290    }
1291    impl<M> Associative for ReverseOperation<M> where M: Associative {}
1292    impl<M> Commutative for ReverseOperation<M> where M: Commutative {}
1293    impl<M> Invertible for ReverseOperation<M>
1294    where
1295        M: Invertible,
1296    {
1297        #[inline]
1298        fn inverse(x: &Self::T) -> Self::T {
1299            M::inverse(x)
1300        }
1301    }
1302    impl<M> Idempotent for ReverseOperation<M> where M: Idempotent {}
1303
1304    #[cfg(test)]
1305    mod tests {
1306        use super::*;
1307        use crate::num::mint_basic::MInt998244353;
1308
1309        #[test]
1310        fn test_reverse_operation() {
1311            type MInt = MInt998244353;
1312            type M = ReverseOperation<LinearOperation<MInt>>;
1313            let iter = (-3..=3).flat_map(|x| (-3..=3).map(move |y| (MInt::from(x), MInt::from(y))));
1314            for a in iter.clone() {
1315                assert!(M::check_unital(&a));
1316                if !a.0.is_zero() {
1317                    assert!(M::check_invertible(&a));
1318                }
1319                for b in iter.clone() {
1320                    for c in iter.clone() {
1321                        assert!(M::check_associative(&a, &b, &c));
1322                    }
1323                }
1324            }
1325        }
1326    }
1327}
1328
1329#[codesnip::entry("TopkOperation")]
1330pub use self::topk_operation_impl::TopkOperation;
1331#[codesnip::entry("TopkOperation", include("algebra", "bounded", "array"))]
1332mod topk_operation_impl {
1333    use super::*;
1334    use std::marker::PhantomData;
1335    pub struct TopkOperation<const K: usize, T>
1336    where
1337        T: Clone + Ord + Bounded,
1338    {
1339        _marker: PhantomData<fn() -> T>,
1340    }
1341    impl<const K: usize, T> Magma for TopkOperation<K, T>
1342    where
1343        T: Clone + Ord + Bounded,
1344    {
1345        type T = [T; K];
1346        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
1347            let mut i = 0;
1348            let mut j = 0;
1349            crate::array![|| if i == K || j != K && x[i] < y[j] {
1350                let t = &y[j];
1351                j += 1;
1352                t.clone()
1353            } else {
1354                let t = &x[i];
1355                i += 1;
1356                t.clone()
1357            }; K]
1358        }
1359    }
1360    impl<const K: usize, T> Unital for TopkOperation<K, T>
1361    where
1362        T: Clone + Ord + Bounded,
1363    {
1364        fn unit() -> Self::T {
1365            crate::array![|| <T as Bounded>::minimum(); K]
1366        }
1367    }
1368    impl<const K: usize, T> Associative for TopkOperation<K, T> where T: Clone + Ord + Bounded {}
1369    impl<const K: usize, T> Commutative for TopkOperation<K, T> where T: Clone + Ord + Bounded {}
1370
1371    #[cfg(test)]
1372    mod tests {
1373        use super::*;
1374        use crate::{array, tools::Xorshift};
1375
1376        #[test]
1377        fn test_topk_operation() {
1378            type M = TopkOperation<4, i64>;
1379            let mut rng = Xorshift::default();
1380            for _ in 0..100 {
1381                let mut x = [i64::MIN; 4];
1382                for _ in 0..100 {
1383                    let mut y = [i64::MIN; 4];
1384                    for y in &mut y {
1385                        *y = rng.random(0..1000);
1386                    }
1387                    y.sort_unstable();
1388                    y.reverse();
1389                    let z = {
1390                        let mut x = x.to_vec();
1391                        x.extend(&y);
1392                        x.sort_unstable();
1393                        x.reverse();
1394                        x.truncate(4);
1395                        x
1396                    };
1397                    let zz = M::operate(&x, &y);
1398                    for (z, zz) in z.iter().zip(&zz) {
1399                        assert_eq!(z, zz);
1400                    }
1401                    x = zz;
1402                }
1403
1404                let mut g = || {
1405                    if rng.random(0..3) == 0 {
1406                        i64::MIN
1407                    } else {
1408                        rng.random(0..10)
1409                    }
1410                };
1411                let mut a = array![|| g(); 4];
1412                a.sort_unstable();
1413                a.reverse();
1414                assert!(M::check_unital(&a));
1415                let mut b = array![|| g(); 4];
1416                b.sort_unstable();
1417                b.reverse();
1418                assert!(M::check_commutative(&a, &b));
1419                let mut c = array![|| g(); 4];
1420                c.sort_unstable();
1421                c.reverse();
1422                assert!(M::check_associative(&a, &b, &c));
1423            }
1424        }
1425    }
1426}
1427
1428#[codesnip::entry("BottomkOperation")]
1429pub use self::bottomk_operation_impl::BottomkOperation;
1430#[codesnip::entry("BottomkOperation", include("algebra", "bounded", "array"))]
1431mod bottomk_operation_impl {
1432    use super::*;
1433    use std::marker::PhantomData;
1434    pub struct BottomkOperation<const K: usize, T>
1435    where
1436        T: Clone + Ord + Bounded,
1437    {
1438        _marker: PhantomData<fn() -> T>,
1439    }
1440    impl<const K: usize, T> Magma for BottomkOperation<K, T>
1441    where
1442        T: Clone + Ord + Bounded,
1443    {
1444        type T = [T; K];
1445        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
1446            let mut i = 0;
1447            let mut j = 0;
1448            crate::array![|| if i == K || j != K && x[i] > y[j] {
1449                let t = &y[j];
1450                j += 1;
1451                t.clone()
1452            } else {
1453                let t = &x[i];
1454                i += 1;
1455                t.clone()
1456            }; K]
1457        }
1458    }
1459    impl<const K: usize, T> Unital for BottomkOperation<K, T>
1460    where
1461        T: Clone + Ord + Bounded,
1462    {
1463        fn unit() -> Self::T {
1464            crate::array![|| <T as Bounded>::maximum(); K]
1465        }
1466    }
1467    impl<const K: usize, T> Associative for BottomkOperation<K, T> where T: Clone + Ord + Bounded {}
1468    impl<const K: usize, T> Commutative for BottomkOperation<K, T> where T: Clone + Ord + Bounded {}
1469
1470    #[cfg(test)]
1471    mod tests {
1472        use super::*;
1473        use crate::{array, tools::Xorshift};
1474
1475        #[test]
1476        fn test_bottomk_operation() {
1477            type M = BottomkOperation<4, i64>;
1478            let mut rng = Xorshift::default();
1479            for _ in 0..100 {
1480                let mut x = [i64::MAX; 4];
1481                for _ in 0..100 {
1482                    let mut y = [i64::MAX; 4];
1483                    for y in &mut y {
1484                        *y = rng.random(0..1000);
1485                    }
1486                    y.sort_unstable();
1487                    let z = {
1488                        let mut x = x.to_vec();
1489                        x.extend(&y);
1490                        x.sort_unstable();
1491                        x.truncate(4);
1492                        x
1493                    };
1494                    let zz = M::operate(&x, &y);
1495                    for (z, zz) in z.iter().zip(&zz) {
1496                        assert_eq!(z, zz);
1497                    }
1498                    x = zz;
1499                }
1500
1501                let mut g = || {
1502                    if rng.random(0..3) == 0 {
1503                        i64::MAX
1504                    } else {
1505                        rng.random(0..10)
1506                    }
1507                };
1508                let mut a = array![|| g(); 4];
1509                a.sort_unstable();
1510                assert!(M::check_unital(&a));
1511                let mut b = array![|| g(); 4];
1512                b.sort_unstable();
1513                assert!(M::check_commutative(&a, &b));
1514                let mut c = array![|| g(); 4];
1515                c.sort_unstable();
1516                assert!(M::check_associative(&a, &b, &c));
1517            }
1518        }
1519    }
1520}
1521
1522#[codesnip::entry("DedupedTopkOperation")]
1523pub use self::deduped_topk_operation_impl::DedupedTopkOperation;
1524#[codesnip::entry("DedupedTopkOperation", include("algebra", "bounded", "array"))]
1525mod deduped_topk_operation_impl {
1526    use super::*;
1527    use std::marker::PhantomData;
1528
1529    pub struct DedupedTopkOperation<const K: usize, T, U>
1530    where
1531        T: Clone + Ord + Bounded,
1532        U: Clone + Eq,
1533    {
1534        _marker: PhantomData<fn() -> (T, U)>,
1535    }
1536    impl<const K: usize, T, U> Magma for DedupedTopkOperation<K, T, U>
1537    where
1538        T: Clone + Ord + Bounded,
1539        U: Clone + Eq,
1540    {
1541        type T = [(T, Option<U>); K];
1542        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
1543            let mut i = 0;
1544            let mut j = 0;
1545            let mut k = 0;
1546            let mut out = crate::array![|| (T::minimum(), None); K];
1547            while k < K && (i < K || j < K) {
1548                if j == K || (i < K && x[i].0 >= y[j].0) {
1549                    if (0..j).all(|l| x[i].1 != y[l].1) {
1550                        out[k] = x[i].clone();
1551                        k += 1;
1552                    }
1553                    i += 1;
1554                } else {
1555                    if (0..i).all(|l| y[j].1 != x[l].1) {
1556                        out[k] = y[j].clone();
1557                        k += 1;
1558                    }
1559                    j += 1;
1560                }
1561            }
1562            out
1563        }
1564    }
1565    impl<const K: usize, T, U> Unital for DedupedTopkOperation<K, T, U>
1566    where
1567        T: Clone + Ord + Bounded,
1568        U: Clone + Eq,
1569    {
1570        fn unit() -> Self::T {
1571            crate::array![|| (T::minimum(), None); K]
1572        }
1573    }
1574    impl<const K: usize, T, U> Associative for DedupedTopkOperation<K, T, U>
1575    where
1576        T: Clone + Ord + Bounded,
1577        U: Clone + Eq,
1578    {
1579    }
1580    impl<const K: usize, T, U> DedupedTopkOperation<K, T, U>
1581    where
1582        T: Clone + Ord + Bounded,
1583        U: Clone + Eq,
1584    {
1585        pub fn insert(x: &mut <Self as Magma>::T, item: (T, U)) {
1586            for i in 0..K {
1587                if x[i].0 < item.0 {
1588                    let j = (i..K)
1589                        .find(|&j| x[j].1.as_ref() == Some(&item.1))
1590                        .unwrap_or(K - 1);
1591                    for k in (i..j).rev() {
1592                        x[k + 1] = x[k].clone();
1593                    }
1594                    x[i] = (item.0, Some(item.1));
1595                    break;
1596                } else if x[i].1.as_ref() == Some(&item.1) {
1597                    break;
1598                }
1599            }
1600        }
1601        pub fn topn<const N: usize, const M: usize>(
1602            x: &<Self as Magma>::T,
1603            excludes: &[U; M],
1604        ) -> [(T, Option<U>); N] {
1605            let mut out = crate::array![|| (T::minimum(), None); N];
1606            let mut i = 0;
1607            let mut j = 0;
1608            while i < K && j < N {
1609                if excludes.iter().all(|e| x[i].1.as_ref() != Some(e)) {
1610                    out[j] = x[i].clone();
1611                    j += 1;
1612                }
1613                i += 1;
1614            }
1615            out
1616        }
1617    }
1618
1619    #[cfg(test)]
1620    mod tests {
1621        use super::*;
1622        use crate::{array, tools::Xorshift};
1623        use std::collections::HashSet;
1624
1625        fn normalize(x: impl IntoIterator<Item = (i64, Option<i32>)>) -> [(i64, Option<i32>); 4] {
1626            let mut x: Vec<_> = x.into_iter().collect();
1627            x.sort_unstable();
1628            x.reverse();
1629            let mut used = HashSet::new();
1630            x.retain(|(_, u)| {
1631                if let Some(u) = u {
1632                    if used.contains(u) {
1633                        return false;
1634                    }
1635                    used.insert(*u);
1636                }
1637                true
1638            });
1639            x.resize_with(4, || (i64::MIN, None));
1640            x.try_into().unwrap()
1641        }
1642
1643        #[test]
1644        fn test_deduped_topk_operation() {
1645            type M = DedupedTopkOperation<4, i64, i32>;
1646            let mut rng = Xorshift::default();
1647            for _ in 0..100 {
1648                let mut x = [(i64::MIN, None); 4];
1649                for _ in 0..100 {
1650                    let mut y = [(i64::MIN, None); 4];
1651                    for y in &mut y {
1652                        *y = (rng.random(0..1000), Some(rng.random(0i32..10)));
1653                    }
1654                    y = normalize(y);
1655                    let z = normalize(x.iter().cloned().chain(y.iter().cloned()));
1656                    let zz = M::operate(&x, &y);
1657                    for (z, zz) in z.iter().zip(&zz) {
1658                        assert_eq!(z.0, zz.0);
1659                    }
1660                    assert_eq!(
1661                        zz.iter()
1662                            .filter_map(|(_, u)| u.as_ref())
1663                            .collect::<HashSet<_>>()
1664                            .len(),
1665                        zz.iter().filter_map(|(_, u)| u.as_ref()).count()
1666                    );
1667                    x = zz;
1668                }
1669
1670                let mut g = || {
1671                    if rng.random(0..3) == 0 {
1672                        (i64::MIN, None)
1673                    } else {
1674                        (rng.random(0..10), Some(rng.random(0i32..10)))
1675                    }
1676                };
1677                let mut a = array![|| g(); 4];
1678                a = normalize(a);
1679                assert!(M::check_unital(&a));
1680                let mut b = array![|| g(); 4];
1681                b = normalize(b);
1682                let mut c = array![|| g(); 4];
1683                c = normalize(c);
1684                assert!(M::check_associative(&a, &b, &c));
1685            }
1686        }
1687
1688        #[test]
1689        fn test_deduped_topk_insert() {
1690            type M = DedupedTopkOperation<4, i64, i32>;
1691            let mut rng = Xorshift::default();
1692            for _ in 0..100 {
1693                let mut x = [(i64::MIN, None); 4];
1694                for _ in 0..100 {
1695                    let t = (rng.random(0..1000), rng.random(0i32..10));
1696                    let z = normalize(x.iter().cloned().chain([(t.0, Some(t.1))]));
1697                    M::insert(&mut x, t);
1698                    for (z, zz) in z.iter().zip(&x) {
1699                        assert_eq!(z.0, zz.0);
1700                    }
1701                    assert_eq!(
1702                        x.iter()
1703                            .filter_map(|(_, u)| u.as_ref())
1704                            .collect::<HashSet<_>>()
1705                            .len(),
1706                        x.iter().filter_map(|(_, u)| u.as_ref()).count()
1707                    );
1708                }
1709            }
1710        }
1711
1712        #[test]
1713        fn test_deduped_topk_topn() {
1714            type M = DedupedTopkOperation<4, i64, i32>;
1715            let mut rng = Xorshift::default();
1716            for _ in 0..100 {
1717                let mut x = [(i64::MIN, None); 4];
1718                for x in &mut x {
1719                    *x = (rng.random(0..1000), Some(rng.random(0i32..10)));
1720                }
1721                x = normalize(x.iter().cloned());
1722                for _ in 0..100 {
1723                    let mut excludes = [0i32; 3];
1724                    for e in &mut excludes {
1725                        *e = rng.random(0i32..10);
1726                    }
1727                    let topn: [_; 3] = M::topn(&x, &excludes);
1728                    let mut expected: Vec<_> = x
1729                        .iter()
1730                        .filter(|(_, u)| excludes.iter().all(|e| u.as_ref() != Some(e)))
1731                        .cloned()
1732                        .take(3)
1733                        .collect();
1734                    expected.resize_with(3, || (i64::MIN, None));
1735                    for (expected, topn) in expected.iter().zip(&topn) {
1736                        assert_eq!(expected.0, topn.0);
1737                    }
1738                }
1739            }
1740        }
1741    }
1742}
1743
1744#[codesnip::entry("DedupedBottomkOperation")]
1745pub use self::deduped_bottomk_operation_impl::DedupedBottomkOperation;
1746#[codesnip::entry("DedupedBottomkOperation", include("algebra", "bounded", "array"))]
1747mod deduped_bottomk_operation_impl {
1748    use super::*;
1749    use std::marker::PhantomData;
1750
1751    pub struct DedupedBottomkOperation<const K: usize, T, U>
1752    where
1753        T: Clone + Ord + Bounded,
1754        U: Clone + Eq,
1755    {
1756        _marker: PhantomData<fn() -> (T, U)>,
1757    }
1758    impl<const K: usize, T, U> Magma for DedupedBottomkOperation<K, T, U>
1759    where
1760        T: Clone + Ord + Bounded,
1761        U: Clone + Eq,
1762    {
1763        type T = [(T, Option<U>); K];
1764        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
1765            let mut i = 0;
1766            let mut j = 0;
1767            let mut k = 0;
1768            let mut out = crate::array![|| (T::maximum(), None); K];
1769            while k < K && (i < K || j < K) {
1770                if j == K || (i < K && x[i].0 <= y[j].0) {
1771                    if (0..j).all(|l| x[i].1 != y[l].1) {
1772                        out[k] = x[i].clone();
1773                        k += 1;
1774                    }
1775                    i += 1;
1776                } else {
1777                    if (0..i).all(|l| y[j].1 != x[l].1) {
1778                        out[k] = y[j].clone();
1779                        k += 1;
1780                    }
1781                    j += 1;
1782                }
1783            }
1784            out
1785        }
1786    }
1787    impl<const K: usize, T, U> Unital for DedupedBottomkOperation<K, T, U>
1788    where
1789        T: Clone + Ord + Bounded,
1790        U: Clone + Eq,
1791    {
1792        fn unit() -> Self::T {
1793            crate::array![|| (T::maximum(), None); K]
1794        }
1795    }
1796    impl<const K: usize, T, U> Associative for DedupedBottomkOperation<K, T, U>
1797    where
1798        T: Clone + Ord + Bounded,
1799        U: Clone + Eq,
1800    {
1801    }
1802    impl<const K: usize, T, U> DedupedBottomkOperation<K, T, U>
1803    where
1804        T: Clone + Ord + Bounded,
1805        U: Clone + Eq,
1806    {
1807        pub fn insert(x: &mut <Self as Magma>::T, item: (T, U)) {
1808            for i in 0..K {
1809                if x[i].0 > item.0 {
1810                    let j = (i..K)
1811                        .find(|&j| x[j].1.as_ref() == Some(&item.1))
1812                        .unwrap_or(K - 1);
1813                    for k in (i..j).rev() {
1814                        x[k + 1] = x[k].clone();
1815                    }
1816                    x[i] = (item.0, Some(item.1));
1817                    break;
1818                } else if x[i].1.as_ref() == Some(&item.1) {
1819                    break;
1820                }
1821            }
1822        }
1823        pub fn bottomn<const N: usize, const M: usize>(
1824            x: &<Self as Magma>::T,
1825            excludes: &[U; M],
1826        ) -> [(T, Option<U>); N] {
1827            let mut out = crate::array![|| (T::maximum(), None); N];
1828            let mut i = 0;
1829            let mut j = 0;
1830            while i < K && j < N {
1831                if excludes.iter().all(|e| x[i].1.as_ref() != Some(e)) {
1832                    out[j] = x[i].clone();
1833                    j += 1;
1834                }
1835                i += 1;
1836            }
1837            out
1838        }
1839    }
1840
1841    #[cfg(test)]
1842    mod tests {
1843        use super::*;
1844        use crate::{array, tools::Xorshift};
1845        use std::collections::HashSet;
1846
1847        fn normalize(x: impl IntoIterator<Item = (i64, Option<i32>)>) -> [(i64, Option<i32>); 4] {
1848            let mut x: Vec<_> = x.into_iter().collect();
1849            x.sort_unstable();
1850            let mut used = HashSet::new();
1851            x.retain(|(_, u)| {
1852                if let Some(u) = u {
1853                    if used.contains(u) {
1854                        return false;
1855                    }
1856                    used.insert(*u);
1857                }
1858                true
1859            });
1860            x.resize_with(4, || (i64::MAX, None));
1861            x.try_into().unwrap()
1862        }
1863
1864        #[test]
1865        fn test_deduped_bottomk_operation() {
1866            type M = DedupedBottomkOperation<4, i64, i32>;
1867            let mut rng = Xorshift::default();
1868            for _ in 0..100 {
1869                let mut x = [(i64::MAX, None); 4];
1870                for _ in 0..100 {
1871                    let mut y = [(i64::MAX, None); 4];
1872                    for y in &mut y {
1873                        *y = (rng.random(0..1000), Some(rng.random(0i32..10)));
1874                    }
1875                    y = normalize(y);
1876                    let z = normalize(x.iter().cloned().chain(y.iter().cloned()));
1877                    let zz = M::operate(&x, &y);
1878                    for (z, zz) in z.iter().zip(&zz) {
1879                        assert_eq!(z.0, zz.0);
1880                    }
1881                    assert_eq!(
1882                        zz.iter()
1883                            .filter_map(|(_, u)| u.as_ref())
1884                            .collect::<HashSet<_>>()
1885                            .len(),
1886                        zz.iter().filter_map(|(_, u)| u.as_ref()).count()
1887                    );
1888                    x = zz;
1889                }
1890
1891                let mut g = || {
1892                    if rng.random(0..3) == 0 {
1893                        (i64::MAX, None)
1894                    } else {
1895                        (rng.random(0..10), Some(rng.random(0i32..10)))
1896                    }
1897                };
1898                let mut a = array![|| g(); 4];
1899                a = normalize(a);
1900                assert!(M::check_unital(&a));
1901                let mut b = array![|| g(); 4];
1902                b = normalize(b);
1903                let mut c = array![|| g(); 4];
1904                c = normalize(c);
1905                assert!(M::check_associative(&a, &b, &c));
1906            }
1907        }
1908
1909        #[test]
1910        fn test_deduped_bottomk_insert() {
1911            type M = DedupedBottomkOperation<4, i64, i32>;
1912            let mut rng = Xorshift::default();
1913            for _ in 0..100 {
1914                let mut x = [(i64::MAX, None); 4];
1915                for _ in 0..100 {
1916                    let t = (rng.random(0..1000), rng.random(0i32..10));
1917                    let z = normalize(x.iter().cloned().chain([(t.0, Some(t.1))]));
1918                    M::insert(&mut x, t);
1919                    for (z, zz) in z.iter().zip(&x) {
1920                        assert_eq!(z.0, zz.0);
1921                    }
1922                    assert_eq!(
1923                        x.iter()
1924                            .filter_map(|(_, u)| u.as_ref())
1925                            .collect::<HashSet<_>>()
1926                            .len(),
1927                        x.iter().filter_map(|(_, u)| u.as_ref()).count()
1928                    );
1929                }
1930            }
1931        }
1932
1933        #[test]
1934        fn test_deduped_bottomk_bottomn() {
1935            type M = DedupedBottomkOperation<4, i64, i32>;
1936            let mut rng = Xorshift::default();
1937            for _ in 0..100 {
1938                let mut x = [(i64::MAX, None); 4];
1939                for x in &mut x {
1940                    *x = (rng.random(0..1000), Some(rng.random(0i32..10)));
1941                }
1942                x = normalize(x.iter().cloned());
1943                for _ in 0..100 {
1944                    let mut excludes = [0i32; 3];
1945                    for e in &mut excludes {
1946                        *e = rng.random(0i32..10);
1947                    }
1948                    let bottomn: [_; 3] = M::bottomn(&x, &excludes);
1949                    let mut expected: Vec<_> = x
1950                        .iter()
1951                        .filter(|(_, u)| excludes.iter().all(|e| u.as_ref() != Some(e)))
1952                        .cloned()
1953                        .take(3)
1954                        .collect();
1955                    expected.resize_with(3, || (i64::MAX, None));
1956                    for (expected, bottomn) in expected.iter().zip(&bottomn) {
1957                        assert_eq!(expected.0, bottomn.0);
1958                    }
1959                }
1960            }
1961        }
1962    }
1963}
1964
1965#[codesnip::entry("PermutationOperation")]
1966pub use self::permutation_operation_impl::PermutationOperation;
1967#[codesnip::entry("PermutationOperation", include("algebra"))]
1968mod permutation_operation_impl {
1969    use super::*;
1970    pub enum PermutationOperation {}
1971    impl Magma for PermutationOperation {
1972        type T = Vec<usize>;
1973        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
1974            let n = x.len().max(y.len());
1975            let z: Vec<_> = (0..n)
1976                .map(|i| {
1977                    let j = y.get(i).cloned().unwrap_or(i);
1978                    x.get(j).cloned().unwrap_or(j)
1979                })
1980                .collect();
1981            z
1982        }
1983    }
1984    impl Associative for PermutationOperation {}
1985    impl Unital for PermutationOperation {
1986        fn unit() -> Self::T {
1987            Vec::new()
1988        }
1989
1990        fn is_unit(x: &Self::T) -> bool
1991        where
1992            Self::T: PartialEq,
1993        {
1994            x.iter().enumerate().all(|(i, &x)| i == x)
1995        }
1996    }
1997    impl Invertible for PermutationOperation {
1998        fn inverse(x: &Self::T) -> Self::T {
1999            let mut y = vec![0; x.len()];
2000            for (i, x) in x.iter().enumerate() {
2001                y[*x] = i;
2002            }
2003            y
2004        }
2005    }
2006
2007    #[cfg(test)]
2008    mod tests {
2009        use super::*;
2010        use crate::tools::Xorshift;
2011
2012        #[test]
2013        fn test_permutation_operation() {
2014            type M = PermutationOperation;
2015            let mut rng = Xorshift::default();
2016            for _ in 0..100 {
2017                let mut a: Vec<usize> = (0..rng.random(0..20)).collect();
2018                let mut b: Vec<usize> = (0..rng.random(0..20)).collect();
2019                let mut c: Vec<usize> = (0..rng.random(0..20)).collect();
2020                rng.shuffle(&mut a);
2021                rng.shuffle(&mut b);
2022                rng.shuffle(&mut c);
2023                assert!(M::check_unital(&a));
2024                assert!(M::check_invertible(&a));
2025                assert!(M::check_associative(&a, &b, &c));
2026            }
2027        }
2028    }
2029}
2030
2031#[codesnip::entry("FindMajorityOperation")]
2032pub use self::find_majority_operation_impl::FindMajorityOperation;
2033#[codesnip::entry("FindMajorityOperation", include("algebra"))]
2034mod find_majority_operation_impl {
2035    use super::*;
2036    use std::{cmp::Ordering, marker::PhantomData};
2037    /// Find majority(strict) of a sequence.
2038    ///
2039    /// fold $x \in S$ with `(Some(x), 1)`
2040    ///
2041    /// `(Some(m), _)` represents `m` may be a majority of $S$.
2042    ///
2043    /// `(None, _)` represents that there is no majority value.
2044    pub struct FindMajorityOperation<T> {
2045        _marker: PhantomData<fn() -> T>,
2046    }
2047    impl<T> Magma for FindMajorityOperation<T>
2048    where
2049        T: Clone + Eq,
2050    {
2051        type T = (Option<T>, usize);
2052        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
2053            if y.0.is_none() {
2054                x.clone()
2055            } else if x.0.is_none() {
2056                y.clone()
2057            } else {
2058                match (x.0.eq(&y.0), x.1.cmp(&y.1)) {
2059                    (true, _) => (x.0.clone(), x.1 + y.1),
2060                    (_, Ordering::Less) => (y.0.clone(), y.1 - x.1),
2061                    (_, Ordering::Equal) => (None, 0),
2062                    (_, Ordering::Greater) => (x.0.clone(), x.1 - y.1),
2063                }
2064            }
2065        }
2066    }
2067    impl<T> Unital for FindMajorityOperation<T>
2068    where
2069        T: Clone + Eq,
2070    {
2071        fn unit() -> Self::T {
2072            (None, 0)
2073        }
2074    }
2075    impl<T> Associative for FindMajorityOperation<T> where T: Clone + Eq {}
2076
2077    #[cfg(test)]
2078    mod tests {
2079        use super::*;
2080        use crate::tools::testutil::{exhaustive_sequences, sample_usize};
2081        use std::collections::HashMap;
2082
2083        #[test]
2084        fn test_find_majority_operation() {
2085            type M = FindMajorityOperation<i32>;
2086            let mut rng = crate::tools::Xorshift::default();
2087            let mut cases: Vec<_> = exhaustive_sequences(-1..=1, 0..=8).collect();
2088            for n in sample_usize(&mut rng, 16, 0..=100, 1000) {
2089                cases.push(rng.random_iter(-5..=5).take(n).collect());
2090            }
2091            for values in cases {
2092                let n = values.len();
2093                let mut count = HashMap::<_, usize>::new();
2094                let mut actual = M::unit();
2095                for &value in &values {
2096                    *count.entry(value).or_default() += 1;
2097                    let element = (Some(value), 1);
2098                    assert!(M::check_unital(&element));
2099                    actual = M::operate(&actual, &element);
2100                }
2101                if let Some((&key, _)) = count.iter().find(|&(_, &count)| count * 2 > n) {
2102                    assert_eq!(actual.0, Some(key));
2103                }
2104                assert!(actual.0.is_none_or(|key| values.contains(&key)));
2105            }
2106        }
2107    }
2108}
2109
2110pub use self::concatenate_operation::{ConcatenateOperation, SortedConcatenateOperation};
2111mod concatenate_operation {
2112    use super::*;
2113    use std::marker::PhantomData;
2114    pub struct ConcatenateOperation<T> {
2115        _marker: PhantomData<fn() -> T>,
2116    }
2117    impl<T> Magma for ConcatenateOperation<T>
2118    where
2119        T: Clone,
2120    {
2121        type T = Vec<T>;
2122        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
2123            x.iter().chain(y.iter()).cloned().collect()
2124        }
2125    }
2126    impl<T> Unital for ConcatenateOperation<T>
2127    where
2128        T: Clone,
2129    {
2130        fn unit() -> Self::T {
2131            Vec::new()
2132        }
2133    }
2134    impl<T> Associative for ConcatenateOperation<T> where T: Clone {}
2135
2136    pub struct SortedConcatenateOperation<T> {
2137        _marker: PhantomData<fn() -> T>,
2138    }
2139    impl<T> Magma for SortedConcatenateOperation<T>
2140    where
2141        T: Clone + Ord,
2142    {
2143        type T = Vec<T>;
2144        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
2145            let mut xit = x.iter().cloned().peekable();
2146            let mut yit = y.iter().cloned().peekable();
2147            let mut z = Vec::with_capacity(x.len() + y.len());
2148            loop {
2149                match (xit.peek(), yit.peek()) {
2150                    (None, None) => break,
2151                    (Some(_), None) => z.push(xit.next().unwrap()),
2152                    (Some(x), Some(y)) if x <= y => z.push(xit.next().unwrap()),
2153                    _ => z.push(yit.next().unwrap()),
2154                }
2155            }
2156            z
2157        }
2158    }
2159    impl<T> Unital for SortedConcatenateOperation<T>
2160    where
2161        T: Clone + Ord,
2162    {
2163        fn unit() -> Self::T {
2164            Vec::new()
2165        }
2166    }
2167    impl<T> Associative for SortedConcatenateOperation<T> where T: Clone + Ord {}
2168    impl<T> Commutative for SortedConcatenateOperation<T> where T: Clone + Ord {}
2169
2170    #[cfg(test)]
2171    mod tests {
2172        use super::*;
2173        use crate::{rand, tools::Xorshift};
2174
2175        #[test]
2176        fn test_concatenate_operation() {
2177            type M = ConcatenateOperation<i32>;
2178            let mut rng = Xorshift::default();
2179            for _ in 0..100 {
2180                rand!(rng, n: 0..4, a: [0..10; n], m: 0..4, b: [0..10; m], l: 0..4, c: [0..10; l]);
2181                assert!(M::check_unital(&a));
2182                assert!(M::check_associative(&a, &b, &c));
2183
2184                let ab: Vec<_> = a.iter().chain(b.iter()).cloned().collect();
2185                assert_eq!(M::operate(&a, &b), ab);
2186            }
2187        }
2188
2189        #[test]
2190        fn test_sorted_concatenate_operation() {
2191            type M = SortedConcatenateOperation<i32>;
2192            let mut rng = Xorshift::default();
2193            for _ in 0..100 {
2194                rand!(rng, n: 0..4, mut a: [0..10; n], m: 0..4, mut b: [0..10; m], l: 0..4, mut c: [0..10; l]);
2195                a.sort_unstable();
2196                b.sort_unstable();
2197                c.sort_unstable();
2198                assert!(M::check_unital(&a));
2199                assert!(M::check_commutative(&a, &b));
2200                assert!(M::check_associative(&a, &b, &c));
2201
2202                let mut ab: Vec<_> = a.iter().chain(b.iter()).cloned().collect();
2203                ab.sort_unstable();
2204                assert_eq!(M::operate(&a, &b), ab);
2205            }
2206        }
2207    }
2208}
2209
2210#[codesnip::entry("MinimumIntervalMovementOperation")]
2211pub use self::minimum_interval_movement_impl::{
2212    MinimumIntervalMovement, MinimumIntervalMovementOperation,
2213};
2214#[codesnip::entry(
2215    "MinimumIntervalMovementOperation",
2216    include("algebra", "bounded", "zero_one")
2217)]
2218mod minimum_interval_movement_impl {
2219    use super::*;
2220    use std::{
2221        marker::PhantomData,
2222        ops::{Add, Sub},
2223    };
2224
2225    pub struct MinimumIntervalMovementOperation<T> {
2226        _marker: PhantomData<fn() -> T>,
2227    }
2228    #[derive(Debug, Clone)]
2229    pub struct MinimumIntervalMovement<T> {
2230        pos_range: (T, T),
2231        move_range: (T, T),
2232        cost: T,
2233    }
2234    impl<T> MinimumIntervalMovement<T>
2235    where
2236        T: Clone + Zero,
2237    {
2238        pub fn new(l: T, r: T) -> Self {
2239            Self {
2240                pos_range: (l.clone(), r.clone()),
2241                move_range: (l, r),
2242                cost: T::zero(),
2243            }
2244        }
2245    }
2246    impl<T> MinimumIntervalMovement<T>
2247    where
2248        T: Clone + Ord + Zero,
2249    {
2250        pub fn position(&self, x: &T) -> T {
2251            x.clamp(&self.pos_range.0, &self.pos_range.1).clone()
2252        }
2253    }
2254    impl<T> MinimumIntervalMovement<T>
2255    where
2256        T: Clone + Ord + Add<Output = T> + Sub<Output = T> + Zero,
2257    {
2258        pub fn move_cost(&self, x: &T) -> T {
2259            x.max(&self.move_range.0).clone() - x.min(&self.move_range.1).clone()
2260                + self.cost.clone()
2261        }
2262    }
2263    impl<T> Magma for MinimumIntervalMovementOperation<T>
2264    where
2265        T: Clone + Ord + Add<Output = T> + Sub<Output = T> + Zero,
2266    {
2267        type T = MinimumIntervalMovement<T>;
2268        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
2269            let pos_range = (
2270                (&x.pos_range.0)
2271                    .clamp(&y.pos_range.0, &y.pos_range.1)
2272                    .clone(),
2273                (&x.pos_range.1)
2274                    .clamp(&y.pos_range.0, &y.pos_range.1)
2275                    .clone(),
2276            );
2277            let move_range = (
2278                (&y.move_range.0)
2279                    .clamp(&x.move_range.0, &x.move_range.1)
2280                    .clone(),
2281                (&y.move_range.1)
2282                    .clamp(&x.move_range.0, &x.move_range.1)
2283                    .clone(),
2284            );
2285            let cost = x.cost.clone() + y.move_cost(&x.position(&move_range.0));
2286            MinimumIntervalMovement {
2287                pos_range,
2288                move_range,
2289                cost,
2290            }
2291        }
2292    }
2293    impl<T> Associative for MinimumIntervalMovementOperation<T> where
2294        T: Clone + Ord + Add<Output = T> + Sub<Output = T> + Zero
2295    {
2296    }
2297    impl<T> Unital for MinimumIntervalMovementOperation<T>
2298    where
2299        T: Clone + Ord + Add<Output = T> + Sub<Output = T> + Zero + Bounded,
2300    {
2301        fn unit() -> Self::T {
2302            MinimumIntervalMovement::new(T::minimum(), T::maximum())
2303        }
2304    }
2305
2306    #[cfg(test)]
2307    mod tests {
2308        use super::*;
2309        use crate::{chmin, tools::Xorshift};
2310        use std::collections::HashMap;
2311
2312        #[test]
2313        fn test_minimum_interval_movement_operation() {
2314            type M = MinimumIntervalMovementOperation<i32>;
2315            let mut rng = Xorshift::default();
2316            for _ in 0..100 {
2317                let mut min = M::unit();
2318                let mut cost = HashMap::new();
2319                let s: i32 = rng.random(-100..100);
2320                cost.insert(s, 0i32);
2321                for _ in 0..10 {
2322                    let l = rng.random(-100..100);
2323                    let r = rng.random(l..=100);
2324                    let m = MinimumIntervalMovement::new(l, r);
2325                    min = M::operate(&min, &m);
2326                    let mut ncost = HashMap::new();
2327                    for (x, c) in cost {
2328                        for nx in l..=r {
2329                            let nc = c + (x - nx).abs();
2330                            chmin!(*ncost.entry(nx).or_insert(nc), nc);
2331                        }
2332                    }
2333                    cost = ncost;
2334                    let x = min.position(&s);
2335                    let c = min.move_cost(&s);
2336                    assert_eq!(Some(&c), cost.get(&x));
2337                }
2338            }
2339        }
2340    }
2341}