Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 26 additions & 12 deletions src/stats/stdlib_stats_corr.fypp
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ contains
${t1}$ :: centeri_(merge(size(x, 2), size(x, 1), mask = 1<dim))
${t1}$ :: centerj_(merge(size(x, 2), size(x, 1), mask = 1<dim))
logical :: mask_(merge(size(x, 2), size(x, 1), mask = 1<dim))
real(${k1}$) :: denom
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
real(${k1}$) :: denom
${t1}$ :: denom


select case(dim)
case(1)
Expand All @@ -218,9 +219,12 @@ contains
#:endif
mask_)

res(j, i) = dot_product( centerj_, centeri_)&
/sqrt(dot_product( centeri_, centeri_)*&
dot_product( centerj_, centerj_))
denom = real(dot_product( centeri_, centeri_), ${k1}$)*real(dot_product( centerj_, centerj_), ${k1}$)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
denom = real(dot_product( centeri_, centeri_), ${k1}$)*real(dot_product( centerj_, centerj_), ${k1}$)
denom = dot_product( centeri_, centeri_)*dot_product( centerj_, centerj_)

Why do you convert the dot_product to a real?

if (denom < epsilon(0._${k1}$)) then
res(j, i) = ieee_value(1._${k1}$, ieee_quiet_nan)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this ok with complex values?

else
res(j, i) = dot_product( centerj_, centeri_)/sqrt(denom)
end if

end do
end do
Expand All @@ -243,9 +247,12 @@ contains
#:endif
mask_)

res(j, i) = dot_product( centeri_, centerj_)&
/sqrt(dot_product( centeri_, centeri_)*&
dot_product( centerj_, centerj_))
denom = real(dot_product( centeri_, centeri_), ${k1}$)*real(dot_product( centerj_, centerj_), ${k1}$)
if (denom < epsilon(0._${k1}$)) then
res(j, i) = ieee_value(1._${k1}$, ieee_quiet_nan)
else
res(j, i) = dot_product( centeri_, centerj_)/sqrt(denom)
end if
end do
end do
case default
Expand All @@ -269,6 +276,7 @@ contains
real(dp) :: centeri_(merge(size(x, 2), size(x, 1), mask = 1<dim))
real(dp) :: centerj_(merge(size(x, 2), size(x, 1), mask = 1<dim))
logical :: mask_(merge(size(x, 2), size(x, 1), mask = 1<dim))
real(dp) :: denom

select case(dim)
case(1)
Expand All @@ -278,9 +286,12 @@ contains
centeri_ = merge( x(:, i) - mean(x(:, i), mask = mask_),0._dp, mask_)
centerj_ = merge( x(:, j) - mean(x(:, j), mask = mask_),0._dp, mask_)

res(j, i) = dot_product( centerj_, centeri_)&
/sqrt(dot_product( centeri_, centeri_)*&
dot_product( centerj_, centerj_))
denom = dot_product( centeri_, centeri_)*dot_product( centerj_, centerj_)
if (denom < epsilon(0._dp)) then
res(j, i) = ieee_value(1._dp, ieee_quiet_nan)
else
res(j, i) = dot_product( centerj_, centeri_)/sqrt(denom)
end if

end do
end do
Expand All @@ -291,9 +302,12 @@ contains
centeri_ = merge( x(i, :) - mean(x(i, :), mask = mask_),0._dp, mask_)
centerj_ = merge( x(j, :) - mean(x(j, :), mask = mask_),0._dp, mask_)

res(j, i) = dot_product( centeri_, centerj_)&
/sqrt(dot_product( centeri_, centeri_)*&
dot_product( centerj_, centerj_))
denom = dot_product( centeri_, centeri_)*dot_product( centerj_, centerj_)
if (denom < epsilon(0._dp)) then
res(j, i) = ieee_value(1._dp, ieee_quiet_nan)
else
res(j, i) = dot_product( centeri_, centerj_)/sqrt(denom)
end if
end do
end do
case default
Expand Down
58 changes: 46 additions & 12 deletions src/stats/stdlib_stats_cov.fypp
Original file line number Diff line number Diff line change
Expand Up @@ -181,28 +181,37 @@ contains
${t1}$ :: centeri_(merge(size(x, 2), size(x, 1), mask = 1<dim))
${t1}$ :: centerj_(merge(size(x, 2), size(x, 1), mask = 1<dim))
logical :: mask_(merge(size(x, 2), size(x, 1), mask = 1<dim))
${t1}$ :: mean_i, mean_j

