Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "SymEngine"
uuid = "123dc426-2d89-5057-bbad-38513e3affd8"
version = "0.13.1"
version = "0.13.2"

[deps]
Compat = "34da2185-b29b-5c13-b0c7-acf172513d20"
Expand Down
9 changes: 7 additions & 2 deletions ext/SymEngineTermInterfaceExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,14 @@ TermInterface.isexpr(x::SymEngine.SymbolicType) = TermInterface.iscall(x)

##TermInterface.issym(x::SymEngine.SymbolicType) = SymEngine.get_symengine_class(x) == :Symbol

TermInterface.operation(x::SymEngine.SymFunction) = x
function TermInterface.operation(x::SymEngine.SymbolicType)
TermInterface.iscall(x) || error("$(typeof(x)) doesn't have an operation!")
return julia_operations[SymEngine.get_type(x) + 1]
TermInterface.iscall(x) || error("Not a call.")
fn = julia_operations[SymEngine.get_type(x) + 1]
if ismissing(fn) && SymEngine.get_julia_class(x) == :functionsymbol
fn = SymEngine.SymFunction(Symbol(SymEngine.get_name(x)))
end
fn
end

function TermInterface.arguments(x::SymEngine.SymbolicType)
Expand Down
2 changes: 2 additions & 0 deletions src/mathfuns.jl
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@ mutable struct SymFunction
end

SymFunction(s::Symbol) = SymFunction(string(s))
Base.Symbol(s::SymFunction) = Symbol(s.name)
Base.nameof(s::SymFunction) = Symbol(s.name)

