Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ InfiniteArraysStatisticsExt = "Statistics"
[compat]
Aqua = "0.8"
ArrayLayouts = "1.8"
BandedMatrices = "1.7.6"
BandedMatrices = "1.11"
Base64 = "1"
BlockArrays = "1.0"
BlockBandedMatrices = "0.13"
Expand Down
3 changes: 2 additions & 1 deletion src/InfiniteArrays.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)

Expand Down
168 changes: 168 additions & 0 deletions src/biinfrange.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
"""
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, ::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
n = 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



function Base._print_matrix(io, @nospecialize(X::AbstractVecOrMat), pre, sep, post, hdots, vdots, ddots, hmod, vmod, ::BiInfUnitRange, ::BiInfUnitRange)
hmod, vmod = Int(hmod)::Int, Int(vmod)::Int
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

# 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

halfmaxpossiblecols = div(screenwidth, 4*(1+sepsize))
maxpossiblecols = 2halfmaxpossiblecols + 1
colsA = -halfmaxpossiblecols:halfmaxpossiblecols

A = alignment(io, X, rowsA, colsA, screenwidth, screenwidth, sepsize, ℵ₀)
c = div(screenwidth-length(hdots)::Int+1,2)+1
Ralign = reverse(alignment(io, X, rowsA, reverse(colsA), c, c, sepsize, ℵ₀))
c = screenwidth - sum(map(sum,Ralign)) - (length(Ralign)-1)*sepsize - length(hdots)::Int
Lalign = alignment(io, X, rowsA, colsA, c, c, sepsize, ℵ₀)
r = 1 # where to put dots on right half

for i in rowsA
if i == rowsA[1]
print(io, i == first(rowsA) ? pre : presp)
print_matrix_vdots(io, vdots, Lalign, sep, vmod, 1, true)
print(io, ddots)
print(io, i == last(rowsA) ? post : postsp * '\n')
end

print(io, i == first(rowsA) ? pre : presp)
print_matrix_row(io, X,Lalign,i,colsA,sep,ℵ₀)
print(io, (i - first(rowsA)) % hmod == 0 ? hdots : repeat(" ", length(hdots)::Int))
# print_matrix_row(io, X,Ralign,i,colsA,sep,ℵ₀)
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(io, i == last(rowsA) ? post : postsp * '\n')
end
end
if isempty(rowsA)
print(io, pre)
print(io, vdots)
length(colsA) > 1 && print(io, " ", ddots)
print(io, post)
end
end
1 change: 1 addition & 0 deletions src/infrange.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
7 changes: 6 additions & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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")
9 changes: 9 additions & 0 deletions test/test_biinfrange.jl
Original file line number Diff line number Diff line change
@@ -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
Loading