diff --git a/src/InfiniteArrays.jl b/src/InfiniteArrays.jl index 5181e74..11bcb60 100644 --- a/src/InfiniteArrays.jl +++ b/src/InfiniteArrays.jl @@ -14,7 +14,7 @@ import Base: *, +, -, /, <, ==, >, \, ≤, ≥, (:), @propagate_inbounds, searchsortedfirst, searchsortedlast, setindex!, show, show_circular, show_delim_array, sign, signbit, similar, size, sort, sort!, step, sum, tail, to_shape, transpose, unaliascopy, union, unitrange_last, unsafe_convert, unsafe_indices, unsafe_length, - vcat, zeros, copyto!, range_start_step_length + vcat, zeros, copyto!, range_start_step_length, undef_ref_str, alignment if VERSION ≥ v"1.11.0-DEV.21" using LinearAlgebra: UpperOrLowerTriangular @@ -204,6 +204,7 @@ end return LazyArrays.searchsortedlast_recursive(n, x, args...) end +include("biinfrange.jl") collect(G::Base.Generator{<:InfRanges}) = BroadcastArray(G.f, G.iter) diff --git a/src/biinfrange.jl b/src/biinfrange.jl new file mode 100644 index 0000000..8647741 --- /dev/null +++ b/src/biinfrange.jl @@ -0,0 +1,102 @@ +""" +BiInfUnitRange() + +Represent -∞:∞ with offset indexing +""" +struct BiInfUnitRange{T<:Real} <: AbstractInfUnitRange{T} end + +BiInfUnitRange() = BiInfUnitRange{Int}() + +AbstractArray{T}(a::BiInfUnitRange) where T<:Real = BiInfUnitRange{T}(a) +AbstractVector{T}(a::BiInfUnitRange) where T<:Real = BiInfUnitRange{T}(a) + +unitrange(a::BiInfUnitRange) = a +Base.has_offset_axes(::BiInfUnitRange) = true + +getindex(v::BiInfUnitRange{T}, i::Integer) where T = convert(T, i) +getindex(v::BiInfUnitRange{T}, i::RealInfinity) where T = i +axes(::BiInfUnitRange) = (BiInfUnitRange(),) +first(::BiInfUnitRange) = -∞ +show(io::IO, ::BiInfUnitRange{Int}) = print(io, "BiInfUnitRange()") + +getindex(r::BiInfUnitRange{T}, s::AbstractUnitRange{<:Integer}) where T = convert(AbstractVector{T}, s) + + + +function Base._print_matrix(io, @nospecialize(X::AbstractVecOrMat), pre, sep, post, hdots, vdots, ddots, hmod, vmod, rowsA::BiInfUnitRange, colsA) + hmod, vmod = Int(hmod)::Int, Int(vmod)::Int + ncols, idxlast = length(colsA), last(colsA) + if !(get(io, :limit, false)::Bool) + screenheight = screenwidth = typemax(Int) + else + sz = displaysize(io)::Tuple{Int,Int} + screenheight, screenwidth = sz[1] - 4, sz[2] + end + screenwidth -= length(pre)::Int + length(post)::Int + presp = repeat(" ", length(pre)::Int) # indent each row to match pre string + postsp = "" + @assert textwidth(hdots) == textwidth(ddots) + sepsize = length(sep)::Int + m, n = length(rowsA), length(colsA) + # To figure out alignments, only need to look at as many rows as could + # fit down screen. If screen has at least as many rows as A, look at A. + # If not, then we only need to look at the first and last chunks of A, + # each half a screen height in size. + quarterheight = div(screenheight,4) + halfheight = 2quarterheight+1 + rowsA = -quarterheight:quarterheight + # Similarly for columns, only necessary to get alignments for as many + # columns as could conceivably fit across the screen + maxpossiblecols = div(screenwidth, 1+sepsize) + if n > maxpossiblecols + colsA = [colsA[(0:maxpossiblecols-1) .+ firstindex(colsA)]; colsA[(end-maxpossiblecols+1):end]] + else + colsA = [colsA;] + end + A = alignment(io, X, rowsA, colsA, screenwidth, screenwidth, sepsize, ncols) + # Nine-slicing is accomplished using print_matrix_row repeatedly + if n <= length(A) # rows don't fit, cols do, so only vertical ellipsis + print_matrix_vdots(io, vdots, A, sep, vmod, 1, false) + print(io, postsp * '\n') + for i in rowsA + print(io, i == first(rowsA) ? pre : presp) + i == 0 && print(io, "\e[1m") + print_matrix_row(io, X,A,i,colsA,sep,idxlast) + i == 0 && print(io, "\e[0m") + print(io, i == last(rowsA) ? post : postsp) + if i != rowsA[end] || i == rowsA[halfheight]; println(io); end + if i == rowsA[halfheight] + print(io, i == first(rowsA) ? pre : presp) + print_matrix_vdots(io, vdots, A, sep, vmod, 1, false) + print(io, i == last(rowsA) ? post : postsp * '\n') + end + end + else # neither rows nor cols fit, so use all 3 kinds of dots + c = div(screenwidth-length(hdots)::Int+1,2)+1 + Ralign = reverse(alignment(io, X, rowsA, reverse(colsA), c, c, sepsize, ncols)) + c = screenwidth - sum(map(sum,Ralign)) - (length(Ralign)-1)*sepsize - length(hdots)::Int + Lalign = alignment(io, X, rowsA, colsA, c, c, sepsize, ncols) + r = mod((length(Ralign)-n+1),vmod) # where to put dots on right half + for i in rowsA + print(io, i == first(rowsA) ? pre : presp) + print_matrix_row(io, X,Lalign,i,colsA[1:length(Lalign)],sep,idxlast) + print(io, (i - first(rowsA)) % hmod == 0 ? hdots : repeat(" ", length(hdots)::Int)) + print_matrix_row(io, X,Ralign,i,(n-length(Ralign)).+colsA,sep,idxlast) + print(io, i == last(rowsA) ? post : postsp) + if i != rowsA[end] || i == rowsA[halfheight]; println(io); end + if i == rowsA[halfheight] + print(io, i == first(rowsA) ? pre : presp) + print_matrix_vdots(io, vdots, Lalign, sep, vmod, 1, true) + print(io, ddots) + print_matrix_vdots(io, vdots, Ralign, sep, vmod, r, false) + print(io, i == last(rowsA) ? post : postsp * '\n') + end + end + end + if isempty(rowsA) + print(io, pre) + print(io, vdots) + length(colsA) > 1 && print(io, " ", ddots) + print(io, post) + end +end diff --git a/src/infrange.jl b/src/infrange.jl index b551551..61ea4c1 100644 --- a/src/infrange.jl +++ b/src/infrange.jl @@ -29,6 +29,7 @@ _range(a::Real, ::Nothing, ::Nothing, len::InfiniteCardinal{0}) _range(a::AbstractFloat, ::Nothing, ::Nothing, len::InfiniteCardinal{0}) = _range(a, oftype(a, 1), nothing, len) _range(a::T, st::T, ::Nothing, ::InfiniteCardinal{0}) where T<:IEEEFloat = InfStepRange{T,T}(a, st) _range(a::T, st::T, ::Nothing, ::InfiniteCardinal{0}) where T<:AbstractFloat = InfStepRange{T,T}(a, st) +_range(a::Infinities.AllInfinities, ::Nothing, ::Nothing, length::Int) = Fill(a, length) range_start_step_length(a, st, ::InfiniteCardinal{0}) = InfStepRange(a, st) range_start_step_length(a::Real, st::IEEEFloat, len::InfiniteCardinal{0}) = range_start_step_length(promote(a, st)..., len) range_start_step_length(a::IEEEFloat, st::Real, len::InfiniteCardinal{0}) = range_start_step_length(promote(a, st)..., len) diff --git a/test/runtests.jl b/test/runtests.jl index cdeebe4..268a28a 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -564,6 +564,10 @@ end @test_throws ArgumentError [1:∞; [1.0]; 1:∞] @test_throws ArgumentError [1:∞; 1; [1]] end + + @testset "range from ∞" begin + @test range(ℵ₀; length=5) ≡ Fill(ℵ₀, 5) + end end @testset "fill" begin @@ -1296,7 +1300,8 @@ end @test !checkbounds(Bool, r, Fill(true, 1)) end +include("test_biinfrange.jl") include("test_infconv.jl") include("test_infblock.jl") include("test_infbanded.jl") -include("test_infblockbanded.jl") +include("test_infblockbanded.jl") \ No newline at end of file diff --git a/test/test_biinfrange.jl b/test/test_biinfrange.jl new file mode 100644 index 0000000..c8b7ded --- /dev/null +++ b/test/test_biinfrange.jl @@ -0,0 +1,9 @@ +using InfiniteArrays, Base64, Test +using InfiniteArrays: BiInfUnitRange + +@testset "-∞:∞" begin + r = BiInfUnitRange() + @test stringmime("text/plain", r) == "BiInfUnitRange()" + @test Fill(1, (r,))[-5] == 1 + @test exp.(r)[-3] == exp(-3) +end \ No newline at end of file