Skip to content

Commit b188d47

Browse files
authored
Merge pull request #425 from JuliaSymbolics/s/safe-real
SafeReal
2 parents 51e9c6d + 89c8639 commit b188d47

File tree

3 files changed

+41
-9
lines changed

3 files changed

+41
-9
lines changed

src/methods.jl

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,13 @@ const diadic = [max, min, hypot, atan, mod, rem, copysign,
1919
polygamma, beta, logbeta]
2020
const previously_declared_for = Set([])
2121

22-
# TODO: it's not possible to dispatch on the symtype! (only problem is Parameter{})
22+
#################### SafeReal #########################
23+
export SafeReal
24+
25+
# ideally the relationship should be the other way around
26+
abstract type SafeReal <: Real end
27+
28+
#######################################################
2329

2430
assert_like(f, T) = nothing
2531
function assert_like(f, T, a, b...)
@@ -82,23 +88,36 @@ end
8288
@number_methods(Pow, term(f, a), term(f, a, b), skipbasics)
8389
@number_methods(Div, term(f, a), term(f, a, b), skipbasics)
8490

85-
for f in diadic
86-
@eval promote_symtype(::$(typeof(f)),
87-
T::Type{<:Number},
88-
S::Type{<:Number}) = promote_type(T, S)
89-
end
90-
91-
for f in [+, -, *, \, /, ^]
91+
for f in vcat(diadic, [+, -, *, \, /, ^])
9292
@eval promote_symtype(::$(typeof(f)),
9393
T::Type{<:Number},
9494
S::Type{<:Number}) = promote_type(T, S)
95+
@eval function promote_symtype(::$(typeof(f)),
96+
T::Type{<:SafeReal},
97+
S::Type{<:Real})
98+
X = promote_type(T, Real)
99+
X == Real ? SafeReal : X
100+
end
101+
@eval function promote_symtype(::$(typeof(f)),
102+
T::Type{<:Real},
103+
S::Type{<:SafeReal})
104+
X = promote_type(Real, S)
105+
X == Real ? SafeReal : X
106+
end
107+
@eval function promote_symtype(::$(typeof(f)),
108+
T::Type{<:SafeReal},
109+
S::Type{<:SafeReal})
110+
X = promote_type(Real, Real)
111+
X == Real ? SafeReal : X
112+
end
95113
end
96114

97115
promote_symtype(::typeof(rem2pi), T::Type{<:Number}, mode) = T
98116
Base.rem2pi(x::Symbolic{<:Number}, mode::Base.RoundingMode) = term(rem2pi, x, mode)
99117

100118
for f in monadic
101119
@eval promote_symtype(::$(typeof(f)), T::Type{<:Number}) = promote_type(T, Real)
120+
@eval promote_symtype(::$(typeof(f)), T::Type{<:SafeReal}) = SafeReal
102121
@eval (::$(typeof(f)))(a::Symbolic{<:Number}) = term($f, a)
103122
end
104123

src/types.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,7 @@ function makeadd(sign, coeff, xs...)
698698
coeff, d
699699
end
700700

701+
add_t(a::Number,b::Number) = promote_symtype(+, symtype(a), symtype(b))
701702
add_t(a,b) = promote_symtype(+, symtype(a), symtype(b))
702703
sub_t(a,b) = promote_symtype(-, symtype(a), symtype(b))
703704
sub_t(a) = promote_symtype(-, symtype(a))
@@ -923,6 +924,9 @@ maybe_intcoeff(x::Rational) = isone(x.den) ? x.num : x
923924
maybe_intcoeff(x) = x
924925

925926
function (::Type{Div{T}})(n, d, simplified=false; metadata=nothing) where {T}
927+
if T<:Number && !(T<:SafeReal)
928+
n, d = quick_cancel(n, d)
929+
end
926930
_iszero(n) && return zero(typeof(n))
927931
_isone(d) && return n
928932

test/basics.jl

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ end
238238
end
239239

240240
@testset "div" begin
241-
@syms x y
241+
@syms x::SafeReal y::Real
242242
@test (2x/2y).num isa Sym
243243
@test (2x/3y).num.coeff == 2
244244
@test (2x/3y).den.coeff == 3
@@ -247,4 +247,13 @@ end
247247
@test (2.5x/3x).num.coeff == 2.5
248248
@test (2.5x/3x).den.coeff == 3
249249
@test (x/3x).den.coeff == 3
250+
251+
@syms x y
252+
@test (2x/2y).num isa Sym
253+
@test (2x/3y).num.coeff == 2
254+
@test (2x/3y).den.coeff == 3
255+
@test (2x/-3x) == -2//3
256+
@test (2.5x/3x).num == 2.5
257+
@test (2.5x/3x).den == 3
258+
@test (x/3x) == 1//3
250259
end

0 commit comments

Comments
 (0)