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