From e4698eee06c84cb4474c016d034a7c4adc590bee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Thu, 14 Aug 2025 17:23:00 +0200 Subject: [PATCH 1/8] Fixes --- src/interface.jl | 2 +- test/broadcast.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/interface.jl b/src/interface.jl index 33dd132..c10338a 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -52,7 +52,7 @@ function promote_operation_fallback( end function promote_operation_fallback( - op::F, + ::F, args::Vararg{Type,N}, ) where {F<:Function,N} return typeof(op(_instantiate_zero.(args)...)) diff --git a/test/broadcast.jl b/test/broadcast.jl index 53b57ee..e6bbc72 100644 --- a/test/broadcast.jl +++ b/test/broadcast.jl @@ -31,7 +31,7 @@ end @test y == 5 # FIXME This should not allocate but I couldn't figure out where these # allocations come from. - n = (VERSION >= v"1.11" ? 42 : 30) * sizeof(Int) + n = (VERSION >= v"1.11" ? 14 : 10) * sizeof(Int) alloc_test(() -> MA.broadcast!!(+, a, b), n) alloc_test(() -> MA.broadcast!!(+, a, c), 0) end From 109d15689adaade1713a6c1145fee3d29bfc7bf9 Mon Sep 17 00:00:00 2001 From: Aayush Sabharwal Date: Mon, 18 Aug 2025 19:01:41 +0530 Subject: [PATCH 2/8] test: mark test as no longer broken --- test/rewrite_generic.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/rewrite_generic.jl b/test/rewrite_generic.jl index 5faac7b..160ec50 100644 --- a/test/rewrite_generic.jl +++ b/test/rewrite_generic.jl @@ -89,8 +89,7 @@ function test_rewrite_nonconcrete_vector() y = Vector{Union{Float64,String}}(x) @test MA.@rewrite(x' * y, move_factors_into_sums = false) == x' * y @test MA.@rewrite(x .+ y, move_factors_into_sums = false) == x .+ y - # Reproducing buggy behavior in MA.@rewrite. - @test_broken MA.@rewrite(x + y, move_factors_into_sums = false) == x + x + @test MA.@rewrite(x + y, move_factors_into_sums = false) == x + x return end From ccb12f8870f15d7aafb9ac8feeb318ef071d3920 Mon Sep 17 00:00:00 2001 From: Aayush Sabharwal Date: Fri, 12 Sep 2025 14:16:24 +0530 Subject: [PATCH 3/8] fix: implement `promote_operation_fallback` for `real` and `imag` --- src/interface.jl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/interface.jl b/src/interface.jl index c10338a..ad96a2c 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -103,6 +103,13 @@ function promote_operation_fallback( ) end +function promote_operation( + ::Union{typeof(real),typeof(imag)}, + ::Type{Complex{T}}, +) where {T} + return T +end + """ promote_operation(op::Function, ArgsTypes::Type...) From 4d1c87ea42f5a025a7e0889a135ba69110c995bb Mon Sep 17 00:00:00 2001 From: Aayush Sabharwal Date: Sat, 13 Sep 2025 17:43:19 +0530 Subject: [PATCH 4/8] fix: make promotion change non-breaking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: BenoƮt Legat --- src/interface.jl | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/interface.jl b/src/interface.jl index ad96a2c..fe4ec22 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -40,7 +40,11 @@ function promote_operation_fallback( ::Type{S}, ::Type{T}, ) where {S,T} - return typeof(op(_instantiate_zero(S), _instantiate_oneunit(T))) + if isconcretetype(S) && isconcretetype(T) + return typeof(op(_instantiate_zero(S), _instantiate_oneunit(T))) + else + return promote_type(S, T) + end end function promote_operation_fallback( @@ -48,14 +52,22 @@ function promote_operation_fallback( ::Type{S}, ::Type{T}, ) where {F<:Function,S,T} - return typeof(op(_instantiate_zero(S), _instantiate_zero(T))) + if isconcretetype(S) && isconcretetype(T) + return typeof(op(_instantiate_zero(S), _instantiate_zero(T))) + else + return promote_type(S, T) + end end function promote_operation_fallback( - ::F, + op::F, args::Vararg{Type,N}, ) where {F<:Function,N} - return typeof(op(_instantiate_zero.(args)...)) + if all(isconcretetype, args) + return typeof(op(_instantiate_zero.(args)...)) + else + return promote_type(args...) + end end promote_operation_fallback(::typeof(*), ::Type{T}) where {T} = T From 97059ac3c63478612ee660fccc1a881702eb45d8 Mon Sep 17 00:00:00 2001 From: Aayush Sabharwal Date: Sun, 14 Sep 2025 16:57:36 +0530 Subject: [PATCH 5/8] test: update allocation tests --- test/broadcast.jl | 2 +- test/utilities.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/broadcast.jl b/test/broadcast.jl index e6bbc72..53b57ee 100644 --- a/test/broadcast.jl +++ b/test/broadcast.jl @@ -31,7 +31,7 @@ end @test y == 5 # FIXME This should not allocate but I couldn't figure out where these # allocations come from. - n = (VERSION >= v"1.11" ? 14 : 10) * sizeof(Int) + n = (VERSION >= v"1.11" ? 42 : 30) * sizeof(Int) alloc_test(() -> MA.broadcast!!(+, a, b), n) alloc_test(() -> MA.broadcast!!(+, a, c), 0) end diff --git a/test/utilities.jl b/test/utilities.jl index 3433fab..eb8c5c3 100644 --- a/test/utilities.jl +++ b/test/utilities.jl @@ -7,7 +7,7 @@ include("dummy.jl") # Allocating size for allocating a `BigInt`. Half size on 32-bit. -const BIGINT_ALLOC = @static if VERSION >= v"1.12" +const BIGINT_ALLOC = @static if VERSION >= v"1.12-beta1" Sys.WORD_SIZE == 64 ? 72 : 36 elseif VERSION >= v"1.11" Sys.WORD_SIZE == 64 ? 56 : 28 From 07ce2fc8eec011441f82d7af2d4ca494209adf6d Mon Sep 17 00:00:00 2001 From: Aayush Sabharwal Date: Tue, 16 Sep 2025 11:56:44 +0530 Subject: [PATCH 6/8] fix: fix `promote_operation` for `Integer / Integer` --- src/interface.jl | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/interface.jl b/src/interface.jl index fe4ec22..c3b3d6f 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -47,6 +47,18 @@ function promote_operation_fallback( end end +function promote_operation_fallback( + op::typeof(/), + ::Type{S}, + ::Type{T}, +) where {S<:Integer,T<:Integer} + if isconcretetype(S) && isconcretetype(T) + return typeof(op(_instantiate_zero(S), _instantiate_oneunit(T))) + else + return promote_type(float(S), float(T)) + end +end + function promote_operation_fallback( op::F, ::Type{S}, From aadf53f7236e175d6d9b0ef2dc6fd0d14f7e6cbc Mon Sep 17 00:00:00 2001 From: Aayush Sabharwal Date: Tue, 16 Sep 2025 11:57:52 +0530 Subject: [PATCH 7/8] test: test `promote_operation` of `real` and `imag` --- test/interface.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/interface.jl b/test/interface.jl index 8c4262a..e73af0a 100644 --- a/test/interface.jl +++ b/test/interface.jl @@ -57,6 +57,11 @@ Base.@irrational theodorus 1.73205080756887729353 sqrt(big(3)) MathConstants.catalan @test MA._instantiate(typeof(theodorus)) == theodorus end + + for op in [real, imag] + @test MA.promote_operation(op, ComplexF64) == Float64 + @test MA.promote_operation(op, Complex{Real}) == Real + end end @testset "Errors" begin From 777be851af8d3f8221cff5d2135a3e5b70f4774d Mon Sep 17 00:00:00 2001 From: Aayush Sabharwal Date: Tue, 16 Sep 2025 11:58:07 +0530 Subject: [PATCH 8/8] test: test new non-concrete `promote_operation` methods --- test/int.jl | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/int.jl b/test/int.jl index ad2538e..b569372 100644 --- a/test/int.jl +++ b/test/int.jl @@ -28,6 +28,18 @@ import MutableArithmetics as MA ) @test_throws err MA.promote_operation(op, Int, Vector{Int}) end + for op in [+, -, *, /, div] + @test MA.promote_operation(op, Int, Number) == Number + @test MA.promote_operation(op, Number, Int) == Number + end + @test MA.promote_operation(/, Int, Integer) == Float64 + @test MA.promote_operation(/, Integer, Integer) == Float64 + @test MA.promote_operation(/, Integer, Int) == Float64 + @test MA.promote_operation(gcd, Int, Integer) == Integer + @test MA.promote_operation(gcd, Integer, Integer) == Integer + @test MA.promote_operation(gcd, Integer, Int) == Integer + @test MA.promote_operation(&, Integer, Integer, Integer) == Integer + @test MA.promote_operation(&, Integer, Integer, Int) == Integer end @testset "add_to!! / add!!" begin @test MA.mutability(Int, MA.add_to!!, Int, Int) isa MA.IsNotMutable