Task: Tropical algebra overloading


C++: #include <iostream>
#include <optional>

using namespace std;

class TropicalAlgebra
{
    
    optional<double> m_value;
    
public:
    friend std::ostream& operator<<(std::ostream&, const TropicalAlgebra&);
    friend TropicalAlgebra pow(const TropicalAlgebra& base, unsigned int exponent) noexcept;
    
    
    TropicalAlgebra() = default;

    
    explicit TropicalAlgebra(double value) noexcept
        : m_value{value} {}

    
    
    TropicalAlgebra& operator+=(const TropicalAlgebra& rhs) noexcept
    {
        if(!m_value)
        {
            
            *this = rhs;
        }
        else if (!rhs.m_value)
        {
            
        }
        else
        {
            
            *m_value = max(*rhs.m_value, *m_value);
        }

        return *this;
    }
    
    
    TropicalAlgebra& operator*=(const TropicalAlgebra& rhs) noexcept
    {
        if(!m_value)
        {
            
            
        }
        else if (!rhs.m_value)
        {
            
            *this = rhs;
        }
        else
        {
            *m_value += *rhs.m_value;
        }

        return *this;
    }
};


inline TropicalAlgebra operator+(TropicalAlgebra lhs, const TropicalAlgebra& rhs) noexcept
{
    
    lhs += rhs;
    return lhs;
}


inline TropicalAlgebra operator*(TropicalAlgebra lhs, const TropicalAlgebra&  rhs) noexcept
{
    lhs *= rhs;
    return lhs;
}


inline TropicalAlgebra pow(const TropicalAlgebra& base, unsigned int exponent) noexcept
{
    auto result = base;
    for(unsigned int i = 1; i < exponent; i++)
    {
        
        result *= base;
    }
    return result;
}


ostream& operator<<(ostream& os, const TropicalAlgebra& pt)
{
    if(!pt.m_value) cout << "-Inf\n";
    else cout << *pt.m_value << "\n";
    return os;
}

int main(void) {
    const TropicalAlgebra a(-2);
    const TropicalAlgebra b(-1);
    const TropicalAlgebra c(-0.5);
    const TropicalAlgebra d(-0.001);
    const TropicalAlgebra e(0);
    const TropicalAlgebra h(1.5);
    const TropicalAlgebra i(2);
    const TropicalAlgebra j(5);
    const TropicalAlgebra k(7);
    const TropicalAlgebra l(8);
    const TropicalAlgebra m; 
    
    cout << "2 * -2 == " << i * a;
    cout << "-0.001 + -Inf == " << d + m;
    cout << "0 * -Inf == " << e * m;
    cout << "1.5 + -1 == " << h + b;
    cout << "-0.5 * 0 == " << c * e;
    cout << "pow(5, 7) == " << pow(j, 7);
    cout << "5 * (8 + 7)) == " << j * (l + k);
    cout << "5 * 8 + 5 * 7 == " << j * l + j * k;
}



Go: package main

import (
    "fmt"
    "log"
    "math"
)

var MinusInf = math.Inf(-1)

type MaxTropical struct{ r float64 }

func newMaxTropical(r float64) MaxTropical {
    if math.IsInf(r, 1) || math.IsNaN(r) {
        log.Fatal("Argument must be a real number or negative infinity.")
    }
    return MaxTropical{r}
}

func (t MaxTropical) eq(other MaxTropical) bool {
    return t.r == other.r
}


func (t MaxTropical) add(other MaxTropical) MaxTropical {
    if t.r == MinusInf {
        return other
    }
    if other.r == MinusInf {
        return t
    }
    return newMaxTropical(math.Max(t.r, other.r))
}


func (t MaxTropical) mul(other MaxTropical) MaxTropical {
    if t.r == 0 {
        return other
    }
    if other.r == 0 {
        return t
    }
    return newMaxTropical(t.r + other.r)
}


func (t MaxTropical) pow(e int) MaxTropical {
    if e < 1 {
        log.Fatal("Exponent must be a positive integer.")
    }
    if e == 1 {
        return t
    }
    p := t
    for i := 2; i <= e; i++ {
        p = p.mul(t)
    }
    return p
}

func (t MaxTropical) String() string {
    return fmt.Sprintf("%g", t.r)
}

func main() {
    
    data := [][]float64{
        {2, -2, 1},
        {-0.001, MinusInf, 0},
        {0, MinusInf, 1},
        {1.5, -1, 0},
        {-0.5, 0, 1},
    }
    for _, d := range data {
        a := newMaxTropical(d[0])
        b := newMaxTropical(d[1])
        if d[2] == 0 {
            fmt.Printf("%s ⊕ %s = %s\n", a, b, a.add(b))
        } else {
            fmt.Printf("%s ⊗ %s = %s\n", a, b, a.mul(b))
        }
    }

    c := newMaxTropical(5)
    fmt.Printf("%s ^ 7 = %s\n", c, c.pow(7))

    d := newMaxTropical(8)
    e := newMaxTropical(7)
    f := c.mul(d.add(e))
    g := c.mul(d).add(c.mul(e))
    fmt.Printf("%s ⊗ (%s ⊕ %s) = %s\n", c, d, e, f)
    fmt.Printf("%s ⊗ %s ⊕ %s ⊗ %s = %s\n", c, d, c, e, g)
    fmt.Printf("%s ⊗ (%s ⊕ %s) == %s ⊗ %s ⊕ %s ⊗ %s is %t\n", c, d, e, c, d, c, e, f.eq(g))
}