// ---
// tags: trop, trident
// crystal-type: circuit
// crystal-domain: comp
// ---
// Max-plus (dual tropical) semiring.
//
// The max-plus semiring (max, +):
// - Addition: a + b = max(a, b)
// - Multiplication: a * b = a + b (ordinary, saturating)
// - Additive identity (ZERO): 0 representing -inf
// - Multiplicative identity (ONE): value 0 encoded as 1
//
// Encoding: MaxPlus(0) = -inf. MaxPlus(v) for v >= 1 represents value (v - 1).
module trop.dual
/// Sentinel for -infinity (additive identity for max).
pub const NEG_INF: U32 = 0
/// A max-plus semiring element.
/// val == 0 is -inf (additive identity).
/// val >= 1 represents the value (val - 1).
pub struct MaxPlus {
val: U32
}
/// Construct a MaxPlus element representing the value v.
/// v must be < 4294967295 (U32 max is reserved for encoding headroom).
pub fn from_val(v: U32) -> MaxPlus {
MaxPlus { val: v + 1 }
}
/// Extract the represented value. Returns NEG_INF sentinel (4294967295) if -inf.
pub fn to_val(m: MaxPlus) -> U32 {
if m.val == 0 {
4294967295
} else {
m.val - 1
}
}
/// Check whether this is -inf.
pub fn is_neg_inf(m: MaxPlus) -> bool {
m.val == 0
}
/// Check whether this is finite.
pub fn is_finite(m: MaxPlus) -> bool {
m.val != 0
}
/// Max-plus addition: max(a, b).
pub fn add(a: MaxPlus, b: MaxPlus) -> MaxPlus {
if a.val > b.val {
a
} else {
b
}
}
/// Max-plus multiplication: a + b (with -inf absorbing).
/// Internal encoding: result.val = a.val + b.val - 1.
pub fn mul(a: MaxPlus, b: MaxPlus) -> MaxPlus {
if a.val == 0 {
MaxPlus { val: 0 }
} else if b.val == 0 {
MaxPlus { val: 0 }
} else {
// Decoded values: (a.val - 1) + (b.val - 1) = a.val + b.val - 2
// Re-encode: a.val + b.val - 2 + 1 = a.val + b.val - 1
let sum: U32 = a.val + b.val
// Overflow check: if sum wrapped, it will be less than either operand
if sum < a.val {
MaxPlus { val: 4294967295 }
} else {
MaxPlus { val: sum - 1 }
}
}
}
/// Max-plus zero: -inf (identity for max).
pub fn zero() -> MaxPlus {
MaxPlus { val: 0 }
}
/// Max-plus one: represents value 0 (identity for addition).
pub fn one() -> MaxPlus {
MaxPlus { val: 1 }
}
trop/tri/dual.tri
ฯ 0.0%