-
Notifications
You must be signed in to change notification settings - Fork 224
Fix Division-by-Zero in Masked Statistical Functions #1122
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
fe2e55f
0bbcbd4
6069bec
be3e1de
88f13a0
4e270be
86962a4
3898ce1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -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 | ||||||
|
|
||||||
| select case(dim) | ||||||
| case(1) | ||||||
|
|
@@ -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}$) | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Why do you convert the dot_product to a |
||||||
| if (denom < epsilon(0._${k1}$)) then | ||||||
| res(j, i) = ieee_value(1._${k1}$, ieee_quiet_nan) | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this ok with |
||||||
| else | ||||||
| res(j, i) = dot_product( centerj_, centeri_)/sqrt(denom) | ||||||
| end if | ||||||
|
|
||||||
| end do | ||||||
| end do | ||||||
|
|
@@ -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 | ||||||
|
|
@@ -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) | ||||||
|
|
@@ -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 | ||||||
|
|
@@ -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 | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -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 | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| 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
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suggest to use |
||||||
|
|
||||||
| 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)) | ||||||
|
|
@@ -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)) | ||||||
|
|
@@ -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)) | ||||||
|
|
@@ -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)) | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 | ||
|
|
@@ -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 | ||
|
|
@@ -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
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this code duplicated for |
||
| #: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
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 | ||
|
|
@@ -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 | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.