Base.Inf for other Number types?

Currently, it seems Inf is only defined for Float*. I am wondering if it possible to extend this to other data types, such as Integer? Then just like zero and one, we can have

julia> infinity(1.0)
Inf
julia> infinity(1)
# An `Inf` of type `Int`.

Currently, I mimic the behavior using typemin and typemax.

function infinity(::T) where T<:Real
    return typemax(T)
end

function isinfinity(n::T) where T<:Real
    return n == infinity(n)
end

Edited: I really have to narrow Number to Real since the infinity of Complex is undefined?

Edited 2: After read all suggestions, I come up following solution: just use a Union type. Thanks for all!

struct MyPhysParameter{T<:Real}
    value_type::T
    allowed_min::Union{T, typeof(Inf)}
    allowed_max::Union{T, typeof(Inf)}
end
2 Likes

eh… I think the issue is that there isn’t an infinity defined in Int… the largest value is 2^63-1 with no spares.

I wonder what is the negative version of 0 for?

1 Like

The zero and one in my post refer to Base.zero and Base.one which simply return 0 and 1 of the same type of the input argument. Examples:

julia> zero(-1.0)
0.0
julia> zero(-1)
0
julia> zero(1 - 2.0im)
0.0 + 0.0im

To Integer, technically yes, since you can define

struct InfinityInteger <: Integer end
Base.isinfinite(::InfinityInteger) = true

etc, but not to Int, since that is a bits type that has no representation for infinity.

Practically, since you have to use at least Union types anyway, I would recommend you just use Inf::Float64 or similar.

2 Likes

Alternatively, you can wrap Int and use sentinel values.

1 Like

I would go for Union{Int64, InfinityInteger}. It’s cleaner, and Union{Int64, Float64} tends to get smushed over time:

julia> [1, Inf]
2-element Array{Float64,1}:
  1.0
 Inf

julia> identity.(Union{Int, Float64}[1, Inf])
2-element Array{Real,1}:
  1
 Inf

And there might be cases where it infers better.

InfiniteArrays.jl has Infinity <: Integer. This is going to be moved to JuliaMath/Infinities.jl as InfiniteCardinal{0}

1 Like

@Tamas_Papp’s answer and others proposing/implementing infinity types are a good ones.

If you want to avoid the Union…I started working on a NaNIntegers package, but never finished it. Here’s the start: https://gist.github.com/timholy/569475b24763d1fbd36a42634192cb74. It uses the second-from-top-bit to indicate NaN. You could modify this to use the third-from-top-bit to indicate infinity. Note you have to write your own rules of mathematics, so there’s still a bit of work to do.

I’d generally recommend against mimicking infinity with typemax:

julia> i = typemax(Int)
9223372036854775807

julia> i+1 == i
false

julia> 2*i == i
false

julia> i-1 == i
false

Any infinity that doesn’t obey those properties is not really infinity.

8 Likes

Great suggestions. However, my usage of infinity is not as ambitious as yours. I only intend to use it as a indicator to mark the infinity, that is to say I will never do any math operations on it.

Here is what I want to do. I want to define a type which describes a physical parameter. Now, with this type I can dispatch some physical computation on it.

struct MyPhysParameter{T<:Real}
    description::String
    variable_name::String
    ascii_label::String
    allowed_min::T # the minimum value allowed for this parameter, can be negative infinity
    allowed_max::T # the maximum value allowed for this parameter, can be positive infinity
end

So I will need a type stable way to define the infinity.

Typical dispatch case

function compute(::MyPhysParameter, data)
    # use the bounds to `rand` or check data validity, etc.
end

If you want to encode the min/max, why not just use typemin/typemax?

Edit:

I only intend to use it as a indicator to mark the infinity, that is to say I will never do any math operations on it.

The problem I foresee with calling this Inf is, what happens when you come back to this after six months away and then forget that you can’t do math operations on it? Calling it Inf is a slippery slope…

4 Likes