@@ -214,26 +214,68 @@ end
214
214
# Also give complex-valued degree definitions. We choose not to overwrite degree, as this will lead to issues in monovecs
215
215
# and their sorting. So now there are two ways to calculate degrees: strictly by considering all variables independently,
216
216
# 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
+
217
242
"""
218
243
degree_complex(t::AbstractTermLike)
219
244
220
245
Return the _total complex degree_ of the monomial of the term `t`, i.e., the maximum of the total degree of the declared
221
246
variables in `t` and the total degree of the conjugate variables in `t`.
222
247
To 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 )
223
271
272
+ """
224
273
degree_complex(t::AbstractTermLike, v::AbstractVariable)
225
274
226
275
Returns the exponent of the variable `v` or its conjugate in the monomial of the term `t`, whatever is larger.
227
276
228
277
See also [`isconj`](@ref).
229
278
"""
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
237
279
function degree_complex (t:: AbstractTermLike , var:: AbstractVariable )
238
280
return degree_complex (monomial (t), var)
239
281
end
@@ -243,7 +285,9 @@ function degree_complex(m::AbstractMonomial, v::AbstractVariable)
243
285
deg_c = 0
244
286
c_v = conj (v)
245
287
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
+ )
247
291
if var == v
248
292
deg += exp
249
293
elseif var == c_v
@@ -253,31 +297,6 @@ function degree_complex(m::AbstractMonomial, v::AbstractVariable)
253
297
return max (deg, deg_c)
254
298
end
255
299
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
-
281
300
"""
282
301
mindegree_complex(p::Union{AbstractPolynomialLike, AbstractVector{<:AbstractTermLike}})
283
302
0 commit comments