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
42#[codesnip::entry("MinOperation")]
43pub use self::min_operation_impl::MinOperation;
44#[codesnip::entry("MinOperation", include("algebra", "bounded"))]
45mod min_operation_impl {
46    use super::*;
47    use std::marker::PhantomData;
48    /// binary operation to select smaller element
49    pub struct MinOperation<T>
50    where
51        T: Clone + Ord + Bounded,
52    {
53        _marker: PhantomData<fn() -> T>,
54    }
55    impl<T> Magma for MinOperation<T>
56    where
57        T: Clone + Ord + Bounded,
58    {
59        type T = T;
60        #[inline]
61        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
62            x.min(y).clone()
63        }
64    }
65    impl<T> Unital for MinOperation<T>
66    where
67        T: Clone + Ord + Bounded,
68    {
69        #[inline]
70        fn unit() -> Self::T {
71            <T as Bounded>::maximum()
72        }
73    }
74    impl<T> Associative for MinOperation<T> where T: Clone + Ord + Bounded {}
75    impl<T> Commutative for MinOperation<T> where T: Clone + Ord + Bounded {}
76    impl<T> Idempotent for MinOperation<T> where T: Clone + Ord + Bounded {}
77}
78
79#[codesnip::entry("FirstOperation")]
80pub use self::first_operation_impl::FirstOperation;
81#[codesnip::entry("FirstOperation", include("algebra"))]
82mod first_operation_impl {
83    use super::*;
84    use std::marker::PhantomData;
85    /// retain the first element
86    pub struct FirstOperation<T>
87    where
88        T: Clone,
89    {
90        _marker: PhantomData<fn() -> T>,
91    }
92    impl<T> Magma for FirstOperation<T>
93    where
94        T: Clone,
95    {
96        type T = Option<T>;
97        #[inline]
98        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
99            x.as_ref().or(y.as_ref()).cloned()
100        }
101    }
102    impl<T> Unital for FirstOperation<T>
103    where
104        T: Clone,
105    {
106        #[inline]
107        fn unit() -> Self::T {
108            None
109        }
110    }
111    impl<T> Associative for FirstOperation<T> where T: Clone {}
112    impl<T> Idempotent for FirstOperation<T> where T: Clone {}
113}
114
115#[codesnip::entry("LastOperation")]
116pub use self::last_operation_impl::LastOperation;
117#[codesnip::entry("LastOperation", include("algebra"))]
118mod last_operation_impl {
119    use super::*;
120    use std::marker::PhantomData;
121    /// retain the last element
122    pub struct LastOperation<T>
123    where
124        T: Clone,
125    {
126        _marker: PhantomData<fn() -> T>,
127    }
128    impl<T> Magma for LastOperation<T>
129    where
130        T: Clone,
131    {
132        type T = Option<T>;
133        #[inline]
134        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
135            y.as_ref().or(x.as_ref()).cloned()
136        }
137    }
138    impl<T> Unital for LastOperation<T>
139    where
140        T: Clone,
141    {
142        #[inline]
143        fn unit() -> Self::T {
144            None
145        }
146    }
147    impl<T> Associative for LastOperation<T> where T: Clone {}
148    impl<T> Idempotent for LastOperation<T> where T: Clone {}
149}
150
151#[codesnip::entry("AdditiveOperation")]
152pub use self::additive_operation_impl::AdditiveOperation;
153#[codesnip::entry("AdditiveOperation", include("algebra", "zero_one"))]
154mod additive_operation_impl {
155    use super::*;
156    use std::{
157        marker::PhantomData,
158        ops::{Add, Neg, Sub},
159    };
160    /// $+$
161    pub struct AdditiveOperation<T>
162    where
163        T: Clone + Zero + Add<Output = T>,
164    {
165        _marker: PhantomData<fn() -> T>,
166    }
167    impl<T> Magma for AdditiveOperation<T>
168    where
169        T: Clone + Zero + Add<Output = T>,
170    {
171        type T = T;
172        #[inline]
173        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
174            x.clone() + y.clone()
175        }
176    }
177    impl<T> Unital for AdditiveOperation<T>
178    where
179        T: Clone + Zero + Add<Output = T>,
180    {
181        #[inline]
182        fn unit() -> Self::T {
183            Zero::zero()
184        }
185    }
186    impl<T> Associative for AdditiveOperation<T> where T: Clone + Zero + Add<Output = T> {}
187    impl<T> Commutative for AdditiveOperation<T> where T: Clone + Zero + Add<Output = T> {}
188    impl<T> Invertible for AdditiveOperation<T>
189    where
190        T: Clone + Zero + Add<Output = T> + Sub<Output = T> + Neg<Output = T>,
191    {
192        #[inline]
193        fn inverse(x: &Self::T) -> Self::T {
194            -x.clone()
195        }
196        #[inline]
197        fn rinv_operate(x: &Self::T, y: &Self::T) -> Self::T {
198            x.clone() - y.clone()
199        }
200    }
201}
202
203#[codesnip::entry("MultiplicativeOperation")]
204pub use self::multiplicative_operation_impl::MultiplicativeOperation;
205#[codesnip::entry("MultiplicativeOperation", include("algebra", "zero_one"))]
206mod multiplicative_operation_impl {
207    use super::*;
208    use std::{
209        marker::PhantomData,
210        ops::{Div, Mul},
211    };
212    /// $\times$
213    pub struct MultiplicativeOperation<T>
214    where
215        T: Clone + One + Mul<Output = T>,
216    {
217        _marker: PhantomData<fn() -> T>,
218    }
219    impl<T> Magma for MultiplicativeOperation<T>
220    where
221        T: Clone + One + Mul<Output = T>,
222    {
223        type T = T;
224        #[inline]
225        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
226            x.clone() * y.clone()
227        }
228    }
229    impl<T> Unital for MultiplicativeOperation<T>
230    where
231        T: Clone + One + Mul<Output = T>,
232    {
233        #[inline]
234        fn unit() -> Self::T {
235            One::one()
236        }
237    }
238    impl<T> Associative for MultiplicativeOperation<T> where T: Clone + One + Mul<Output = T> {}
239    impl<T> Commutative for MultiplicativeOperation<T> where T: Clone + One + Mul<Output = T> {}
240    impl<T> Invertible for MultiplicativeOperation<T>
241    where
242        T: Clone + One + Mul<Output = T> + Div<Output = T>,
243    {
244        #[inline]
245        fn inverse(x: &Self::T) -> Self::T {
246            Self::unit().div(x.clone())
247        }
248        #[inline]
249        fn rinv_operate(x: &Self::T, y: &Self::T) -> Self::T {
250            (x.clone()).div(y.clone())
251        }
252    }
253}
254
255#[codesnip::entry("LinearOperation")]
256pub use self::linear_operation_impl::LinearOperation;
257#[codesnip::entry("LinearOperation", include("algebra", "zero_one"))]
258mod linear_operation_impl {
259    use super::*;
260    use std::{
261        marker::PhantomData,
262        ops::{Add, Div, Mul, Neg, Sub},
263    };
264    /// $(a, b) \circ (c, d) = \lambda x. c \times (a \times x + b) + d$
265    pub struct LinearOperation<T>
266    where
267        T: Clone + Zero + Add<Output = T> + One + Mul<Output = T>,
268    {
269        _marker: PhantomData<fn() -> T>,
270    }
271    impl<T> Magma for LinearOperation<T>
272    where
273        T: Clone + Zero + One + Add<Output = T> + Mul<Output = T>,
274    {
275        type T = (T, T);
276        #[inline]
277        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
278            (
279                y.0.clone() * x.0.clone(),
280                y.0.clone() * x.1.clone() + y.1.clone(),
281            )
282        }
283    }
284    impl<T> Unital for LinearOperation<T>
285    where
286        T: Clone + Zero + One + Add<Output = T> + Mul<Output = T>,
287    {
288        #[inline]
289        fn unit() -> Self::T {
290            (One::one(), Zero::zero())
291        }
292    }
293    impl<T> Associative for LinearOperation<T> where
294        T: Clone + Zero + One + Add<Output = T> + Mul<Output = T>
295    {
296    }
297    impl<T> Invertible for LinearOperation<T>
298    where
299        T: Clone
300            + Zero
301            + One
302            + Add<Output = T>
303            + Sub<Output = T>
304            + Neg<Output = T>
305            + Mul<Output = T>
306            + Div<Output = T>,
307    {
308        fn inverse(x: &Self::T) -> Self::T {
309            let y = <T as One>::one().div(x.0.clone());
310            (y.clone(), -y.mul(x.1.clone()))
311        }
312    }
313}
314
315#[codesnip::entry("BitAndOperation")]
316pub use self::bitand_operation_impl::{BitAndIdentity, BitAndOperation};
317#[codesnip::entry("BitAndOperation", include("algebra"))]
318mod bitand_operation_impl {
319    use super::*;
320    use std::{marker::PhantomData, ops::BitAnd};
321    /// &
322    pub struct BitAndOperation<T>
323    where
324        T: Clone + BitAndIdentity,
325    {
326        _marker: PhantomData<fn() -> T>,
327    }
328    pub trait BitAndIdentity: Sized + BitAnd<Output = Self> {
329        fn all_one() -> Self;
330    }
331    #[macro_export]
332    macro_rules! impl_bitand_identity {
333        ([$($wh:tt)*], $t:ty, $all_one:expr) => {
334            impl<$($wh)*> BitAndIdentity for $t {
335                #[inline]
336                fn all_one() -> Self {
337                    $all_one
338                }
339            }
340        };
341        ($t:ty, $all_one:expr) => {
342            impl BitAndIdentity for $t {
343                #[inline]
344                fn all_one() -> Self {
345                    $all_one
346                }
347            }
348        };
349    }
350    impl_bitand_identity!(bool, true);
351    impl_bitand_identity!(usize, usize::MAX);
352    impl_bitand_identity!(u8, u8::MAX);
353    impl_bitand_identity!(u16, u16::MAX);
354    impl_bitand_identity!(u32, u32::MAX);
355    impl_bitand_identity!(u64, u64::MAX);
356    impl_bitand_identity!(isize, isize::MIN);
357    impl_bitand_identity!(i8, i8::MIN);
358    impl_bitand_identity!(i16, i16::MIN);
359    impl_bitand_identity!(i32, i32::MIN);
360    impl_bitand_identity!(i64, i64::MIN);
361    impl<T> Magma for BitAndOperation<T>
362    where
363        T: Clone + BitAndIdentity,
364    {
365        type T = T;
366        #[inline]
367        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
368            x.clone() & y.clone()
369        }
370    }
371    impl<T> Unital for BitAndOperation<T>
372    where
373        T: Clone + BitAndIdentity,
374    {
375        #[inline]
376        fn unit() -> Self::T {
377            BitAndIdentity::all_one()
378        }
379    }
380    impl<T> Associative for BitAndOperation<T> where T: Clone + BitAndIdentity {}
381    impl<T> Commutative for BitAndOperation<T> where T: Clone + BitAndIdentity {}
382    impl<T> Idempotent for BitAndOperation<T> where T: Clone + BitAndIdentity {}
383}
384
385#[codesnip::entry("BitOrOperation")]
386pub use self::bitor_operation_impl::{BitOrIdentity, BitOrOperation};
387#[codesnip::entry("BitOrOperation", include("algebra"))]
388mod bitor_operation_impl {
389    use super::*;
390    use std::{marker::PhantomData, ops::BitOr};
391    /// |
392    pub struct BitOrOperation<T>
393    where
394        T: Clone + BitOrIdentity,
395    {
396        _marker: PhantomData<fn() -> T>,
397    }
398    pub trait BitOrIdentity: Sized + BitOr<Output = Self> {
399        fn all_zero() -> Self;
400    }
401    #[macro_export]
402    macro_rules! impl_bitor_identity {
403        ([$($wh:tt)*], $t:ty, $all_zero:expr) => {
404            impl<$($wh)*> BitOrIdentity for $t {
405                #[inline]
406                fn all_zero() -> Self {
407                    $all_zero
408                }
409            }
410        };
411        ($t:ty, $all_zero:expr) => {
412            impl BitOrIdentity for $t {
413                #[inline]
414                fn all_zero() -> Self {
415                    $all_zero
416                }
417            }
418        };
419    }
420    impl_bitor_identity!(bool, false);
421    impl_bitor_identity!(usize, 0);
422    impl_bitor_identity!(u8, 0);
423    impl_bitor_identity!(u16, 0);
424    impl_bitor_identity!(u32, 0);
425    impl_bitor_identity!(u64, 0);
426    impl_bitor_identity!(isize, 0);
427    impl_bitor_identity!(i8, 0);
428    impl_bitor_identity!(i16, 0);
429    impl_bitor_identity!(i32, 0);
430    impl_bitor_identity!(i64, 0);
431    impl<T> Magma for BitOrOperation<T>
432    where
433        T: Clone + BitOrIdentity,
434    {
435        type T = T;
436        #[inline]
437        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
438            x.clone() | y.clone()
439        }
440    }
441    impl<T> Unital for BitOrOperation<T>
442    where
443        T: Clone + BitOrIdentity,
444    {
445        #[inline]
446        fn unit() -> Self::T {
447            BitOrIdentity::all_zero()
448        }
449    }
450    impl<T> Associative for BitOrOperation<T> where T: Clone + BitOrIdentity {}
451    impl<T> Commutative for BitOrOperation<T> where T: Clone + BitOrIdentity {}
452    impl<T> Idempotent for BitOrOperation<T> where T: Clone + BitOrIdentity {}
453}
454
455#[codesnip::entry("BitXorOperation")]
456pub use self::bitxor_operation_impl::{BitXorIdentity, BitXorOperation};
457#[codesnip::entry("BitXorOperation", include("algebra"))]
458mod bitxor_operation_impl {
459    use super::*;
460    use std::{marker::PhantomData, ops::BitXor};
461    /// ^
462    pub struct BitXorOperation<T>
463    where
464        T: Clone + BitXorIdentity,
465    {
466        _marker: PhantomData<fn() -> T>,
467    }
468    pub trait BitXorIdentity: Sized + BitXor<Output = Self> {
469        fn xor_zero() -> Self;
470    }
471    #[macro_export]
472    macro_rules! impl_bitxor_identity {
473        ([$($wh:tt)*], $t:ty, $xor_zero:expr) => {
474            impl<$($wh)*> BitXorIdentity for $t {
475                #[inline]
476                fn xor_zero() -> Self { $xor_zero }
477            }
478        };
479        ($t:ty, $xor_zero:expr) =>{
480            impl BitXorIdentity for $t {
481                #[inline]
482                fn xor_zero() -> Self { $xor_zero }
483            }
484        };
485    }
486    impl_bitxor_identity!(bool, false);
487    impl_bitxor_identity!(usize, 0);
488    impl_bitxor_identity!(u8, 0);
489    impl_bitxor_identity!(u16, 0);
490    impl_bitxor_identity!(u32, 0);
491    impl_bitxor_identity!(u64, 0);
492    impl_bitxor_identity!(isize, 0);
493    impl_bitxor_identity!(i8, 0);
494    impl_bitxor_identity!(i16, 0);
495    impl_bitxor_identity!(i32, 0);
496    impl_bitxor_identity!(i64, 0);
497    impl<T> Magma for BitXorOperation<T>
498    where
499        T: Clone + BitXorIdentity,
500    {
501        type T = T;
502        #[inline]
503        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
504            x.clone() ^ y.clone()
505        }
506    }
507    impl<T> Unital for BitXorOperation<T>
508    where
509        T: Clone + BitXorIdentity,
510    {
511        #[inline]
512        fn unit() -> Self::T {
513            BitXorIdentity::xor_zero()
514        }
515    }
516    impl<T> Associative for BitXorOperation<T> where T: Clone + BitXorIdentity {}
517    impl<T> Commutative for BitXorOperation<T> where T: Clone + BitXorIdentity {}
518    impl<T> Invertible for BitXorOperation<T>
519    where
520        T: Clone + BitXorIdentity,
521    {
522        fn inverse(x: &Self::T) -> Self::T {
523            x.clone()
524        }
525    }
526}
527
528#[codesnip::entry("LogicalLinearOperation")]
529pub use self::logical_linear_operation_impl::LogicalLinearOperation;
530#[codesnip::entry(
531    "LogicalLinearOperation",
532    include("algebra", "BitXorOperation", "BitAndOperation")
533)]
534mod logical_linear_operation_impl {
535    use super::*;
536    use std::{
537        marker::PhantomData,
538        ops::{BitAnd, BitXor},
539    };
540    /// $(a, b) \circ (c, d) = \lambda x. c \wedge (a \wedge x \oplus b) \oplus d$
541    pub struct LogicalLinearOperation<T>
542    where
543        T: Clone + BitXorIdentity + BitAndIdentity + BitXor<Output = T> + BitAnd<Output = T>,
544    {
545        _marker: PhantomData<fn() -> T>,
546    }
547    impl<T> LogicalLinearOperation<T>
548    where
549        T: Clone + BitXorIdentity + BitAndIdentity + BitXor<Output = T> + BitAnd<Output = T>,
550    {
551        pub fn eval((a, b): &<Self as Magma>::T, x: &T) -> T {
552            a.clone() & x.clone() ^ b.clone()
553        }
554    }
555    impl<T> Magma for LogicalLinearOperation<T>
556    where
557        T: Clone + BitXorIdentity + BitAndIdentity + BitXor<Output = T> + BitAnd<Output = T>,
558    {
559        type T = (T, T);
560        #[inline]
561        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
562            (
563                y.0.clone() & x.0.clone(),
564                y.0.clone() & x.1.clone() ^ y.1.clone(),
565            )
566        }
567    }
568    impl<T> Unital for LogicalLinearOperation<T>
569    where
570        T: Clone + BitXorIdentity + BitAndIdentity + BitXor<Output = T> + BitAnd<Output = T>,
571    {
572        #[inline]
573        fn unit() -> Self::T {
574            (BitAndIdentity::all_one(), BitXorIdentity::xor_zero())
575        }
576    }
577    impl<T> Associative for LogicalLinearOperation<T> where
578        T: Clone + BitXorIdentity + BitAndIdentity + BitXor<Output = T> + BitAnd<Output = T>
579    {
580    }
581}
582
583#[codesnip::entry("TupleOperation", include("algebra"))]
584mod tuple_operation_impl {
585    #![allow(unused_variables, clippy::unused_unit)]
586    use super::*;
587    macro_rules! impl_tuple_operation {
588        (@impl $($T:ident)*, $($i:tt)*) => {
589            impl<$($T: Magma),*> Magma for ($($T,)*) {
590                type T = ($(<$T as Magma>::T,)*);
591                #[inline]
592                fn operate(x: &Self::T, y: &Self::T) -> Self::T {
593                    ($(<$T as Magma>::operate(&x.$i, &y.$i),)*)
594                }
595            }
596            impl<$($T: Unital),*> Unital for ($($T,)*) {
597                #[inline]
598                fn unit() -> Self::T {
599                    ($(<$T as Unital>::unit(),)*)
600                }
601            }
602            impl<$($T: Associative),*> Associative for ($($T,)*) {}
603            impl<$($T: Commutative),*> Commutative for ($($T,)*) {}
604            impl<$($T: Idempotent),*> Idempotent for ($($T,)*) {}
605            impl<$($T: Invertible),*> Invertible for ($($T,)*) {
606                #[inline]
607                fn inverse(x: &Self::T) -> Self::T {
608                    ($(<$T as Invertible>::inverse(&x.$i),)*)
609                }
610            }
611        };
612        (@inner [$($T:ident)*][] [$($i:tt)*][]) => {
613            impl_tuple_operation!(@impl $($T)*, $($i)*);
614        };
615        (@inner [$($T:ident)*][$U:ident $($Rest:ident)*] [$($i:tt)*][$j:tt $($rest:tt)*]) => {
616            impl_tuple_operation!(@impl $($T)*, $($i)*);
617            impl_tuple_operation!(@inner [$($T)* $U][$($Rest)*] [$($i)* $j][$($rest)*]);
618        };
619        ($($T:ident)*, $($i:tt)*) => {
620            impl_tuple_operation!(@inner [][$($T)*] [][$($i)*]);
621        };
622    }
623    impl_tuple_operation!(A B C D E F G H I J, 0 1 2 3 4 5 6 7 8 9);
624}
625
626#[codesnip::entry("ArrayOperation")]
627pub use self::array_operation_impl::ArrayOperation;
628#[codesnip::entry("ArrayOperation", include("algebra", "array"))]
629mod array_operation_impl {
630    #![allow(unused_variables, clippy::unused_unit)]
631    use super::*;
632    use crate::array;
633    use std::marker::PhantomData;
634    pub struct ArrayOperation<M, const N: usize> {
635        _marker: PhantomData<fn() -> M>,
636    }
637    impl<M, const N: usize> Magma for ArrayOperation<M, N>
638    where
639        M: Magma,
640    {
641        type T = [M::T; N];
642        #[inline]
643        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
644            array!(|i| M::operate(&x[i], &y[i]); N)
645        }
646    }
647    impl<M, const N: usize> Unital for ArrayOperation<M, N>
648    where
649        M: Unital,
650    {
651        #[inline]
652        fn unit() -> Self::T {
653            array!(|| M::unit(); N)
654        }
655    }
656    impl<M, const N: usize> Associative for ArrayOperation<M, N> where M: Associative {}
657    impl<M, const N: usize> Commutative for ArrayOperation<M, N> where M: Commutative {}
658    impl<M, const N: usize> Idempotent for ArrayOperation<M, N> where M: Idempotent {}
659    impl<M, const N: usize> Invertible for ArrayOperation<M, N>
660    where
661        M: Invertible,
662    {
663        #[inline]
664        fn inverse(x: &Self::T) -> Self::T {
665            array!(|i| M::inverse(&x[i]); N)
666        }
667    }
668}
669
670#[codesnip::entry("CountingOperation")]
671pub use self::counting_operation_impl::CountingOperation;
672#[codesnip::entry("CountingOperation", include("algebra"))]
673mod counting_operation_impl {
674    use super::*;
675    use std::marker::PhantomData;
676    pub struct CountingOperation<M> {
677        _marker: PhantomData<fn() -> M>,
678    }
679    impl<M> Magma for CountingOperation<M>
680    where
681        M: Magma,
682        M::T: PartialEq,
683    {
684        type T = (M::T, usize);
685        #[inline]
686        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
687            if x.0 == y.0 {
688                (x.0.clone(), x.1 + y.1)
689            } else {
690                let z = M::operate(&x.0, &y.0);
691                if z == x.0 {
692                    (z, x.1)
693                } else if z == y.0 {
694                    (z, y.1)
695                } else {
696                    (z, 1)
697                }
698            }
699        }
700    }
701    impl<M> Unital for CountingOperation<M>
702    where
703        M: Unital,
704        M::T: PartialEq,
705    {
706        #[inline]
707        fn unit() -> Self::T {
708            (M::unit(), 0)
709        }
710    }
711    impl<M> Associative for CountingOperation<M> where M: Associative {}
712    impl<M> Commutative for CountingOperation<M> where M: Commutative {}
713    impl<M> Idempotent for CountingOperation<M> where M: Idempotent {}
714}
715
716#[codesnip::entry("ReverseOperation")]
717pub use self::reverse_operation_impl::ReverseOperation;
718#[codesnip::entry("ReverseOperation", include("algebra"))]
719mod reverse_operation_impl {
720    use super::*;
721    use std::marker::PhantomData;
722    pub struct ReverseOperation<M> {
723        _marker: PhantomData<fn() -> M>,
724    }
725    impl<M> Magma for ReverseOperation<M>
726    where
727        M: Magma,
728    {
729        type T = M::T;
730        #[inline]
731        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
732            M::operate(y, x)
733        }
734    }
735    impl<M> Unital for ReverseOperation<M>
736    where
737        M: Unital,
738    {
739        #[inline]
740        fn unit() -> Self::T {
741            M::unit()
742        }
743    }
744    impl<M> Associative for ReverseOperation<M> where M: Associative {}
745    impl<M> Commutative for ReverseOperation<M> where M: Commutative {}
746    impl<M> Invertible for ReverseOperation<M>
747    where
748        M: Invertible,
749    {
750        #[inline]
751        fn inverse(x: &Self::T) -> Self::T {
752            M::inverse(x)
753        }
754    }
755    impl<M> Idempotent for ReverseOperation<M> where M: Idempotent {}
756}
757
758#[codesnip::entry("TopkOperation")]
759pub use self::topk_operation_impl::TopkOperation;
760#[codesnip::entry("TopkOperation", include("algebra", "bounded", "array"))]
761mod topk_operation_impl {
762    use super::*;
763    use std::marker::PhantomData;
764    pub struct TopkOperation<const K: usize, T>
765    where
766        T: Clone + Ord + Bounded,
767    {
768        _marker: PhantomData<fn() -> T>,
769    }
770    impl<const K: usize, T> Magma for TopkOperation<K, T>
771    where
772        T: Clone + Ord + Bounded,
773    {
774        type T = [T; K];
775        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
776            let mut i = 0;
777            let mut j = 0;
778            crate::array![|| if i == K || j != K && x[i] < y[j] {
779                let t = &y[j];
780                j += 1;
781                t.clone()
782            } else {
783                let t = &x[i];
784                i += 1;
785                t.clone()
786            }; K]
787        }
788    }
789    impl<const K: usize, T> Unital for TopkOperation<K, T>
790    where
791        T: Clone + Ord + Bounded,
792    {
793        fn unit() -> Self::T {
794            crate::array![|| <T as Bounded>::minimum(); K]
795        }
796    }
797    impl<const K: usize, T> Associative for TopkOperation<K, T> where T: Clone + Ord + Bounded {}
798    impl<const K: usize, T> Commutative for TopkOperation<K, T> where T: Clone + Ord + Bounded {}
799
800    #[cfg(test)]
801    mod tests {
802        use super::*;
803        use crate::tools::Xorshift;
804
805        #[test]
806        fn test_topk() {
807            let mut rng = Xorshift::new();
808            for _ in 0..100 {
809                let mut x = [i64::MIN; 4];
810                for _ in 0..100 {
811                    let mut y = [i64::MIN; 4];
812                    for y in &mut y {
813                        *y = rng.random(0..1000);
814                    }
815                    y.sort_unstable();
816                    y.reverse();
817                    let z = {
818                        let mut x = x.to_vec();
819                        x.extend(&y);
820                        x.sort_unstable();
821                        x.reverse();
822                        x.truncate(4);
823                        x
824                    };
825                    let zz = TopkOperation::<4, i64>::operate(&x, &y);
826                    for (z, zz) in z.iter().zip(&zz) {
827                        assert_eq!(z, zz);
828                    }
829                    x = zz;
830                }
831            }
832        }
833    }
834}
835
836#[codesnip::entry("BottomkOperation")]
837pub use self::bottomk_operation_impl::BottomkOperation;
838#[codesnip::entry("BottomkOperation", include("algebra", "bounded", "array"))]
839mod bottomk_operation_impl {
840    use super::*;
841    use std::marker::PhantomData;
842    pub struct BottomkOperation<const K: usize, T>
843    where
844        T: Clone + Ord + Bounded,
845    {
846        _marker: PhantomData<fn() -> T>,
847    }
848    impl<const K: usize, T> Magma for BottomkOperation<K, T>
849    where
850        T: Clone + Ord + Bounded,
851    {
852        type T = [T; K];
853        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
854            let mut i = 0;
855            let mut j = 0;
856            crate::array![|| if i == K || j != K && x[i] > y[j] {
857                let t = &y[j];
858                j += 1;
859                t.clone()
860            } else {
861                let t = &x[i];
862                i += 1;
863                t.clone()
864            }; K]
865        }
866    }
867    impl<const K: usize, T> Unital for BottomkOperation<K, T>
868    where
869        T: Clone + Ord + Bounded,
870    {
871        fn unit() -> Self::T {
872            crate::array![|| <T as Bounded>::maximum(); K]
873        }
874    }
875    impl<const K: usize, T> Associative for BottomkOperation<K, T> where T: Clone + Ord + Bounded {}
876    impl<const K: usize, T> Commutative for BottomkOperation<K, T> where T: Clone + Ord + Bounded {}
877
878    #[cfg(test)]
879    mod tests {
880        use super::*;
881        use crate::tools::Xorshift;
882
883        #[test]
884        fn test_bottomk() {
885            let mut rng = Xorshift::new();
886            for _ in 0..100 {
887                let mut x = [i64::MAX; 4];
888                for _ in 0..100 {
889                    let mut y = [i64::MAX; 4];
890                    for y in &mut y {
891                        *y = rng.random(0..1000);
892                    }
893                    y.sort_unstable();
894                    let z = {
895                        let mut x = x.to_vec();
896                        x.extend(&y);
897                        x.sort_unstable();
898                        x.truncate(4);
899                        x
900                    };
901                    let zz = BottomkOperation::<4, i64>::operate(&x, &y);
902                    for (z, zz) in z.iter().zip(&zz) {
903                        assert_eq!(z, zz);
904                    }
905                    x = zz;
906                }
907            }
908        }
909    }
910}
911
912#[codesnip::entry("PermutationOperation")]
913pub use self::permutation_operation_impl::PermutationOperation;
914#[codesnip::entry("PermutationOperation", include("algebra"))]
915mod permutation_operation_impl {
916    use super::*;
917    pub enum PermutationOperation {}
918    impl Magma for PermutationOperation {
919        type T = Vec<usize>;
920        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
921            y.iter()
922                .map(|&y| if y < x.len() { x[y] } else { y })
923                .collect()
924        }
925    }
926    impl Associative for PermutationOperation {}
927    impl Unital for PermutationOperation {
928        fn unit() -> Self::T {
929            Vec::new()
930        }
931    }
932    impl Invertible for PermutationOperation {
933        fn inverse(x: &Self::T) -> Self::T {
934            let mut y = vec![0; x.len()];
935            for (i, x) in x.iter().enumerate() {
936                y[*x] = i;
937            }
938            y
939        }
940    }
941}
942
943#[codesnip::entry("FindMajorityOperation")]
944pub use self::find_majority_operation_impl::FindMajorityOperation;
945#[codesnip::entry("FindMajorityOperation", include("algebra"))]
946mod find_majority_operation_impl {
947    use super::*;
948    use std::{cmp::Ordering, marker::PhantomData};
949    /// Find majority(strict) of a sequence.
950    ///
951    /// fold $x \in S$ with `(Some(x), 1)`
952    ///
953    /// `(Some(m), _)` represents `m` may be a majority of $S$.
954    ///
955    /// `(None, _)` represents that there is no majority value.
956    pub struct FindMajorityOperation<T> {
957        _marker: PhantomData<fn() -> T>,
958    }
959    impl<T> Magma for FindMajorityOperation<T>
960    where
961        T: Clone + Eq,
962    {
963        type T = (Option<T>, usize);
964        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
965            if y.0.is_none() {
966                x.clone()
967            } else if x.0.is_none() {
968                y.clone()
969            } else {
970                match (x.0.eq(&y.0), x.1.cmp(&y.1)) {
971                    (true, _) => (x.0.clone(), x.1 + y.1),
972                    (_, Ordering::Less) => (y.0.clone(), y.1 - x.1),
973                    (_, Ordering::Equal) => (None, 0),
974                    (_, Ordering::Greater) => (x.0.clone(), x.1 - y.1),
975                }
976            }
977        }
978    }
979    impl<T> Unital for FindMajorityOperation<T>
980    where
981        T: Clone + Eq,
982    {
983        fn unit() -> Self::T {
984            (None, 0)
985        }
986    }
987    impl<T> Associative for FindMajorityOperation<T> {}
988}
989
990pub use self::concatenate_operation::{ConcatenateOperation, SortedConcatenateOperation};
991mod concatenate_operation {
992    use super::*;
993    use std::marker::PhantomData;
994    pub struct ConcatenateOperation<T> {
995        _marker: PhantomData<fn() -> T>,
996    }
997    impl<T> Magma for ConcatenateOperation<T>
998    where
999        T: Clone,
1000    {
1001        type T = Vec<T>;
1002        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
1003            x.iter().chain(y.iter()).cloned().collect()
1004        }
1005    }
1006    impl<T> Unital for ConcatenateOperation<T>
1007    where
1008        T: Clone,
1009    {
1010        fn unit() -> Self::T {
1011            Vec::new()
1012        }
1013    }
1014    impl<T> Associative for ConcatenateOperation<T> {}
1015
1016    pub struct SortedConcatenateOperation<T> {
1017        _marker: PhantomData<fn() -> T>,
1018    }
1019    impl<T> Magma for SortedConcatenateOperation<T>
1020    where
1021        T: Clone + Ord,
1022    {
1023        type T = Vec<T>;
1024        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
1025            let mut xit = x.iter().cloned().peekable();
1026            let mut yit = y.iter().cloned().peekable();
1027            let mut z = Vec::with_capacity(x.len() + y.len());
1028            loop {
1029                match (xit.peek(), yit.peek()) {
1030                    (None, None) => break,
1031                    (Some(_), None) => z.push(xit.next().unwrap()),
1032                    (Some(x), Some(y)) if x <= y => z.push(xit.next().unwrap()),
1033                    _ => z.push(yit.next().unwrap()),
1034                }
1035            }
1036            z
1037        }
1038    }
1039    impl<T> Unital for SortedConcatenateOperation<T>
1040    where
1041        T: Clone + Ord,
1042    {
1043        fn unit() -> Self::T {
1044            Vec::new()
1045        }
1046    }
1047    impl<T> Associative for SortedConcatenateOperation<T> {}
1048    impl<T> Commutative for SortedConcatenateOperation<T> {}
1049}
1050
1051#[codesnip::entry("MinimumIntervalMovementOperation")]
1052pub use self::minimum_interval_movement_impl::{
1053    MinimumIntervalMovement, MinimumIntervalMovementOperation,
1054};
1055#[codesnip::entry(
1056    "MinimumIntervalMovementOperation",
1057    include("algebra", "bounded", "zero_one")
1058)]
1059mod minimum_interval_movement_impl {
1060    use super::*;
1061    use std::{
1062        marker::PhantomData,
1063        ops::{Add, Sub},
1064    };
1065
1066    pub struct MinimumIntervalMovementOperation<T> {
1067        _marker: PhantomData<fn() -> T>,
1068    }
1069    #[derive(Debug, Clone)]
1070    pub struct MinimumIntervalMovement<T> {
1071        pos_range: (T, T),
1072        move_range: (T, T),
1073        cost: T,
1074    }
1075    impl<T> MinimumIntervalMovement<T>
1076    where
1077        T: Clone + Zero,
1078    {
1079        pub fn new(l: T, r: T) -> Self {
1080            Self {
1081                pos_range: (l.clone(), r.clone()),
1082                move_range: (l, r),
1083                cost: T::zero(),
1084            }
1085        }
1086    }
1087    impl<T> MinimumIntervalMovement<T>
1088    where
1089        T: Clone + Ord + Zero,
1090    {
1091        pub fn position(&self, x: &T) -> T {
1092            x.clamp(&self.pos_range.0, &self.pos_range.1).clone()
1093        }
1094    }
1095    impl<T> MinimumIntervalMovement<T>
1096    where
1097        T: Clone + Ord + Add<Output = T> + Sub<Output = T> + Zero,
1098    {
1099        pub fn move_cost(&self, x: &T) -> T {
1100            x.max(&self.move_range.0).clone() - x.min(&self.move_range.1).clone()
1101                + self.cost.clone()
1102        }
1103    }
1104    impl<T> Magma for MinimumIntervalMovementOperation<T>
1105    where
1106        T: Clone + Ord + Add<Output = T> + Sub<Output = T> + Zero,
1107    {
1108        type T = MinimumIntervalMovement<T>;
1109        fn operate(x: &Self::T, y: &Self::T) -> Self::T {
1110            let pos_range = (
1111                (&x.pos_range.0)
1112                    .clamp(&y.pos_range.0, &y.pos_range.1)
1113                    .clone(),
1114                (&x.pos_range.1)
1115                    .clamp(&y.pos_range.0, &y.pos_range.1)
1116                    .clone(),
1117            );
1118            let move_range = (
1119                (&y.move_range.0)
1120                    .clamp(&x.move_range.0, &x.move_range.1)
1121                    .clone(),
1122                (&y.move_range.1)
1123                    .clamp(&x.move_range.0, &x.move_range.1)
1124                    .clone(),
1125            );
1126            let cost = x.cost.clone() + y.move_cost(&x.position(&move_range.0));
1127            MinimumIntervalMovement {
1128                pos_range,
1129                move_range,
1130                cost,
1131            }
1132        }
1133    }
1134    impl<T> Associative for MinimumIntervalMovementOperation<T> {}
1135    impl<T> Unital for MinimumIntervalMovementOperation<T>
1136    where
1137        T: Clone + Ord + Add<Output = T> + Sub<Output = T> + Zero + Bounded,
1138    {
1139        fn unit() -> Self::T {
1140            MinimumIntervalMovement::new(T::minimum(), T::maximum())
1141        }
1142    }
1143}