Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 27 additions & 3 deletions src/TropicalNumbers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ export TropicalTypes, AbstractSemiring

export TropicalAndOr
export Tropical, TropicalF64, TropicalF32, TropicalF16, TropicalI64, TropicalI32, TropicalI16
export TropicalMaxMul, TropicalMaxMulF64, TropicalMaxMulF32, TropicalMaxMulF16, TropicalMaxMulI64, TropicalMaxMulI32, TropicalMaxMulI16
export TropicalMaxPlus, TropicalMaxPlusF64, TropicalMaxPlusF32, TropicalMaxPlusF16, TropicalMaxPlusI64, TropicalMaxPlusI32, TropicalMaxPlusI16
export TropicalMinPlus, TropicalMinPlusF64, TropicalMinPlusF32, TropicalMinPlusF16, TropicalMinPlusI64, TropicalMinPlusI32, TropicalMinPlusI16
export TropicalMaxMul, TropicalMaxMulF64, TropicalMaxMulF32, TropicalMaxMulF16, TropicalMaxMulI64, TropicalMaxMulI32, TropicalMaxMulI16
export TropicalMaxMin, TropicalMaxMinF64, TropicalMaxMinF32, TropicalMaxMinF16, TropicalMaxMinI64, TropicalMaxMinI32, TropicalMaxMinI16
export TropicalBitwise, TropicalBitwiseI64, TropicalBitwiseI32, TropicalBitwiseI16
export CountingTropical, CountingTropicalF16, CountingTropicalF32, CountingTropicalF64, CountingTropicalI16, CountingTropicalI32, CountingTropicalI64


Expand Down Expand Up @@ -41,6 +43,8 @@ include("tropical_maxplus.jl")
include("tropical_andor.jl")
include("tropical_minplus.jl")
include("tropical_maxmul.jl")
include("tropical_maxmin.jl")
include("tropical_bitwise.jl")
include("counting_tropical.jl")

const TropicalTypes{T} = Union{CountingTropical{T}, Tropical{T}}
Expand All @@ -53,17 +57,20 @@ for NBIT in [16, 32, 64]
@eval const $(Symbol(:TropicalMaxPlus, :F, NBIT)) = TropicalMaxPlus{$(Symbol(:Float, NBIT))}
@eval const $(Symbol(:TropicalMinPlus, :F, NBIT)) = TropicalMinPlus{$(Symbol(:Float, NBIT))}
@eval const $(Symbol(:TropicalMaxMul, :F, NBIT)) = TropicalMaxMul{$(Symbol(:Float, NBIT))}
@eval const $(Symbol(:TropicalMaxMin, :F, NBIT)) = TropicalMaxMin{$(Symbol(:Float, NBIT))}
@eval const $(Symbol(:CountingTropical, :F, NBIT)) = CountingTropical{$(Symbol(:Float, NBIT)),$(Symbol(:Float, NBIT))}

@eval const $(Symbol(:Tropical, :I, NBIT)) = Tropical{$(Symbol(:Int, NBIT))}
@eval const $(Symbol(:TropicalMaxPlus, :I, NBIT)) = TropicalMaxPlus{$(Symbol(:Int, NBIT))}
@eval const $(Symbol(:TropicalMinPlus, :I, NBIT)) = TropicalMinPlus{$(Symbol(:Int, NBIT))}
@eval const $(Symbol(:TropicalMaxMul, :I, NBIT)) = TropicalMaxMul{$(Symbol(:Int, NBIT))}
@eval const $(Symbol(:TropicalMaxMin, :I, NBIT)) = TropicalMaxMin{$(Symbol(:Int, NBIT))}
@eval const $(Symbol(:TropicalBitwise, :I, NBIT)) = TropicalBitwise{$(Symbol(:Int, NBIT))}
@eval const $(Symbol(:CountingTropical, :I, NBIT)) = CountingTropical{$(Symbol(:Int, NBIT)),$(Symbol(:Float, NBIT))}
end

