diff --git a/src/SymEngine.jl b/src/SymEngine.jl index 8a1ebaa..e7be3cb 100644 --- a/src/SymEngine.jl +++ b/src/SymEngine.jl @@ -34,6 +34,7 @@ include("calculus.jl") include("recipes.jl") include("dense-matrix.jl") +include("deprecated.jl") function __init__() init_constants() end diff --git a/src/deprecated.jl b/src/deprecated.jl new file mode 100644 index 0000000..3aa6733 --- /dev/null +++ b/src/deprecated.jl @@ -0,0 +1,25 @@ +function real(::Val{<:Any}, x) + if is_constant(x) + real(evalf(x)) # keep this after removing deprecation + else + Base.depwarn( + """The `real` method for a symbol is deprecated. Its use is for + numeric values only.""", + :real; force=true + ) + x + end +end + +function imag(::Val{<:Any},x) + if is_constant(x) + imag(evalf(x)) # keep this after removing deprecation + else + Base.depwarn( + """The `imag` method for a symbol is deprecated. Its use is for + numeric values only.""", + :imag; force=true + ) + throw(InexactError()) # wrong as it was; seems like it should have been Basic(0) + end +end diff --git a/src/mathops.jl b/src/mathops.jl index 9a0611a..acfc8f1 100644 --- a/src/mathops.jl +++ b/src/mathops.jl @@ -126,6 +126,8 @@ function init_constants() @init_constant NAN nan end +RealConstants = (PI, E, EulerGamma, Catalan, GoldenRatio, oo) + ## ## Conversions Base.convert(::Type{Basic}, x::Irrational{:π}) = PI Base.convert(::Type{Basic}, x::Irrational{:e}) = E diff --git a/src/numerics.jl b/src/numerics.jl index 74ea3a3..1e1a7a3 100644 --- a/src/numerics.jl +++ b/src/numerics.jl @@ -207,22 +207,56 @@ function _imag(b::Basic) return a end -real(x::Basic) = Basic(real(SymEngine.BasicType(x))) -real(x::SymEngine.BasicType) = x - -imag(x::Basic) = Basic(imag(SymEngine.BasicType(x))) -imag(x::BasicType{Val{:Integer}}) = Basic(0) -imag(x::BasicType{Val{:RealDouble}}) = Basic(0) -imag(x::BasicType{Val{:RealMPFR}}) = Basic(0) -imag(x::BasicType{Val{:Rational}}) = Basic(0) -imag(x::SymEngine.BasicType) = throw(InexactError()) - -# Because of the definitions above, `real(x) == x` for `x::Basic` -# such as `x = symbols("x")`. Thus, it is consistent to define the -conj(x::Basic) = Basic(conj(SymEngine.BasicType(x))) -# To allow future extension, we define the fallback on `BasicType``. -conj(x::BasicType) = 2 * real(x.x) - x.x +real(x::Basic) = real(get_symengine_class_val(x), x) +real(::T, x) where {T<:RealNumberType} = x +real(::T, x) where {T<:ComplexNumberType} = _real(x) +function real(::Val{:Constant}, x) + any(==(x), RealConstants) && return Basic(x) + x == NaN && return x + x == IM && return zero(x) + x == zoo && return oo +end +#= +function real(::Val{<:Any},x) + if is_constant(x) + real(evalf(x)) + else + throw(ArgumentError("The `real` method is only defined for numeric constants")) + end +end +=# + +imag(x::Basic) = imag(get_symengine_class_val(x), x) +imag(::T, x) where {T<:RealNumberType} = Basic(zero(x)) +imag(::T, x) where {T<:ComplexNumberType} = _imag(x) +function imag(::Val{:Constant}, x) + any(==(x), RealConstants) && return Basic(x) + x == NAN && return x + x == IM && return zero(x) + x == zoo && return oo +end +#= after deprecation removed +function imag(::Val{<:Any},x) + if is_constant(x) + imag(evalf(x)) + else + throw(ArgumentError("The `imag` method is only defined for numeric constants")) + end +end +=# + +conj(x::Basic) = conj(get_symengine_class_val(x), x) +conj(::T,x) where {T<:RealNumberType} = x +conj(::T,x) where {T<:ComplexNumberType} = _real(x) - _imag(x)*IM +function conj(::Val{:Constant}, x) + any(==(x), RealConstants) && return x + x == NAN && return x + x == IM && return zero(x) + x == zoo && return oo +end + +conj(::Val{<:Any}, x) = 2*real(x) - x ## For generic programming in Julia float(x::Basic) = float(N(x)) diff --git a/src/types.jl b/src/types.jl index 86c6fb2..318fc41 100644 --- a/src/types.jl +++ b/src/types.jl @@ -241,10 +241,15 @@ convert(::Type{T}, val::T) where {T<:BasicType} = val real_number_types = [:Integer, :RealDouble, :Rational, :RealMPFR] complex_number_types = [:Complex, :ComplexDouble, :ComplexMPC] number_types = vcat(real_number_types, complex_number_types) + BasicNumber = Union{[SymEngine.BasicType{Val{i}} for i in number_types]...} BasicRealNumber = Union{[SymEngine.BasicType{Val{i}} for i in real_number_types]...} BasicComplexNumber = Union{[SymEngine.BasicType{Val{i}} for i in complex_number_types]...} +NumberType = Union{(Val{i} for i in number_types)...} +RealNumberType = Union{(Val{i} for i in real_number_types)...} +ComplexNumberType = Union{(Val{i} for i in complex_number_types)...} + op_types = [:Mul, :Add, :Pow, :Symbol, :Const] BasicOp = Union{[SymEngine.BasicType{Val{i}} for i in op_types]...} diff --git a/test/runtests.jl b/test/runtests.jl index 2336e45..ec36ae7 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -386,6 +386,24 @@ expr = x^3 + 3*x^2*y + 3*x*y^2 + y^3 + 1 end end +@testset "real/imag/conj" begin + @test real(Basic(1.5)) == 1.5 + @test isa(real(2 + 3IM), Basic) + @test real(2 + 3IM) == 2 + + @test imag(Basic(1.5)) == 0 + @test isa(imag(2 + 3IM), Basic) + @test imag(2 + 3IM) == Basic(3) + + for a ∈ (1, 1.0, 1//2, 2im, 3.14*im, 1 + im, 1.2 + 3im) # , pi + for λ ∈ (real, imag, conj) + u,v = Basic(λ(a)), λ(Basic(a)) + @test abs(u-v) == 0 # avoid Basic(0) ≠ Basic(0.0) + end + end + +end + @test round(Basic(3.14)) == 3.0 @test round(Basic(3.14); digits=1) == 3.1 @@ -415,4 +433,5 @@ end @test deserialized == data end +include("test-deprecated.jl") VERSION >= v"1.9.0" && include("test-allocations.jl") diff --git a/test/test-dense-matrix.jl b/test/test-dense-matrix.jl index 8ca1e5a..42ad50c 100644 --- a/test/test-dense-matrix.jl +++ b/test/test-dense-matrix.jl @@ -44,10 +44,6 @@ out = M \ b @test SymEngine.dense_matrix_eye(2,2,0) == Basic[1 0; 0 1] -# dot product -@test dot(x, x) == x^2 -@test dot([1, x, 0], [y, -2, 1]) == y - 2x - @testset "dense matrix" begin @vars a b c d x y A = [a b; c d] @@ -55,4 +51,4 @@ out = M \ b res = A \ B @test res == [(x - b*(y - c*x/a)/(d - b*c/a))/a, (y - c*x/a)/(d - b*c/a)] -end \ No newline at end of file +end diff --git a/test/test-deprecated.jl b/test/test-deprecated.jl new file mode 100644 index 0000000..9f3059e --- /dev/null +++ b/test/test-deprecated.jl @@ -0,0 +1,18 @@ +using SymEngine +using LinearAlgebra +using Test + +@testset "real/imag/conj deprecation" begin + @vars x y + # dot product + @test dot(x, x) == x^2 + @test dot([1, x, 0], [y, -2, 1]) == y - 2x + + + @vars x + for ex = (x, x^2) + @test real(ex) == ex + @test_throws MethodError imag(ex) + @test conj(ex) == ex + end +end