Skip to content

Commit 255f641

Browse files
authored
specialize sum for FillArrays (#182)
* specialize sum for FillArrays * fix namespace issue * define InfiniteArrays in-house * move infinitearrays to its own file * test for sum with map * compare map with broadcasting
1 parent d19b7ec commit 255f641

File tree

4 files changed

+78
-1
lines changed

4 files changed

+78
-1
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "FillArrays"
22
uuid = "1a297f60-69ca-5386-bcde-b61e274b549b"
3-
version = "0.13.3"
3+
version = "0.13.4"
44

55
[deps]
66
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"

src/FillArrays.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,9 @@ end
515515
# Cumsum
516516
#########
517517

518+
# These methods are necessary to deal with infinite arrays
519+
sum(x::AbstractFill) = getindex_value(x)*length(x)
520+
sum(f, x::AbstractFill) = length(x) * f(getindex_value(x))
518521
sum(x::Zeros) = getindex_value(x)
519522

520523
cumsum(x::AbstractFill{<:Any,1}) = range(getindex_value(x); step=getindex_value(x),

test/infinitearrays.jl

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Infinite Arrays implementation from
2+
# https://github.com/JuliaLang/julia/blob/master/test/testhelpers/InfiniteArrays.jl
3+
module InfiniteArrays
4+
export OneToInf, Infinity
5+
6+
"""
7+
Infinity()
8+
Represents infinite cardinality. Note that `Infinity <: Integer` to support
9+
being treated as an index.
10+
"""
11+
struct Infinity <: Integer end
12+
13+
Base.:(==)(::Infinity, ::Int) = false
14+
Base.:(==)(::Int, ::Infinity) = false
15+
Base.:(<)(::Int, ::Infinity) = true
16+
Base.:(<)(::Infinity, ::Int) = false
17+
Base.:()(::Int, ::Infinity) = true
18+
Base.:()(::Infinity, ::Int) = false
19+
Base.:()(::Infinity, ::Infinity) = true
20+
Base.:(-)(::Infinity, ::Int) = Infinity()
21+
Base.:(+)(::Infinity, ::Int) = Infinity()
22+
Base.:(:)(::Infinity, ::Infinity) = 1:0
23+
24+
Base.:(+)(::Integer, ::Infinity) = Infinity()
25+
Base.:(+)(::Infinity, ::Integer) = Infinity()
26+
Base.:(*)(::Integer, ::Infinity) = Infinity()
27+
Base.:(*)(::Infinity, ::Integer) = Infinity()
28+
29+
Base.isinf(::Infinity) = true
30+
31+
abstract type AbstractInfUnitRange{T<:Real} <: AbstractUnitRange{T} end
32+
Base.length(r::AbstractInfUnitRange) = Infinity()
33+
Base.size(r::AbstractInfUnitRange) = (Infinity(),)
34+
Base.unitrange(r::AbstractInfUnitRange) = InfUnitRange(r)
35+
Base.last(r::AbstractInfUnitRange) = Infinity()
36+
Base.axes(r::AbstractInfUnitRange) = (OneToInf(),)
37+
38+
"""
39+
OneToInf(n)
40+
Define an `AbstractInfUnitRange` that behaves like `1:∞`, with the added
41+
distinction that the limits are guaranteed (by the type system) to
42+
be 1 and ∞.
43+
"""
44+
struct OneToInf{T<:Integer} <: AbstractInfUnitRange{T} end
45+
46+
OneToInf() = OneToInf{Int}()
47+
48+
Base.axes(r::OneToInf) = (r,)
49+
Base.first(r::OneToInf{T}) where {T} = oneunit(T)
50+
Base.oneto(::Infinity) = OneToInf()
51+
52+
struct InfUnitRange{T<:Real} <: AbstractInfUnitRange{T}
53+
start::T
54+
end
55+
Base.first(r::InfUnitRange) = r.start
56+
InfUnitRange(a::InfUnitRange) = a
57+
InfUnitRange{T}(a::AbstractInfUnitRange) where T<:Real = InfUnitRange{T}(first(a))
58+
InfUnitRange(a::AbstractInfUnitRange{T}) where T<:Real = InfUnitRange{T}(first(a))
59+
unitrange(a::AbstractInfUnitRange) = InfUnitRange(a)
60+
Base.:(:)(start::T, stop::Infinity) where {T<:Integer} = InfUnitRange{T}(start)
61+
function getindex(v::InfUnitRange{T}, i::Integer) where T
62+
@boundscheck i > 0 || Base.throw_boundserror(v, i)
63+
convert(T, first(v) + i - 1)
64+
end
65+
end

test/runtests.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using FillArrays, LinearAlgebra, SparseArrays, StaticArrays, Random, Base64, Test, Statistics
22
import FillArrays: AbstractFill, RectDiagonal, SquareEye
33

4+
include("infinitearrays.jl")
5+
46
@testset "fill array constructors and convert" begin
57
for (Typ, funcs) in ((:Zeros, :zeros), (:Ones, :ones))
68
@eval begin
@@ -620,6 +622,13 @@ end
620622
@test diff(Fill(1,10)) Zeros{Int}(9)
621623
@test diff(Ones{Float64}(10)) Zeros{Float64}(9)
622624
@test_throws UndefKeywordError cumsum(Fill(1,1,5))
625+
626+
@testset "infinite arrays" begin
627+
A = Ones{Int}((InfiniteArrays.OneToInf(),))
628+
@test isinf(sum(A))
629+
@test sum(A) == length(A)
630+
@test sum(x->x^2, A) == sum(A.^2)
631+
end
623632
end
624633

625634
@testset "Broadcast" begin

0 commit comments

Comments
 (0)