From 77f0520e2fe5375fd4d54500327c99b3cd2f9fae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Gauth=C3=A9?= Date: Tue, 28 Jan 2025 19:11:51 -0500 Subject: [PATCH 1/7] first draft for SectorUnitRange --- src/GradedUnitRanges.jl | 3 + src/newgradedunitrange.jl | 109 ++++++++++++++++++++++++++++++ src/sectorunitrange.jl | 116 ++++++++++++++++++++++++++++++++ test/test_newgradedunitrange.jl | 78 +++++++++++++++++++++ test/test_sectorunitrange.jl | 95 ++++++++++++++++++++++++++ 5 files changed, 401 insertions(+) create mode 100644 src/newgradedunitrange.jl create mode 100644 src/sectorunitrange.jl create mode 100644 test/test_newgradedunitrange.jl create mode 100644 test/test_sectorunitrange.jl diff --git a/src/GradedUnitRanges.jl b/src/GradedUnitRanges.jl index e675bc4..6b0a587 100644 --- a/src/GradedUnitRanges.jl +++ b/src/GradedUnitRanges.jl @@ -10,4 +10,7 @@ include("gradedunitrangedual.jl") include("onetoone.jl") include("fusion.jl") +include("sectorunitrange.jl") +include("newgradedunitrange.jl") + end diff --git a/src/newgradedunitrange.jl b/src/newgradedunitrange.jl new file mode 100644 index 0000000..6d538f3 --- /dev/null +++ b/src/newgradedunitrange.jl @@ -0,0 +1,109 @@ + +using BlockArrays: BlockArrays + +struct NewGradedUnitRange{T,BlockLasts,Sector} <: AbstractGradedUnitRange{T,BlockLasts} + nondual_labels::Vector{Sector} + multiplicity_range::BlockedOneTo{T,BlockLasts} # TBD offset != 1? + isdual::Bool + + function NewGradedUnitRange(glabels, grange, gisdual) + return new{eltype(grange),Vector{eltype(grange)},eltype(glabels)}( + glabels, grange, gisdual + ) + end +end + +# +# Accessors +# +nondual_labels(g::NewGradedUnitRange) = g.nondual_labels +multiplicity_range(g::NewGradedUnitRange) = g.multiplicity_range +isdual(g::NewGradedUnitRange) = g.isdual + +# +# GradedUnitRanges interface +# +function GradedUnitRanges.sector_type( + ::Type{<:NewGradedUnitRange{T,BlockLasts,Sector}} +) where {T,BlockLasts,Sector} + return Sector +end + +function blocklabels(g::NewGradedUnitRange) + return isdual(g) ? dual.(nondual_labels(g)) : nondual_labels(g) +end + +function dual(g::NewGradedUnitRange) + return NewGradedUnitRange(nondual_labels(g), multiplicity_range(g), !isdual(g)) +end + +function flip(g::NewGradedUnitRange) + return NewGradedUnitRange(dual.(nondual_labels(g)), multiplicity_range(g), !isdual(g)) +end + +function space_isequal(g1::NewGradedUnitRange, g2::NewGradedUnitRange) + return nondual_labels(g1) == nondual_labels(g2) && + blockisequal(multiplicity_range(g1), multiplicity_range(g2)) && + isdual(g1) == isdual(g2) +end + +# +# Base interface +# +Base.length(g::NewGradedUnitRange) = sum(length.(blocks(g))) + +function Base.show(io::IO, g::NewGradedUnitRange) + return print(io, nameof(typeof(g)), blocklabels(g), multiplicity_range(g)) +end + +function Base.show(io::IO, ::MIME"text/plain", g::NewGradedUnitRange) + print(io, typeof(g)) + if isdual(g) + print(io, " dual") + end + println() + return print(io, join(repr.(blocks(g)), '\n')) +end + +# +# BlockArrays interface +# +function BlockArrays.mortar(v::Vector{<:SectorUnitRange}) + glabels = nondual_sector.(v) + grange = blockedrange(length.(multiplicity_range.(v))) + gisdual = isdual(first(v)) + # TODO add checks + return NewGradedUnitRange(glabels, grange, gisdual) +end + +function BlockArrays.blocks(g::NewGradedUnitRange) + return sectorunitrange.( + nondual_labels(g), blocks(multiplicity_range(g)), isdual(g), blockfirsts(g) + ) +end + +BlockArrays.blocklengths(g::NewGradedUnitRange) = length.(blocks(g)) + +function BlockArrays.blockfirsts(g::NewGradedUnitRange) + return vcat([1], blocklasts(g)[begin:(end - 1)]) +end + +function BlockArrays.blocklasts(g::NewGradedUnitRange) + return cumsum(length.(nondual_labels(g)) .* blocklengths(multiplicity_range(g))) +end + +# +# getitem & slicing +# +Base.getindex(g::NewGradedUnitRange, b::Block{1}) = blocks(g)[Int(b)] + +function Base.getindex( + g::NewGradedUnitRange, br::BlockRange{1,R} +) where {R<:Tuple{AbstractUnitRange{Int64}}} # TODO remove ambiguities & use more generic def + return mortar(blocks(g)[Int.(br)]) +end + +# TODO remove Tuple with kronecker(:, .) +function Base.getindex(g::NewGradedUnitRange, bx::Tuple{<:Block{1},Colon,<:Any}) + return blocks(g)[Int(first(bx))][:, last(bx)] +end diff --git a/src/sectorunitrange.jl b/src/sectorunitrange.jl new file mode 100644 index 0000000..d8072a5 --- /dev/null +++ b/src/sectorunitrange.jl @@ -0,0 +1,116 @@ + +using BlockArrays: BlockArrays + +struct SectorUnitRange{T,Sector,Range<:AbstractUnitRange{T}} <: AbstractUnitRange{T} + nondual_sector::Sector + multiplicity_range::Range + isdual::Bool + offset::T + + function SectorUnitRange(s, r, b, offset) + return new{eltype(r),typeof(s),typeof(r)}(s, r, b, offset) + end +end + +# +# Constructors +# +sectorunitrange(s, r, b=false, offset=1) = SectorUnitRange(s, r, b, offset) + +# +# accessors +# +nondual_sector(sr::SectorUnitRange) = sr.nondual_sector +multiplicity_range(sr::SectorUnitRange) = sr.multiplicity_range +isdual(sr::SectorUnitRange) = sr.isdual +offset(sr::SectorUnitRange) = sr.offset + +# +# Base interface +# +Base.axes(sr::SectorUnitRange) = Base.oneto(length(sr)) + +Base.eachindex(sr::SectorUnitRange) = Base.oneto(length(sr)) + +function Base.first(sr::SectorUnitRange) + return offset(sr) + length(nondual_sector(sr)) * (first(multiplicity_range(sr)) - 1) +end + +Base.lastindex(sr::SectorUnitRange) = length(sr) + +function Base.length(sr::SectorUnitRange) + return length(nondual_sector(sr)) * length(multiplicity_range(sr)) +end # TBD directly quantum_dimension(nondual_sector(sr))? + +Base.iterate(sr::SectorUnitRange) = iterate(first(sr):last(sr)) +Base.iterate(sr::SectorUnitRange, i::Integer) = iterate(first(sr):last(sr), i) + +Base.last(sr::SectorUnitRange) = first(sr) + length(sr) + +Base.getindex(sr::SectorUnitRange, i::Integer) = range(sr)[i] +function Base.getindex(sr::SectorUnitRange, r::AbstractUnitRange{T}) where {T<:Integer} + return range(sr)[r] +end + +# TODO replace Colon indexing with kronecker(:, i) +Base.getindex(sr::SectorUnitRange, ::Colon, i2::Integer) = sr[:, i2:i2] +function Base.getindex(sr::SectorUnitRange, ::Colon, r::AbstractUnitRange) + return sectorunitrange( + nondual_sector(sr), multiplicity_range(sr)[r], isdual(sr), offset(sr) + ) +end + +Base.range(sr::SectorUnitRange) = first(sr):last(sr) + +function Base.show(io::IO, sr::SectorUnitRange) + print(io, nameof(typeof(sr)), " ", offset(sr), " .+ ") + if isdual(sr) + print(io, "dual(", nondual_sector(sr), ")") + else + print(io, nondual_sector(sr)) + end + return print(io, " => ", multiplicity_range(sr)) +end + +# +# GradedUnitRanges interface +# +function blocklabels(sr::SectorUnitRange) + return isdual(sr) ? [dual(nondual_sector(sr))] : [nondual_sector(sr)] +end + +function dual(sr::SectorUnitRange) + return sectorunitrange( + nondual_sector(sr), multiplicity_range(sr), !isdual(sr), offset(sr) + ) +end + +function flip(sr::SectorUnitRange) + return sectorunitrange( + dual(nondual_sector(sr)), multiplicity_range(sr), !isdual(sr), offset(sr) + ) +end + +function map_blocklabels(f, sr::SectorUnitRange) + return sectorunitrange( + f(nondual_sector(sr)), multiplicity_range(sr), isdual(sr), offset(sr) + ) +end + +sector_type(::Type{<:SectorUnitRange{T,Sector}}) where {T,Sector} = Sector + +function space_isequal(sr1::SectorUnitRange, sr2::SectorUnitRange) + return nondual_sector(sr1) == nondual_sector(sr2) && + isdual(sr1) == isdual(sr2) && + multiplicity_range(sr1) == multiplicity_range(sr2) && + offset(sr1) == offset(sr2) +end + +# +# BlockArrays interface +# +BlockArrays.blocks(sr::SectorUnitRange) = [sr] + +BlockArrays.blocklength(::SectorUnitRange) = 1 + +BlockArrays.blocklengths(sr::SectorUnitRange) = [length(sr)] # TBD return length(multiplicity_range(sr)) ? diff --git a/test/test_newgradedunitrange.jl b/test/test_newgradedunitrange.jl new file mode 100644 index 0000000..d42afb6 --- /dev/null +++ b/test/test_newgradedunitrange.jl @@ -0,0 +1,78 @@ +using Test: @test, @test_throws, @testset + +using BlockArrays: Block, blocklength, blocklengths, blockisequal, blocks, mortar + +using GradedUnitRanges: + AbstractGradedUnitRange, + NewGradedUnitRange, + SectorUnitRange, + blocklabels, + dual, + gradedrange, + flip, + isdual, + multiplicity_range, + nondual_sector, + offset, + sector_type, + sectorunitrange, + space_isequal +using SymmetrySectors: AbstractSector, SU, quantum_dimension + +Base.length(s::AbstractSector) = quantum_dimension(s) + +@testset "NewGradedUnitRange" begin + sr1 = sectorunitrange(SU((1, 0)), 1:2) + g1 = mortar([sr1]) + @test g1 isa NewGradedUnitRange + @test blocklabels(g1) == [SU((1, 0))] + @test blockisequal(multiplicity_range(g1), blockedrange([2])) + @test !isdual(g1) + + @test length(g1) == 6 + @test blocklength(g1) == 1 + @test blocklengths(g1) == [6] + @test space_isequal(only(blocks(g1)), sr1) + + sr2 = sectorunitrange(SU((2, 1)), 3:3, false, 6) + g2 = mortar([sr1, sr2]) + @test g2 isa NewGradedUnitRange + @test blocklabels(g2) == [SU((1, 0)), SU((2, 1))] + @test blockisequal(multiplicity_range(g2), blockedrange([2, 1])) + @test !isdual(g2) + @test space_isequal(g2, g2) + @test !space_isequal(g1, g2) + + @test length(g2) == 14 + @test blocklength(g2) == 2 + @test blocklengths(g2) == [6, 8] + @test all(space_isequal.(blocks(g2), [sr1, sr2])) + @test space_isequal(g2[Block(1)], sr1) + @test space_isequal(g2[Block(2)], sr2) + + g2b = dual(g2) + @test g2b isa NewGradedUnitRange + @test blocklabels(g2b) == [SU((1, 1)), SU((2, 1))] + @test blockisequal(multiplicity_range(g2b), blockedrange([2, 1])) + @test isdual(g2b) + + g2f = flip(g2) + @test g2f isa NewGradedUnitRange + @test blocklabels(g2f) == [SU((1, 0)), SU((2, 1))] + @test blockisequal(multiplicity_range(g2f), blockedrange([2, 1])) + @test isdual(g2f) + + # slicing + @test space_isequal(g2[Block.(1:2)], g2) + @test space_isequal(g2[Block.(1:2)], g2) + + @test space_isequal(g2[(Block(1),:,1)], sectorunitrange(SU((1, 0)), 1:1, false, 1)) + @test space_isequal(g2[(Block(1),:,2)], sectorunitrange(SU((1, 0)), 2:2, false, 1)) + @test space_isequal(g2[(Block(1),:,1:2)], sectorunitrange(SU((1, 0)), 1:2, false, 1)) + @test_throws BoundsError g2[(Block(1),:,3)] + + @test space_isequal(g2[(Block(2),:,1)], sectorunitrange(SU((2, 1)), 3:3, false, 6)) + @test space_isequal(g2[(Block(2),:,1:1)], sectorunitrange(SU((2, 1)), 3:3, false, 6)) + @test_throws BoundsError g2[(Block(2),:,2)] + @test_throws BoundsError g2[(Block(2),:,3:3)] # misleading? +end diff --git a/test/test_sectorunitrange.jl b/test/test_sectorunitrange.jl new file mode 100644 index 0000000..e339ea9 --- /dev/null +++ b/test/test_sectorunitrange.jl @@ -0,0 +1,95 @@ +using Test: @test, @test_throws, @testset + +using BlockArrays: Block, blocklength, blocklengths, blockisequal, blocks + +using GradedUnitRanges: + SectorUnitRange, + blocklabels, + dual, + flip, + isdual, + multiplicity_range, + nondual_sector, + offset, + sector_type, + sectorunitrange, + space_isequal +using SymmetrySectors: AbstractSector, SU, quantum_dimension + +Base.length(s::AbstractSector) = quantum_dimension(s) + +@testset "SectorUnitRange" begin + sr = sectorunitrange(SU((1, 0)), 2:3, false, 3) + @test sr isa SectorUnitRange + @test space_isequal(sr, sr) + @test !space_isequal(sr, sectorunitrange(SU((1, 1)), 2:3, false, 3)) + @test !space_isequal(sr, sectorunitrange(SU((1, 0)), 3:3, false, 3)) + @test !space_isequal(sr, sectorunitrange(SU((1, 0)), 2:3, true, 3)) + @test !space_isequal(sr, sectorunitrange(SU((1, 0)), 2:3, false, 2)) + + # accessors + @test nondual_sector(sr) == SU((1, 0)) + @test multiplicity_range(sr) == 2:3 + @test offset(sr) == 3 + @test !isdual(sr) + + @test space_isequal( + sectorunitrange(SU((1, 0)), 2:3, false, 1), sectorunitrange(SU((1, 0)), 2:3) + ) + + # Base interface + @test length(sr) == 6 + @test firstindex(sr) == 1 + @test lastindex(sr) == 6 + @test first(sr) == 6 + @test last(sr) == 12 + @test eltype(sr) === Int + @test eachindex(sr) == Base.oneto(6) + + sr2 = copy(sr) + @test sr2 isa SectorUnitRange + @test space_isequal(sr, sr2) + sr3 = deepcopy(sr) + @test sr3 isa SectorUnitRange + @test space_isequal(sr, sr3) + + # BlockArrays interface + @test blocklength(sr) == 1 + @test blocklengths(sr) == [6] + @test only(blocks(sr)) === sr + @test blockisequal(sr, sr) + + # GradedUnitRanges interface + @test sector_type(sr) === SU{3,2} + @test sector_type(typeof(sr)) === SU{3,2} + @test blocklabels(sr) == [SU((1, 0))] + + srd = dual(sr) + @test nondual_sector(srd) == SU((1, 0)) + @test blocklabels(srd) == [SU((1, 1))] + @test multiplicity_range(srd) == 2:3 + @test offset(srd) == 3 + @test isdual(srd) + + srf = flip(sr) + @test nondual_sector(srf) == SU((1, 1)) + @test blocklabels(srf) == [SU((1, 0))] + @test multiplicity_range(srf) == 2:3 + @test offset(srf) == 3 + @test isdual(srf) + + # getindex + for i in 1:6 + @test sr[i] == i + 5 + end + @test sr[2:3] == 7:8 + @test sr[Block(1)] === sr + @test_throws BlockBoundsError sr[Block(2)] + + sr2 = sr[:, 1] + @test sr2 isa SectorUnitRange + @test space_isequal(sr2, sectorunitrange(SU((1, 0)), 2:2, false, 3)) + sr3 = sr[:, 1:2] + @test sr3 isa SectorUnitRange + @test space_isequal(sr3, sectorunitrange(SU((1, 0)), 2:3, false, 3)) +end From 83c3bf511a9d27c7049f62a12c504143a59e1236 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Gauth=C3=A9?= Date: Tue, 28 Jan 2025 19:44:28 -0500 Subject: [PATCH 2/7] use directly Tuple in getindex --- src/newgradedunitrange.jl | 8 ++++---- src/sectorunitrange.jl | 9 +++++---- test/test_newgradedunitrange.jl | 16 ++++++++-------- test/test_sectorunitrange.jl | 4 ++-- 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/newgradedunitrange.jl b/src/newgradedunitrange.jl index 6d538f3..f7fb0d6 100644 --- a/src/newgradedunitrange.jl +++ b/src/newgradedunitrange.jl @@ -93,7 +93,7 @@ function BlockArrays.blocklasts(g::NewGradedUnitRange) end # -# getitem & slicing +# slicing # Base.getindex(g::NewGradedUnitRange, b::Block{1}) = blocks(g)[Int(b)] @@ -103,7 +103,7 @@ function Base.getindex( return mortar(blocks(g)[Int.(br)]) end -# TODO remove Tuple with kronecker(:, .) -function Base.getindex(g::NewGradedUnitRange, bx::Tuple{<:Block{1},Colon,<:Any}) - return blocks(g)[Int(first(bx))][:, last(bx)] +# TODO replace Tuple with kronecker +function Base.getindex(g::NewGradedUnitRange, bx::Tuple{<:Block{1},<:Any}) + return blocks(g)[Int(first(bx))][(:, last(bx))] end diff --git a/src/sectorunitrange.jl b/src/sectorunitrange.jl index d8072a5..4eb3510 100644 --- a/src/sectorunitrange.jl +++ b/src/sectorunitrange.jl @@ -47,16 +47,17 @@ Base.iterate(sr::SectorUnitRange, i::Integer) = iterate(first(sr):last(sr), i) Base.last(sr::SectorUnitRange) = first(sr) + length(sr) +# slicing Base.getindex(sr::SectorUnitRange, i::Integer) = range(sr)[i] function Base.getindex(sr::SectorUnitRange, r::AbstractUnitRange{T}) where {T<:Integer} return range(sr)[r] end -# TODO replace Colon indexing with kronecker(:, i) -Base.getindex(sr::SectorUnitRange, ::Colon, i2::Integer) = sr[:, i2:i2] -function Base.getindex(sr::SectorUnitRange, ::Colon, r::AbstractUnitRange) +# TODO replace (:,x) indexing with kronecker(:, x) +Base.getindex(sr::SectorUnitRange, t::Tuple{Colon,<:Integer}) = sr[(:, last(t):last(t))] +function Base.getindex(sr::SectorUnitRange, t::Tuple{Colon,<:AbstractUnitRange}) return sectorunitrange( - nondual_sector(sr), multiplicity_range(sr)[r], isdual(sr), offset(sr) + nondual_sector(sr), multiplicity_range(sr)[last(t)], isdual(sr), offset(sr) ) end diff --git a/test/test_newgradedunitrange.jl b/test/test_newgradedunitrange.jl index d42afb6..9f5ea5c 100644 --- a/test/test_newgradedunitrange.jl +++ b/test/test_newgradedunitrange.jl @@ -66,13 +66,13 @@ Base.length(s::AbstractSector) = quantum_dimension(s) @test space_isequal(g2[Block.(1:2)], g2) @test space_isequal(g2[Block.(1:2)], g2) - @test space_isequal(g2[(Block(1),:,1)], sectorunitrange(SU((1, 0)), 1:1, false, 1)) - @test space_isequal(g2[(Block(1),:,2)], sectorunitrange(SU((1, 0)), 2:2, false, 1)) - @test space_isequal(g2[(Block(1),:,1:2)], sectorunitrange(SU((1, 0)), 1:2, false, 1)) - @test_throws BoundsError g2[(Block(1),:,3)] + @test space_isequal(g2[(Block(1), 1)], sectorunitrange(SU((1, 0)), 1:1, false, 1)) + @test space_isequal(g2[(Block(1), 2)], sectorunitrange(SU((1, 0)), 2:2, false, 1)) + @test space_isequal(g2[(Block(1), 1:2)], sectorunitrange(SU((1, 0)), 1:2, false, 1)) + @test_throws BoundsError g2[(Block(1), 3)] - @test space_isequal(g2[(Block(2),:,1)], sectorunitrange(SU((2, 1)), 3:3, false, 6)) - @test space_isequal(g2[(Block(2),:,1:1)], sectorunitrange(SU((2, 1)), 3:3, false, 6)) - @test_throws BoundsError g2[(Block(2),:,2)] - @test_throws BoundsError g2[(Block(2),:,3:3)] # misleading? + @test space_isequal(g2[(Block(2), 1)], sectorunitrange(SU((2, 1)), 3:3, false, 6)) + @test space_isequal(g2[(Block(2), 1:1)], sectorunitrange(SU((2, 1)), 3:3, false, 6)) + @test_throws BoundsError g2[(Block(2), 2)] + @test_throws BoundsError g2[(Block(2), 3:3)] # misleading? end diff --git a/test/test_sectorunitrange.jl b/test/test_sectorunitrange.jl index e339ea9..9f7b7bd 100644 --- a/test/test_sectorunitrange.jl +++ b/test/test_sectorunitrange.jl @@ -86,10 +86,10 @@ Base.length(s::AbstractSector) = quantum_dimension(s) @test sr[Block(1)] === sr @test_throws BlockBoundsError sr[Block(2)] - sr2 = sr[:, 1] + sr2 = sr[(:, 1)] @test sr2 isa SectorUnitRange @test space_isequal(sr2, sectorunitrange(SU((1, 0)), 2:2, false, 3)) - sr3 = sr[:, 1:2] + sr3 = sr[(:, 1:2)] @test sr3 isa SectorUnitRange @test space_isequal(sr3, sectorunitrange(SU((1, 0)), 2:3, false, 3)) end From 71ec6a605ab3e19c45cda2096473964d2c500806 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Gauth=C3=A9?= Date: Tue, 28 Jan 2025 19:47:47 -0500 Subject: [PATCH 3/7] add broken firsts --- test/test_newgradedunitrange.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/test_newgradedunitrange.jl b/test/test_newgradedunitrange.jl index 9f5ea5c..349cfc9 100644 --- a/test/test_newgradedunitrange.jl +++ b/test/test_newgradedunitrange.jl @@ -62,6 +62,8 @@ Base.length(s::AbstractSector) = quantum_dimension(s) @test blockisequal(multiplicity_range(g2f), blockedrange([2, 1])) @test isdual(g2f) + @test_broken blockfirsts(g2) == first.(blocks(g2)) + # slicing @test space_isequal(g2[Block.(1:2)], g2) @test space_isequal(g2[Block.(1:2)], g2) From c6fbea388162cb41a40fc7b78c098b0d4affe583 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Gauth=C3=A9?= Date: Tue, 28 Jan 2025 19:56:58 -0500 Subject: [PATCH 4/7] fix offset --- src/sectorunitrange.jl | 18 +++++++----------- test/test_newgradedunitrange.jl | 4 +++- test/test_sectorunitrange.jl | 18 +++++++++--------- 3 files changed, 19 insertions(+), 21 deletions(-) diff --git a/src/sectorunitrange.jl b/src/sectorunitrange.jl index 4eb3510..25b18ce 100644 --- a/src/sectorunitrange.jl +++ b/src/sectorunitrange.jl @@ -23,7 +23,7 @@ sectorunitrange(s, r, b=false, offset=1) = SectorUnitRange(s, r, b, offset) nondual_sector(sr::SectorUnitRange) = sr.nondual_sector multiplicity_range(sr::SectorUnitRange) = sr.multiplicity_range isdual(sr::SectorUnitRange) = sr.isdual -offset(sr::SectorUnitRange) = sr.offset +Base.first(sr::SectorUnitRange) = sr.offset # # Base interface @@ -32,10 +32,6 @@ Base.axes(sr::SectorUnitRange) = Base.oneto(length(sr)) Base.eachindex(sr::SectorUnitRange) = Base.oneto(length(sr)) -function Base.first(sr::SectorUnitRange) - return offset(sr) + length(nondual_sector(sr)) * (first(multiplicity_range(sr)) - 1) -end - Base.lastindex(sr::SectorUnitRange) = length(sr) function Base.length(sr::SectorUnitRange) @@ -57,14 +53,14 @@ end Base.getindex(sr::SectorUnitRange, t::Tuple{Colon,<:Integer}) = sr[(:, last(t):last(t))] function Base.getindex(sr::SectorUnitRange, t::Tuple{Colon,<:AbstractUnitRange}) return sectorunitrange( - nondual_sector(sr), multiplicity_range(sr)[last(t)], isdual(sr), offset(sr) + nondual_sector(sr), multiplicity_range(sr)[last(t)], isdual(sr), first(sr) ) end Base.range(sr::SectorUnitRange) = first(sr):last(sr) function Base.show(io::IO, sr::SectorUnitRange) - print(io, nameof(typeof(sr)), " ", offset(sr), " .+ ") + print(io, nameof(typeof(sr)), " ", first(sr), " .+ ") if isdual(sr) print(io, "dual(", nondual_sector(sr), ")") else @@ -82,19 +78,19 @@ end function dual(sr::SectorUnitRange) return sectorunitrange( - nondual_sector(sr), multiplicity_range(sr), !isdual(sr), offset(sr) + nondual_sector(sr), multiplicity_range(sr), !isdual(sr), first(sr) ) end function flip(sr::SectorUnitRange) return sectorunitrange( - dual(nondual_sector(sr)), multiplicity_range(sr), !isdual(sr), offset(sr) + dual(nondual_sector(sr)), multiplicity_range(sr), !isdual(sr), first(sr) ) end function map_blocklabels(f, sr::SectorUnitRange) return sectorunitrange( - f(nondual_sector(sr)), multiplicity_range(sr), isdual(sr), offset(sr) + f(nondual_sector(sr)), multiplicity_range(sr), isdual(sr), first(sr) ) end @@ -104,7 +100,7 @@ function space_isequal(sr1::SectorUnitRange, sr2::SectorUnitRange) return nondual_sector(sr1) == nondual_sector(sr2) && isdual(sr1) == isdual(sr2) && multiplicity_range(sr1) == multiplicity_range(sr2) && - offset(sr1) == offset(sr2) + first(sr1) == first(sr2) end # diff --git a/test/test_newgradedunitrange.jl b/test/test_newgradedunitrange.jl index 349cfc9..f93463a 100644 --- a/test/test_newgradedunitrange.jl +++ b/test/test_newgradedunitrange.jl @@ -62,7 +62,9 @@ Base.length(s::AbstractSector) = quantum_dimension(s) @test blockisequal(multiplicity_range(g2f), blockedrange([2, 1])) @test isdual(g2f) - @test_broken blockfirsts(g2) == first.(blocks(g2)) + @test blockfirsts(g2) == first.(blocks(g2)) + @test blocklasts(g2) == [6, 14] + @test space_isequal(mortar(blocks(g2)), g2) # slicing @test space_isequal(g2[Block.(1:2)], g2) diff --git a/test/test_sectorunitrange.jl b/test/test_sectorunitrange.jl index 9f7b7bd..9d64f86 100644 --- a/test/test_sectorunitrange.jl +++ b/test/test_sectorunitrange.jl @@ -10,7 +10,6 @@ using GradedUnitRanges: isdual, multiplicity_range, nondual_sector, - offset, sector_type, sectorunitrange, space_isequal @@ -30,7 +29,7 @@ Base.length(s::AbstractSector) = quantum_dimension(s) # accessors @test nondual_sector(sr) == SU((1, 0)) @test multiplicity_range(sr) == 2:3 - @test offset(sr) == 3 + @test first(sr) == 3 @test !isdual(sr) @test space_isequal( @@ -41,8 +40,7 @@ Base.length(s::AbstractSector) = quantum_dimension(s) @test length(sr) == 6 @test firstindex(sr) == 1 @test lastindex(sr) == 6 - @test first(sr) == 6 - @test last(sr) == 12 + @test last(sr) == 9 @test eltype(sr) === Int @test eachindex(sr) == Base.oneto(6) @@ -68,21 +66,23 @@ Base.length(s::AbstractSector) = quantum_dimension(s) @test nondual_sector(srd) == SU((1, 0)) @test blocklabels(srd) == [SU((1, 1))] @test multiplicity_range(srd) == 2:3 - @test offset(srd) == 3 + @test first(srd) == 3 @test isdual(srd) srf = flip(sr) @test nondual_sector(srf) == SU((1, 1)) @test blocklabels(srf) == [SU((1, 0))] @test multiplicity_range(srf) == 2:3 - @test offset(srf) == 3 + @test first(srf) == 3 @test isdual(srf) # getindex - for i in 1:6 - @test sr[i] == i + 5 + @test_throws BoundsError sr[0] + @test_throws BoundsError sr[8] + for i in 1:7 + @test sr[i] == i + 2 end - @test sr[2:3] == 7:8 + @test sr[2:3] == 4:5 @test sr[Block(1)] === sr @test_throws BlockBoundsError sr[Block(2)] From f61071604b554caa0a9547847b3e80c3c61de216 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Gauth=C3=A9?= Date: Tue, 28 Jan 2025 20:39:24 -0500 Subject: [PATCH 5/7] fix formatting --- src/sectorunitrange.jl | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/sectorunitrange.jl b/src/sectorunitrange.jl index 25b18ce..9432daa 100644 --- a/src/sectorunitrange.jl +++ b/src/sectorunitrange.jl @@ -77,9 +77,7 @@ function blocklabels(sr::SectorUnitRange) end function dual(sr::SectorUnitRange) - return sectorunitrange( - nondual_sector(sr), multiplicity_range(sr), !isdual(sr), first(sr) - ) + return sectorunitrange(nondual_sector(sr), multiplicity_range(sr), !isdual(sr), first(sr)) end function flip(sr::SectorUnitRange) From 8f5e081fc75ac5ec1a302c64f4d986045db2a9dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Gauth=C3=A9?= Date: Tue, 28 Jan 2025 20:44:37 -0500 Subject: [PATCH 6/7] remove offset --- test/test_newgradedunitrange.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/test/test_newgradedunitrange.jl b/test/test_newgradedunitrange.jl index f93463a..9c00a4c 100644 --- a/test/test_newgradedunitrange.jl +++ b/test/test_newgradedunitrange.jl @@ -13,7 +13,6 @@ using GradedUnitRanges: isdual, multiplicity_range, nondual_sector, - offset, sector_type, sectorunitrange, space_isequal From b900afc6a93bdff8a29573b735b1f052f3e1b75b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Gauth=C3=A9?= Date: Wed, 29 Jan 2025 12:00:36 -0500 Subject: [PATCH 7/7] fix last --- src/sectorunitrange.jl | 2 +- test/test_sectorunitrange.jl | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sectorunitrange.jl b/src/sectorunitrange.jl index 9432daa..66e1d53 100644 --- a/src/sectorunitrange.jl +++ b/src/sectorunitrange.jl @@ -41,7 +41,7 @@ end # TBD directly quantum_dimension(nondual_sector(sr))? Base.iterate(sr::SectorUnitRange) = iterate(first(sr):last(sr)) Base.iterate(sr::SectorUnitRange, i::Integer) = iterate(first(sr):last(sr), i) -Base.last(sr::SectorUnitRange) = first(sr) + length(sr) +Base.last(sr::SectorUnitRange) = first(sr) + length(sr) - 1 # slicing Base.getindex(sr::SectorUnitRange, i::Integer) = range(sr)[i] diff --git a/test/test_sectorunitrange.jl b/test/test_sectorunitrange.jl index 9d64f86..321f649 100644 --- a/test/test_sectorunitrange.jl +++ b/test/test_sectorunitrange.jl @@ -40,7 +40,7 @@ Base.length(s::AbstractSector) = quantum_dimension(s) @test length(sr) == 6 @test firstindex(sr) == 1 @test lastindex(sr) == 6 - @test last(sr) == 9 + @test last(sr) == 8 @test eltype(sr) === Int @test eachindex(sr) == Base.oneto(6) @@ -78,8 +78,8 @@ Base.length(s::AbstractSector) = quantum_dimension(s) # getindex @test_throws BoundsError sr[0] - @test_throws BoundsError sr[8] - for i in 1:7 + @test_throws BoundsError sr[7] + for i in 1:6 @test sr[i] == i + 2 end @test sr[2:3] == 4:5