Skip to content
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

ENH: issue overflow warning when using abs on np.int8(-128) #21648

Merged
merged 18 commits into from Jun 13, 2022

Conversation

Micky774
Copy link
Contributor

@Micky774 Micky774 commented Jun 2, 2022

Related Issues/PRs

Resolves #21289

Changes

Checks condition a == NPY_MIN_@NAME@ to determine whether an overflow error has occurred for np.int8 type. See #21289 and #21188 (comment) for reference.

Comments

This is my first PR and it's not-quite-complete yet but I wanted to open it so that I could gather some feedback and assistance. In particular, I'm not sure if this change is sufficient, nor how to write tests for this that adhere to NumPy standards. Any help would be appreciated!

Co-authored-by: Sebastian Berg <sebastian@sipsolutions.net>
@Micky774
Copy link
Contributor Author

Micky774 commented Jun 4, 2022

Couple things I found that I have addressed in this PR (trying to avoid too large a scope):

  1. There was no fperror handling for absolute in scalarmath.c so I added it to the .src file.
  2. signed vs unsigned overflow tests were set up incorrectly. In particular, test_scalar_unsigned_integer_overflow was actually titled test_scalar_signed_integer_overflow and overwrote it (not sure if intentional?)
  3. The test_scalar_signed_integer_overflow test fails on integer floor division, so I set that as xfail to deal with in a follow-up PR.

@ganesh-k13
Copy link
Member

Just mentioning #21507 as it handles a few cases.

Copy link
Member

@seberg seberg left a comment

Choose a reason for hiding this comment

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

Thanks, seems like it should be pretty much ready, the main thing is that I would prefer omitting the unnecessary floating point flag handling.

numpy/core/src/umath/scalarmath.c.src Outdated Show resolved Hide resolved
numpy/core/src/umath/scalarmath.c.src Show resolved Hide resolved
@@ -898,7 +898,8 @@ def test_scalar_integer_operation_overflow(dtype, operation):
@pytest.mark.parametrize("operation", [
lambda min, neg_1: abs(min),
lambda min, neg_1: min * neg_1,
lambda min, neg_1: min // neg_1], ids=["abs", "*", "//"])
pytest.param(lambda min, neg_1: min // neg_1,
marks=pytest.mark.xfail)], ids=["abs", "*", "//"])
Copy link
Member

Choose a reason for hiding this comment

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

Probably need to comment it out or skip this, because it is just too broken...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

At the risk of slightly expanding the scope of this PR, I went ahead and just avoided the actual error-causing computation in the integer division function, setting it to return NPY_MIN_@NAME@ as I think matches gcc behavior (in lieu of true defined behavior, this is the next-best thing imo). The test runs now, and the behavior matches expectations I think.

Copy link
Member

Choose a reason for hiding this comment

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

OK, I would like to backport these division fixes at some point. But I am starting to suspect we should make a PR with those from scratch… (i.e. a backport only PR)

@seberg
Copy link
Member

seberg commented Jun 10, 2022

@ganesh-k13 maybe you want to review/finalize this? @Micky774, unfortunately, I don't quite believe you have double-checked that the tests check everything as advertised :). Can you please make sure we have tests for this new abs path (and the negative one for that matter). Tests that fail without the changes applied.

EDIT: To be clear, modulo making sure the tests actually exist/do what they should, I think this can go in.

@@ -167,7 +167,7 @@ static NPY_INLINE int
}
#if @neg@
else if (b == -1 && a == NPY_MIN_@NAME@) {
*out = a / b;
*out = NPY_MIN_@NAME@;
return NPY_FPE_OVERFLOW;
Copy link
Member

Choose a reason for hiding this comment

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

This is suspicious: is this line really not hit during tests?

Copy link
Member

Choose a reason for hiding this comment

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

Yep #21507 has tests that covers this.

Copy link
Member

Choose a reason for hiding this comment

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

I think both PRs have tests for this, so suspect that it is just in-lining/optimization leading to coverage errors (that might be the first time I have seen coverage failing, but...).

@ganesh-k13 if you prefer it to not be included here, maybe just push the change yourself? (We have to mark that one additional test as skip then probably.) Otherwise, I am happy to merge as-is.

Yes, it would be nice to follow-up to expand the tests so that they raise the error, and there is still lots of little stuff to clear out in multiplication... But at this point it feels like iterating here is getting tricky.

return NULL;
}
Py_XDECREF(errobj);
}
Copy link
Member

Choose a reason for hiding this comment

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

It is suspicious that these new lines are not marked as being tested

Copy link
Member

Choose a reason for hiding this comment

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