# alias
for T in [:Tropical, :TropicalMaxMul, :TropicalMinPlus, :CountingTropical]
for T in [:Tropical, :TropicalMaxMul, :TropicalMaxMin, :CountingTropical]
for OP in [:>, :<, :(==), :>=, :<=, :isless]
@eval Base.$OP(a::$T, b::$T) = $OP(a.n, b.n)
end
Expand All @@ -76,6 +83,16 @@ for T in [:Tropical, :TropicalMaxMul, :TropicalMinPlus, :CountingTropical]
end
end

for T in [:TropicalMinPlus, :TropicalBitwise]
@eval begin
content(x::$T) = x.n
content(x::Type{$T{X}}) where X = X
Base.isapprox(x::AbstractArray{<:$T}, y::AbstractArray{<:$T}; kwargs...) = all(isapprox.(x, y; kwargs...))
Base.show(io::IO, ::MIME"text/plain", t::$T) = Base.show(io, t)
Base.isnan(x::$T) = isnan(content(x))
end
end

for T in [:TropicalAndOr]
for OP in [:>, :<, :(==), :>=, :<=, :isless]
@eval Base.$OP(a::$T, b::$T) = $OP(a.n, b.n)
Expand All @@ -88,7 +105,7 @@ for T in [:TropicalAndOr]
end
end

for T in [:Tropical, :TropicalMaxMul, :TropicalMinPlus, :CountingTropical]
for T in [:Tropical, :TropicalMinPlus, :TropicalMaxMul, :CountingTropical]
@eval begin
# this is for CUDA matmul
Base.:(*)(a::$T, b::Bool) = b ? a : zero(a)
Expand All @@ -100,4 +117,11 @@ for T in [:Tropical, :TropicalMaxMul, :TropicalMinPlus, :CountingTropical]
end
end

for T in [:TropicalMaxMin, :TropicalBitwise]
@eval begin
Base.:(*)(a::$T, b::Bool) = b ? a : zero(a)
Base.:(*)(b::Bool, a::$T) = b ? a : zero(a)
end
end

end # module
109 changes: 109 additions & 0 deletions src/tropical_bitwise.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
"""
TropicalBitwise{T} <: AbstractSemiring

TropicalBitwise is a semiring algebra, can be described by
* TropicalBitwise, (ℝ, |, &, 0, ~0).

It maps
* `+` to `|`
* `*` to `&`
* `0` to `0`
* `1` to ~0`

Example
-------------------------
```jldoctest; setup=:(using TropicalNumbers)
julia> TropicalBitwise(1) + TropicalBitwise(3)
3ₛ

julia> TropicalBitwise(1) * TropicalBitwise(3)
1ₛ

julia> zero(TropicalBitwiseI64)
0ₛ

julia> one(TropicalBitwiseI64)
-1ₛ
```
"""
struct TropicalBitwise{T} <: AbstractSemiring
n::T
end

function TropicalBitwise(a::TropicalBitwise)
return TropicalBitwise(a.n)
end

function TropicalBitwise{T}(a::TropicalBitwise) where {T}
return TropicalBitwise{T}(a.n)
end

function Base.show(io::IO, a::TropicalBitwise)
print(io, "$(a.n)ₛ")
return
end

function Base.isapprox(a::TropicalBitwise, b::TropicalBitwise; kw...)
return isapprox(a.n, b.n; kw...)
end

function Base.promote_rule(::Type{TropicalBitwise{U}}, ::Type{TropicalBitwise{V}}) where {U, V}
W = promote_type(U, V)
return TropicalBitwise{W}
end

function Base.:+(a::TropicalBitwise, b::TropicalBitwise)
n = a.n | b.n
return TropicalBitwise(n)
end

function Base.:*(a::TropicalBitwise, b::TropicalBitwise)
n = a.n & b.n
return TropicalBitwise(n)
end