select case(dim)
case(1)
do i = 1, size(res, 2)
do j = 1, size(res, 1)
mask_ = mask(:, i) .and. mask(:, j)
centeri_ = merge( x(:, i) - mean(x(:, i), mask = mask_),&
n = count(mask_)
if (n < 2) then
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (n < 2) then
if (n == 0) then

n <2 does not match the explanation given for opening this PR. Should it be n==0?

res(j, i) = ieee_value(1._${k1}$, ieee_quiet_nan)
cycle
end if

mean_i = sum(x(:, i), mask = mask_) / real(n, ${k1}$)
mean_j = sum(x(:, j), mask = mask_) / real(n, ${k1}$)
Comment on lines +197 to +198
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest to use stdlib mean function.


centeri_ = merge( x(:, i) - mean_i,&
#:if t1[0] == 'r'
0._${k1}$,&
#:else
cmplx(0,0,kind=${k1}$),&
#:endif
mask_)
centerj_ = merge( x(:, j) - mean(x(:, j), mask = mask_),&
centerj_ = merge( x(:, j) - mean_j,&
#:if t1[0] == 'r'
0._${k1}$,&
#:else
cmplx(0,0,kind=${k1}$),&
#:endif
mask_)

n = count(mask_)
res(j, i) = dot_product( centerj_, centeri_)&
/ (n - merge(1, 0,&
optval(corrected, .true.) .and. n > 0))
Expand All @@ -212,22 +221,30 @@ contains
do i = 1, size(res, 2)
do j = 1, size(res, 1)
mask_ = mask(i, :) .and. mask(j, :)
centeri_ = merge( x(i, :) - mean(x(i, :), mask = mask_),&
n = count(mask_)
if (n < 2) then
res(j, i) = ieee_value(1._${k1}$, ieee_quiet_nan)
cycle
end if

mean_i = sum(x(i, :), mask = mask_) / real(n, ${k1}$)
mean_j = sum(x(j, :), mask = mask_) / real(n, ${k1}$)

centeri_ = merge( x(i, :) - mean_i,&
#:if t1[0] == 'r'
0._${k1}$,&
#:else
cmplx(0,0,kind=${k1}$),&
#:endif
mask_)
centerj_ = merge( x(j, :) - mean(x(j, :), mask = mask_),&
centerj_ = merge( x(j, :) - mean_j,&
#:if t1[0] == 'r'
0._${k1}$,&
#:else
cmplx(0,0,kind=${k1}$),&
#:endif
mask_)

n = count(mask_)
res(j, i) = dot_product( centeri_, centerj_)&
/ (n - merge(1, 0,&
optval(corrected, .true.) .and. n > 0))
Expand Down Expand Up @@ -255,16 +272,25 @@ contains
real(dp) :: centeri_(merge(size(x, 2), size(x, 1), mask = 1<dim))
real(dp) :: centerj_(merge(size(x, 2), size(x, 1), mask = 1<dim))
logical :: mask_(merge(size(x, 2), size(x, 1), mask = 1<dim))
real(dp) :: mean_i, mean_j

select case(dim)
case(1)
do i = 1, size(res, 2)
do j = 1, size(res, 1)
mask_ = mask(:, i) .and. mask(:, j)
centeri_ = merge( x(:, i) - mean(x(:, i), mask = mask_),0._dp, mask_)
centerj_ = merge( x(:, j) - mean(x(:, j), mask = mask_),0._dp, mask_)

n = count(mask_)
if (n < 2) then
res(j, i) = ieee_value(1._dp, ieee_quiet_nan)
cycle
end if

mean_i = sum(real(x(:, i), dp), mask = mask_) / real(n, dp)
mean_j = sum(real(x(:, j), dp), mask = mask_) / real(n, dp)

centeri_ = merge( real(x(:, i), dp) - mean_i, 0._dp, mask_)
centerj_ = merge( real(x(:, j), dp) - mean_j, 0._dp, mask_)

res(j, i) = dot_product( centerj_, centeri_)&
/ (n - merge(1, 0,&
optval(corrected, .true.) .and. n > 0))
Expand All @@ -274,10 +300,18 @@ contains
do i = 1, size(res, 2)
do j = 1, size(res, 1)
mask_ = mask(i, :) .and. mask(j, :)
centeri_ = merge( x(i, :) - mean(x(i, :), mask = mask_),0._dp, mask_)
centerj_ = merge( x(j, :) - mean(x(j, :), mask = mask_),0._dp, mask_)

n = count(mask_)
if (n < 2) then
res(j, i) = ieee_value(1._dp, ieee_quiet_nan)
cycle
end if

mean_i = sum(real(x(i, :), dp), mask = mask_) / real(n, dp)
mean_j = sum(real(x(j, :), dp), mask = mask_) / real(n, dp)

centeri_ = merge( real(x(i, :), dp) - mean_i, 0._dp, mask_)
centerj_ = merge( real(x(j, :), dp) - mean_j, 0._dp, mask_)

res(j, i) = dot_product( centeri_, centerj_)&
/ (n - merge(1, 0,&
optval(corrected, .true.) .and. n > 0))
Expand Down
52 changes: 48 additions & 4 deletions src/stats/stdlib_stats_mean.fypp
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,15 @@ contains
${t1}$, intent(in) :: x${ranksuffix(rank)}$
logical, intent(in) :: mask${ranksuffix(rank)}$
${t1}$ :: res
real(${k1}$) :: n

res = sum(x, mask) / real(count(mask, kind = int64), ${k1}$)
n = real(count(mask, kind = int64), ${k1}$)
if (n == 0._${k1}$) then
res = ieee_value(1._${k1}$, ieee_quiet_nan)
return
end if

res = sum(x, mask) / n
Comment on lines +111 to +116
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am puzzle by this change as the original code will return NaN when count(mask)=0. So, what is the benefit of this change?


end function ${RName}$
#:endfor
Expand All @@ -120,8 +127,15 @@ contains
${t1}$, intent(in) :: x${ranksuffix(rank)}$
logical, intent(in) :: mask${ranksuffix(rank)}$
real(dp) :: res
real(dp) :: n

n = real(count(mask, kind = int64), dp)
if (n == 0._dp) then
res = ieee_value(1._dp, ieee_quiet_nan)
return
end if

res = sum(real(x, dp), mask) / real(count(mask, kind = int64), dp)
res = sum(real(x, dp), mask) / n

end function ${RName}$
#:endfor
Expand All @@ -135,9 +149,24 @@ contains
integer, intent(in) :: dim
logical, intent(in) :: mask${ranksuffix(rank)}$
${t1}$ :: res${reduced_shape('x', rank, 'dim')}$
real(${k1}$) :: n${reduced_shape('x', rank, 'dim')}$

if (dim >= 1 .and. dim <= ${rank}$) then
res = sum(x, dim, mask) / real(count(mask, dim), ${k1}$)
#:if rank == 1
n = real(count(mask), ${k1}$)
if (n == 0._${k1}$) then
res = ieee_value(1._${k1}$, ieee_quiet_nan)
else
res = sum(x, dim, mask) / n
end if
Comment on lines +156 to +161
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this code duplicated for dim==1? the following one would do the job too.

#:else
n = real(count(mask, dim), ${k1}$)
where (n > 0._${k1}$)
res = sum(x, dim, mask) / n
elsewhere
res = ieee_value(1._${k1}$, ieee_quiet_nan)
end where
#:endif
Comment on lines +155 to +169
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code is more complex to undertand than the original one. So,what is its benefit?

else
call error_stop("ERROR (mean): wrong dimension")
end if
Expand All @@ -155,9 +184,24 @@ contains
integer, intent(in) :: dim
logical, intent(in) :: mask${ranksuffix(rank)}$
real(dp) :: res${reduced_shape('x', rank, 'dim')}$
real(dp) :: n${reduced_shape('x', rank, 'dim')}$

if (dim >= 1 .and. dim <= ${rank}$) then
res = sum(real(x, dp), dim, mask) / real(count(mask, dim), dp)
#:if rank == 1
n = real(count(mask), dp)
if (n == 0._dp) then
res = ieee_value(1._dp, ieee_quiet_nan)
else
res = sum(real(x, dp), dim, mask) / n
end if
#:else
n = real(count(mask, dim), dp)
where (n > 0._dp)
res = sum(real(x, dp), dim, mask) / n
elsewhere
res = ieee_value(1._dp, ieee_quiet_nan)
end where
#:endif
else
call error_stop("ERROR (mean): wrong dimension")
end if
Expand Down
40 changes: 38 additions & 2 deletions src/stats/stdlib_stats_var.fypp
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,12 @@ contains
${t1}$ :: mean

n = real(count(mask, kind = int64), ${k1}$)

if (n == 0._${k1}$) then
res = ieee_value(1._${k1}$, ieee_quiet_nan)
return
end if

mean = sum(x, mask) / n

#:if t1[0] == 'r'
Expand All @@ -188,6 +194,12 @@ contains
real(dp) :: n, mean

n = real(count(mask, kind = int64), dp)

if (n == 0._dp) then
res = ieee_value(1._dp, ieee_quiet_nan)
return
end if

mean = sum(real(x, dp), mask) / n

res = sum((real(x, dp) - mean)**2, mask) / (n -&
Expand Down Expand Up @@ -217,7 +229,19 @@ contains
#:for fi in range(1, rank+1)
case(${fi}$)
n = count(mask, dim)
mean = sum(x, dim, mask) / n
#:if rank == 1
if (n > 0) then
mean = sum(x, dim, mask) / n
else
mean = 0
end if
#:else
where (n > 0)
mean = sum(x, dim, mask) / n
elsewhere
mean = 0
end where
#:endif
do i = 1, size(x, dim)
#:if t1[0] == 'r'
res = res + merge( (x${select_subarray(rank, [(fi, 'i')])}$ - mean)**2,&
Expand Down Expand Up @@ -257,7 +281,19 @@ contains
#:for fi in range(1, rank+1)
case(${fi}$)
n = count(mask, dim)
mean = sum(real(x, dp), dim, mask) / n
#:if rank == 1
if (n > 0) then
mean = sum(real(x, dp), dim, mask) / n
else
mean = 0
end if
#:else
where (n > 0)
mean = sum(real(x, dp), dim, mask) / n
elsewhere
mean = 0
end where
#:endif
do i = 1, size(x, dim)
res = res + merge((real(x${select_subarray(rank, [(fi, 'i')])}$, dp) - mean)**2,&
0._dp, mask${select_subarray(rank, [(fi, 'i')])}$)
Expand Down
Loading