@@ -37,63 +37,38 @@ function _is_sin_cos(ex::BasicSymbolic)
3737 return isterm (ex) && (operation (ex) === sin || operation (ex) === cos)
3838end
3939
40- function _trig_mul_to_sum (a:: BasicSymbolic , b:: BasicSymbolic )
41- op1, op2 = operation (a), operation (b)
42- x = first (arguments (a))
43- y = first (arguments (b))
44- if op1 === cos && op2 === cos
45- return (cos (x - y) + cos (x + y)) / 2
46- elseif op1 === sin && op2 === sin
47- return (cos (x - y) - cos (x + y)) / 2
48- elseif op1 === sin && op2 === cos
49- return (sin (x + y) + sin (x - y)) / 2
50- elseif op1 === cos && op2 === sin
51- return (sin (x + y) - sin (x - y)) / 2
52- end
53- return nothing
54- end
40+ const _rw_trig_mul_to_sum = SymbolicUtils. Rewriters. Chain ([
41+ SymbolicUtils. @rule (cos (~ x) * cos (~ y) => (cos (~ x - ~ y) + cos (~ x + ~ y)) / 2 ),
42+ SymbolicUtils. @rule (sin (~ x) * sin (~ y) => (cos (~ x - ~ y) - cos (~ x + ~ y)) / 2 ),
43+ SymbolicUtils. @rule (sin (~ x) * cos (~ y) => (sin (~ x + ~ y) + sin (~ x - ~ y)) / 2 ),
44+ SymbolicUtils. @rule (cos (~ x) * sin (~ y) => (sin (~ x + ~ y) - sin (~ x - ~ y)) / 2 ),
45+ ])
46+
47+ const _rw_trig_expand = SymbolicUtils. Rewriters. Fixpoint (
48+ SymbolicUtils. Rewriters. Postwalk (
49+ SymbolicUtils. Rewriters. Chain ([
50+ SymbolicUtils. @rule ((cos (~ x))^ 2 => (1 + cos (2 * ~ x)) / 2 ),
51+ SymbolicUtils. @rule ((sin (~ x))^ 2 => (1 - cos (2 * ~ x)) / 2 ),
52+ _rw_trig_mul_to_sum,
53+ ]),
54+ ),
55+ )
5556
5657function _trig_expand_products (x:: BasicSymbolic )
5758 # Expand trig products/powers into sums so `get_independent` can isolate constants.
58- y = Postwalk (
59- ex -> begin
60- if ispow (ex)
61- base, exponent = arguments (ex)
62- exp_val = SymbolicUtils. unwrap_const (exponent)
63- if exp_val isa Integer && exp_val == 2 && _is_sin_cos (base)
64- arg = first (arguments (base))
65- if operation (base) === cos
66- return (1 + cos (2 * arg)) / 2
67- else
68- return (1 - cos (2 * arg)) / 2
69- end
70- end
71- elseif ismul (ex)
72- # In SymbolicUtils v4, `arguments(ismul(...))` includes the numeric coefficient
73- # even though `ex.coeff` also stores it. Avoid double-counting it.
74- factors = BasicSymbolic[
75- f for f in arguments (ex) if ! (SymbolicUtils. unwrap_const (f) isa Number)
76- ]
77- trig_idx = findall (_is_sin_cos, factors)
78- if length (trig_idx) >= 2
79- i, j = trig_idx[1 ], trig_idx[2 ]
80- repl = _trig_mul_to_sum (factors[i], factors[j])
81- if repl != = nothing
82- others = BasicSymbolic[]
83- for (k, f) in pairs (factors)
84- (k == i || k == j) && continue
85- push! (others, f)
86- end
87- coeff = ex. coeff
88- return coeff * prod (others; init= 1 ) * repl
89- end
90- end
91- end
92- return ex
93- end ,
94- )(
95- x
96- )
59+ y = Postwalk (ex -> begin
60+ if ismul (ex)
61+ # In SymbolicUtils v4, `arguments(ismul(...))` includes the numeric coefficient
62+ # even though `ex.coeff` also stores it. Avoid double-counting it.
63+ coeff = ex. coeff
64+ factors = BasicSymbolic[
65+ f for f in arguments (ex) if ! (SymbolicUtils. unwrap_const (f) isa Number)
66+ ]
67+ rest = isempty (factors) ? 1 : prod (factors; init= 1 )
68+ return coeff * _rw_trig_expand (rest)
69+ end
70+ return _rw_trig_expand (ex)
71+ end )(x)
9772 return SymbolicUtils. expand (y)
9873end
9974_trig_expand_products (x:: Num ) = wrap (_trig_expand_products (unwrap (x)))
0 commit comments