@@ -69,6 +69,14 @@ function SymbolicIndexingInterface.symbolic_type(::Type{<:BasicSymbolic})
6969 ScalarSymbolic ()
7070end
7171
72+ """
73+ $(TYPEDSIGNATURES)
74+
75+ Return the inner `Symbolic` wrapped in a non-symbolic subtype. Defaults to
76+ returning the input as-is.
77+ """
78+ unwrap (x) = x
79+
7280function exprtype (x:: BasicSymbolic )
7381 @compactified x:: BasicSymbolic begin
7482 Term => TERM
@@ -538,10 +546,17 @@ function Sym{T}(name::Symbol; kw...) where {T}
538546 BasicSymbolic (s)
539547end
540548
549+ function unwrap_arr! (arr)
550+ for i in eachindex (arr)
551+ arr[i] = unwrap (arr[i])
552+ end
553+ end
554+
541555function Term {T} (f, args; kw... ) where T
542556 if eltype (args) != = Any
543557 args = convert (Vector{Any}, args)
544558 end
559+ unwrap_arr! (args)
545560
546561 s = Term {T} (;f= f, arguments= args, hash= Ref (UInt (0 )), hash2= Ref (UInt (0 )), kw... )
547562 BasicSymbolic (s)
@@ -551,7 +566,16 @@ function Term(f, args; metadata=NO_METADATA)
551566 Term {_promote_symtype(f, args)} (f, args, metadata= metadata)
552567end
553568
569+ function unwrap_dict (dict)
570+ if any (k -> unwrap (k) != = k, keys (dict))
571+ return typeof (dict)(unwrap (k) => v for (k, v) in dict)
572+ end
573+ return dict
574+ end
575+
554576function Add (:: Type{T} , coeff, dict; metadata= NO_METADATA, kw... ) where T
577+ coeff = unwrap (coeff)
578+ dict = unwrap_dict (dict)
555579 if isempty (dict)
556580 return coeff
557581 elseif _iszero (coeff) && length (dict) == 1
@@ -569,6 +593,8 @@ function Add(::Type{T}, coeff, dict; metadata=NO_METADATA, kw...) where T
569593end
570594
571595function Mul (T, a, b; metadata= NO_METADATA, kw... )
596+ a = unwrap (a)
597+ b = unwrap_dict (b)
572598 isempty (b) && return a
573599 if _isone (a) && length (b) == 1
574600 pair = first (b)
@@ -613,6 +639,8 @@ function maybe_intcoeff(x)
613639end
614640
615641function Div {T} (n, d, simplified= false ; metadata= nothing , kwargs... ) where {T}
642+ n = unwrap (n)
643+ d = unwrap (d)
616644 if T<: Number && ! (T<: SafeReal )
617645 n, d = quick_cancel (n, d)
618646 end
662690@inline denominators (x) = isdiv (x) ? numerators (x. den) : Any[1 ]
663691
664692function Pow {T} (a, b; metadata= NO_METADATA, kwargs... ) where {T}
693+ a = unwrap (a)
694+ b = unwrap (b)
665695 _iszero (b) && return 1
666696 _isone (b) && return a
667697 s = Pow {T} (; base= a, exp= b, arguments= [], metadata)
@@ -760,6 +790,7 @@ function makepow(a, b)
760790end
761791
762792function term (f, args... ; type = nothing )
793+ args = map (unwrap, args)
763794 if type === nothing
764795 T = _promote_symtype (f, args)
765796 else
@@ -894,6 +925,7 @@ Base.ImmutableDict(d::ImmutableDict{K,V}, x, y) where {K, V} = ImmutableDict{K,
894925
895926assocmeta (d:: Dict , ctx, val) = (d= copy (d); d[ctx] = val; d)
896927function assocmeta (d:: Base.ImmutableDict , ctx, val):: ImmutableDict{DataType,Any}
928+ val = unwrap (val)
897929 # optimizations
898930 # If using upto 3 contexts, things stay compact
899931 if isdefined (d, :parent )
@@ -915,7 +947,7 @@ function setmetadata(s::Symbolic, ctx::DataType, val)
915947 @set s. metadata = assocmeta (s. metadata, ctx, val)
916948 else
917949 # fresh Dict
918- @set s. metadata = Base. ImmutableDict {DataType, Any} (ctx, val)
950+ @set s. metadata = Base. ImmutableDict {DataType, Any} (ctx, unwrap ( val) )
919951 end
920952end
921953
@@ -1333,6 +1365,10 @@ function +(a::SN, b::SN)
13331365end
13341366
13351367function + (a:: Number , b:: SN )
1368+ tmp = unwrap (a)
1369+ if tmp != = a
1370+ return tmp + b
1371+ end
13361372 ! issafecanon (+ , b) && return term (+ , a, b) # Don't flatten if args have metadata
13371373 iszero (a) && return b
13381374 if isadd (b)
@@ -1399,6 +1435,10 @@ function *(a::SN, b::SN)
13991435end
14001436
14011437function * (a:: Number , b:: SN )
1438+ tmp = unwrap (a)
1439+ if tmp != = a
1440+ return tmp * b
1441+ end
14021442 ! issafecanon (* , b) && return term (* , a, b)
14031443 if iszero (a)
14041444 a
@@ -1439,6 +1479,7 @@ end
14391479# ##
14401480
14411481function ^ (a:: SN , b)
1482+ b = unwrap (b)
14421483 ! issafecanon (^ , a,b) && return Pow (a, b)
14431484 if b isa Number && iszero (b)
14441485 # fast path
0 commit comments