tenferro_ext_tropical/
algebra.rs

1//! Tropical algebra markers, [`HasAlgebra`], and [`Semiring`] implementations.
2//!
3//! Each zero-sized struct identifies a tropical algebra for use with
4//! semiring-family execution traits such as
5//! [`TensorSemiringCore<Alg>`](tenferro_prims::TensorSemiringCore). The orphan
6//! rule is satisfied because the algebra markers are defined in this crate.
7//!
8//! | Algebra marker | Scalar wrapper | ⊕ | ⊗ |
9//! |----------------|---------------|---|---|
10//! | [`MaxPlusAlgebra<T>`] | [`MaxPlus<T>`](crate::MaxPlus) | max | + |
11//! | [`MinPlusAlgebra<T>`] | [`MinPlus<T>`](crate::MinPlus) | min | + |
12//! | [`MaxMulAlgebra<T>`] | [`MaxMul<T>`](crate::MaxMul) | max | × |
13
14use std::marker::PhantomData;
15
16use tenferro_algebra::{Algebra, HasAlgebra, Semiring};
17
18use crate::scalar::{MaxMul, MaxPlus, MinPlus};
19
20/// Generates a tropical algebra marker struct with HasAlgebra and Semiring impls.
21///
22/// For each invocation, this creates:
23/// - A generic zero-sized marker struct `$marker<T>`
24/// - `HasAlgebra` impls mapping `$wrapper<f32>` and `$wrapper<f64>` to the marker
25/// - `Semiring` impls for `$marker<f32>` and `$marker<f64>`
26///
27/// The `$add_fn` and `$mul_fn` closures define the semiring operations and must
28/// be valid for both f32 and f64.
29macro_rules! define_tropical_algebra {
30    (
31        $(#[$meta:meta])*
32        $marker:ident, $wrapper:ident,
33        zero_f32: $z32:expr, one_f32: $o32:expr,
34        zero_f64: $z64:expr, one_f64: $o64:expr
35    ) => {
36        $(#[$meta])*
37        #[derive(Debug, Clone, Copy)]
38        pub struct $marker<T>(PhantomData<T>);
39
40        impl HasAlgebra for $wrapper<f32> {
41            type Algebra = $marker<f32>;
42        }
43
44        impl HasAlgebra for $wrapper<f64> {
45            type Algebra = $marker<f64>;
46        }
47
48        impl Algebra for $marker<f32> {
49            type Scalar = $wrapper<f32>;
50        }
51
52        impl Algebra for $marker<f64> {
53            type Scalar = $wrapper<f64>;
54        }
55
56        impl Semiring for $marker<f32> {
57            fn zero() -> Self::Scalar { $z32 }
58            fn one() -> Self::Scalar { $o32 }
59            fn add(a: Self::Scalar, b: Self::Scalar) -> Self::Scalar { a + b }
60            fn mul(a: Self::Scalar, b: Self::Scalar) -> Self::Scalar { a * b }
61        }
62
63        impl Semiring for $marker<f64> {
64            fn zero() -> Self::Scalar { $z64 }
65            fn one() -> Self::Scalar { $o64 }
66            fn add(a: Self::Scalar, b: Self::Scalar) -> Self::Scalar { a + b }
67            fn mul(a: Self::Scalar, b: Self::Scalar) -> Self::Scalar { a * b }
68        }
69    };
70}
71
72define_tropical_algebra!(
73    /// Algebra marker for the max-plus tropical semiring (⊕ = max, ⊗ = +).
74    ///
75    /// Generic over the inner scalar type `T` (typically `f32` or `f64`).
76    /// Used as the algebra parameter `Alg` in semiring-family execution traits
77    /// such as
78    /// [`TensorSemiringCore<MaxPlusAlgebra<T>>`](tenferro_prims::TensorSemiringCore).
79    ///
80    /// # Examples
81    ///
82    /// ```
83    /// use tenferro_algebra::Semiring;
84    /// use tenferro_ext_tropical::{MaxPlus, MaxPlusAlgebra};
85    ///
86    /// let z = <MaxPlusAlgebra<f64> as Semiring>::zero();
87    /// assert_eq!(z, MaxPlus(f64::NEG_INFINITY));
88    /// let z32 = <MaxPlusAlgebra<f32> as Semiring>::zero();
89    /// assert_eq!(z32, MaxPlus(f32::NEG_INFINITY));
90    /// ```
91    MaxPlusAlgebra, MaxPlus,
92    zero_f32: MaxPlus(f32::NEG_INFINITY), one_f32: MaxPlus(0.0f32),
93    zero_f64: MaxPlus(f64::NEG_INFINITY), one_f64: MaxPlus(0.0f64)
94);
95
96define_tropical_algebra!(
97    /// Algebra marker for the min-plus tropical semiring (⊕ = min, ⊗ = +).
98    ///
99    /// # Examples
100    ///
101    /// ```
102    /// use tenferro_algebra::Semiring;
103    /// use tenferro_ext_tropical::{MinPlus, MinPlusAlgebra};
104    ///
105    /// let z = <MinPlusAlgebra<f64> as Semiring>::zero();
106    /// assert_eq!(z, MinPlus(f64::INFINITY));
107    /// ```
108    MinPlusAlgebra, MinPlus,
109    zero_f32: MinPlus(f32::INFINITY), one_f32: MinPlus(0.0f32),
110    zero_f64: MinPlus(f64::INFINITY), one_f64: MinPlus(0.0f64)
111);
112
113define_tropical_algebra!(
114    /// Algebra marker for the max-times tropical semiring (⊕ = max, ⊗ = ×).
115    ///
116    /// # Examples
117    ///
118    /// ```
119    /// use tenferro_algebra::Semiring;
120    /// use tenferro_ext_tropical::{MaxMul, MaxMulAlgebra};
121    ///
122    /// let z = <MaxMulAlgebra<f64> as Semiring>::zero();
123    /// assert_eq!(z, MaxMul(0.0f64));
124    /// ```
125    MaxMulAlgebra, MaxMul,
126    zero_f32: MaxMul(0.0f32), one_f32: MaxMul(1.0f32),
127    zero_f64: MaxMul(0.0f64), one_f64: MaxMul(1.0f64)
128);
129
130#[cfg(test)]
131mod tests;