@@ -78,3 +78,69 @@ function Base.rand!(out::AbstractArray{T}, d::DiscreteRV) where T<:Integer
7878end
7979
8080@deprecate draw Base. rand
81+
82+
83+ struct MVDiscreteRV{TV1<: AbstractArray ,TV2<: AbstractVector ,K,TI<: Integer }
84+ q:: TV1
85+ Q:: TV2
86+ dims:: NTuple{K,TI}
87+
88+ function MVDiscreteRV {TV1,TV2,K,TI} (q:: TV1 , Q:: TV2 , dims:: NTuple{K,TI} ) where {TV1,TV2,K,TI}
89+ abs (sum (q) - 1.0 ) > 1e-10 && error (" q should sum to 1" )
90+ abs (Q[end ] - 1.0 ) > 1e-10 && error (" Q[end] should be 1" )
91+ length (Q) != prod (dims) && error (" Number of elements is inconsistent" )
92+
93+ new {TV1,TV2,K,TI} (q, Q, dims)
94+ end
95+ end
96+
97+
98+ function MVDiscreteRV (q:: TV1 ) where TV1<: AbstractArray
99+ Q = cumsum (vec (q))
100+ dims = size (q)
101+
102+ return MVDiscreteRV {typeof(q),typeof(Q),length(dims),eltype(dims)} (q, Q, dims)
103+ end
104+
105+
106+ """
107+ Make a single draw from the multivariate discrete distribution.
108+
109+ ##### Arguments
110+
111+ - `d::MVDiscreteRV`: The `MVDiscreteRV` type represetning the distribution
112+
113+ ##### Returns
114+
115+ - `out::NTuple{Int}`: One draw from the discrete distribution
116+ """
117+ function Base. rand (d:: MVDiscreteRV )
118+ x = rand ()
119+ i = searchsortedfirst (d. Q, x)
120+
121+ return ind2sub (d. dims, i)
122+ end
123+
124+ """
125+ Make multiple draws from the discrete distribution represented by a
126+ `MVDiscreteRV` instance
127+
128+ ##### Arguments
129+
130+ - `d::MVDiscreteRV`: The `DiscreteRV` type representing the distribution
131+ - `k::Int`
132+
133+ ##### Returns
134+
135+ - `out::Vector{NTuple{Int}}`: `k` draws from `d`
136+ """
137+ Base. rand (d:: MVDiscreteRV{T1,T2,K,TI} , k:: V ) where {T1,T2,K,TI,V} =
138+ NTuple{K,TI}[rand (d) for i in 1 : k]
139+
140+ function Base. rand! (out:: AbstractArray{NTuple{K,TI}} , d:: MVDiscreteRV ) where {K,TI}
141+ @inbounds for I in eachindex (out)
142+ out[I] = rand (d)
143+ end
144+
145+ return out
146+ end
0 commit comments