@@ -191,6 +191,54 @@ function trig_to_exp(x::BasicSymbolic)
191191 return Symbolics. substitute (x, Dict (rules))
192192end
193193
194+ " Convert a single exp(arg) node to trig form with sign normalization.
195+ Returns `nothing` if the node is not an exp call (for use with PassThrough)."
196+ function _exp_to_trig_node (x:: BasicSymbolic )
197+ ! (isterm (x) && operation (x) === exp) && return nothing
198+
199+ arg = first (arguments (x))
200+
201+ # exp(0) = 1: handle literal zero argument
202+ arg_val = arg isa BasicSymbolic ? unwrap_const (arg) : arg
203+ if arg_val isa Number && iszero (arg_val)
204+ return 1
205+ end
206+
207+ trigarg = Symbolics. expand (- im * arg) # the argument of the to-be trig function
208+ trigarg = simplify_complex (trigarg)
209+
210+ # After expansion and simplification, check if trigarg is zero (exp(0) = 1)
211+ ta_val = trigarg isa BasicSymbolic ? unwrap_const (trigarg) : trigarg
212+ if ta_val isa Number && iszero (ta_val)
213+ return 1
214+ end
215+
216+ # put arguments of trigs into a standard form such that sin(x) = -sin(-x), cos(x) = cos(-x) are recognized
217+ if isadd (trigarg)
218+ first_symbol = minimum (
219+ cat (
220+ string .(sorted_arguments (trigarg)),
221+ string .(sorted_arguments (- trigarg));
222+ dims= 1 ,
223+ ),
224+ )
225+
226+ # put trigarg => -trigarg the lowest alphabetic argument of trigarg is lower than that of -trigarg
227+ # this is a meaningless key but gives unique signs to all sums
228+ is_first = minimum (string .(sorted_arguments (trigarg))) == first_symbol
229+ return if is_first
230+ cos (- trigarg) - im * sin (- trigarg)
231+ else
232+ cos (trigarg) + im * sin (trigarg)
233+ end
234+ end
235+ return if ismul (trigarg) && _has_negative_coefficient (trigarg)
236+ cos (- trigarg) - im * sin (- trigarg)
237+ else
238+ cos (trigarg) + im * sin (trigarg)
239+ end
240+ end
241+
194242"""
195243 exp_to_trig(x::BasicSymbolic)
196244 exp_to_trig(x)
@@ -210,51 +258,9 @@ trigonometric arguments for consistent simplification.
210258function exp_to_trig (x:: BasicSymbolic )
211259 if isadd (x) || isdiv (x) || ismul (x)
212260 return _apply_termwise (exp_to_trig, x)
213- elseif isterm (x) && operation (x) === exp
214- arg = first (arguments (x))
215-
216- # exp(0) = 1: handle literal zero argument
217- arg_val = arg isa BasicSymbolic ? unwrap_const (arg) : arg
218- if arg_val isa Number && iszero (arg_val)
219- return 1
220- end
221-
222- trigarg = Symbolics. expand (- im * arg) # the argument of the to-be trig function
223- trigarg = simplify_complex (trigarg)
224-
225- # After expansion and simplification, check if trigarg is zero (exp(0) = 1)
226- ta_val = trigarg isa BasicSymbolic ? unwrap_const (trigarg) : trigarg
227- if ta_val isa Number && iszero (ta_val)
228- return 1
229- end
230-
231- # put arguments of trigs into a standard form such that sin(x) = -sin(-x), cos(x) = cos(-x) are recognized
232- if isadd (trigarg)
233- first_symbol = minimum (
234- cat (
235- string .(sorted_arguments (trigarg)),
236- string .(sorted_arguments (- trigarg));
237- dims= 1 ,
238- ),
239- )
240-
241- # put trigarg => -trigarg the lowest alphabetic argument of trigarg is lower than that of -trigarg
242- # this is a meaningless key but gives unique signs to all sums
243- is_first = minimum (string .(sorted_arguments (trigarg))) == first_symbol
244- return if is_first
245- cos (- trigarg) - im * sin (- trigarg)
246- else
247- cos (trigarg) + im * sin (trigarg)
248- end
249- end
250- return if ismul (trigarg) && _has_negative_coefficient (trigarg)
251- cos (- trigarg) - im * sin (- trigarg)
252- else
253- cos (trigarg) + im * sin (trigarg)
254- end
255- else
256- return x
257261 end
262+ result = _exp_to_trig_node (x)
263+ return isnothing (result) ? x : result
258264end
259265
260266" Check if a Mul expression has a negative leading coefficient"
0 commit comments