@@ -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