Skip to content

Commit d38252f

Browse files
authored
Fix indexing for tensorizers (#354)
* fix indexing for tensorizers * remove findfirst for AbstractFill tensorizer
1 parent 7a137ac commit d38252f

File tree

5 files changed

+51
-30
lines changed

5 files changed

+51
-30
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "ApproxFunBase"
22
uuid = "fbd15aa5-315a-5a7d-a8a4-24992e37be05"
3-
version = "0.7.62"
3+
version = "0.7.63"
44

55
[deps]
66
AbstractFFTs = "621f4979-c628-5d54-868e-fcf4e3e8185c"

src/LinearAlgebra/helper.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,7 @@ function resize!(it::CachedIterator,n::Integer)
569569
end
570570

571571

572-
eltype(it::CachedIterator{T}) where {T} = T
572+
eltype(it::Type{<:CachedIterator{T}}) where {T} = T
573573

574574
iterate(it::CachedIterator) = iterate(it,1)
575575
function iterate(it::CachedIterator,st::Int)
@@ -696,9 +696,9 @@ end
696696

697697
const TrivialInterlacer{d} = BlockInterlacer{<:NTuple{d,Ones}}
698698

699-
BlockInterlacer(v::AbstractVector) = BlockInterlacer(tuple(v...))
699+
BlockInterlacer(v::AbstractVector) = BlockInterlacer(Tuple(v))
700700

701-
Base.eltype(it::BlockInterlacer) = Tuple{Int,Int}
701+
eltype(::Type{<:BlockInterlacer}) = Tuple{Int,Int}
702702

703703
dimensions(b::BlockInterlacer) = map(sum,b.blocks)
704704
dimension(b::BlockInterlacer,k) = sum(b.blocks[k])

src/Multivariate/TensorSpace.jl

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,11 @@ end
2727
const Tensorizer2D{AA, BB} = Tensorizer{Tuple{AA, BB}}
2828
const TrivialTensorizer{d} = Tensorizer{NTuple{d,Ones{Int,1,Tuple{OneToInf{Int}}}}}
2929

30-
Base.eltype(a::Tensorizer) = NTuple{length(a.blocks),Int}
31-
Base.eltype(::Tensorizer{<:NTuple{d}}) where {d} = NTuple{d,Int}
30+
eltype(::Type{<:Tensorizer{<:Tuple{Vararg{Any,N}}}}) where {N} = NTuple{N,Int}
3231
dimensions(a::Tensorizer) = map(sum,a.blocks)
3332
Base.length(a::Tensorizer) = mapreduce(sum,*,a.blocks)
3433

34+
Base.keys(a::Tensorizer) = oneto(length(a))
3535

3636
function start(a::TrivialTensorizer{d}) where {d}
3737
# ((block_dim_1, block_dim_2,...), (itaration_number, iterator, iterator_state)), (itemssofar, length)
@@ -131,21 +131,32 @@ function Base.findfirst(::TrivialTensorizer{2},kj::Tuple{Int,Int})
131131
n=k+j-2
132132
(n*(n+1))÷2+k
133133
else
134-
0
134+
nothing
135135
end
136136
end
137-
138-
function Base.findfirst(sp::Tensorizer{Tuple{<:AbstractFill{S},<:AbstractFill{T}}},kj::Tuple{Int,Int}) where {S,T}
137+
function Base.findfirst(sp::Tensorizer{<:NTuple{2,Ones{Int}}}, kj::NTuple{2,Int})
139138
k,j=kj
140139

141-
if k > 0 && j > 0
142-
a,b = getindex_value(sp.blocks[1]),getindex_value(sp.blocks[2])
143-
kb1,kr = fldmod(k-1,a)
144-
jb1,jr = fldmod(j-1,b)
145-
nb=kb1+jb1
146-
a*b*(nb*(nb+1)÷2+kb1)+a*jr+kr+1
140+
len1, len2 = length(sp.blocks[1]), length(sp.blocks[2])
141+
if 0 < k <= len1 && 0 < j <= len2
142+
kb1 = k-1
143+
jb1 = j-1
144+
nb=kb1+jb1+1
145+
# Fully filled blocks, that go from (1,n) to (n,1)
146+
nb_full = min(nb-1, len2)
147+
ind = nb_full*(nb_full+1)÷2
148+
# Number of partially filled blocks, that is blocks where `a` in (`a`,`b`) doesn't start at 1
149+
# This happens when `b` in a block starts from `length(sp.blocks[2])` and `a` starts from > 1
150+
nb_part = nb - nb_full - 1
151+
if nb_part > 0
152+
ind -= nb_part * (1 - 2nb_full + nb_part) ÷ 2
153+
end
154+
sum12 = nb + 1 # a + b where the element is (a,b)
155+
start2 = min(nb, len2) # the second element is bound by the number of blocks
156+
nel_block = start2 - j + 1 # the second index decreases
157+
ind += nel_block
147158
else
148-
0
159+
nothing
149160
end
150161
end
151162

@@ -186,23 +197,12 @@ blocklengths(it::Tensorizer) = tensorblocklengths(it.blocks...)
186197
blocklengths(it::CachedIterator) = blocklengths(it.iterator)
187198

188199
function getindex(it::TrivialTensorizer{2},n::Integer)
189-
m=block(it,n)
200+
m=Int(block(it,n))
190201
p=findfirst(it,(1,m))
191202
j=1+n-p
192203
j,m-j+1
193204
end
194205

195-
# could be cleaned up using blocks
196-
function getindex(it::Tensorizer{<:Tuple{<:AbstractFill{S},<:AbstractFill{T}}},n::Integer) where {S,T}
197-
a,b = getindex_value(it.blocks[1]),getindex_value(it.blocks[2])
198-
nb1,nr = fldmod(n-1,a*b) # nb1 = "nb" - 1, i.e. using zero-base
199-
m1=block(it,n).n[1]-1
200-
pb1=fld(findfirst(it,(1,b*m1+1))-1,a*b)
201-
jb1=nb1-pb1
202-
kr1,jr1 = fldmod(nr,a)
203-
b*jb1+jr1+1,a*(m1-jb1)+kr1+1
204-
end
205-
206206

207207
blockstart(it,K)::Int = K==1 ? 1 : sum(blocklengths(it)[1:K-1])+1
208208
blockstop(it,::PosInfinity) = ℵ₀

src/Operators/Operator.jl

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@ abstract type Operator{T} end #T is the entry type, Float64 or Complex{Float64}
1717
const VectorOrTupleOfOp{O<:Operator} = Union{AbstractVector{O}, Tuple{O, Vararg{O}}}
1818
const ArrayOrTupleOfOp{O<:Operator} = Union{AbstractArray{O}, Tuple{O, Vararg{O}}}
1919

20-
eltype(::Operator{T}) where {T} = T
2120
eltype(::Type{<:Operator{T}}) where {T} = T
22-
eltype(::Type{OT}) where {OT<:Operator} = eltype(supertype(OT))
2321

2422
promote_eltypeof(As::ArrayOrTupleOfOp{<:Operator{T}}) where {T} = T
2523

test/runtests.jl

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ using ApproxFunBase: ∞
33
using Aqua
44
using SpecialFunctions
55
using BandedMatrices
6+
using FillArrays
67

78
@testset "Project quality" begin
89
Aqua.test_all(ApproxFunBase, ambiguities=false)
@@ -475,5 +476,27 @@ end
475476
@test all(iszero, B)
476477
end
477478

479+
@testset "Tensorizer" begin
480+
@testset "TrivialTensorizer" begin
481+
ax = Ones{Int}(∞)
482+
t = ApproxFunBase.Tensorizer((ax,ax))
483+
v = collect(Iterators.take(t, 15))
484+
@test eltype(v) == eltype(t)
485+
@testset for (i, vi) in enumerate(v)
486+
@test vi == t[i]
487+
@test findfirst(t, vi) == i
488+
end
489+
end
490+
@testset "Tensorizer2D" begin
491+
ax = Ones{Int}(4)
492+
t = ApproxFunBase.Tensorizer((ax,ax))
493+
v = collect(Iterators.take(t, 15))
494+
@test eltype(v) == eltype(t)
495+
@testset for (i, vi) in enumerate(v)
496+
@test findfirst(t, vi) == i
497+
end
498+
end
499+
end
500+
478501
@time include("ETDRK4Test.jl")
479502
include("show.jl")

0 commit comments

Comments
 (0)