Skip to content

Commit 22de316

Browse files
authored
Merge pull request #284 from jverzani/predicates
add some predicates; coeff
2 parents 4ae979c + 32f21ee commit 22de316

File tree

4 files changed

+77
-5
lines changed

4 files changed

+77
-5
lines changed

src/mathfuns.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,15 @@ for (meth, libnm) in [(:nextprime,:nextprime)
110110
eval(Expr(:export, meth))
111111
end
112112

113+
"Return coefficient of `x^n` term, `x` a symbol"
114+
function coeff(b::Basic, x, n)
115+
c = Basic()
116+
out = ccall((:basic_coeff, libsymengine), Nothing,
117+
(Ref{Basic},Ref{Basic},Ref{Basic},Ref{Basic}),
118+
c,b,Basic(x), Basic(n))
119+
c
120+
end
121+
113122
function Base.convert(::Type{CVecBasic}, x::Vector{T}) where T
114123
vec = CVecBasic()
115124
for i in x

src/numerics.jl

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,51 @@ isnan(x::Basic) = ( x == NAN )
212212
isinf(x::Basic) = !isnan(x) & !isfinite(x)
213213
isless(x::Basic, y::Basic) = isless(N(x), N(y))
214214

215+
# is_a_functions
216+
# could use metaprogramming here
217+
is_a_Number(x::Basic) =
218+
Bool(convert(Int, ccall((:is_a_Number, libsymengine),
219+
Cuint, (Ref{Basic},), x)))
220+
is_a_Integer(x::Basic) =
221+
Bool(convert(Int, ccall((:is_a_Integer, libsymengine),
222+
Cuint, (Ref{Basic},), x)))
223+
is_a_Rational(x::Basic) =
224+
Bool(convert(Int, ccall((:is_a_Rational, libsymengine),
225+
Cuint, (Ref{Basic},), x)))
226+
is_a_RealDouble(x::Basic) =
227+
Bool(convert(Int, ccall((:is_a_RealDouble, libsymengine),
228+
Cuint, (Ref{Basic},), x)))
229+
is_a_RealMPFR(x::Basic) =
230+
Bool(convert(Int, ccall((:is_a_RealMPFR, libsymengine),
231+
Cuint, (Ref{Basic},), x)))
232+
is_a_Complex(x::Basic) =
233+
Bool(convert(Int, ccall((:is_a_Complex, libsymengine),
234+
Cuint, (Ref{Basic},), x)))
235+
is_a_ComplexDouble(x::Basic) =
236+
Bool(convert(Int, ccall((:is_a_ComplexDouble, libsymengine),
237+
Cuint, (Ref{Basic},), x)))
238+
is_a_ComplexMPC(x::Basic) =
239+
Bool(convert(Int, ccall((:is_a_ComplexMPC, libsymengine),
240+
Cuint, (Ref{Basic},), x)))
241+
242+
Base.isinteger(x::Basic) = is_a_Integer(x)
243+
function Base.isreal(x::Basic)
244+
is_a_Number(x) || return false
245+
is_a_Integer(x) || is_a_Rational(x) || is_a_RealDouble(x) || is_a_RealMPFR(x)
246+
end
247+
248+
# may not allocate; seems more idiomatic than default x == zero(x)
249+
function Base.iszero(x::Basic)
250+
is_a_Number(x) || return false
251+
x == zero(x)
252+
end
253+
254+
function Base.isone(x::Basic)
255+
is_a_Number(x) || return false
256+
x == one(x)
257+
end
258+
259+
215260

216261
## These should have support in symengine-wrapper, but currently don't
217262
trunc(x::Basic, args...) = Basic(trunc(N(x), args...))

src/types.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -233,13 +233,13 @@ BasicTrigFunction = Union{[SymEngine.BasicType{Val{i}} for i in trig_types]...}
233233

234234
###
235235
"Is expression a symbol"
236-
is_symbol(x::Basic) = is_symbol(BasicType(x))
237-
is_symbol(x::BasicType{Val{:Symbol}}) = true
238-
is_symbol(x::BasicType) = false
239-
236+
function is_symbol(x::SymbolicType)
237+
res = ccall((:is_a_Symbol, libsymengine), Cuint, (Ref{Basic},), x)
238+
Bool(convert(Int,res))
239+
end
240240

241241
"Does expression contain the symbol"
242-
function has_symbol(ex::Basic, x::Basic)
242+
function has_symbol(ex::SymbolicType, x::SymbolicType)
243243
is_symbol(x) || throw(ArgumentError("Not a symbol"))
244244
res = ccall((:basic_has_symbol, libsymengine), Cuint, (Ref{Basic},Ref{Basic}), ex, x)
245245
Bool(convert(Int, res))

test/runtests.jl

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,21 @@ println()
8080
@test subs(sin(x), x, pi) == 0
8181
@test sind(Basic(30)) == 1 // 2
8282

83+
## predicates
84+
@vars x
85+
u,v,w = x(2.1), x(1), x(0)
86+
@test isreal(u)
87+
@test !isinteger(u)
88+
@test isinteger(v)
89+
@test isone(v)
90+
@test iszero(w)
91+
@test (@allocated isreal(u)) == 0
92+
@test (@allocated isinteger(v)) == 0
93+
@test (@allocated isone(x)) == 0
94+
@test (@allocated iszero(x)) == 0
95+
@test (@allocated isone(v)) > 0 # checking v==zero(v) value allocates
96+
@test (@allocated iszero(w)) > 0
97+
8398
## calculus
8499
x,y = symbols("x y")
85100
n = Basic(2)
@@ -188,9 +203,12 @@ x,y,z = symbols("x y z")
188203
# is/has/free symbol(s)
189204
@vars x y z
190205
@test SymEngine.is_symbol(x)
206+
@test (@allocated SymEngine.is_symbol(x)) == 0
191207
@test !SymEngine.is_symbol(x(2))
192208
@test !SymEngine.is_symbol(x^2)
193209
@test SymEngine.has_symbol(x^2, x)
210+
@test SymEngine.has_symbol(x, x)
211+
@test @allocated(SymEngine.has_symbol(x, x)) == 0
194212
@test SymEngine.has_symbol(sin(sin(sin(x))), x)
195213
@test !SymEngine.has_symbol(x^2, y)
196214
@test Set(free_symbols(x*y)) == Set([x,y])

0 commit comments

Comments
 (0)