-
Notifications
You must be signed in to change notification settings - Fork 184
/
Copy pathstdlib_stats_moment.fypp
110 lines (94 loc) · 3.4 KB
/
stdlib_stats_moment.fypp
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#:include "common.fypp"
#:set RANKS = range(1, MAXRANK + 1)
#:set REDRANKS = range(2, MAXRANK + 1)
#:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES
submodule (stdlib_stats) stdlib_stats_moment
use, intrinsic:: ieee_arithmetic, only: ieee_value, ieee_quiet_nan
use stdlib_error, only: error_stop
use stdlib_optval, only: optval
implicit none
contains
#:for k1, t1 in RC_KINDS_TYPES
#:for rank in RANKS
#:set RName = rname("moment",rank, t1, k1)
module function ${RName}$(x, order, dim, center, mask) result(res)
${t1}$, intent(in) :: x${ranksuffix(rank)}$
integer, intent(in) :: order
integer, intent(in) :: dim
${t1}$, intent(in), optional :: center${reduced_shape('x', rank, 'dim')}$
logical, intent(in), optional :: mask
${t1}$ :: res${reduced_shape('x', rank, 'dim')}$
integer :: i
real(${k1}$) :: n
${t1}$, allocatable :: mean_${ranksuffix(rank-1)}$
if (.not.optval(mask, .true.)) then
res = ieee_value(1._${k1}$, ieee_quiet_nan)
return
end if
n = real(size(x, dim), ${k1}$)
res = 0
select case(dim)
#:for fi in range(1, rank+1)
case(${fi}$)
if (present(center)) then
do i = 1, size(x, ${fi}$)
res = res + (x${select_subarray(rank, [(fi, 'i')])}$ - center)**order
end do
else
allocate(mean_, source = mean(x, ${fi}$))
do i = 1, size(x, ${fi}$)
res = res + (x${select_subarray(rank, [(fi, 'i')])}$ - mean_)**order
end do
deallocate(mean_)
end if
#:endfor
case default
call error_stop("ERROR (moment): wrong dimension")
end select
res = res / n
end function ${RName}$
#:endfor
#:endfor
#:for k1, t1 in INT_KINDS_TYPES
#:for rank in RANKS
#:set RName = rname("moment",rank, t1, k1, 'dp')
module function ${RName}$(x, order, dim, center, mask) result(res)
${t1}$, intent(in) :: x${ranksuffix(rank)}$
integer, intent(in) :: order
integer, intent(in) :: dim
real(dp),intent(in), optional :: center${reduced_shape('x', rank, 'dim')}$
logical, intent(in), optional :: mask
real(dp) :: res${reduced_shape('x', rank, 'dim')}$
integer :: i
real(dp) :: n
real(dp), allocatable :: mean_${ranksuffix(rank-1)}$
if (.not.optval(mask, .true.)) then
res = ieee_value(1._dp, ieee_quiet_nan)
return
end if
n = real(size(x, dim), dp)
res = 0
select case(dim)
#:for fi in range(1, rank+1)
case(${fi}$)
if (present(center)) then
do i = 1, size(x, ${fi}$)
res = res + (real(x${select_subarray(rank, [(fi, 'i')])}$, dp) -&
center)**order
end do
else
allocate(mean_, source = mean(x, ${fi}$))
do i = 1, size(x, ${fi}$)
res = res + (real(x${select_subarray(rank, [(fi, 'i')])}$, dp) - mean_)**order
end do
deallocate(mean_)
end if
#:endfor
case default
call error_stop("ERROR (moment): wrong dimension")
end select
res = res / n
end function ${RName}$
#:endfor
#:endfor
end submodule