Skip to content

Commit 7397e96

Browse files
authored
Merge pull request #144 from jvdp1/variance_dev
Addition of variance function in stdlib_experimental_stats
2 parents e12ce0f + 01e897c commit 7397e96

9 files changed

+930
-3
lines changed

Diff for: src/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ set(fppFiles
66
stdlib_experimental_optval.fypp
77
stdlib_experimental_stats.fypp
88
stdlib_experimental_stats_mean.fypp
9+
stdlib_experimental_stats_var.fypp
910
)
1011

1112

Diff for: src/Makefile.manual

+7-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ SRC = stdlib_experimental_ascii.f90 \
55
stdlib_experimental_kinds.f90 \
66
f18estop.f90 \
77
stdlib_experimental_stats.f90 \
8-
stdlib_experimental_stats_mean.f90
8+
stdlib_experimental_stats_mean.f90 \
9+
stdlib_experimental_stats_var.f90
910

1011
LIB = libstdlib.a
1112

@@ -42,6 +43,11 @@ stdlib_experimental_stats_mean.o: \
4243
stdlib_experimental_optval.o \
4344
stdlib_experimental_kinds.o \
4445
stdlib_experimental_stats.o
46+
stdlib_experimental_stats_var.o: \
47+
stdlib_experimental_optval.o \
48+
stdlib_experimental_kinds.o \
49+
stdlib_experimental_stats.o
4550
stdlib_experimental_io.f90: stdlib_experimental_io.fypp
4651
stdlib_experimental_stats.f90: stdlib_experimental_stats.fypp
4752
stdlib_experimental_stats_mean.f90: stdlib_experimental_stats_mean.fypp
53+
stdlib_experimental_stats_var.f90: stdlib_experimental_stats_var.fypp

Diff for: src/common.fypp

+25
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ ${prefix + joinstr.join([line.strip() for line in txt.split("\n")]) + suffix}$
9797
#:endif
9898
#:enddef
9999

100+
100101
#! Generates a routine name from a generic name, rank, type and kind
101102
#!
102103
#! Args:
@@ -113,4 +114,28 @@ ${prefix + joinstr.join([line.strip() for line in txt.split("\n")]) + suffix}$
113114
$:"{0}_{1}_{2}{3}_{2}{3}".format(gname, rank, type[0], kind) if suffix == '' else "{0}_{1}_{2}{3}_{4}".format(gname, rank, type[0], kind, suffix)
114115
#:enddef
115116

117+
118+
#! Generates an array rank suffix for subarrays reducing the dimension
119+
#!
120+
#! Args:
121+
#! rank (int): Rank of the original variable
122+
#! selectors (array): Dimension and name of the variable(s)
123+
#!
124+
#! Returns:
125+
#! Array rank suffix string enclosed in braces
126+
#!
127+
#! E.g.,
128+
#! select_subarray(5 , [(4, 'i'), (5, 'j')])}$
129+
#! -> (:, :, :, i, j)
130+
#!
131+
#:def select_subarray(rank, selectors)
132+
#:assert rank > 0
133+
#:set seldict = dict(selectors)
134+
#:call join_lines(joinstr=", ", prefix="(", suffix=")")
135+
#:for i in range(1, rank + 1)
136+
$:seldict.get(i, ":")
137+
#:endfor
138+
#:endcall
139+
#:enddef
140+
116141
#:endmute

Diff for: src/stdlib_experimental_stats.fypp

+99-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ module stdlib_experimental_stats
77
implicit none
88
private
99
! Public API
10-
public :: mean
10+
public :: mean, var
1111

1212
interface mean
1313
#:for k1, t1 in RC_KINDS_TYPES
@@ -104,4 +104,102 @@ module stdlib_experimental_stats
104104

105105
end interface mean
106106

