InfiniteArrays.jl
InfiniteArrays.jl copied to clipboard
Infinite random sequence
Hello,
I don't know whether this is possible (it is in Haskell) nor whether this would fit the scope of this library but infinite random sequences would be a nice feature.
Cheers.
I agree. This should be pretty easy to implement as <: AbstractCachedArray, by storing the seed for the last computed entry.
alternatively one could make it completely unallocating by only storing the seed for the first entry, though this will make getindex slow
Did this ever get implemented anywhere? Something like
using LazyArrays: LazyArrays, AbstractCachedVector
using Random
using InfiniteArrays
mutable struct InfRandVector{T,RNG} <: AbstractCachedVector{T}
const rng::RNG
const data::Vector{T}
datasize::Int
end
InfRandVector{T}(rng::RNG) where {T, RNG} = (_rng = copy(rng); InfRandVector{T,typeof(_rng)}(_rng, T[], 0)) # copy(rng) can have different type to rng
function InfRandVector(rng::RNG=Random.default_rng()) where {RNG}
_rng = copy(rng) # don't disrupt seed
T = typeof(rand(_rng))
return InfRandVector{T}(rng)
end
Base.size(::InfRandVector) = ℵ₀
Base.axes(::InfRandVector) = (1:ℵ₀,)
Base.length(::InfRandVector) = ℵ₀
function LazyArrays.resizedata!(seq::InfRandVector{T}, inds) where {T}
newlen = maximum(inds)
curlen = length(seq.data)
newlen > curlen || return seq
resize!(seq.data, newlen)
# rand!(seq.rng, view(seq.data, curlen+1:newlen), T)
# ^ rand() is not actually sequential.. rand(Random.seed!(123), 1000) ≠ (rng = Random.seed!(123); [rand(rng) for _ in 1:1000])
for i in (curlen+1):newlen
seq.data[i] = rand(seq.rng, T)
end
seq.datasize = newlen
return seq
end
using Test
seq = InfRandVector(Random.seed!(Random.default_rng(), 123))
@test seq[1] == seq[1]
val = seq[1]
@test seq[1:10000] == seq[1:10000]
@test seq[1] == val # didn't change after resizing
@inferred seq[1]
rng = Random.seed!(123)
_seq = [rand(rng) for _ in 1:1000]
@test _seq[1:1000] == seq[1:1000]
seems to work.