Skip to content

Commit eb0e5bb

Browse files
fix ambiguities (#40)
* fix ambiguities * Update cardinality.jl * update * update * update * update * update * multiplication * Update ambiguities.jl * update * isinf and isfinite * mod * fld, cld, div * cleanup * cleanup and add a test * test ComplexInfinity promotion * Update Infinities.jl * Update runtests.jl * coverage * coverage * add a note * add tests for #47 --------- Co-authored-by: Sheehan Olver <[email protected]>
1 parent 1b8c2ce commit eb0e5bb

File tree

9 files changed

+242
-441
lines changed

9 files changed

+242
-441
lines changed

src/Infinities.jl

Lines changed: 13 additions & 273 deletions
Original file line numberDiff line numberDiff line change
@@ -34,81 +34,15 @@ _convert(::Type{Float16}, ::Infinity) = Inf16
3434
_convert(::Type{T}, ::Infinity) where {T<:Real} = convert(T, Inf)::T
3535
(::Type{T})(x::Infinity) where {T<:Real} = _convert(T, x)
3636

37-
3837
sign(y::Infinity) = 1
3938
angle(x::Infinity) = 0
39+
signbit(::Infinity) = false
4040

4141
one(::Type{Infinity}) = 1
4242
oneunit(::Type{Infinity}) = 1
4343
oneunit(::Infinity) = 1
4444
zero(::Infinity) = 0
4545

46-
isinf(::Infinity) = true
47-
isfinite(::Infinity) = false
48-
49-
==(x::Infinity, y::Infinity) = true
50-
==(x::Infinity, y::Number) = isinf(y) && angle(y) == angle(x)
51-
==(y::Number, x::Infinity) = x == y
52-
53-
isless(x::Infinity, y::Infinity) = false
54-
isless(x::Real, y::Infinity) = isfinite(x) || signbit(x)
55-
isless(x::AbstractFloat, y::Infinity) = isless(x, convert(typeof(x), y))
56-
isless(x::Infinity, y::AbstractFloat) = false
57-
isless(x::Infinity, y::Real) = false
58-
59-
(::Infinity, ::Infinity) = true
60-
<(::Infinity, ::Infinity) = false
61-
62-
<(x::Real, ::Infinity) = isfinite(x) || signbit(x)
63-
(::Real, ::Infinity) = true
64-
<(::Infinity, ::Real) = false
65-
(::Infinity, y::Real) = isinf(y) && !signbit(y)
66-
67-
min(::Infinity, ::Infinity) =
68-
max(::Infinity, ::Infinity) =
69-
min(x::Real, ::Infinity) = x
70-
max(::Real, ::Infinity) =
71-
min(::Infinity, x::Real) = x
72-
max(::Infinity, ::Real) =
73-
74-
+(::Infinity) =
75-
+(::Infinity, ::Infinity) =
76-
+(::Number, y::Infinity) =
77-
+(::Infinity, ::Number) =
78-
-(::Infinity, ::Number) =
79-
80-
+(::Integer, y::Infinity) =
81-
+(::Infinity, ::Integer) =
82-
-(::Infinity, ::Integer) =
83-
84-
-(::Infinity, ::Infinity) = NotANumber()
85-
86-
# ⊻ is xor
87-
*(::Infinity) =
88-
*(::Infinity, ::Infinity) =
89-
90-
91-
92-
for OP in (:fld,:cld,:div)
93-
@eval begin
94-
$OP(::Infinity, ::Real) =
95-
$OP(::Infinity, ::Infinity) = NotANumber()
96-
end
97-
end
98-
99-
div(::T, ::Infinity) where T<:Real = zero(T)
100-
fld(x::T, ::Infinity) where T<:Real = signbit(x) ? -one(T) : zero(T)
101-
cld(x::T, ::Infinity) where T<:Real = signbit(x) ? zero(T) : one(T)
102-
103-
mod(::Infinity, ::Infinity) = NotANumber()
104-
mod(::Infinity, ::Real) = NotANumber()
105-
function mod(x::Real, ::Infinity)
106-
x 0 || throw(ArgumentError("mod(x,∞) is unbounded for x < 0"))
107-
x
108-
end
109-
110-
111-
11246
struct RealInfinity <: Real
11347
signbit::Bool
11448
end
@@ -117,135 +51,24 @@ RealInfinity() = RealInfinity(false)
11751
RealInfinity(::Infinity) = RealInfinity()
11852
RealInfinity(x::RealInfinity) = x
11953

120-
-(::Infinity) = RealInfinity(true)
121-
-(x::Number, ::Infinity) = x + (-∞)
122-
-(x::Integer, ::Infinity) = x + (-∞)
123-
-(x::Complex, ::Infinity) = x + (-∞)
124-
-(x::Complex{Bool}, ::Infinity) = x + (-∞)
125-
126-
127-
isinf(::RealInfinity) = true
128-
isfinite(::RealInfinity) = false
129-
130-
promote_rule(::Type{Infinity}, ::Type{RealInfinity}) = RealInfinity
131-
_convert(::Type{RealInfinity}, ::Infinity) = RealInfinity(false)
132-
13354
_convert(::Type{Float16}, x::RealInfinity) = sign(x)*Inf16
13455
_convert(::Type{Float32}, x::RealInfinity) = sign(x)*Inf32
13556
_convert(::Type{Float64}, x::RealInfinity) = sign(x)*Inf64
13657
_convert(::Type{T}, x::RealInfinity) where {T<:Real} = sign(x)*convert(T, Inf)
13758
(::Type{T})(x::RealInfinity) where {T<:Real} = _convert(T, x)
13859

60+
for Typ in (RealInfinity, Infinity)
61+
@eval Bool(x::$Typ) = throw(InexactError(:Bool, Bool, x)) # ambiguity fix
62+
end
13963

14064
signbit(y::RealInfinity) = y.signbit
14165
sign(y::RealInfinity) = 1-2signbit(y)
14266
angle(x::RealInfinity) = π*signbit(x)
143-
mod(::RealInfinity, ::RealInfinity) = NotANumber()
144-
mod(::RealInfinity, ::Real) = NotANumber()
145-
function mod(x::Real, y::RealInfinity)
146-
signbit(x) == signbit(y) || throw(ArgumentError("mod($x,$y) is unbounded"))
147-
x
148-
end
14967

15068
string(y::RealInfinity) = signbit(y) ? "-∞" : "+∞"
15169
show(io::IO, y::RealInfinity) = print(io, string(y))
15270

153-
==(x::RealInfinity, y::Infinity) = !x.signbit
154-
==(y::Infinity, x::RealInfinity) = !x.signbit
155-
==(x::RealInfinity, y::RealInfinity) = x.signbit == y.signbit
156-
157-
==(x::RealInfinity, y::Number) = isinf(y) && signbit(y) == signbit(x)
158-
==(y::Number, x::RealInfinity) = x == y
159-
160-
isless(x::RealInfinity, y::RealInfinity) = signbit(x) && !signbit(y)
161-
for Typ in (:Number, :Real, :Integer, :AbstractFloat)
162-
@eval begin
163-
isless(x::RealInfinity, y::$Typ) = signbit(x) && y -
164-
isless(x::$Typ, y::RealInfinity) = !signbit(y) && x
165-
+(::$Typ, y::RealInfinity) = y
166-
+(y::RealInfinity, ::$Typ) = y
167-
-(y::RealInfinity, ::$Typ) = y
168-
-(::$Typ, y::RealInfinity) = -y
169-
function *(a::$Typ, y::RealInfinity)
170-
iszero(a) && throw(ArgumentError("Cannot multiply $a * $y"))
171-
a > 0 ? y : (-y)
172-
end
173-
end
174-
end
175-
176-
(::RealInfinity, ::Infinity) = true
177-
(::Infinity, s::RealInfinity) = !signbit(s)
178-
<(s::RealInfinity, ::Infinity) = signbit(s)
179-
<(::Infinity, ::RealInfinity) = false
180-
181-
isless(x::RealInfinity, ::Infinity) = isless(x, RealInfinity())
182-
isless(::Infinity, x::RealInfinity) = isless(RealInfinity(), x)
183-
184-
185-
function -(::Infinity, y::RealInfinity)
186-
signbit(y) || throw(ArgumentError("Cannot subtract ∞ from ∞"))
187-
188-
end
189-
190-
function -(x::RealInfinity, ::Infinity)
191-
signbit(x) || throw(ArgumentError("Cannot subtract ∞ from ∞"))
192-
x
193-
end
194-
195-
function -(x::RealInfinity, y::RealInfinity)
196-
signbit(x) == !signbit(y) || throw(ArgumentError("Cannot subtract ∞ from ∞"))
197-
x
198-
end
199-
200-
-(y::RealInfinity) = RealInfinity(!y.signbit)
201-
202-
function +(x::RealInfinity, y::RealInfinity)
203-
x == y || throw(ArgumentError("Angles must be the same to add ∞"))
204-
x
205-
end
206-
207-
+(x::RealInfinity, y::Infinity) = x+RealInfinity(y)
208-
+(x::Infinity, y::RealInfinity) = RealInfinity(x)+y
209-
210-
# ⊻ is xor
211-
*(a::RealInfinity, b::RealInfinity) = RealInfinity(signbit(a) signbit(b))
212-
*(a::Infinity, b::RealInfinity) = RealInfinity(a)*b
213-
*(a::RealInfinity, b::Infinity) = a*RealInfinity(b)
214-
215-
*(a::Integer, y::Infinity) = a*RealInfinity(y)
216-
*(y::Infinity, a::Integer) = RealInfinity(y)*a
217-
218-
*(a::Real, y::Infinity) = a*RealInfinity(y)
219-
*(y::Infinity, a::Real) = RealInfinity(y)*a
220-
221-
*(y::RealInfinity, a::Real) = a*y
222-
*(y::RealInfinity, a::Integer) = a*y
223-
224-
<(x::RealInfinity, y::RealInfinity) = signbit(x) & !signbit(y)
225-
(x::RealInfinity, y::RealInfinity) = signbit(x) | !signbit(y)
226-
227-
for OP in (:<,:)
228-
@eval begin
229-
$OP(x::Real, y::RealInfinity) = !signbit(y)
230-
$OP(y::RealInfinity, x::Real) = signbit(y)
231-
end
232-
end
233-
234-
235-
min(x::RealInfinity, y::RealInfinity) = RealInfinity(x.signbit | y.signbit)
236-
max(x::RealInfinity, y::RealInfinity) = RealInfinity(x.signbit & y.signbit)
237-
min(x::Real, y::RealInfinity) = y.signbit ? y : x
238-
max(x::Real, y::RealInfinity) = y.signbit ? x : y
239-
min(x::RealInfinity, y::Real) = x.signbit ? x : y
240-
max(x::RealInfinity, y::Real) = x.signbit ? y : x
241-
min(x::RealInfinity, ::Infinity) = x
242-
max(::RealInfinity, ::Infinity) =
243-
min(::Infinity, x::RealInfinity) = x
244-
max(::Infinity, x::RealInfinity) =
245-
246-
247-
248-
######
71+
#######
24972
# ComplexInfinity
25073
#######
25174

@@ -268,15 +91,12 @@ ComplexInfinity{T}(::Infinity) where T<:Real = ComplexInfinity{T}()
26891
ComplexInfinity(::Infinity) = ComplexInfinity()
26992
ComplexInfinity{T}(x::RealInfinity) where T<:Real = ComplexInfinity{T}(signbit(x))
27093
ComplexInfinity(x::RealInfinity) = ComplexInfinity(signbit(x))
94+
ComplexInfinity{T}(x::ComplexInfinity) where T<:Real = ComplexInfinity(T(signbit(x))) # ambiguity fix
27195

96+
signbit(y::ComplexInfinity{Bool}) = y.signbit
97+
signbit(y::ComplexInfinity{<:Integer}) = !(mod(y.signbit,2) == 0)
98+
signbit(y::ComplexInfinity) = y.signbit
27299

273-
274-
isinf(::ComplexInfinity) = true
275-
isfinite(::ComplexInfinity) = false
276-
277-
278-
promote_rule(::Type{Infinity}, ::Type{ComplexInfinity{T}}) where T = ComplexInfinity{T}
279-
promote_rule(::Type{RealInfinity}, ::Type{ComplexInfinity{T}}) where T = ComplexInfinity{T}
280100
convert(::Type{ComplexInfinity{T}}, ::Infinity) where T = ComplexInfinity{T}()
281101
convert(::Type{ComplexInfinity}, ::Infinity) = ComplexInfinity()
282102
convert(::Type{ComplexInfinity{T}}, x::RealInfinity) where T = ComplexInfinity{T}(x)
@@ -285,95 +105,15 @@ convert(::Type{ComplexInfinity}, x::RealInfinity) = ComplexInfinity(x)
285105

286106
sign(y::ComplexInfinity{<:Integer}) = mod(y.signbit,2) == 0 ? 1 : -1
287107
angle(x::ComplexInfinity) = π*x.signbit
288-
mod(::ComplexInfinity{<:Integer}, ::Integer) = NotANumber()
289-
290108

291109
show(io::IO, x::ComplexInfinity) = print(io, "exp($(x.signbit)*im*π)∞")
292110

293-
==(x::ComplexInfinity, y::Infinity) = x.signbit == 0
294-
==(y::Infinity, x::ComplexInfinity) = x.signbit == 0
295-
==(x::ComplexInfinity, y::RealInfinity) = x.signbit == signbit(y)
296-
==(y::RealInfinity, x::ComplexInfinity) = x.signbit == signbit(y)
297-
==(x::ComplexInfinity, y::ComplexInfinity) = x.signbit == y.signbit
298-
299-
==(x::ComplexInfinity, y::Number) = isinf(y) && angle(y) == angle(x)
300-
==(y::Number, x::ComplexInfinity) = x == y
301-
302-
isless(x::ComplexInfinity{Bool}, y::ComplexInfinity{Bool}) = x.signbit && !y.signbit
303-
isless(x::Number, y::ComplexInfinity{Bool}) = !y.signbit && x
304-
isless(x::ComplexInfinity{Bool}, y::Number) = x.signbit && y -
305-
306-
-(y::ComplexInfinity{B}) where B<:Integer = sign(y) == 1 ? ComplexInfinity(one(B)) : ComplexInfinity(zero(B))
307-
308-
function +(x::ComplexInfinity, y::ComplexInfinity)
309-
x == y || throw(ArgumentError("Angles must be the same to add ∞"))
310-
promote_type(typeof(x),typeof(y))(x.signbit)
311-
end
312-
313-
+(x::ComplexInfinity, y::Infinity) = x+ComplexInfinity(y)
314-
+(x::Infinity, y::ComplexInfinity) = ComplexInfinity(x)+y
315-
+(x::ComplexInfinity, y::RealInfinity) = x+ComplexInfinity(y)
316-
+(x::RealInfinity, y::ComplexInfinity) = ComplexInfinity(x)+y
317-
+(::Number, y::ComplexInfinity) = y
318-
+(y::ComplexInfinity, ::Number) = y
319-
-(y::ComplexInfinity, ::Number) = y
320-
-(::Number, y::ComplexInfinity) = -y
321-
322-
+(::Complex, ::Infinity) = ComplexInfinity()
323-
+(::Infinity, ::Complex) = ComplexInfinity()
324-
-(::Infinity, ::Complex) = ComplexInfinity()
325-
+(::Complex{Bool}, ::Infinity) = ComplexInfinity()
326-
+(::Infinity, ::Complex{Bool}) = ComplexInfinity()
327-
-(::Infinity, ::Complex{Bool}) = ComplexInfinity()
328-
329-
+(::Complex, y::RealInfinity) = ComplexInfinity(y)
330-
+(y::RealInfinity, ::Complex) = ComplexInfinity(y)
331-
-(y::RealInfinity, ::Complex) = ComplexInfinity(y)
332-
+(::Complex{Bool}, y::RealInfinity) = ComplexInfinity(y)
333-
+(y::RealInfinity, ::Complex{Bool}) = ComplexInfinity(y)
334-
-(y::RealInfinity, ::Complex{Bool}) = ComplexInfinity(y)
335-
336-
337-
# ⊻ is xor
338-
*(a::ComplexInfinity{Bool}, b::ComplexInfinity{Bool}) = ComplexInfinity(a.signbit b.signbit)
339-
*(a::ComplexInfinity, b::ComplexInfinity) = ComplexInfinity(a.signbit + b.signbit)
340-
*(a::Infinity, b::ComplexInfinity) = ComplexInfinity(a)*b
341-
*(a::ComplexInfinity, b::Infinity) = a*ComplexInfinity(b)
342-
*(a::RealInfinity, b::ComplexInfinity) = ComplexInfinity(a)*b
343-
*(a::ComplexInfinity, b::RealInfinity) = a*ComplexInfinity(b)
344-
345-
*(a::Real, y::ComplexInfinity) = a > 0 ? y : (-y)
346-
*(y::ComplexInfinity, a::Real) = a*y
347-
348-
*(a::Number, y::ComplexInfinity) = ComplexInfinity(y.signbit+angle(a)/π)
349-
*(y::ComplexInfinity, a::Number) = a*y
350-
351-
*(a::Complex, y::Infinity) = a*ComplexInfinity(y)
352-
*(y::Infinity, a::Complex) = ComplexInfinity(y)*a
353-
354-
*(a::Complex,y::RealInfinity) = a*ComplexInfinity(y)
355-
*(y::RealInfinity, a::Complex) = ComplexInfinity(y)*a
356-
357-
for OP in (:fld,:cld,:div)
358-
@eval $OP(y::ComplexInfinity, a::Number) = y*(1/sign(a))
359-
end
360-
361-
min(x::ComplexInfinity{B}, y::ComplexInfinity{B}) where B<:Integer = sign(x) == -1 ? x : y
362-
max(x::ComplexInfinity{B}, ::ComplexInfinity{B}) where B<:Integer = sign(x) == 1 ? x : y
363-
min(x::Real, y::ComplexInfinity{B}) where B<:Integer = sign(y) == 1 ? x : y
364-
min(x::ComplexInfinity{B}, y::Real) where B<:Integer = min(y,x)
365-
max(x::Real, y::ComplexInfinity{B}) where B<:Integer = sign(y) == 1 ? y : x
366-
max(x::ComplexInfinity{B}, y::Real) where B<:Integer = max(y,x)
367-
368-
for OP in (:<,:)
369-
@eval begin
370-
$OP(x::Real, y::ComplexInfinity{B}) where B<:Integer = sign(y) == 1
371-
$OP(y::ComplexInfinity{B}, x::Real) where B<:Integer = sign(y) == -1
372-
end
373-
end
374-
375111
Base.hash(::Infinity) = 0x020113134b21797f # made up
376112

377113

378114
include("cardinality.jl")
115+
include("interface.jl")
116+
include("compare.jl")
117+
include("algebra.jl")
118+
include("ambiguities.jl")
379119
end # module

0 commit comments

Comments
 (0)