@@ -214,26 +214,68 @@ end
214214# Also give complex-valued degree definitions. We choose not to overwrite degree, as this will lead to issues in monovecs
215215# and their sorting. So now there are two ways to calculate degrees: strictly by considering all variables independently,
216216# and also by looking at their complex structure.
217+ for fn in (:degree_complex , :halfdegree )
218+ @eval function $fn (t:: AbstractTermLike )
219+ realdeg = 0
220+ cpdeg = 0
221+ conjdeg = 0
222+ for (var, exp) in powers (t)
223+ if isreal (var)
224+ realdeg += exp
225+ (isrealpart (var) || isimagpart (var)) && error (
226+ " Cannot calculate complex degrees when real or imaginary parts are present" ,
227+ )
228+ else
229+ if isconj (var)
230+ conjdeg += exp
231+ else
232+ cpdeg += exp
233+ end
234+ end
235+ end
236+ return $ (
237+ fn === :degree_complex ? :(realdeg) : :(div (realdeg, 2 , RoundUp))
238+ ) + max (cpdeg, conjdeg)
239+ end
240+ end
241+
217242"""
218243 degree_complex(t::AbstractTermLike)
219244
220245Return the _total complex degree_ of the monomial of the term `t`, i.e., the maximum of the total degree of the declared
221246variables in `t` and the total degree of the conjugate variables in `t`.
222247To be well-defined, the monomial must not contain real parts or imaginary parts of variables.
248+ If `x₁` and `x₂` are real-valued variables and `z₁` and `z₂` are complex-valued,
249+ - `degree_complex(x₁^2 * x₂^3) = 5`
250+ - `degree_complex(z₁^3 * conj(z₁)^4) = max(3, 4) = 4` and `degree_complex(z₁^4 * conj(z₁)^3) = max(4, 3) = 4`
251+ - `degree_complex(z₁^3 * z₂ * conj(z₁)^2 * conj(z₂)^4) = max(4, 6) = 6` and
252+ `degree_complex(z₁^4 * z₂ * conj(z₁) * conj(z₂)^3) = max(5, 4) = 5`
253+ - `degree_complex(x₁^2 * x₂^3 * z₁^3 * z₂ * conj(z₁)^2 * conj(z₂)^4) = 5 + max(4, 6) = 11`
254+ """
255+ degree_complex (t:: AbstractTermLike )
256+
257+ """
258+ halfdegree(t::AbstractTermLike)
259+
260+ Return the equivalent of `ceil(degree(t)/2)`` for real-valued terms or `degree_complex(t)` for terms with only complex
261+ variables; however, respect any mixing between complex and real-valued variables.
262+ To be well-defined, the monomial must not contain real parts or imaginary parts of variables.
263+ If `x₁` and `x₂` are real-valued variables and `z₁` and `z₂` are complex-valued,
264+ - `halfdegree(x₁^2 * x₂^3) = ⌈5/2⌉ = 3`
265+ - `halfdegree(z₁^3 * conj(z₁)^4) = max(3, 4) = 4` and `halfdegree(z₁^4 * conj(z₁)^3) = max(4, 3) = 4`
266+ - `halfdegree(z₁^3 * z₂ * conj(z₁)^2 * conj(z₂)^4) = max(4, 6) = 6` and
267+ `halfdegree(z₁^4 * z₂ * conj(z₁) * conj(z₂)^3) = max(5, 4) = 5`
268+ - `halfdegree(x₁^2 * x₂^3 * z₁^3 * z₂ * conj(z₁)^2 * conj(z₂)^4) = ⌈5/2⌉ + max(4, 6) = 9`
269+ """
270+ halfdegree (t:: AbstractTermLike )
223271
272+ """
224273 degree_complex(t::AbstractTermLike, v::AbstractVariable)
225274
226275Returns the exponent of the variable `v` or its conjugate in the monomial of the term `t`, whatever is larger.
227276
228277See also [`isconj`](@ref).
229278"""
230- function degree_complex (t:: AbstractTermLike )
231- vars = variables (t)
232- @assert (! any (isrealpart, vars) && ! any (isimagpart, vars))
233- grouping = isconj .(vars)
234- exps = exponents (t)
235- return max (sum (exps[grouping]), sum (exps[map (! , grouping)]))
236- end
237279function degree_complex (t:: AbstractTermLike , var:: AbstractVariable )
238280 return degree_complex (monomial (t), var)
239281end
@@ -243,7 +285,9 @@ function degree_complex(m::AbstractMonomial, v::AbstractVariable)
243285 deg_c = 0
244286 c_v = conj (v)
245287 for (var, exp) in powers (m)
246- @assert (! isrealpart (var) && ! isimagpart (var))
288+ (isrealpart (var) || isimagpart (var)) && error (
289+ " Cannot calculate complex degrees when real or imaginary parts are present" ,
290+ )
247291 if var == v
248292 deg += exp
249293 elseif var == c_v
@@ -253,31 +297,6 @@ function degree_complex(m::AbstractMonomial, v::AbstractVariable)
253297 return max (deg, deg_c)
254298end
255299
256- """
257- halfdegree(t::AbstractTermLike)
258-
259- Return the equivalent of `ceil(degree(t)/2)`` for real-valued terms or `degree_complex(t)` for terms with only complex
260- variables; however, respect any mixing between complex and real-valued variables.
261- """
262- function halfdegree (t:: AbstractTermLike )
263- realdeg = 0
264- cpdeg = 0
265- conjdeg = 0
266- for (var, exp) in powers (t)
267- if isreal (var)
268- realdeg += exp
269- else
270- if isconj (var)
271- conjdeg += exp
272- else
273- @assert (! isrealpart (var) && ! isimagpart (var))
274- cpdeg += exp
275- end
276- end
277- end
278- return ((realdeg + 1 ) >> 1 ) + max (cpdeg, conjdeg)
279- end
280-
281300"""
282301 mindegree_complex(p::Union{AbstractPolynomialLike, AbstractVector{<:AbstractTermLike}})
283302
0 commit comments