function Base.zero(::Type{T}) where {T <: TropicalBitwise}
return typemin(T)
end

function Base.zero(::T) where {T <: TropicalBitwise}
return zero(T)
end

function Base.one(::Type{T}) where {T <: TropicalBitwise}
return typemax(T)
end

function Base.one(::T) where {T <: TropicalBitwise}
return one(T)
end

function Base.typemin(::Type{TropicalBitwise{T}}) where {T}
n = zero(T)
return TropicalBitwise(n)
end

function Base.typemax(::Type{TropicalBitwise{T}}) where {T}
n = ~zero(T)
return TropicalBitwise(n)
end

function Base.:(==)(a::TropicalBitwise, b::TropicalBitwise)
return a.n == b.n
end

function Base.:>=(a::TropicalBitwise, b::TropicalBitwise)
return b.n <= a.n
end

function Base.:<=(a::TropicalBitwise, b::TropicalBitwise)
return a.n | b.n == b.n
end

function Base.:<(a::TropicalBitwise, b::TropicalBitwise)
return a != b && a <= b
end

function Base.:>(a::TropicalBitwise, b::TropicalBitwise)
return b < a
end
89 changes: 89 additions & 0 deletions src/tropical_maxmin.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
"""
TropicalMaxMin{T} <: AbstractSemiring

TropicalMaxMin is a semiring algebra, can be described by
* TropicalMaxMin, (ℝ, max, min, -Inf, Inf).

It maps
* `+` to `max` in regular algebra,
* `*` to `min` in regular algebra,
* `0` to `-Inf` in regular algebra (for integer content types, this is a small integer).
* `1` to `Inf` in regular algebra, (for integer content types, this is a large integer)

Example
-------------------------
```jldoctest; setup=:(using TropicalNumbers)
julia> TropicalMaxMin(1.0) + TropicalMaxMin(3.0)
3.0ₛ

julia> TropicalMaxMin(1.0) * TropicalMaxMin(3.0)
1.0ₛ

julia> zero(TropicalMaxMinF64)
-Infₛ

julia> one(TropicalMaxMinF64)
Infₛ
```
"""
struct TropicalMaxMin{T} <: AbstractSemiring
n::T
end

function TropicalMaxMin(a::TropicalMaxMin)
return TropicalMaxMin(a.n)
end

function TropicalMaxMin{T}(a::TropicalMaxMin) where {T}
return TropicalMaxMin{T}(a.n)
end

function Base.show(io::IO, a::TropicalMaxMin)
print(io, "$(a.n)ₛ")
return
end

function Base.isapprox(a::TropicalMaxMin, b::TropicalMaxMin; kw...)
return isapprox(a.n, b.n; kw...)
end

function Base.promote_rule(::Type{TropicalMaxMin{U}}, ::Type{TropicalMaxMin{V}}) where {U, V}
W = promote_type(U, V)
return TropicalMaxMin{W}
end

function Base.:+(a::TropicalMaxMin, b::TropicalMaxMin)
n = max(a.n, b.n)
return TropicalMaxMin(n)
end

function Base.:*(a::TropicalMaxMin, b::TropicalMaxMin)
n = min(a.n, b.n)
return TropicalMaxMin(n)
end

function Base.zero(::Type{T}) where {T <: TropicalMaxMin}
return typemin(T)
end

function Base.zero(::T) where {T <: TropicalMaxMin}
return zero(T)
end

function Base.one(::Type{T}) where {T <: TropicalMaxMin}
return typemax(T)
end

function Base.one(::T) where {T <: TropicalMaxMin}
return one(T)
end

function Base.typemin(::Type{TropicalMaxMin{T}}) where {T}
n = neginf(T)
return TropicalMaxMin(n)
end

