@@ -316,3 +316,126 @@ compare(a, b, ::Type{Reverse{O}}) where {O} = compare(b, a, O)
316316Returns the [`AbstractMonomialOrdering`](@ref) used for the monomials of `p`.
317317"""
318318function ordering end
319+
320+ _last_lex_index (n, :: Type{LexOrder} ) = n
321+ _prev_lex_index (i, :: Type{LexOrder} ) = i - 1
322+ _not_first_indices (n, :: Type{LexOrder} ) = n: - 1 : 2
323+ _last_lex_index (_, :: Type{InverseLexOrder} ) = 1
324+ _prev_lex_index (i, :: Type{InverseLexOrder} ) = i + 1
325+ _not_first_indices (n, :: Type{InverseLexOrder} ) = 1 : (n- 1 )
326+ _last_lex_index (n, :: Type{Graded{M}} ) where {M} = _last_lex_index (n, M)
327+ _prev_lex_index (i, :: Type{Graded{M}} ) where {M} = _prev_lex_index (i, M)
328+ _not_first_indices (n, :: Type{Graded{M}} ) where {M} = _not_first_indices (n, M)
329+
330+ """
331+ struct ExponentsIterator{M}(
332+ object;
333+ min_deg::Int = 0,
334+ max_deg::Union{Nothing,Int} = nothing,
335+ inline::Bool = false,
336+ )
337+
338+ An iterator for generating monomial exponents for monomial
339+ ordering `M`. The type of the vector of exponents is the type of
340+ `object` and is length (i.e., the number of variables) is `length(object)`.
341+ """
342+ struct ExponentsIterator{M,D<: Union{Nothing,Int} ,O}
343+ object:: O # Used to get number of variables and get new zero elements
344+ min_deg:: Int
345+ max_deg:: D
346+ inline:: Bool
347+ end
348+
349+ function ExponentsIterator {M} (object; min_deg:: Int = 0 , max_deg:: Union{Nothing,Int} = nothing , inline:: Bool = false ) where {M}
350+ ExponentsIterator {M,typeof(max_deg),typeof(object)} (object, min_deg, max_deg, inline)
351+ end
352+
353+ function ExponentsIterator (args... ; kws... )
354+ return ExponentsIterator {Graded{LexOrder}} (args... ; kws... )
355+ end
356+
357+ Base. eltype (:: Type{ExponentsIterator{M,D,O}} ) where {M,D,O} = O
358+ Base. IteratorSize (:: Type{<:ExponentsIterator{M,Nothing}} ) where {M} = Base. IsInfinite ()
359+ Base. IteratorSize (:: Type{<:ExponentsIterator{M,Int}} ) where {M} = Base. HasLength ()
360+
361+ function Base. length (it:: ExponentsIterator{M,Int} ) where {M}
362+ len = binomial (nvariables (it) + it. max_deg, nvariables (it))
363+ if it. min_deg > 0
364+ len -= binomial (nvariables (it) + it. min_deg, nvariables (it))
365+ end
366+ return len
367+ end
368+
369+ nvariables (it:: ExponentsIterator ) = length (it. object)
370+
371+ _increase_degree (it:: ExponentsIterator{<:Graded,Nothing} , _) = false
372+ _increase_degree (it:: ExponentsIterator{<:Graded,Int} , _) = false
373+ _increase_degree (it:: ExponentsIterator{M,Nothing} , _) where {M} = true
374+ _increase_degree (it:: ExponentsIterator{M,Int} , deg) where {M} = deg < it. max_deg
375+
376+ # We just changed the degree by removing `Δ`,
377+ # In graded ordering, we just add `Δ` to maintain the same degree
378+ _adjust_degree (:: ExponentsIterator{<:Graded} , _, Δ) = Δ
379+ # Otherwise, we just need the degree to stay above `it.min_deg`,
380+ # so we need to add `it.min_deg - deg`
381+ _adjust_degree (it:: ExponentsIterator , deg, _) = min (0 , it. min_deg - deg)
382+
383+ _setindex! (x, v, i) = Base. setindex! (x, v, i)
384+ _setindex! (x:: Tuple , v, i) = Base. setindex (x, v, i)
385+ _increment! (x, i) = _setindex! (x, x[i] + 1 , i)
386+
387+ _zero (x) = zero (x)
388+ _zero (x:: Tuple ) = zero .(x)
389+
390+ _zero! (x) = fill! (x, 0 )
391+ _zero! (x:: Tuple ) = _zero (x)
392+
393+ _copy (x) = copy (x)
394+ _copy (x:: Tuple ) = x
395+
396+ function _iterate! (it:: ExponentsIterator{M} , z, deg) where {M}
397+ if _increase_degree (it, deg)
398+ z = _increment! (z, _last_lex_index (nvariables (it), M))
399+ return z, deg + 1
400+ end
401+ I = _not_first_indices (nvariables (it), M)
402+ i = findfirst (i -> ! iszero (z[i]), I)
403+ if isnothing (i)
404+ if ! isnothing (it. max_deg) && deg == it. max_deg
405+ return
406+ end
407+ z = _zero! (z)
408+ z = _setindex! (z, deg + 1 , _last_lex_index (nvariables (it), M))
409+ return z, deg + 1
410+ end
411+ j = I[i]
412+ Δ = z[j] - 1
413+ _setindex! (z, 0 , j)
414+ deg -= Δ
415+ Δ = _adjust_degree (it, deg, Δ)
416+ deg += Δ
417+ z = _setindex! (z, Δ, _last_lex_index (nvariables (it), M))
418+ z = _increment! (z, _prev_lex_index (j, M))
419+ return z, deg
420+ end
421+
422+ function Base. iterate (it:: ExponentsIterator{M} ) where {M}
423+ if nvariables (it) == 0
424+ return
425+ end
426+ z = _zero (it. object)
427+ z = _setindex! (z, it. min_deg, _last_lex_index (nvariables (it), M))
428+ return z, (z, it. min_deg)
429+ end
430+
431+ function Base. iterate (it:: ExponentsIterator , state)
432+ z, deg = state
433+ if ! it. inline
434+ z = _copy (z)
435+ end
436+ state = _iterate! (it, z, deg)
437+ if isnothing (state)
438+ return
439+ end
440+ return state[1 ], state
441+ end
0 commit comments