Skip to content

Commit 9cb7026

Browse files
committed
recurse=false and restrict called functions in PolyForm
1 parent 6ddcfca commit 9cb7026

File tree

1 file changed

+34
-28
lines changed

1 file changed

+34
-28
lines changed

src/polyform.jl

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ struct PolyForm{T, M} <: Symbolic{T}
1616
sym2term::Dict # Symbol("sin-$hash(sin(x+y))") --> sin(x+y) => sin(PolyForm(...))
1717
metadata::M
1818
end
19+
(::PolyForm{T})(p, d1, d2, m) where {T} = PolyForm{T, typeof(m)}(p, d1, d2, m)
1920

2021
Base.hash(p::PolyForm, u::UInt64) = xor(hash(p.p, u), trunc(UInt, 0xbabacacababacaca))
2122
Base.isequal(x::PolyForm, y::PolyForm) = isequal(x.p, y.p)
@@ -25,6 +26,7 @@ Base.isequal(x::PolyForm, y::PolyForm) = isequal(x.p, y.p)
2526
# start over if necessary
2627
const PVAR2SYM = Ref(WeakRef())
2728
const SYM2TERM = Ref(WeakRef())
29+
clear_dicts() = (PVAR2SYM[] = WeakRef(nothing); SYM2TERM[] = WeakRef(nothing); nothing)
2830
function get_pvar2sym()
2931
v = PVAR2SYM[].value
3032
if v === nothing
@@ -55,16 +57,21 @@ function mix_dicts(p, q)
5557
end
5658

5759
# forward gcd
58-
Base.div(x::PolyForm, y::PolyForm) = PolyForm(div(x.p, y.p), mix_dicts(x, y)...)
59-
Base.div(x::Integer, y::PolyForm) = PolyForm(div(x, y.p), y.pvar2sym, y.sym2term)
60-
Base.div(x::PolyForm, y::Integer) = PolyForm(div(x.p, y), x.pvar2sym, x.sym2term)
6160

62-
Base.gcd(x::PolyForm, y::PolyForm) = PolyForm(_gcd(x.p, y.p), mix_dicts(x, y)...)
63-
Base.gcd(x::Integer, y::PolyForm) = PolyForm(_gcd(x, y.p), y.pvar2sym, y.sym2term)
64-
Base.gcd(x::PolyForm, y::Integer) = PolyForm(_gcd(x.p, y), x.pvar2sym, x.sym2term)
61+
PF = :(PolyForm{promote_type(/, symtype(x), symtype(y))})
62+
@eval begin
63+
Base.div(x::PolyForm, y::PolyForm) = $PF(div(x.p, y.p), mix_dicts(x, y)...)
64+
Base.div(x::Integer, y::PolyForm) = $PF(div(x, y.p), y.pvar2sym, y.sym2term)
65+
Base.div(x::PolyForm, y::Integer) = $PF(div(x.p, y), x.pvar2sym, x.sym2term)
66+
67+
Base.gcd(x::PolyForm, y::PolyForm) = $PF(_gcd(x.p, y.p), mix_dicts(x, y)...)
68+
Base.gcd(x::Integer, y::PolyForm) = $PF(_gcd(x, y.p), y.pvar2sym, y.sym2term)
69+
Base.gcd(x::PolyForm, y::Integer) = $PF(_gcd(x.p, y), x.pvar2sym, x.sym2term)
70+
end
71+
6572
_isone(p::PolyForm) = isone(p.p)
6673

67-
function polyize(x, pvar2sym, sym2term, vtype, pow)
74+
function polyize(x, pvar2sym, sym2term, vtype, pow, Fs, recurse)
6875
if istree(x)
6976
if !(symtype(x) <: Number)
7077
error("Cannot convert $x of symtype $(symtype(x)) into a PolyForm")
@@ -73,19 +80,28 @@ function polyize(x, pvar2sym, sym2term, vtype, pow)
7380
op = operation(x)
7481
args = arguments(x)
7582

76-
local_polyize(y) = polyize(y, pvar2sym, sym2term, vtype, pow)
83+
local_polyize(y) = polyize(y, pvar2sym, sym2term, vtype, pow, Fs, recurse)
7784

78-
if op == (+)
85+
if typeof(+) <: Fs && op == (+)
7986
return sum(local_polyize, args)
80-
elseif op == (*)
87+
elseif typeof(*) <: Fs && op == (*)
8188
return prod(local_polyize, args)
82-
elseif op == (^) && args[2] isa Integer && args[2] > 0
89+
elseif typeof(^) <: Fs && op == (^) && args[2] isa Integer && args[2] > 0
8390
@assert length(args) == 2
8491
return local_polyize(args[1])^(args[2])
8592
else
8693
# create a new symbol to store this
8794

88-
name = Symbol(string(op), "-", hash(x))
95+
y = if recurse
96+
similarterm(x,
97+
op,
98+
map(a->PolyForm(a, pvar2sym, sym2term, vtype, Fs, recurse),
99+
args), symtype(x))
100+
else
101+
x
102+
end
103+
104+
name = Symbol(string(op), "-", hash(y))
89105

90106
@label lookup
91107
sym = Sym{symtype(x)}(name)
@@ -98,10 +114,8 @@ function polyize(x, pvar2sym, sym2term, vtype, pow)
98114
end
99115
end
100116

101-
sym2term[sym] = x => similarterm(x,
102-
op,
103-
map(a->PolyForm(a, pvar2sym, sym2term, vtype),
104-
args), symtype(x))
117+
sym2term[sym] = x => y
118+
105119
return local_polyize(sym)
106120
end
107121
elseif x isa Number
@@ -120,22 +134,16 @@ function PolyForm(x::Symbolic{<:Number},
120134
pvar2sym=get_pvar2sym(),
121135
sym2term=get_sym2term(),
122136
vtype=DynamicPolynomials.PolyVar{true};
137+
Fs = Union{typeof(+), typeof(*), typeof(^)},
138+
recurse=false,
123139
metadata=metadata(x))
124140

125141
# Polyize and return a PolyForm
126-
p = polyize(x, pvar2sym, sym2term, vtype, pow)
142+
p = polyize(x, pvar2sym, sym2term, vtype, pow, Fs, recurse)
127143
MP.isconstant(p) && return convert(Number, p)
128144
PolyForm{symtype(x), typeof(metadata)}(p, pvar2sym, sym2term, metadata)
129145
end
130146

131-
function PolyForm(x::MP.AbstractPolynomialLike,
132-
pvar2sym=get_pvar2sym(),
133-
sym2term=get_sym2term(),
134-
metadata=nothing)
135-
# make number go
136-
PolyForm{Number, Nothing}(x, pvar2sym, sym2term, metadata)
137-
end
138-
139147
PolyForm(x, args...;kw...) = x
140148

141149
istree(x::PolyForm) = true
@@ -184,9 +192,7 @@ function arguments(x::PolyForm{T}) where {T}
184192
end
185193
end
186194

187-
function Base.show(io::IO, x::PolyForm)
188-
Base.printstyled(io, sprint(io->show_term(io, x)), color=:yellow)
189-
end
195+
Base.show(io::IO, x::PolyForm) = show_term(io, x)
190196

191197
"""
192198
expand(expr)

0 commit comments

Comments
 (0)