107+
108+
interface var
109+
110+
#:for k1, t1 in RC_KINDS_TYPES
111+
#:for rank in RANKS
112+
#:set RName = rname("var_all",rank, t1, k1)
113+
module function ${RName}$(x, mask) result(res)
114+
${t1}$, intent(in) :: x${ranksuffix(rank)}$
115+
logical, intent(in), optional :: mask
116+
real(${k1}$) :: res
117+
end function ${RName}$
118+
#:endfor
119+
#:endfor
120+
121+
#:for k1, t1 in INT_KINDS_TYPES
122+
#:for rank in RANKS
123+
#:set RName = rname("var_all",rank, t1, k1, 'dp')
124+
module function ${RName}$(x, mask) result(res)
125+
${t1}$, intent(in) :: x${ranksuffix(rank)}$
126+
logical, intent(in), optional :: mask
127+
real(dp) :: res
128+
end function ${RName}$
129+
#:endfor
130+
#:endfor
131+
132+
#:for k1, t1 in RC_KINDS_TYPES
133+
#:for rank in RANKS
134+
#:set RName = rname("var",rank, t1, k1)
135+
module function ${RName}$(x, dim, mask) result(res)
136+
${t1}$, intent(in) :: x${ranksuffix(rank)}$
137+
integer, intent(in) :: dim
138+
logical, intent(in), optional :: mask
139+
real(${k1}$) :: res${reduced_shape('x', rank, 'dim')}$
140+
end function ${RName}$
141+
#:endfor
142+
#:endfor
143+
144+
#:for k1, t1 in INT_KINDS_TYPES
145+
#:for rank in RANKS
146+
#:set RName = rname("var",rank, t1, k1, 'dp')
147+
module function ${RName}$(x, dim, mask) result(res)
148+
${t1}$, intent(in) :: x${ranksuffix(rank)}$
149+
integer, intent(in) :: dim
150+
logical, intent(in), optional :: mask
151+
real(dp) :: res${reduced_shape('x', rank, 'dim')}$
152+
end function ${RName}$
153+
#:endfor
154+
#:endfor
155+
156+
#:for k1, t1 in RC_KINDS_TYPES
157+
#:for rank in RANKS
158+
#:set RName = rname("var_mask_all",rank, t1, k1)
159+
module function ${RName}$(x, mask) result(res)
160+
${t1}$, intent(in) :: x${ranksuffix(rank)}$
161+
logical, intent(in) :: mask${ranksuffix(rank)}$
162+
real(${k1}$) :: res
163+
end function ${RName}$
164+
#:endfor
165+
#:endfor
166+
167+
#:for k1, t1 in INT_KINDS_TYPES
168+
#:for rank in RANKS
169+
#:set RName = rname("var_mask_all",rank, t1, k1, 'dp')
170+
module function ${RName}$(x, mask) result(res)
171+
${t1}$, intent(in) :: x${ranksuffix(rank)}$
172+
logical, intent(in) :: mask${ranksuffix(rank)}$
173+
real(dp) :: res
174+
end function ${RName}$
175+
#:endfor
176+
#:endfor
177+
178+
#:for k1, t1 in RC_KINDS_TYPES
179+
#:for rank in RANKS
180+
#:set RName = rname("var_mask",rank, t1, k1)
181+
module function ${RName}$(x, dim, mask) result(res)
182+
${t1}$, intent(in) :: x${ranksuffix(rank)}$
183+
integer, intent(in) :: dim
184+
logical, intent(in) :: mask${ranksuffix(rank)}$
185+
real(${k1}$) :: res${reduced_shape('x', rank, 'dim')}$
186+
end function ${RName}$
187+
#:endfor
188+
#:endfor
189+
190+
#:for k1, t1 in INT_KINDS_TYPES
191+
#:for rank in RANKS
192+
#:set RName = rname("var_mask",rank, t1, k1, 'dp')
193+
module function ${RName}$(x, dim, mask) result(res)
194+
${t1}$, intent(in) :: x${ranksuffix(rank)}$
195+
integer, intent(in) :: dim
196+
logical, intent(in) :: mask${ranksuffix(rank)}$
197+
real(dp) :: res${reduced_shape('x', rank, 'dim')}$
198+
end function ${RName}$
199+
#:endfor
200+
#:endfor
201+
202+
end interface var
203+
204+
107205
end module stdlib_experimental_stats

Diff for: src/stdlib_experimental_stats.md

+53
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## Implemented
44

55
* `mean`
6+
* `var`
67

78
## `mean` - mean of array elements
89

@@ -47,3 +48,55 @@ program demo_mean
4748
reshape(x, [ 2, 3 ] ) > 3.) !returns [ NaN, 4.0, 5.5 ]
4849
end program demo_mean
4950
```
51+
52+
## `var` - variance of array elements
53+
54+
### Description
55+
56+
Returns the variance of all the elements of `array`, or of the elements of `array` along dimension `dim` if provided, and if the corresponding element in `mask` is `true`.
57+
58+
The variance is defined as the best unbiased estimator and is computed as:
59+
60+
```
61+
var(x) = 1/(n-1) sum_i (array(i) - mean(array))^2
62+
```
63+
64+
### Syntax
65+
66+
`result = var(array [, mask])`
67+
68+
`result = var(array, dim [, mask])`
69+
70+
### Arguments
71+
72+
`array`: Shall be an array of type `integer`, `real`, or `complex`.
73+
74+
`dim`: Shall be a scalar of type `integer` with a value in the range from 1 to n, where n is the rank of `array`.
75+
76+
`mask` (optional): Shall be of type `logical` and either by a scalar or an array of the same shape as `array`.
77+
78+
### Return value
79+
80+
If `array` is of type `real` or `complex`, the result is of the same type as `array`.
81+
If `array` is of type `integer`, the result is of type `double precision`.
82+
83+
If `dim` is absent, a scalar with the variance of all elements in `array` is returned. Otherwise, an array of rank n-1, where n equals the rank of `array`, and a shape similar to that of `ar
84+
ray` with dimension `dim` dropped is returned.
85+
86+
If `mask` is specified, the result is the variance of all elements of `array` corresponding to `true` elements of `mask`. If every element of `mask` is `false`, the result is IEEE `NaN`.
87+
88+
### Example
89+
90+
```fortran
91+
program demo_var
92+
use stdlib_experimental_stats, only: var
93+
implicit none
94+
real :: x(1:6) = [ 1., 2., 3., 4., 5., 6. ]
95+
print *, var(x) !returns 3.5
96+
print *, var( reshape(x, [ 2, 3 ] )) !returns 3.5
97+
print *, var( reshape(x, [ 2, 3 ] ), 1) !returns [0.5, 0.5, 0.5]
98+
print *, var( reshape(x, [ 2, 3 ] ), 1,&
99+
reshape(x, [ 2, 3 ] ) > 3.) !returns [0., NaN, 0.5]
100+
end program demo_var
101+
```
102+

0 commit comments

Comments
 (0)