@@ -576,6 +576,19 @@ function hasmetadata(s::Symbolic, ctx)
576
576
metadata (s) isa AbstractDict && haskey (metadata (s), ctx)
577
577
end
578
578
579
+ function issafecanon (f, s)
580
+ if isnothing (metadata (s)) || issym (s)
581
+ return true
582
+ else
583
+ _issafecanon (f, s)
584
+ end
585
+ end
586
+ _issafecanon (:: typeof (* ), s) = ! istree (s) || ! (operation (s) in (+ ,* ,^ ))
587
+ _issafecanon (:: typeof (+ ), s) = ! istree (s) || ! (operation (s) in (+ ,* ))
588
+ _issafecanon (:: typeof (^ ), s) = ! istree (s) || ! (operation (s) in (* , ^ ))
589
+
590
+ issafecanon (f, ss... ) = all (x-> issafecanon (f, x), ss)
591
+
579
592
function getmetadata (s:: Symbolic , ctx)
580
593
md = metadata (s)
581
594
if md isa AbstractDict
@@ -1016,6 +1029,7 @@ sub_t(a) = promote_symtype(-, symtype(a))
1016
1029
1017
1030
import Base: (+ ), (- ), (* ), (// ), (/ ), (\ ), (^ )
1018
1031
function + (a:: SN , b:: SN )
1032
+ ! issafecanon (+ , a,b) && return term (+ , a, b) # Don't flatten if args have metadata
1019
1033
if isadd (a) && isadd (b)
1020
1034
return Add (add_t (a,b),
1021
1035
a. coeff + b. coeff,
@@ -1031,6 +1045,7 @@ function +(a::SN, b::SN)
1031
1045
end
1032
1046
1033
1047
function + (a:: Number , b:: SN )
1048
+ ! issafecanon (+ , b) && return term (+ , a, b) # Don't flatten if args have metadata
1034
1049
iszero (a) && return b
1035
1050
if isadd (b)
1036
1051
Add (add_t (a,b), a + b. coeff, b. dict)
@@ -1044,11 +1059,13 @@ end
1044
1059
+ (a:: SN ) = a
1045
1060
1046
1061
function - (a:: SN )
1062
+ ! issafecanon (* , a) && return term (- , a)
1047
1063
isadd (a) ? Add (sub_t (a), - a. coeff, mapvalues ((_,v) -> - v, a. dict)) :
1048
1064
Add (sub_t (a), makeadd (- 1 , 0 , a)... )
1049
1065
end
1050
1066
1051
1067
function - (a:: SN , b:: SN )
1068
+ (! issafecanon (+ , a) || ! issafecanon (* , b)) && return term (- , a, b)
1052
1069
isadd (a) && isadd (b) ? Add (sub_t (a,b),
1053
1070
a. coeff - b. coeff,
1054
1071
_merge (- , a. dict,
@@ -1067,6 +1084,7 @@ mul_t(a) = promote_symtype(*, symtype(a))
1067
1084
1068
1085
function * (a:: SN , b:: SN )
1069
1086
# Always make sure Div wraps Mul
1087
+ ! issafecanon (* , a, b) && return term (* , a, b)
1070
1088
if isdiv (a) && isdiv (b)
1071
1089
Div (a. num * b. num, a. den * b. den)
1072
1090
elseif isdiv (a)
@@ -1093,6 +1111,7 @@ function *(a::SN, b::SN)
1093
1111
end
1094
1112
1095
1113
function * (a:: Number , b:: SN )
1114
+ ! issafecanon (* , b) && return term (* , a, b)
1096
1115
if iszero (a)
1097
1116
a
1098
1117
elseif isone (a)
@@ -1132,6 +1151,7 @@ end
1132
1151
# ##
1133
1152
1134
1153
function ^ (a:: SN , b)
1154
+ ! issafecanon (^ , a,b) && return Pow (a, b)
1135
1155
if b isa Number && iszero (b)
1136
1156
# fast path
1137
1157
1
0 commit comments