Skip to content

Commit 731f211

Browse files
blegatbowenszhu
andauthored
Fix promote_operation for irrational numbers (#165)
* Fix promote_operation for irrational numbers * Fixes * Support user-defined `Irrational` in `promote_operation` (#166) * Update `promote_operation` for `Irrational` * Add test for `promote_operation` with user-defined `Irrational` input * Format * Make `_instantiate(::Type{Irrational{S}})` return corresponding value Co-authored-by: Bowen S. Zhu <[email protected]>
1 parent 5b2a1f0 commit 731f211

File tree

2 files changed

+37
-3
lines changed

2 files changed

+37
-3
lines changed

src/interface.jl

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,20 @@ function promote_operation_fallback(
2525
)
2626
end
2727

28+
_instantiate_zero(::Type{S}) where {S} = zero(S)
29+
_instantiate_oneunit(::Type{S}) where {S} = oneunit(S)
30+
31+
# this is valid because Irrational numbers are defined in global scope as const
32+
_instantiate(::Type{S}) where {S<:Irrational} = S()
33+
_instantiate_zero(::Type{S}) where {S<:AbstractIrrational} = _instantiate(S)
34+
_instantiate_oneunit(::Type{S}) where {S<:AbstractIrrational} = _instantiate(S)
35+
2836
function promote_operation_fallback(
2937
::typeof(/),
3038
::Type{S},
3139
::Type{T},
3240
) where {S,T}
33-
return typeof(zero(S) / oneunit(T))
41+
return typeof(_instantiate_zero(S) / _instantiate_oneunit(T))
3442
end
3543

3644
# Julia v1.0.x has trouble with inference with the `Vararg` method, see
@@ -40,14 +48,14 @@ function promote_operation_fallback(
4048
::Type{S},
4149
::Type{T},
4250
) where {F<:Function,S,T}
43-
return typeof(op(zero(S), zero(T)))
51+
return typeof(op(_instantiate_zero(S), _instantiate_zero(T)))
4452
end
4553

4654
function promote_operation_fallback(
4755
op::F,
4856
args::Vararg{Type,N},
4957
) where {F<:Function,N}
50-
return typeof(op(zero.(args)...))
58+
return typeof(op(_instantiate_zero.(args)...))
5159
end
5260

5361
promote_operation_fallback(::typeof(*), ::Type{T}) where {T} = T

test/interface.jl

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,36 @@ function MA.promote_operation(
2727
end
2828
MA.mutability(::Type{DummyMutable}) = MA.IsMutable()
2929

30+
# Theodorus' constant √3 (deined in global scope due to const)
31+
Base.@irrational theodorus 1.73205080756887729353 sqrt(big(3))
3032
@testset "promote_operation" begin
3133
@test MA.promote_operation(/, Rational{Int}, Rational{Int}) == Rational{Int}
3234
@test MA.promote_operation(-, DummyMutable, DummyMutable) == DummyMutable
3335
@test MA.promote_operation(/, DummyMutable, DummyMutable) == DummyMutable
36+
@testset "Issue #164" begin
37+
() = MA.promote_operation(+, Int, typeof(π))
38+
@test () == Float64
39+
alloc_test(iπ, 0)
40+
ℯbf() = MA.promote_operation(+, typeof(ℯ), BigFloat)
41+
@test ℯbf() == BigFloat
42+
# TODO this allocates as it creates the `BigFloat`
43+
#alloc_test(ℯbf, 0)
44+
() = MA.promote_operation(/, Bool, typeof(Base.MathConstants.γ))
45+
@test () == Float64
46+
alloc_test(bγ, 0)
47+
φf32() = MA.promote_operation(*, typeof(Base.MathConstants.φ), Float32)
48+
@test φf32() == Float32
49+
alloc_test(φf32, 0)
50+
# test user-defined Irrational
51+
i_theodorus() = MA.promote_operation(+, Int, typeof(theodorus))
52+
@test i_theodorus() == Float64
53+
alloc_test(i_theodorus, 0)
54+
# test _instantiate(::Type{S}) where {S<:Irrational} return value
55+
@test MA._instantiate(typeof(π)) == π
56+
@test MA._instantiate(typeof(MathConstants.catalan)) ==
57+
MathConstants.catalan
58+
@test MA._instantiate(typeof(theodorus)) == theodorus
59+
end
3460
end
3561

3662
@testset "Errors" begin

0 commit comments

Comments
 (0)