Skip to content

Commit 252adfb

Browse files
authored
Add support for Reverse ordering (#320)
* Add support for Reverse ordering * Fix * Fix format * v0.5.9
1 parent 8d2db43 commit 252adfb

File tree

3 files changed

+91
-42
lines changed

3 files changed

+91
-42
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name = "MultivariatePolynomials"
22
uuid = "102ac46a-7ee4-5c85-9060-abc95bfdeaa3"
33
license = "MIT"
44
repo = "https://github.com/JuliaAlgebra/MultivariatePolynomials.jl"
5-
version = "0.5.8"
5+
version = "0.5.9"
66

77
[deps]
88
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"

src/comparison.jl

Lines changed: 76 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -346,16 +346,6 @@ end
346346

347347
Base.isless(t1::AbstractTermLike, t2::AbstractTermLike) = compare(t1, t2) < 0
348348

349-
_last_lex_index(n, ::Type{LexOrder}) = n
350-
_prev_lex_index(i, ::Type{LexOrder}) = i - 1
351-
_not_first_indices(n, ::Type{LexOrder}) = n:-1:2
352-
_last_lex_index(_, ::Type{InverseLexOrder}) = 1
353-
_prev_lex_index(i, ::Type{InverseLexOrder}) = i + 1
354-
_not_first_indices(n, ::Type{InverseLexOrder}) = 1:(n-1)
355-
_last_lex_index(n, ::Type{Graded{M}}) where {M} = _last_lex_index(n, M)
356-
_prev_lex_index(i, ::Type{Graded{M}}) where {M} = _prev_lex_index(i, M)
357-
_not_first_indices(n, ::Type{Graded{M}}) where {M} = _not_first_indices(n, M)
358-
359349
"""
360350
struct ExponentsIterator{M}(
361351
object;
@@ -418,25 +408,39 @@ struct ExponentsIterator{M,D<:Union{Nothing,Int},O}
418408
mindegree::Int
419409
maxdegree::D
420410
inline::Bool
421-
end
422411

423-
function ExponentsIterator{M}(
424-
object;
425-
mindegree::Int = 0,
426-
maxdegree::Union{Nothing,Int} = nothing,
427-
inline::Bool = false,
428-
) where {M}
429-
if length(object) == 0 && isnothing(maxdegree)
430-
# Otherwise, it will incorrectly think that the iterator is infinite
431-
# while it actually has zero elements
432-
maxdegree = mindegree
412+
function ExponentsIterator{M}(
413+
object;
414+
mindegree::Int = 0,
415+
maxdegree::Union{Nothing,Int} = nothing,
416+
inline::Bool = false,
417+
) where {M}
418+
if mindegree < 0
419+
throw(
420+
ArgumentError(
421+
"The `mindegree` of `ExponentsIterator` cannot be negative.",
422+
),
423+
)
424+
end
425+
if M <: Reverse
426+
throw(
427+
ArgumentError(
428+
"Ordering `$M` is not a valid ordering, use `Graded{$M}` instead.",
429+
),
430+
)
431+
end
432+
if length(object) == 0 && isnothing(maxdegree)
433+
# Otherwise, it will incorrectly think that the iterator is infinite
434+
# while it actually has zero elements
435+
maxdegree = mindegree
436+
end
437+
return new{M,typeof(maxdegree),typeof(object)}(
438+
object,
439+
mindegree,
440+
maxdegree,
441+
inline,
442+
)
433443
end
434-
return ExponentsIterator{M,typeof(maxdegree),typeof(object)}(
435-
object,
436-
mindegree,
437-
maxdegree,
438-
inline,
439-
)
440444
end
441445

442446
Base.eltype(::Type{ExponentsIterator{M,D,O}}) where {M,D,O} = O
@@ -460,6 +464,22 @@ end
460464

461465
nvariables(it::ExponentsIterator) = length(it.object)
462466

467+
_last_lex_index(n, ::Type{LexOrder}) = n
468+
_prev_lex_index(i, ::Type{LexOrder}) = i - 1
469+
_not_first_indices(n, ::Type{LexOrder}) = n:-1:2
470+
_last_lex_index(_, ::Type{InverseLexOrder}) = 1
471+
_prev_lex_index(i, ::Type{InverseLexOrder}) = i + 1
472+
_not_first_indices(n, ::Type{InverseLexOrder}) = 1:(n-1)
473+
_last_lex_index(n, ::Type{Reverse{LexOrder}}) = 1
474+
_prev_lex_index(i, ::Type{Reverse{LexOrder}}) = i + 1
475+
_not_first_indices(n, ::Type{Reverse{LexOrder}}) = (n-1):-1:1
476+
_last_lex_index(n, ::Type{Reverse{InverseLexOrder}}) = n
477+
_prev_lex_index(i, ::Type{Reverse{InverseLexOrder}}) = i - 1
478+
_not_first_indices(n, ::Type{Reverse{InverseLexOrder}}) = 2:n
479+
_last_lex_index(n, ::Type{Graded{M}}) where {M} = _last_lex_index(n, M)
480+
_prev_lex_index(i, ::Type{Graded{M}}) where {M} = _prev_lex_index(i, M)
481+
_not_first_indices(n, ::Type{Graded{M}}) where {M} = _not_first_indices(n, M)
482+
463483
_increase_degree(it::ExponentsIterator{<:Graded,Nothing}, _) = false
464484
_increase_degree(it::ExponentsIterator{<:Graded,Int}, _) = false
465485
_increase_degree(it::ExponentsIterator{M,Nothing}, _) where {M} = true
@@ -474,9 +494,10 @@ _adjust_degree(::ExponentsIterator{<:Graded}, _, Δ) = Δ
474494
# so we need to add `it.mindegree - deg`
475495
_adjust_degree(it::ExponentsIterator, deg, _) = max(0, it.mindegree - deg)
476496

497+
# Same as `BangBang.setindex!!`
477498
_setindex!(x, v, i) = Base.setindex!(x, v, i)
478499
_setindex!(x::Tuple, v, i) = Base.setindex(x, v, i)
479-
_increment!(x, i) = _setindex!(x, x[i] + 1, i)
500+
_increment!(x, Δ, i) = _setindex!(x, x[i] + Δ, i)
480501

481502
_zero(x) = zero(x)
482503
_zero(x::Tuple) = zero.(x)
@@ -487,9 +508,34 @@ _zero!(x::Tuple) = _zero(x)
487508
_copy(x) = copy(x)
488509
_copy(x::Tuple) = x
489510

511+
function __iterate!(
512+
it::ExponentsIterator{Graded{Reverse{M}}},
513+
z,
514+
i,
515+
deg,
516+
) where {M}
517+
z = _increment!(z, -1, i)
518+
k = _last_lex_index(nvariables(it), M)
519+
Δ = z[k] + 1
520+
z = _setindex!(z, 0, k)
521+
z = _setindex!(z, Δ, _prev_lex_index(i, Reverse{M}))
522+
return z, deg
523+
end
524+
525+
function __iterate!(it::ExponentsIterator{M}, z, i, deg) where {M}
526+
Δ = z[i] - 1
527+
z = _setindex!(z, 0, i)
528+
deg -= Δ
529+
Δ = _adjust_degree(it, deg, Δ)
530+
deg += Δ
531+
z = _setindex!(z, Δ, _last_lex_index(nvariables(it), M))
532+
z = _increment!(z, 1, _prev_lex_index(i, M))
533+
return z, deg
534+
end
535+
490536
function _iterate!(it::ExponentsIterator{M}, z, deg) where {M}
491537
if _increase_degree(it, deg)
492-
z = _increment!(z, _last_lex_index(nvariables(it), M))
538+
z = _increment!(z, 1, _last_lex_index(nvariables(it), M))
493539
return z, deg + 1
494540
end
495541
I = _not_first_indices(nvariables(it), M)
@@ -502,17 +548,7 @@ function _iterate!(it::ExponentsIterator{M}, z, deg) where {M}
502548
z = _setindex!(z, deg + 1, _last_lex_index(nvariables(it), M))
503549
return z, deg + 1
504550
end
505-
j = I[i]
506-
Δ = z[j] - 1
507-
z = _setindex!(z, 0, j)
508-
j = I[i]
509-
deg -= Δ
510-
Δ = _adjust_degree(it, deg, Δ)
511-
deg += Δ
512-
z = _setindex!(z, Δ, _last_lex_index(nvariables(it), M))
513-
j = I[i]
514-
z = _increment!(z, _prev_lex_index(j, M))
515-
return z, deg
551+
return __iterate!(it, z, I[i], deg)
516552
end
517553

518554
function Base.iterate(it::ExponentsIterator{M}) where {M}

test/comparison.jl

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,26 @@ function _test(nvars::Int, M; kws...)
1616
return
1717
end
1818

19+
function test_errors()
20+
err = ArgumentError(
21+
"The `mindegree` of `ExponentsIterator` cannot be negative.",
22+
)
23+
@test_throws err ExponentsIterator{LexOrder}([0], mindegree = -1)
24+
M = Reverse{LexOrder}
25+
err = ArgumentError(
26+
"Ordering `$M` is not a valid ordering, use `Graded{$M}` instead.",
27+
)
28+
@test_throws err ExponentsIterator{M}([0], maxdegree = 2)
29+
end
30+
1931
function test_exponents_iterator()
2032
@testset "nvariables = $nvars" for nvars in 0:3
2133
@testset "mindegree = $mindegree" for mindegree in 0:3
2234
@testset "maxdegree = $maxdegree" for maxdegree in
2335
vcat(nothing, 0:3)
2436
for L in [LexOrder, InverseLexOrder]
25-
@testset "M = $M" for M in [L, Graded{L}]
37+
@testset "M = $M" for M in
38+
[L, Graded{L}, Graded{Reverse{L}}]
2639
_test(nvars, M; mindegree, maxdegree)
2740
end
2841
end

0 commit comments

Comments
 (0)