Skip to content

Commit 79dbbbe

Browse files
authored
Merge branch 'fortran-lang:master' into iterative
2 parents 724289f + 3d0243e commit 79dbbbe

File tree

6 files changed

+442
-130
lines changed

6 files changed

+442
-130
lines changed

doc/specs/stdlib_stats_distribution_exponential.md

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,29 @@ Experimental
1515
### Description
1616

1717
An exponential distribution is the distribution of time between events in a Poisson point process.
18-
The inverse scale parameter `lambda` specifies the average time between events (\(\lambda\)), also called the rate of events.
18+
The inverse `scale` parameter `lambda` specifies the average time between events (\(\lambda\)), also called the rate of events. The location `loc` specifies the value by which the distribution is shifted.
1919

20-
Without argument, the function returns a random sample from the standard exponential distribution \(E(\lambda=1)\).
20+
Without argument, the function returns a random sample from the unshifted standard exponential distribution \(E(\lambda=1)\) or \(E(loc=0, scale=1)\).
2121

22-
With a single argument, the function returns a random sample from the exponential distribution \(E(\lambda=\text{lambda})\).
22+
With a single argument of type `real`, the function returns a random sample from the exponential distribution \(E(\lambda=\text{lambda})\).
2323
For complex arguments, the real and imaginary parts are sampled independently of each other.
2424

25-
With two arguments, the function returns a rank-1 array of exponentially distributed random variates.
25+
With one argument of type `real` and one argument of type `integer`, the function returns a rank-1 array of exponentially distributed random variates for (E(\lambda=\text{lambda})\).
26+
27+
With two arguments of type `real`, the function returns a random sample from the exponential distribution \(E(loc=loc, scale=scale)\).
28+
For complex arguments, the real and imaginary parts are sampled independently of each other.
29+
30+
With two arguments of type `real` and one argument of type `integer`, the function returns a rank-1 array of exponentially distributed random variates for \(E(loc=loc, scale=scale)\).
2631

2732
@note
2833
The algorithm used for generating exponential random variates is fundamentally limited to double precision.[^1]
2934

3035
### Syntax
3136

37+
`result = ` [[stdlib_stats_distribution_exponential(module):rvs_exp(interface)]] `([loc, scale] [[, array_size]])`
38+
39+
or
40+
3241
`result = ` [[stdlib_stats_distribution_exponential(module):rvs_exp(interface)]] `([lambda] [[, array_size]])`
3342

3443
### Class
@@ -40,13 +49,21 @@ Elemental function
4049
`lambda`: optional argument has `intent(in)` and is a scalar of type `real` or `complex`.
4150
If `lambda` is `real`, its value must be positive. If `lambda` is `complex`, both the real and imaginary components must be positive.
4251

52+
`loc`: optional argument has `intent(in)` and is a scalar of type `real` or `complex`.
53+
54+
`scale`: optional argument has `intent(in)` and is a positive scalar of type `real` or `complex`.
55+
If `scale` is `real`, its value must be positive. If `scale` is `complex`, both the real and imaginary components must be positive.
56+
4357
`array_size`: optional argument has `intent(in)` and is a scalar of type `integer` with default kind.
4458

4559
### Return value
4660

47-
The result is a scalar or rank-1 array with a size of `array_size`, and the same type as `lambda`.
61+
If `lambda` is passed, the result is a scalar or rank-1 array with a size of `array_size`, and the same type as `lambda`.
4862
If `lambda` is non-positive, the result is `NaN`.
4963

64+
If `loc` and `scale` are passed, the result is a scalar or rank-1 array with a size of `array_size`, and the same type as `scale`.
65+
If `scale` is non-positive, the result is `NaN`.
66+
5067
### Example
5168