function (f::SymFunction)(x::CVecBasic)
a = Basic()
Expand Down
3 changes: 2 additions & 1 deletion src/mathops.jl
Original file line number Diff line number Diff line change
Expand Up @@ -129,13 +129,14 @@ end
## ## Conversions
Base.convert(::Type{Basic}, x::Irrational{:π}) = PI
Base.convert(::Type{Basic}, x::Irrational{:e}) = E
Base.convert(::Type{Basic}, x::Irrational{:ℯ}) = E
Base.convert(::Type{Basic}, x::Irrational{:γ}) = EulerGamma
Base.convert(::Type{Basic}, x::Irrational{:catalan}) = Catalan
Base.convert(::Type{Basic}, x::Irrational{:φ}) = (1 + Basic(5)^Basic(1//2))/2
Base.convert(::Type{BasicType}, x::Irrational) = BasicType(convert(Basic, x))

## Logical operators
Base.:<(x::SymbolicType, y::SymbolicType) = N(x) < N(y)
Base.:<(x::SymbolicType, y::SymbolicType) = is_constant(x) && is_constant(y) && N(x) < N(y)
Base.:<(x::SymbolicType, y) = <(promote(x,y)...)
Base.:<(x, y::SymbolicType) = <(promote(x,y)...)

Expand Down
6 changes: 5 additions & 1 deletion src/numerics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ function N(::Val{<:Any}, b::Basic)
imag(out) == Basic(0.0) ? N(real(out)) : N(out)
end

unwrap_const(b) = is_constant(b) ? N(b) : b

## deprecate N(::BasicType)
N(b::BasicType{T}) where {T} = N(convert(Basic, b), T)

Expand Down Expand Up @@ -279,7 +281,9 @@ function Base.isone(x::Basic)
x == one(x)
end


## julia predicates we can mirror
Base.iseven(x::Basic) = is_a_Integer(x) && iseven(convert(Integer, x))
Base.isodd(x::Basic) = is_a_Integer(x) && isodd(convert(Integer, x))

## These should have support in symengine-wrapper, but currently don't
trunc(x::Basic, args...) = Basic(trunc(N(x), args...))
Expand Down
18 changes: 11 additions & 7 deletions src/subs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -77,28 +77,32 @@ map_fn(key, fn_map) = haskey(fn_map, key) ? fn_map[key] : Symbol(lowercase(strin

const julia_classes = map_fn.(symengine_classes, (fn_map,))
get_julia_class(x::Basic) = julia_classes[get_type(x) + 1]
Base.nameof(ex::Basic) = Symbol(toString(ex))
get_julia_class(x::SymFunction) = Symbol(x)

#_convert(::Type{Expr}, ex::SymFunction) = Symbol(ex)
function _convert(::Type{Expr}, ex::Basic)
fn = get_symengine_class(ex)

if fn == :Symbol
return nameof(ex)
if fn ∈ (:Symbol,)
return Symbol(ex)
elseif (fn in number_types) || (fn == :Constant)
return N(ex)
end
fn′ = get_julia_class(ex)

if fn′ === :functionsymbol
fn′ = Symbol(get_name(ex))
end

as = get_args(ex)
fn′ = get_julia_class(ex)
Expr(:call, fn′, [_convert(Expr,a) for a in as]...)
Expr(:call, fn′, (_convert(Expr,a) for a in as)...)
end


function convert(::Type{Expr}, ex::Basic)
fn = get_symengine_class(ex)

if fn == :Symbol
return Expr(:call, :*, nameof(ex), 1)
return Expr(:call, :*, Symbol(ex), 1)
elseif (fn in number_types) || (fn == :Constant)
return Expr(:call, :*, N(ex), 1)
end
Expand Down
24 changes: 12 additions & 12 deletions src/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -245,18 +245,18 @@ convert(::Type{T}, val::T) where {T<:BasicType} = val

## some type unions possibly useful for dispatch
## Names here match those returned by get_symengine_class()
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]...}

op_types = [:Mul, :Add, :Pow, :Symbol, :Const]
BasicOp = Union{[SymEngine.BasicType{Val{i}} for i in op_types]...}

trig_types = [:Sin, :Cos, :Tan, :Csc, :Sec, :Cot, :ASin, :ACos, :ATan, :ACsc, :ASec, :ACot]
BasicTrigFunction = Union{[SymEngine.BasicType{Val{i}} for i in trig_types]...}
const real_number_types = [:Integer, :RealDouble, :Rational, :RealMPFR]
const complex_number_types = [:Complex, :ComplexDouble, :ComplexMPC]
const number_types = vcat(real_number_types, complex_number_types)
const BasicNumber = Union{[SymEngine.BasicType{Val{i}} for i in number_types]...}
const BasicRealNumber = Union{[SymEngine.BasicType{Val{i}} for i in real_number_types]...}
const BasicComplexNumber = Union{[SymEngine.BasicType{Val{i}} for i in complex_number_types]...}

const op_types = [:Mul, :Add, :Pow, :Symbol, :Const]
const BasicOp = Union{[SymEngine.BasicType{Val{i}} for i in op_types]...}

const trig_types = [:Sin, :Cos, :Tan, :Csc, :Sec, :Cot, :ASin, :ACos, :ATan, :ACsc, :ASec, :ACot]
const BasicTrigFunction = Union{[SymEngine.BasicType{Val{i}} for i in trig_types]...}



Expand Down
23 changes: 23 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,18 @@ u,v,w = x(2.1), x(1), x(0)
@test isinteger(v)
@test isone(v)
@test iszero(w)
@test iseven(x) == iseven(u) == iseven(v)
@test iseven(w)
@test isodd(x) == isodd(w) == isodd(u)
@test isodd(v)
@test (@allocated isreal(u)) == 0
@test (@allocated isinteger(v)) == 0
@test (@allocated isone(x)) == 0
@test (@allocated iszero(x)) == 0
@test (@allocated isone(v)) > 0 # checking v==zero(v) value allocates
@test (@allocated iszero(w)) > 0
@test (@allocated iseven(v)) > 0
@test (@allocated isodd(v)) > 0

## calculus
x,y = symbols("x y")
Expand Down Expand Up @@ -189,6 +195,7 @@ A = [x 2]
@test lambdify(A, [x])(1) == [1 2]
@test lambdify(A)(1) == [1 2]
@test isa(convert.(Expr, [0 x x+1]), Array{Expr})
@test all(x -> isa(x, Union{Number, Symbol, Expr}), SymEngine._convert.(Expr, [0 x x+1]))

## N, convert, _convert
for val in samples
Expand Down Expand Up @@ -335,6 +342,20 @@ t = BigFloat(1.23)
@test Basic(:(-y)) == -y
@test Basic(:(-2*(x-2*y))) == -2*(x-2*y)

# Check that constructing Basic from Irrational works
for a ∈ (:pi, :ℯ, :e, :φ, :γ,
MathConstants.eulergamma,
MathConstants.π,
MathConstants.catalan,
MathConstants.pi,
MathConstants.φ,
MathConstants.ℯ,
MathConstants.e,
MathConstants.golden,
MathConstants.γ)
@test Basic(a) isa Basic
end

@test Basic(0)/0 == NAN
@test subs(1/x, x, 0) == Basic(1)/0

Expand All @@ -345,6 +366,8 @@ d = Dict(x=>y, y=>x)
@test sin(PI/2-x) == cos(x)

f = SymFunction("f")
@test nameof(f) == :f
@test_throws MethodError nameof(f(x))
@test string(f(x, y)) == "f(x, y)"
@test string(f([x, y])) == "f(x, y)"
@test string(f(2*x)) == "f(2*x)"
Expand Down
3 changes: 2 additions & 1 deletion test/test-SymbolicUtils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ using SymEngine

import TermInterface
@testset "TermInterface" begin
@vars x
@vars x, ∫()
@test !TermInterface.iscall(x)
@test TermInterface.iscall(x^2)
@test TermInterface.operation(sin(x)) == sin
@test TermInterface.arguments(sin(x)) == [x]
@test nameof(TermInterface.operation(∫(sin(x), x))) == nameof(∫)
end

#=
Expand Down
Loading