Hmmm, right. The first one is OK (I don't think it can be reasonably covered, it indicates an internal/critical error).

To hit the second one, we should also check for:

with np.errstate(over="raise"):
    with pytest.raises(FloatingPointError):
         operation

Copy link
Member

@ganesh-k13 ganesh-k13 left a comment

Choose a reason for hiding this comment

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

Sorry I missed the ping Sebastian, yeah the changes look ok but seems like Azure pipelines shows tests failed for windows builds that need to be checked.

@@ -167,7 +167,7 @@ static NPY_INLINE int
}
#if @neg@
else if (b == -1 && a == NPY_MIN_@NAME@) {
*out = a / b;
*out = NPY_MIN_@NAME@;
Copy link
Member

Choose a reason for hiding this comment

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

I think #21507 will cover it so we can remove this here perhaps? All though I'm happy to rebase if it goes in first.

@seberg
Copy link
Member

seberg commented Jun 12, 2022

Gah, this is a mess... The linux code (mostly) uses npy_mul_with_overflow_@name@ which is probably great and correct when the builtin is available. When it is not available, it seems just plain +wrong for signed inputs.
The overflow checks themselves seem all pretty bogus to be honest? Just xfail the test? We should fix it, but not here... Maybe same with the division test (to be able to pull out the change as Ganesh said).

Sorry that this is a a bit of never-ending story, because these integer overflow checks are so spotty, right now.

@Micky774
Copy link
Contributor Author

Gah, this is a mess... The linux code (mostly) uses npy_mul_with_overflow_@name@ which is probably great and correct when the builtin is available. When it is not available, it seems just plain +wrong for signed inputs. The overflow checks themselves seem all pretty bogus to be honest? Just xfail the test? We should fix it, but not here... Maybe same with the division test (to be able to pull out the change as Ganesh said).

Sorry that this is a a bit of never-ending story, because these integer overflow checks are so spotty, right now.

I just spent the last couple hours eventually finding that check and scratching my head at it, so I appreciate the confirmation that I'm not going insane XD

Yeah it seems there's some systemic revisions necessary here. I suppose the least-invasive, most-likely-to-not-idle result would be to:

  1. Maintain the current changes for abs
  2. Maintain the enabling of the signed-overflow test (via the rename)
  3. Maintain the enabling of the unsigned-overflow test (via removal of xfail)
  4. xfail the multiplication test on the signed-overflow test to defer to a later PR
  5. Tentatively be okay w/ some lack of code coverage, depending on BUG: Better report integer division overflow #21507

Does that sound about right?

And thanks to all of you for your patience with this 😄

Micky774 and others added 2 commits June 12, 2022 14:04
This is because similar changes are already included in a different
PR that fixes up more places where division may have problems.
@seberg
Copy link
Member

seberg commented Jun 13, 2022

OK, just added that commit myself, so that this is again focused only on abs and adding the FPE raising logic (as it also affects negative partially).

I am going to merge it once the tests pass, thanks @Micky774 and Ganesh. @Micky774 it would be cool to look into the open issues here:

  • -min_signed_int was missing the check I think?
  • It would be cool if those tests (well my failed attempt to write some ;)), gets fixed up to also run the code with np.errstate(all="raise") to cover the error path.
  • I really would like to fix up the multiplication, that requires a bit of thought and its own PR though! (not as important as fixing the division stuff, but also somewhat important NEP 50!).

@seberg
Copy link
Member

seberg commented Jun 13, 2022

Only the ppc64le job isn't finished yet not going to wait for that. Thanks.

@seberg seberg merged commit cadfd83 into numpy:main Jun 13, 2022
@Micky774 Micky774 deleted the absolute_byte_overflow branch June 14, 2022 02:42
seberg pushed a commit that referenced this pull request Jun 18, 2022
Related Issues/PRs
Follow-up to #21648

Changes
Adds check to scalar negative for determining whether an overflow warning should be raised for signed integers. Improves testing for negative operator on unsigned integers.
@seberg
Copy link
Member

seberg commented Jun 18, 2022

xref gh-21506 (for an eventual release note summarizing these).

seberg pushed a commit that referenced this pull request Jul 17, 2022
…ication (#21793)

Remane `npy_mul_with_overflow_intp` to `npy_mul_sizes_with_overflow` as it only allows positive numbers.  Then introduce new versions for all integers (not intp) to use it for the integer scalar math with overflow detection.
(It is OK to use everywhere, just for sizes we know they will be positive normally.)

Related to #21506

Follow-up to #21648
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

BUG: abs(np.int8(-128)) should arguably give an OverflowWarning
5 participants