function Base.typemax(::Type{TropicalMaxMin{T}}) where {T}
n = posinf(T)
return TropicalMaxMin(n)
end
25 changes: 25 additions & 0 deletions src/tropical_minplus.jl
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,31 @@ Base.inv(x::TropicalMinPlus) = TropicalMinPlus(-x.n)
Base.:/(x::TropicalMinPlus, y::TropicalMinPlus) = TropicalMinPlus(x.n - y.n)
Base.div(x::TropicalMinPlus, y::TropicalMinPlus) = TropicalMinPlus(x.n - y.n)

# ordering
function Base.:(==)(a::TropicalMinPlus, b::TropicalMinPlus)
return b.n == a.n
end

function Base.:>=(a::TropicalMinPlus, b::TropicalMinPlus)
return b.n >= a.n
end

function Base.:<=(a::TropicalMinPlus, b::TropicalMinPlus)
return b.n <= a.n
end

function Base.:<(a::TropicalMinPlus, b::TropicalMinPlus)
return b.n < a.n
end

function Base.:>(a::TropicalMinPlus, b::TropicalMinPlus)
return b.n > a.n
end

function Base.isless(a::TropicalMinPlus, b::TropicalMinPlus)
return isless(b.n, a.n)
end

Base.isapprox(x::TropicalMinPlus, y::TropicalMinPlus; kwargs...) = isapprox(x.n, y.n; kwargs...)

# promotion rules
Expand Down
8 changes: 8 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ end
include("tropical_maxplus.jl")
end

@testset "tropical max min" begin
include("tropical_maxmin.jl")
end

@testset "tropical bitwise" begin
include("tropical_bitwise.jl")
end

@testset "counting_tropical" begin
include("counting_tropical.jl")
end
Expand Down
39 changes: 39 additions & 0 deletions test/tropical_bitwise.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using Test
using TropicalNumbers

@testset "TropicalBitwise max mul" begin
@test TropicalBitwise(3) * TropicalBitwise(4) == TropicalBitwise(0)
@test TropicalBitwise(3) + TropicalBitwise(4) == TropicalBitwise(7)
@test TropicalBitwise(4) + TropicalBitwise(1) == TropicalBitwise(5)
@test zero(TropicalBitwise(2)) == TropicalBitwise(0)
@test one(TropicalBitwise(2)) == TropicalBitwise(~0)
@test TropicalBitwise(2) ≈ TropicalBitwise(2)
@test TropicalBitwiseI32(2).n isa Int32
@test TropicalBitwiseI16(2).n isa Int16
@test TropicalBitwiseI64(2).n isa Int64

@test content(TropicalBitwise(3)) == 3
@test TropicalBitwise{UInt32}(TropicalBitwise(0)) isa TropicalBitwise{UInt32}
println(TropicalBitwiseI64(3))

# promote and convert
t1 = TropicalBitwise(2)
t2 = TropicalBitwise(UInt32(2))
@test TropicalBitwiseI32(t1) === TropicalBitwise(Int32(2))
@test promote(t1, t2) === (t1, t1)

@test content(TropicalBitwiseI64) == Int64

@test promote(TropicalBitwise{Int64}(1), TropicalBitwise{UInt64}(2)) == (TropicalBitwise{Int64}(1), TropicalBitwise{Int64}(2))
@test promote(TropicalBitwise{Int64}(1)) == (TropicalBitwise{Int64}(1),)
@test promote_type(TropicalBitwise{Int64}, TropicalBitwiseI32) == TropicalBitwiseI64
@test promote_type(TropicalBitwise{Int64}, TropicalBitwiseI32, TropicalBitwise{UInt32}) == TropicalBitwiseI64

x = TropicalBitwise(2)
@test x * true == x * one(x)
@test x * false == x * zero(x)
@test true * x == one(x) * x
@test false * x == zero(x) * x

@test TropicalBitwise(0) < TropicalBitwise(10) <= TropicalBitwise(10) <= TropicalBitwise(~0)
end
Loading
Loading