Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Removing the special handling in classlibnative for atan2(±∞, ±∞) and pow(-1.0, ±∞).#10295

Merged
danmoseley merged 2 commits intodotnet:masterfrom
tannergooding:ieee-math
Mar 23, 2017
Merged

Removing the special handling in classlibnative for atan2(±∞, ±∞) and pow(-1.0, ±∞).#10295
danmoseley merged 2 commits intodotnet:masterfrom
tannergooding:ieee-math

Conversation

@tannergooding
Copy link
Member

These functions were incorrectly adjusting the handling for specific edge cases and making them differ from the result specified in IEEE 754.

This resolves https://github.com/dotnet/coreclr/issues/9806 and https://github.com/dotnet/coreclr/issues/9807

@tannergooding
Copy link
Member Author

FYI. @mellinoe

@tannergooding
Copy link
Member Author

tannergooding commented Mar 19, 2017

Also fixed the logic for Pow in the PAL layer to match the current windows behavior and the IEEE spec. This should resolve https://github.com/dotnet/coreclr/issues/10289

Edit: The HAVE_COMPATIBLE_POW check was also broken, so that it would always fail. Fixing it means that Linux and Mac are calling directly into pow with no additional overhead now.

@tannergooding
Copy link
Member Author

The HAVE_COMPATIBLE_EXP logic is currently broken as well. It is failing for Mac and Linux, when it shouldn't be. However, the initial fix I did, seems to block CMAKE on the Linux ARM Emulator Cross Build.

@tannergooding
Copy link
Member Author

The OSX10.12 job is failing, but in a manner unrelated to this PR.

@tannergooding
Copy link
Member Author

OSX10.12 jobs in general seem to have been failing for a while now.

@tannergooding
Copy link
Member Author

This should be good now, @mellinoe.

@mellinoe
Copy link

Someone more familiar with the native code here should probably review this, but I'm supportive of the direction.

@tannergooding
Copy link
Member Author

tagging @janvorli, @AndyAyersMS, and @jkotas, who reviewed things last time I touched this code 😄

Copy link

@dcwuser dcwuser left a comment

Choose a reason for hiding this comment

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

This is a good change. I'm particularly pleased to see that it is accomplished by removing unnecessary checks instead of adding new ones.

{ -2.7182818284590452, 1, -2.7182818284590452, PAL_EPSILON * 10 }, // x: -(e) expected: e
{ -2.7182818284590452, PAL_POSINF, PAL_POSINF, 0 }, // x: -(e)

{ -1.0, PAL_NEGINF, 1.0, PAL_EPSILON * 10 },
Copy link

Choose a reason for hiding this comment

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

These are exact results. Why do we allow variance PAL_EPSILON * 10 instead of PAL_EPSILON or 0?

Copy link
Member Author

@tannergooding tannergooding Mar 20, 2017

Choose a reason for hiding this comment

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

I have a work item to clean up these tests in general (actually doing validation for exact values, and against negative zero, etc). I've already done this in the corefx pr (which adds the managed version of these tests), for the most part. I just haven't gotten to it here yet.

Copy link
Member Author

Choose a reason for hiding this comment

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

As for why PAL_EPSILON * 10, the comment on PAL_EPSILON explains.

Basically, we are allowed 15-17 digits of precision. That is 0.xxxxxxxxxxxxxxxxx (validate against PAL_EPSILON) or x.xxxxxxxxxxxxxxxx (PAL_EPSILON * 10) or xx.xxxxxxxxxxxxxxx (PAL_EPSILON * 100) or even 0.0xxxxxxxxxxxxxxxxx (PAL_EPSILON / 10).

If we just used PAL_EPSILON everywhere, we would get incorrect results for larger or smaller results.

Copy link

Choose a reason for hiding this comment

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

I'm not talking about everywhere, I'm talking about the specific tests you added in this PR, where we can expect the result to be exact, e.g. (-1)^(-inf) = 1.0, not 1.0 +/ 1.0E-15.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, its probably the case that we can expect an exact result here. I was just being consistent with the existing convention here.

There are plenty of things that could be improved. For example, the PAL layer (as a compatibility test) currently checks if atan2(0.0, -0.1) is within 0.0000001 digits of PI, (https://github.com/dotnet/coreclr/blob/master/src/pal/src/configure.cmake#L797), such logic is incredibly broken 😄

I have been working on a separate PR that fixes all of this up, and it will be corrected when that goes out. This PR, at the very least, will fix the validate function to properly check:

  • Exact results
  • NaN
  • -0.0
  • +0.0
  • Negative Infinity
  • Positive Infinity
  • Results that are within 15 digits of the expected value

Copy link
Member Author

Choose a reason for hiding this comment

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

That being said, if you feel strongly about this going in as inexact (especially considering the 1500 other scenarios we validate that are also inexact), I can fix it now, rather than as a whole in the separate PR.

Copy link

Choose a reason for hiding this comment

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

No, this is very minor. I just wanted to understand the reason. It's fine to fix them all in one go later.

@tannergooding
Copy link
Member Author

test OSX10.12 x64 Checked Build and Test please

Looks like jobs are passing now. Will rebase if it fails again.

@tannergooding
Copy link
Member Author

Ping Could I get a review of the PAL/native changes here.

@danmoseley
Copy link
Member

ping of @janvorli, @AndyAyersMS, and @jkotas could someone look?

Copy link
Member

@jkotas jkotas left a comment

Choose a reason for hiding this comment

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

The floating point functions in the PAL exist just to support System.Math, they are not used for anything else.

The behavior of System.Math functions in corner cases will differ from full framework after this change - the tests will need to be special cased for netfx. I think it is fine because of it aligns us with the standard behavior.

@danmoseley danmoseley merged commit 72c57d9 into dotnet:master Mar 23, 2017
jorive pushed a commit to guhuro/coreclr that referenced this pull request May 4, 2017
… pow(-1.0, ±∞). (dotnet#10295)

* Removing the special handling in classlibnative for atan2(±∞, ±∞) and pow(-1.0, ±∞).

* Fixing up the logic for HAVE_COMPATIBLE_POW in the PAL layer.
MichalStrehovsky added a commit to MichalStrehovsky/corert that referenced this pull request May 5, 2017
We need test updates from dotnet/coreclr#10295, but updating the entire
test suite is kind of expensive because it will need rebaselining.
MichalStrehovsky added a commit to dotnet/corert that referenced this pull request May 5, 2017
We need test updates from dotnet/coreclr#10295, but updating the entire
test suite is kind of expensive because it will need rebaselining.
@karelz karelz modified the milestone: 2.0.0 Aug 28, 2017
@tannergooding tannergooding deleted the ieee-math branch May 30, 2018 04:16
EgorBo added a commit to mono/coreclr that referenced this pull request Aug 30, 2018
marek-safar pushed a commit to mono/coreclr that referenced this pull request Aug 30, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Math.Atan2 does not follow IEEE 754 for all inputs

7 participants