5269
```fortran
@@ -69,8 +86,14 @@ For a complex variable \(z=(x + y i)\) with independent real \(x\) and imaginary
6986

7087
$$f(x+\mathit{i}y)=f(x)f(y)=\begin{cases} \lambda_{x} \lambda_{y} e^{-(\lambda_{x} x + \lambda_{y} y)} &x\geqslant 0, y\geqslant 0 \\\\ 0 &\text{otherwise}\end{cases}$$
7188

89+
Instead of of the inverse scale parameter `lambda`, it is possible to pass `loc` and `scale`, where \(scale = \frac{1}{\lambda}\) and `loc` specifies the value by which the distribution is shifted.
90+
7291
### Syntax
7392

93+
`result = ` [[stdlib_stats_distribution_exponential(module):pdf_exp(interface)]] `(x, loc, scale)`
94+
95+
or
96+
7497
`result = ` [[stdlib_stats_distribution_exponential(module):pdf_exp(interface)]] `(x, lambda)`
7598

7699
### Class
@@ -84,11 +107,17 @@ Elemental function
84107
`lambda`: has `intent(in)` and is a scalar of type `real` or `complex`.
85108
If `lambda` is `real`, its value must be positive. If `lambda` is `complex`, both the real and imaginary components must be positive.
86109

110+
`loc`: has `intent(in)` and is a scalar of type `real` or `complex`.
111+
112+
`scale`: has `intent(in)` and is a positive scalar of type `real` or `complex`.
113+
If `scale` is `real`, its value must be positive. If `scale` is `complex`, both the real and imaginary components must be positive.
114+
87115
All arguments must have the same type.
88116

89117
### Return value
90118

91-
The result is a scalar or an array, with a shape conformable to the arguments, and the same type as the input arguments. If `lambda` is non-positive, the result is `NaN`.
119+
The result is a scalar or an array, with a shape conformable to the arguments, and the same type as the input arguments. If non-positive `lambda` or `scale`, the result is `NaN`.
120+
92121

93122
### Example
94123

@@ -112,8 +141,14 @@ For a complex variable \(z=(x + y i)\) with independent real \(x\) and imaginar
112141

113142
$$F(x+\mathit{i}y)=F(x)F(y)=\begin{cases} (1 - e^{-\lambda_{x} x})(1 - e^{-\lambda_{y} y}) &x\geqslant 0, \;\; y\geqslant 0 \\\\ 0 & \text{otherwise} \end{cases}$$
114143

144+
Alternative to the inverse scale parameter `lambda`, it is possible to pass `loc` and `scale`, where \(scale = \frac{1}{\lambda}\) and `loc` specifies the value by which the distribution is shifted.
145+
115146
### Syntax
116147

148+
`result = ` [[stdlib_stats_distribution_exponential(module):cdf_exp(interface)]] `(x, loc, scale)`
149+
150+
or
151+
117152
`result = ` [[stdlib_stats_distribution_exponential(module):cdf_exp(interface)]] `(x, lambda)`
118153

119154
### Class
@@ -127,11 +162,16 @@ Elemental function
127162
`lambda`: has `intent(in)` and is a scalar of type `real` or `complex`.
128163
If `lambda` is `real`, its value must be positive. If `lambda` is `complex`, both the real and imaginary components must be positive.
129164

165+
`loc`: has `intent(in)` and is a scalar of type `real` or `complex`.
166+
167+
`scale`: has `intent(in)` and is a positive scalar of type `real` or `complex`.
168+
If `scale` is `real`, its value must be positive. If `scale` is `complex`, both the real and imaginary components must be positive.
169+
130170
All arguments must have the same type.
131171

132172
### Return value
133173

134-
The result is a scalar or an array, with a shape conformable to the arguments, and the same type as the input arguments. If `lambda` is non-positive, the result is `NaN`.
174+
The result is a scalar or an array, with a shape conformable to the arguments, and the same type as the input arguments. With non-positive `lambda` or `scale`, the result is `NaN`.
135175

136176
### Example
137177

example/stats_distribution_exponential/example_exponential_cdf.f90

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,60 +4,80 @@ program example_exponential_cdf
44
rexp => rvs_exp
55

66
implicit none
7-
real, dimension(2, 3, 4) :: x, lambda
7+
real, dimension(2, 3, 4) :: x, loc, scale
88
real :: xsum
9-
complex :: scale
9+
complex :: cloc, cscale
1010
integer :: seed_put, seed_get, i
1111

1212
seed_put = 1234567
1313
call random_seed(seed_put, seed_get)
1414

15-
! standard exponential cumulative distribution at x=1.0
15+
! standard exponential cumulative distribution at x=1.0 with loc=0.0, scale=1.0
16+
print *, exp_cdf(1.0, 0.0, 1.0)
17+
! 0.632120550
18+
19+
! standard exponential cumulative distribution at x=1.0 with lambda=1.0
1620
print *, exp_cdf(1.0, 1.0)
1721
! 0.632120550
1822

1923
! cumulative distribution at x=2.0 with lambda=2
2024
print *, exp_cdf(2.0, 2.0)
2125
! 0.981684387
2226

23-
! cumulative distribution at x=2.0 with lambda=-1.0 (out of range)
24-
print *, exp_cdf(2.0, -1.0)
27+
! cumulative distribution at x=2.0 with loc=0.0 and scale=0.5 (equivalent of lambda=2)
28+
print *, exp_cdf(2.0, 0.0, 0.5)
29+
! 0.981684387
30+
31+
! cumulative distribution at x=2.5 with loc=0.5 and scale=0.5 (equivalent of lambda=2)
32+
print *, exp_cdf(2.5, 0.5, 0.5)
33+
! 0.981684387
34+
35+
! cumulative distribution at x=2.0 with loc=0.0 and scale=-1.0 (out of range)
36+
print *, exp_cdf(2.0, 0.0, -1.0)
2537
! NaN
2638

39+
! cumulative distribution at x=0.5 with loc=1.0 and scale=1.0, putting x below the minimum
40+
print *, exp_cdf(0.5, 1.0, 1.0)
41+
! 0.00000000
42+
2743
! standard exponential random variates array
28-
x = reshape(rexp(0.5, 24), [2, 3, 4])
44+
x = reshape(rexp(0.0, 2.0, 24), [2, 3, 4])
2945

3046
! a rank-3 exponential cumulative distribution
31-
lambda(:, :, :) = 0.5
32-
print *, exp_cdf(x, lambda)
47+
loc(:, :, :) = 0.0
48+
scale(:, :, :) = 2.0
49+
print *, exp_cdf(x, loc, scale)
3350
! 0.301409245 0.335173965 5.94930053E-02 0.113003314
3451
! 0.365694344 0.583515942 0.113774836 0.838585377
3552
! 0.509324908 0.127967060 0.857194781 0.893231630
3653
! 0.355383813 0.470882893 0.574203610 0.799321830
3754
! 0.546216846 0.111995399 0.801794767 0.922525287
38-
! 0.937719882 0.301136374 3.44503522E-02 0.134661376
55+
! 0.937719882 0.301136374 3.44503522E-02 0.134661376
56+
3957

40-
! cumulative distribution array where lambda<=0.0 for certain elements
41-
print *, exp_cdf([1.0, 1.0, 1.0], [1.0, 0.0, -1.0])
58+
! cumulative distribution array where scale<=0.0 for certain elements
59+
print *, exp_cdf([1.0, 1.0, 1.0], [0.0, 0.0, 0.0], [1.0, 0.0, -1.0])
4260
! 0.632120550 NaN NaN
4361

44-
! `cdf_exp` is pure and, thus, can be called concurrently
62+
! `cdf_exp` is pure and, thus, can be called concurrently
4563
xsum = 0.0
4664
do concurrent (i=1:size(x,3))
47-
xsum = xsum + sum(exp_cdf(x(:,:,i), lambda(:,:,i)))
65+
xsum = xsum + sum(exp_cdf(x(:,:,i), loc(:,:,i), scale(:,:,i)))
4866
end do
4967
print *, xsum
5068
! 11.0886612
5169

52-
! complex exponential cumulative distribution at (0.5,0.5) with real part of
53-
! lambda=0.5 and imaginary part of lambda=1.0
54-
scale = (0.5, 1.0)
55-
print *, exp_cdf((0.5, 0.5), scale)
70+
! complex exponential cumulative distribution at (0.5, 0.0, 2) with real part of
71+
! scale=2 and imaginary part of scale=1.0
72+
cloc = (0.0, 0.0)
73+
cscale = (2, 1.0)
74+
print *, exp_cdf((0.5, 0.5), cloc, cscale)
5675
! 8.70351046E-02
5776

58-
! As above, but with lambda%im < 0
59-
scale = (1.0, -2.0)
60-
print *, exp_cdf((1.5, 1.0), scale)
77+
! As above, but with scale%im < 0
78+
cloc = (0.0, 0.0)
79+
cscale = (1.0, -2.0)
80+
print *, exp_cdf((1.5, 1.0), cloc, cscale)
6181
! NaN
6282

6383
end program example_exponential_cdf

example/stats_distribution_exponential/example_exponential_pdf.f90

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,59 +4,74 @@ program example_exponential_pdf
44
rexp => rvs_exp
55

66
implicit none
7-
real, dimension(2, 3, 4) :: x, lambda
7+
real, dimension(2, 3, 4) :: x, loc, scale
88
real :: xsum
9-
complex :: scale
9+
complex :: cloc, cscale
1010
integer :: seed_put, seed_get, i
1111

1212
seed_put = 1234567
1313
call random_seed(seed_put, seed_get)
1414

15-
! probability density at x=1.0 in standard exponential
15+
! probability density at x=1.0 with loc=0 and scale=1.0
16+
print *, exp_pdf(1.0, 0.0, 1.0)
17+
! 0.367879450
18+
19+
! probability density at x=1.0 with lambda=1.0
1620
print *, exp_pdf(1.0, 1.0)
1721
! 0.367879450
1822

1923
! probability density at x=2.0 with lambda=2.0
20-
print *, exp_pdf(2.0, 2.0)
24+
print *, exp_pdf(2.0, 2.0)
25+
! 3.66312787E-02
26+
27+
! probability density at x=2.0 with loc=0.0 and scale=0.5 (lambda=2.0)
28+
print *, exp_pdf(2.0, 0.0, 0.5)
29+
! 3.66312787E-02
30+
31+
! probability density at x=1.5 with loc=0.5 and scale=0.5 (lambda=2.0)
32+
print *, exp_pdf(2.5, 0.5, 0.5)
2133
! 3.66312787E-02
2234

23-
! probability density at x=2.0 with lambda=-1.0 (out of range)
24-
print *, exp_pdf(2.0, -1.0)
35+
! probability density at x=2.0 with loc=0.0 and scale=-1.0 (out of range)
36+
print *, exp_pdf(2.0, 0.0, -1.0)
2537
! NaN
2638

27-
! standard exponential random variates array
28-
x = reshape(rexp(0.5, 24), [2, 3, 4])
39+
! standard exponential random variates array
40+
x = reshape(rexp(0.0, 2.0, 24), [2, 3, 4])
2941

3042
! a rank-3 exponential probability density
31-
lambda(:, :, :) = 0.5
32-
print *, exp_pdf(x, lambda)
43+
loc(:, :, :) = 0.0
44+
scale(:, :, :) = 2.0
45+
print *, exp_pdf(x, loc, scale)
3346
! 0.349295378 0.332413018 0.470253497 0.443498343 0.317152828
3447
! 0.208242029 0.443112582 8.07073265E-02 0.245337561 0.436016470
3548
! 7.14025944E-02 5.33841923E-02 0.322308093 0.264558554 0.212898195
3649
! 0.100339092 0.226891592 0.444002301 9.91026312E-02 3.87373678E-02
37-
! 3.11400592E-02 0.349431813 0.482774824 0.432669312
50+
! 3.11400592E-02 0.349431813 0.482774824 0.432669312
3851

39-
! probability density array where lambda<=0.0 for certain elements
40-
print *, exp_pdf([1.0, 1.0, 1.0], [1.0, 0.0, -1.0])
52+
! probability density array where scale<=0.0 for certain elements (loc = 0.0)
53+
print *, exp_pdf([1.0, 1.0, 1.0], [0.0, 0.0, 0.0], [1.0, 0.0, -1.0])
4154
! 0.367879450 NaN NaN
4255

43-
! `pdf_exp` is pure and, thus, can be called concurrently
56+
! `pdf_exp` is pure and, thus, can be called concurrently
4457
xsum = 0.0
4558
do concurrent (i=1:size(x,3))
46-
xsum = xsum + sum(exp_pdf(x(:,:,i), lambda(:,:,i)))
59+
xsum = xsum + sum(exp_pdf(x(:,:,i), loc(:,:,i), scale(:,:,i)))
4760
end do
4861
print *, xsum
4962
! 6.45566940
5063

51-
! complex exponential probability density function at (1.5,1.0) with real part
52-
! of lambda=1.0 and imaginary part of lambda=2.0
53-
scale = (1.0, 2.)
54-
print *, exp_pdf((1.5, 1.0), scale)
64+
! complex exponential probability density function at (1.5, 0.0, 1.0) with real part
65+
! of scale=1.0 and imaginary part of scale=0.5
66+
cloc = (0.0, 0.0)
67+
cscale = (1.0, 0.5)
68+
print *, exp_pdf((1.5, 1.0), cloc, cscale)
5569
! 6.03947677E-02
5670

57-
! As above, but with lambda%re < 0
58-
scale = (-1.0, 2.)
59-
print *, exp_pdf((1.5, 1.0), scale)
71+
! As above, but with scale%re < 0
72+
cloc = (0.0, 0.0)
73+
cscale = (-1.0, 2.0)
74+
print *, exp_pdf((1.5, 1.0), cloc, cscale)
6075
! NaN
6176

6277
end program example_exponential_pdf

example/stats_distribution_exponential/example_exponential_rvs.f90

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,30 +3,38 @@ program example_exponential_rvs
33
use stdlib_stats_distribution_exponential, only: rexp => rvs_exp
44

55
implicit none
6-
complex :: scale
6+
complex :: cloc, cscale
77
integer :: seed_put, seed_get
88

99
seed_put = 1234567
1010
call random_seed(seed_put, seed_get)
1111

12-
print *, rexp() !single standard exponential random variate
13-
14-
! 0.358690143
15-
16-
print *, rexp(2.0) !exponential random variate with lambda=2.0
17-
18-
! 0.816459715
19-
20-
print *, rexp(0.3, 10) !an array of 10 variates with lambda=0.3
21-
22-
! 1.84008647E-02 3.59742008E-02 0.136567295 0.262772143 3.62352766E-02
23-
! 0.547133625 0.213591918 4.10784185E-02 0.583882213 0.671128035
24-
25-
scale = (2.0, 0.7)
26-
print *, rexp(scale)
27-
!single complex exponential random variate with real part of lambda=2.0;
28-
!imagainary part of lambda=0.7
29-
30-
! (1.41435969,4.081114382E-02)
12+
! single standard exponential random variate
13+
print *, rexp()
14+
! 0.358690143
15+
16+
! exponential random variate with loc=0 and scale=0.5 (lambda=2)
17+
print *, rexp(0.0, 0.5)
18+
! 0.122672431
19+
20+
! exponential random variate with lambda=2
21+
print *, rexp(2.0)
22+
! 0.204114929
23+
24+
! exponential random variate with loc=0.6 and scale=0.2 (lambda=5)
25+
print *, rexp(0.6, 0.2)
26+
! 0.681645989
27+
28+
! an array of 10 variates with loc=0.0 and scale=3.0 (lambda=1/3)
29+
print *, rexp(0.0, 3.0, 10)
30+
! 1.36567295 2.62772131 0.362352759 5.47133636 2.13591909
31+
! 0.410784155 5.83882189 6.71128035 1.31730068 1.90963650
32+
33+
! single complex exponential random variate with real part of scale=0.5 (lambda=2.0);
34+
! imagainary part of scale=1.6 (lambda=0.625)
35+
cloc = (0.0, 0.0)
36+
cscale = (0.5, 1.6)
37+
print *, rexp(cloc, cscale)
38+
! (0.426896989,2.56968451)
3139

3240
end program example_exponential_rvs

0 commit comments

Comments
 (0)