Skip to main content

dbsp/
algebra.rs

1//! This module contains declarations of abstract algebraic concepts:
2//! monoids, groups, rings, etc.
3
4#[macro_use]
5mod checked_int;
6mod floats;
7mod lattice;
8mod order;
9mod present;
10
11pub mod zset;
12
13pub use checked_int::CheckedInt;
14pub use floats::{F32, F64};
15pub use lattice::Lattice;
16pub use order::{PartialOrder, TotalOrder};
17pub use present::Present;
18pub use zset::{
19    DynZWeight, IndexedZSet, IndexedZSetReader, OrdIndexedZSet, OrdIndexedZSetFactories, OrdZSet,
20    OrdZSetFactories, VecIndexedZSet, VecIndexedZSetFactories, VecZSet, VecZSetFactories, ZBatch,
21    ZBatchReader, ZCursor, ZSet, ZSetReader, ZTrace, ZWeight,
22};
23
24use num::PrimInt;
25use size_of::SizeOf;
26use std::{
27    fmt::{Debug, Display},
28    marker::PhantomData,
29    num::Wrapping,
30    ops::{Add, AddAssign, Mul, Neg},
31    rc::Rc,
32};
33
34/// Trait for types where the minimum value is known
35pub trait MinValue {
36    fn min_value() -> Self;
37}
38
39/// Trait for types where the maximum value is known
40pub trait MaxValue {
41    fn max_value() -> Self;
42}
43
44/// Trait for integer types returning the first
45/// value representable in this type which is
46/// too large for the previous narrower type
47pub trait FirstLargeValue {
48    fn large() -> Self;
49}
50
51/// Trait for primitive integers that are unsigned
52pub trait UnsignedPrimInt: PrimInt + FirstLargeValue + HasZero + Debug + Display {}
53
54impl FirstLargeValue for u8 {
55    fn large() -> Self {
56        // There is no narrower unsigned type
57        0x1
58    }
59}
60
61impl FirstLargeValue for u16 {
62    fn large() -> Self {
63        0x100
64    }
65}
66
67impl FirstLargeValue for u32 {
68    fn large() -> Self {
69        0x10000
70    }
71}
72
73impl FirstLargeValue for u64 {
74    fn large() -> Self {
75        0x1_0000_0000
76    }
77}
78
79impl FirstLargeValue for u128 {
80    fn large() -> Self {
81        0x1_0000_0000_0000_0000
82    }
83}
84
85impl UnsignedPrimInt for u8 {}
86impl UnsignedPrimInt for u16 {}
87impl UnsignedPrimInt for u32 {}
88impl UnsignedPrimInt for u64 {}
89impl UnsignedPrimInt for u128 {}
90
91/// Trait for primitive integers that are signed
92pub trait SignedPrimInt:
93    PrimInt + Neg<Output = Self> + HasZero + HasOne + Ord + Debug + Display
94{
95}
96
97// For all primitive signed integers we also implement
98// MinValue and MaxValue
99macro_rules! make_signed {
100    ($type: ty) => {
101        impl MinValue for $type {
102            fn min_value() -> Self {
103                <$type>::MIN
104            }
105        }
106
107        impl MaxValue for $type {
108            fn max_value() -> Self {
109                <$type>::MAX
110            }
111        }
112
113        impl SignedPrimInt for $type {}
114    };
115}
116
117make_signed!(i8);
118make_signed!(i16);
119make_signed!(i32);
120make_signed!(i64);
121make_signed!(i128);
122
123/// A trait for types that have a zero value.
124///
125/// This is similar to the standard Zero trait, but that
126/// trait depends on Add and HasZero doesn't.
127pub trait HasZero {
128    fn is_zero(&self) -> bool;
129
130    fn zero() -> Self;
131}
132
133/// Implement `HasZero` for types that already implement `Zero`.
134macro_rules! impl_has_zero {
135    ($($type:ty),* $(,)?) => {
136        $(
137            impl $crate::algebra::HasZero for $type {
138                #[inline]
139                fn is_zero(&self) -> bool {
140                    *self == 0
141                }
142
143                #[inline]
144                fn zero() -> Self {
145                    0
146                }
147            }
148        )*
149    };
150}
151
152impl_has_zero! {
153    u8,
154    i8,
155    u16,
156    i16,
157    u32,
158    i32,
159    u64,
160    i64,
161    u128,
162    i128,
163    usize,
164    isize,
165}
166
167impl<T> HasZero for Option<T> {
168    #[inline]
169    fn is_zero(&self) -> bool {
170        self.is_none()
171    }
172
173    #[inline]
174    fn zero() -> Self {
175        None
176    }
177}
178
179// TODO: Implement for `std::num::Saturating` once stable
180impl<T> HasZero for Wrapping<T>
181where
182    T: HasZero,
183{
184    #[inline]
185    fn is_zero(&self) -> bool {
186        self.0.is_zero()
187    }
188
189    #[inline]
190    fn zero() -> Self {
191        Self(T::zero())
192    }
193}
194
195/// A trait for types that have a one value.
196/// This is similar to the standard One trait, but that
197/// trait depends on Mul and HasOne doesn't.
198pub trait HasOne {
199    fn one() -> Self;
200}
201
202/// Implement `HasOne` for types that already implement `One`.
203macro_rules! impl_has_one {
204    ($($type:ty),* $(,)?) => {
205        $(
206            impl $crate::algebra::HasOne for $type {
207                #[inline]
208                fn one() -> Self {
209                    1
210                }
211            }
212        )*
213    };
214}
215
216impl_has_one! {
217    u8,
218    i8,
219    u16,
220    i16,
221    u32,
222    i32,
223    u64,
224    i64,
225    u128,
226    i128,
227    usize,
228    isize,
229}
230
231impl<T> HasOne for Rc<T>
232where
233    T: HasOne,
234{
235    #[inline]
236    fn one() -> Self {
237        Rc::new(<T as HasOne>::one())
238    }
239}
240
241/// Like the Add trait, but with arguments by reference.
242pub trait AddByRef<Rhs = Self> {
243    fn add_by_ref(&self, other: &Rhs) -> Self;
244}
245
246/// Implementation of AddByRef for types that have an Add.
247impl<T> AddByRef for T
248where
249    for<'a> &'a T: Add<Output = T>,
250{
251    #[inline]
252    fn add_by_ref(&self, other: &Self) -> Self {
253        self.add(other)
254    }
255}
256
257/// Like the Neg trait, but with arguments by reference.
258pub trait NegByRef {
259    fn neg_by_ref(&self) -> Self;
260}
261
262/// Implementation of NegByRef for types that have a Neg.
263impl<T> NegByRef for T
264where
265    for<'a> &'a T: Neg<Output = T>,
266{
267    #[inline]
268    fn neg_by_ref(&self) -> Self {
269        self.neg()
270    }
271}
272
273/// Like the AddAsssign trait, but with arguments by reference
274pub trait AddAssignByRef<Rhs = Self> {
275    fn add_assign_by_ref(&mut self, other: &Rhs);
276}
277
278/// Implemenation of AddAssignByRef for types that already have `AddAssign<&T>`.
279impl<T> AddAssignByRef for T
280where
281    for<'a> T: AddAssign<&'a T>,
282{
283    #[inline]
284    fn add_assign_by_ref(&mut self, other: &Self) {
285        self.add_assign(other)
286    }
287}
288
289/// Like the Mul trait, but with arguments by reference
290pub trait MulByRef<Rhs = Self> {
291    type Output;
292
293    fn mul_by_ref(&self, other: &Rhs) -> Self::Output;
294}
295
296/// Implementation of MulByRef for types that already have Mul.
297impl<T> MulByRef<T> for T
298where
299    for<'a> &'a T: Mul<Output = Self>,
300{
301    type Output = Self;
302
303    #[inline]
304    fn mul_by_ref(&self, other: &Self) -> Self::Output {
305        self.mul(other)
306    }
307}
308
309/// A type with an associative addition.
310/// We trust the implementation to have an associative addition.
311/// (this cannot be checked statically).
312// TODO: Add a `for<'a> Add<&'a Self, Output = Self>` bound for adding an owned
313// and a referenced value together
314pub trait SemigroupValue: Clone + Eq + SizeOf + AddByRef + AddAssignByRef + 'static {}
315
316impl<T> SemigroupValue for T where T: Clone + Eq + SizeOf + AddByRef + AddAssignByRef + 'static {}
317
318/// A type with an associative addition and a zero.
319pub trait MonoidValue: SemigroupValue + HasZero {}
320
321/// Default implementation for all types that have an addition and a zero.
322impl<T> MonoidValue for T where T: SemigroupValue + HasZero {}
323
324/// A Group is a Monoid with a with negation operation.
325/// We expect all our groups to be commutative.
326pub trait GroupValue: MonoidValue + Neg<Output = Self> + NegByRef {}
327
328/// Default implementation of GroupValue for all types that have the required
329/// traits.
330impl<T> GroupValue for T where T: MonoidValue + Neg<Output = Self> + NegByRef {}
331
332/// A Group with a multiplication operation is a Ring.
333pub trait RingValue: GroupValue + Mul<Output = Self> + MulByRef<Output = Self> + HasOne {}
334
335/// Default implementation of RingValue for all types that have the required
336/// traits.
337impl<T> RingValue for T where T: GroupValue + Mul<Output = Self> + MulByRef<Output = Self> + HasOne {}
338
339/// A ring where elements can be compared with zero
340pub trait ZRingValue: RingValue {
341    /// True if value is greater or equal to zero.
342    fn ge0(&self) -> bool;
343
344    /// True if value is less than or equal to zero.
345    fn le0(&self) -> bool;
346}
347
348/// Default implementation of `ZRingValue` for all types that have the required
349/// traits.
350impl<T> ZRingValue for T
351where
352    T: RingValue + Ord,
353{
354    #[inline]
355    fn ge0(&self) -> bool {
356        *self >= Self::zero()
357    }
358
359    #[inline]
360    fn le0(&self) -> bool {
361        *self <= Self::zero()
362    }
363}
364
365impl MulByRef<isize> for i8 {
366    type Output = Self;
367
368    #[inline]
369    fn mul_by_ref(&self, w: &isize) -> Self::Output {
370        (*self as isize * w) as Self
371    }
372}
373
374impl MulByRef<isize> for i16 {
375    type Output = Self;
376
377    #[inline]
378    fn mul_by_ref(&self, w: &isize) -> Self::Output {
379        (*self as isize * w) as Self
380    }
381}
382
383impl MulByRef<isize> for i32 {
384    type Output = Self;
385
386    #[inline]
387    fn mul_by_ref(&self, w: &isize) -> Self::Output {
388        (*self as isize * w) as Self
389    }
390}
391
392impl MulByRef<isize> for i64 {
393    type Output = Self;
394
395    #[inline]
396    fn mul_by_ref(&self, w: &isize) -> Self::Output {
397        (*self as isize * w) as Self
398    }
399}
400
401impl MulByRef<isize> for i128 {
402    type Output = Self;
403
404    #[inline]
405    fn mul_by_ref(&self, w: &isize) -> Self::Output {
406        (*self * (*w as i128)) as Self
407    }
408}
409
410impl MulByRef<isize> for f32 {
411    type Output = Self;
412
413    #[inline]
414    fn mul_by_ref(&self, w: &isize) -> Self::Output {
415        *self * ((*w) as f32)
416    }
417}
418
419impl MulByRef<isize> for f64 {
420    type Output = Self;
421
422    #[inline]
423    fn mul_by_ref(&self, w: &isize) -> Self::Output {
424        *self * ((*w) as f64)
425    }
426}
427
428impl MulByRef<isize> for F32 {
429    type Output = Self;
430
431    #[inline]
432    fn mul_by_ref(&self, w: &isize) -> Self::Output {
433        *self * ((*w) as f32)
434    }
435}
436
437impl MulByRef<isize> for F64 {
438    type Output = Self;
439
440    #[inline]
441    fn mul_by_ref(&self, w: &isize) -> Self::Output {
442        *self * ((*w) as f64)
443    }
444}
445
446/////////// `MulByRef<i64>`
447
448impl MulByRef<i64> for i8 {
449    type Output = Self;
450
451    #[inline]
452    fn mul_by_ref(&self, w: &i64) -> Self::Output {
453        (*self as i64 * w) as Self
454    }
455}
456
457impl MulByRef<i64> for i16 {
458    type Output = Self;
459
460    #[inline]
461    fn mul_by_ref(&self, w: &i64) -> Self::Output {
462        (*self as i64 * w) as Self
463    }
464}
465
466impl MulByRef<i64> for i32 {
467    type Output = Self;
468
469    #[inline]
470    fn mul_by_ref(&self, w: &i64) -> Self::Output {
471        (*self as i64 * w) as Self
472    }
473}
474
475impl MulByRef<i64> for isize {
476    type Output = Self;
477
478    #[inline]
479    fn mul_by_ref(&self, w: &i64) -> Self::Output {
480        (*self as i64 * w) as Self
481    }
482}
483
484impl MulByRef<i64> for i128 {
485    type Output = Self;
486
487    #[inline]
488    fn mul_by_ref(&self, w: &i64) -> Self::Output {
489        (*self * (*w as i128)) as Self
490    }
491}
492
493impl MulByRef<i64> for f32 {
494    type Output = Self;
495
496    #[inline]
497    fn mul_by_ref(&self, w: &i64) -> Self::Output {
498        *self * ((*w) as f32)
499    }
500}
501
502impl MulByRef<i64> for f64 {
503    type Output = Self;
504
505    #[inline]
506    fn mul_by_ref(&self, w: &i64) -> Self::Output {
507        *self * ((*w) as f64)
508    }
509}
510
511impl MulByRef<i64> for F32 {
512    type Output = Self;
513
514    #[inline]
515    fn mul_by_ref(&self, w: &i64) -> Self::Output {
516        *self * ((*w) as f32)
517    }
518}
519
520impl MulByRef<i64> for F64 {
521    type Output = Self;
522
523    #[inline]
524    fn mul_by_ref(&self, w: &i64) -> Self::Output {
525        *self * ((*w) as f64)
526    }
527}
528
529/////////// `MulByRef<i32>`
530
531impl MulByRef<i32> for i8 {
532    type Output = Self;
533
534    #[inline]
535    fn mul_by_ref(&self, w: &i32) -> Self::Output {
536        (*self as i32 * w) as Self
537    }
538}
539
540impl MulByRef<i32> for i16 {
541    type Output = Self;
542
543    #[inline]
544    fn mul_by_ref(&self, w: &i32) -> Self::Output {
545        (*self as i32 * w) as Self
546    }
547}
548
549impl MulByRef<i32> for i64 {
550    type Output = Self;
551
552    #[inline]
553    fn mul_by_ref(&self, w: &i32) -> Self::Output {
554        (*self * (*w as i64)) as Self
555    }
556}
557
558impl MulByRef<i32> for i128 {
559    type Output = Self;
560
561    #[inline]
562    fn mul_by_ref(&self, w: &i32) -> Self::Output {
563        (*self * (*w as i128)) as Self
564    }
565}
566
567impl MulByRef<i32> for isize {
568    type Output = Self;
569
570    #[inline]
571    fn mul_by_ref(&self, w: &i32) -> Self::Output {
572        (*self as i32 * w) as Self
573    }
574}
575
576impl MulByRef<i32> for f32 {
577    type Output = Self;
578
579    #[inline]
580    fn mul_by_ref(&self, w: &i32) -> Self::Output {
581        *self * ((*w) as f32)
582    }
583}
584
585impl MulByRef<i32> for f64 {
586    type Output = Self;
587
588    #[inline]
589    fn mul_by_ref(&self, w: &i32) -> Self::Output {
590        *self * ((*w) as f64)
591    }
592}
593
594impl MulByRef<i32> for F32 {
595    type Output = Self;
596
597    #[inline]
598    fn mul_by_ref(&self, w: &i32) -> Self::Output {
599        *self * ((*w) as f32)
600    }
601}
602
603impl MulByRef<i32> for F64 {
604    type Output = Self;
605
606    #[inline]
607    fn mul_by_ref(&self, w: &i32) -> Self::Output {
608        *self * ((*w) as f64)
609    }
610}
611
612/////////// generic implementation for Option<t>
613
614pub trait OptionWeightType {}
615impl OptionWeightType for isize {}
616impl OptionWeightType for i8 {}
617impl OptionWeightType for i16 {}
618impl OptionWeightType for i32 {}
619impl OptionWeightType for i64 {}
620impl OptionWeightType for f32 {}
621impl OptionWeightType for f64 {}
622impl OptionWeightType for F32 {}
623impl OptionWeightType for F64 {}
624impl OptionWeightType for Present {}
625
626impl<T, S> MulByRef<S> for Option<T>
627where
628    T: MulByRef<S, Output = T>,
629    S: OptionWeightType,
630{
631    type Output = Self;
632
633    #[inline]
634    fn mul_by_ref(&self, rhs: &S) -> Self::Output {
635        self.as_ref().map(|lhs| lhs.mul_by_ref(rhs))
636    }
637}
638
639impl<T, S> MulByRef<S> for &Option<T>
640where
641    T: MulByRef<S, Output = T>,
642    S: OptionWeightType,
643{
644    type Output = Option<T>;
645
646    #[inline]
647    fn mul_by_ref(&self, rhs: &S) -> Self::Output {
648        self.as_ref().map(|lhs| lhs.mul_by_ref(rhs))
649    }
650}
651
652/// Semigroup over values of type `V`.
653///
654/// This trait defines an associative binary operation
655/// over values of type `V`.  Unlike [`SemigroupValue`],
656/// which can only be implemented once per type, it allows
657/// creating multiple semigroup structures over the same type.
658/// For example, integers form semigroups with addition,
659/// multiplication, min, and max operations, among others.
660// TODO: add optimized methods that take arguments by value,
661// and that combine more than two elements.
662pub trait Semigroup<V> {
663    /// Apply the semigroup operation to `left` and `right`.
664    fn combine(left: &V, right: &V) -> V;
665
666    /// Apply the semigroup operation to values of type `Option<V>`.
667    ///
668    /// This method defines a monoid over values of type `Option<V>` with
669    /// `None` as the neutral element.  It returns:
670    /// * `None`, if both arguments are `None`,
671    /// * `left` (`right`), if `right` (`left`) is `None`,
672    /// * `combine(left.unwrap(), right.unwrap())` otherwise.
673    fn combine_opt(left: &Option<V>, right: &Option<V>) -> Option<V>
674    where
675        V: Clone,
676    {
677        if let Some(left) = left {
678            if let Some(right) = right {
679                Some(Self::combine(left, right))
680            } else {
681                Some(left.clone())
682            }
683        } else {
684            right.clone()
685        }
686    }
687}
688
689/// Trait [`Semigroup`] implementation for types that
690/// implement [`SemigroupValue`].
691///
692/// Implements `Semigroup<V>` using `V`'s natural plus
693/// operation.
694#[derive(Clone)]
695pub struct DefaultSemigroup<V>(PhantomData<V>);
696
697impl<V> Semigroup<V> for DefaultSemigroup<V>
698where
699    V: SemigroupValue,
700{
701    fn combine(left: &V, right: &V) -> V {
702        left.add_by_ref(right)
703    }
704}
705
706/// [`Semigroup`] implementation that panics with "not implemented"
707/// message.
708// TODO: this is a temporary thing that can be used with aggregation operators,
709// which currently don't invoke the `Semigroup` trait (but this will change
710// in the future).
711#[derive(Clone)]
712pub struct UnimplementedSemigroup<V>(PhantomData<V>);
713
714impl<V> Semigroup<V> for UnimplementedSemigroup<V> {
715    fn combine(_left: &V, _right: &V) -> V {
716        unimplemented!()
717    }
718}
719
720#[cfg(test)]
721mod integer_ring_tests {
722    use super::*;
723
724    #[test]
725    fn fixed_integer_tests() {
726        assert_eq!(0, <i64 as HasZero>::zero());
727        assert_eq!(1, <i64 as HasOne>::one());
728        let two = <i64 as HasOne>::one().add_by_ref(&<i64 as HasOne>::one());
729        assert_eq!(2, two);
730        assert_eq!(-2, two.neg_by_ref());
731        assert_eq!(-4, two.mul_by_ref(&two.neg_by_ref()));
732    }
733
734    #[test]
735    fn fixed_isize_tests() {
736        assert_eq!(0, <isize as HasZero>::zero());
737        assert_eq!(1, <isize as HasOne>::one());
738        let two = <isize as HasOne>::one().add_by_ref(&<isize as HasOne>::one());
739        assert_eq!(2, two);
740        assert_eq!(-2, two.neg_by_ref());
741        assert_eq!(-4, two.mul_by_ref(&two.neg_by_ref()));
742    }
743
744    #[test]
745    fn fixed_i64_tests() {
746        assert_eq!(0, <i64 as HasZero>::zero());
747        assert_eq!(1, <i64 as HasOne>::one());
748        let two = <i64 as HasOne>::one().add_by_ref(&<i64 as HasOne>::one());
749        assert_eq!(2, two);
750        assert_eq!(-2, two.neg_by_ref());
751        assert_eq!(-4, two.mul_by_ref(&two.neg_by_ref()));
752    }
753}