diff --git a/src/SymEngine.jl b/src/SymEngine.jl index 8a1ebaa..2986d72 100644 --- a/src/SymEngine.jl +++ b/src/SymEngine.jl @@ -36,6 +36,10 @@ include("dense-matrix.jl") function __init__() init_constants() + + global TrueFalseMap = CMapBasicBasic() + TrueFalseMap[True] = ONE + TrueFalseMap[False] = ZERO end end diff --git a/src/mathops.jl b/src/mathops.jl index 9a0611a..9f092b0 100644 --- a/src/mathops.jl +++ b/src/mathops.jl @@ -95,7 +95,8 @@ Base.one(::Type{T}) where {T<:BasicType} = BasicType(Basic(1)) ## Math constants ## no oo! -for op in [:IM, :PI, :E, :EulerGamma, :Catalan, :GoldenRatio, :oo, :zoo, :NAN] +for op in [:IM, :PI, :E, :EulerGamma, :Catalan, :GoldenRatio, :oo, :zoo, + :NEGINFINITY, :NAN, :ZERO, :ONE, :MINUSONE, :True, :False] @eval begin const $op = Basic(C_NULL) end @@ -123,15 +124,22 @@ function init_constants() @init_constant GoldenRatio GoldenRatio @init_constant oo infinity @init_constant zoo complex_infinity + @init_constant NEGINFINITY neginfinity @init_constant NAN nan + @init_constant ZERO zero + @init_constant ONE one + @init_constant MINUSONE minus_one + ccall((:bool_set_true, libsymengine), Nothing, (Ref{Basic},), True) + ccall((:bool_set_false, libsymengine), Nothing, (Ref{Basic},), False) end -## ## Conversions +## Conversions Base.convert(::Type{Basic}, x::Irrational{:π}) = PI Base.convert(::Type{Basic}, x::Irrational{:e}) = 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{Basic}, x::Bool) = x ? True : False Base.convert(::Type{BasicType}, x::Irrational) = BasicType(convert(Basic, x)) ## Logical operators diff --git a/src/numerics.jl b/src/numerics.jl index 74ea3a3..03c8048 100644 --- a/src/numerics.jl +++ b/src/numerics.jl @@ -12,6 +12,8 @@ function evalf(b::Basic, bits::Integer=53, real::Bool=false) if status == 0 return c else + b′ = subs(b, TrueFalseMap) # replace any True/False with 1/0 + b′ != b && return evalf(b′, bits, real) throw(ArgumentError("symbolic value cannot be evaluated to a numeric value")) end end @@ -91,6 +93,7 @@ N(::Val{:RealMPFR}, b::Basic) = _convert(BigFloat, b) N(::Val{:Complex}, b::Basic) = complex(N(real(b)), N(imag(b))) N(::Val{:ComplexMPC}, b::Basic) = complex(N(real(b)), N(imag(b))) N(::Val{:ComplexDouble}, b::Basic) = complex(N(real(b)), N(imag(b))) +N(::Val{:BooleanAtom}, b::Basic) = b == True ? 1 : 0 N(::Val{:NaN}, b::Basic) = NaN function N(::Val{:Infty}, b::Basic) diff --git a/src/subs.jl b/src/subs.jl index 0d4d39e..90f8291 100644 --- a/src/subs.jl +++ b/src/subs.jl @@ -80,7 +80,7 @@ function _convert(::Type{Expr}, ex::Basic) if fn == :Symbol return nameof(ex) - elseif (fn in number_types) || (fn == :Constant) + elseif (fn in number_types) || (fn == :Constant) || (fn == :BooleanAtom) return N(ex) end diff --git a/src/types.jl b/src/types.jl index 86c6fb2..6e7a0a2 100644 --- a/src/types.jl +++ b/src/types.jl @@ -82,6 +82,7 @@ Basic(x::Basic) = x Base.promote_rule(::Type{Basic}, ::Type{S}) where {S<:Number} = Basic Base.promote_rule(::Type{S}, ::Type{Basic}) where {S<:Number} = Basic Base.promote_rule(::Type{S}, ::Type{Basic}) where {S<:AbstractIrrational} = Basic +Base.promote_rule(::Type{Bool}, ::Type{Basic}) = Basic ## Class ID get_type(s::Basic) = ccall((:basic_get_type, libsymengine), UInt, (Ref{Basic},), s) diff --git a/src/utils.jl b/src/utils.jl index 1f17287..5aeb8ae 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -33,4 +33,3 @@ function have_component(comp::String) false end end - diff --git a/test/runtests.jl b/test/runtests.jl index 2336e45..457679b 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -386,6 +386,13 @@ expr = x^3 + 3*x^2*y + 3*x*y^2 + y^3 + 1 end end +@testset "Symbolic Booleans" begin + @test N(True) == 1 + @test N(False) == 0 + v = Basic(1) + True + @test N(v) == 1 + true +end + @test round(Basic(3.14)) == 3.0 @test round(Basic(3.14); digits=1) == 3.1