-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathdrawTruncNormal.m
55 lines (40 loc) · 1.11 KB
/
drawTruncNormal.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
function ydraw = drawTruncNormal(mu,sqrtVCV,elb,rndStream)
% generates 1 draw from truncated scalar normal N(mu, sqrtVCV * sqrtVCV')
% subject to ydraws <= elb
% returns scalar ydraws
%
% Coded by Elmar Mertens, em@elmarmertens.com
if ~isscalar(mu) && ~isscalar(sqrtVCV)
error('this function is for scalars only')
end
if nargin < 4
rndStream = getDefaultStream;
end
if isnumeric(rndStream)
udraw = rndStream;
else
udraw = rand(rndStream);
end
tol = 1e-10; % to decide when sqrtVCV diagonals are zero
N = 1;
if N ~= length(mu)
error('dimension mismatch')
end
% make sure that sqrtVCV has positive diagonals
% (sqrt factors obtained from QR can have negative diagonals, for example)
sqrtVCV = abs(sqrtVCV);
thismu = mu;
if sqrtVCV > tol
ub = (elb - thismu) ./ sqrtVCV;
% PHIbar = normcdf(ub);
PHIbar = 0.5 * erfc(- sqrt(0.5) * ub);
% zdraw = norminv(udraw * PHIbar);
if PHIbar > eps
zdraw = -sqrt(2) * erfcinv(2 * udraw * PHIbar);
else
zdraw = ub;
end
ydraw = thismu + sqrtVCV * zdraw;
else
ydraw = thismu;
end