// ---
// tags: trop, trident
// crystal-type: circuit
// crystal-domain: comp
// ---

//  Tropical semiring element over U32.
//
//  The tropical semiring (min, +):
//    - Tropical addition: a + b = min(a, b)
//    - Tropical multiplication: a * b = a + b (ordinary, saturating)
//    - Additive identity (ZERO): +inf (U32 max = 4294967295)
//    - Multiplicative identity (ONE): 0

module trop.element

/// Sentinel for +infinity (tropical zero, additive identity).
pub const INF: U32 = 4294967295

/// A tropical semiring element wrapping a U32.
/// val == INF represents +infinity.
/// val == 0 represents tropical one (multiplicative identity).
pub struct Tropical {
    val: U32
}

/// Construct a Tropical element from a raw U32.
pub fn from_u32(v: U32) -> Tropical {
    Tropical { val: v }
}

/// Extract the inner U32 value.
pub fn as_u32(t: Tropical) -> U32 {
    t.val
}

/// Check whether this element is +inf (tropical zero).
pub fn is_inf(t: Tropical) -> bool {
    t.val == INF
}

/// Check whether this element is finite.
pub fn is_finite(t: Tropical) -> bool {
    t.val != INF
}

/// Tropical addition: min(a, b).
/// If either operand is INF, returns the other.
pub fn add(a: Tropical, b: Tropical) -> Tropical {
    if a.val < b.val {
        a
    } else {
        b
    }
}

/// Tropical multiplication: a + b (saturating).
/// If either operand is INF, or if the sum overflows U32, returns INF.
pub fn mul(a: Tropical, b: Tropical) -> Tropical {
    if a.val == INF {
        Tropical { val: INF }
    } else if b.val == INF {
        Tropical { val: INF }
    } else {
        let sum: U32 = a.val + b.val
        // Overflow check: if sum wrapped around, it will be less than either operand.
        // Also guard against hitting the INF sentinel exactly.
        if sum < a.val {
            Tropical { val: INF }
        } else if sum == INF {
            Tropical { val: INF }
        } else {
            Tropical { val: sum }
        }
    }
}

/// Tropical zero: +inf (identity for min).
pub fn zero() -> Tropical {
    Tropical { val: INF }
}

/// Tropical one: 0 (identity for ordinary addition).
pub fn one() -> Tropical {
    Tropical { val: 0 }
}

Local Graph