1use 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 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 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 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 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 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 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 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 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 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 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 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 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}