-
Notifications
You must be signed in to change notification settings - Fork 5.3k
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
8290973: In AffineTransform, equals(Object) is inconsistent with hashCode() #9121
8290973: In AffineTransform, equals(Object) is inconsistent with hashCode() #9121
Conversation
…nd with hashCode().
👋 Welcome back desruisseaux! A progress list of the required criteria for merging this PR into |
@desruisseaux The following label will be automatically applied to this pull request:
When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing list. If you would like to change these labels, use the /label pull request command. |
@desruisseaux This pull request has been inactive for more than 4 weeks and will be automatically closed if another 4 weeks passes without any activity. To avoid this, simply add a new comment to the pull request. Feel free to ask for assistance if you need help with progressing this pull request towards integration! |
Hello, this is a reminder for a pull request: in the |
Webrevs
|
Mailing list message from Philip Race on client-libs-dev: Hardly a "reminder". The PR is just 10 minutes old. Anything before the -phil. On 7/25/22 10:38 AM, Martin Desruisseaux wrote: |
Mailing list message from Martin Desruisseaux on client-libs-dev: Hello Phil Le 25/07/2022 ? 19:44, Philip Race a ?crit?:
Sorry for that noise, but I didn't sent that message today. That message
I was not aware of that page. The last time that I contributed, I have ??? Thanks, ??? ??? Martin |
I've run all tests we have and not too surprised they pass since the affected values However I've been reading the docs about NaN and +/-0 equivalence at Since I recalled that NaN == NaN will always return false, it seemed what you have But then the docs say +0 and -0 should not be equal whereas for backwards compatibility Not sure why only in this case was the compatibility important. I'd like to hear what @jddarcy (Joe Darcy) thinks about all of this. |
Indeed, in this proposed patch +0 is considered equal to -0 mainly for preserving current behaviour. The proposed new But there is also an additional reason. It is because two
A call to
Both translation terms become negative (as expected), including zero. But transforming points with that |
Have you checked all tests ? I did not see it |
*/ | ||
private static long hash(double m) { | ||
long h = Double.doubleToLongBits(m); | ||
if (h == 0x8000000000000000L) h = 0; // Replace -0 by +0. |
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.
Another idiom to accomplish this is
return Double.doubleToLongBits(m + 0.0); // Turn -0.0 to +0.0
For the equals contract, members of an equivalence class should all be equal to each other, meaning they are substitutable for each other in some sense. Different equivalence classes can be defined for the same set of values, one notable example being == (object identity) versus calling .equals(). From my reading of AffineTransform, it should be an acceptable substitution to use -0.0 rather +0.0. As noted a NaN value is "the same" as another NaN in the sense being tested in this method. One way to express this would be to define private static boolean equiv(double a, double b) { Adding 0.0 turn -0.0 into +0.0 and has no other effect. Double.compare treats NaN inputs as the same. This could then do pair-wise comparison of the various components, return equiv(m00, a.m00) && equiv(m01, a.m01) && ... If this is the equals function, than the hash can be a combination of Double.doubleToLongBits(m01 +0.0) ... using adding 0.0 adding to remove the case of -0.0. As is already being done, using doubleToLongBits instead of doubleToRawLongBits is important so that all NaN values get mapped the same. A different equals and hashCode could be constructed if all 90 degree rotations (of the same length) were considered the same, but that would require more work to construct. HTH |
@desruisseaux This change now passes all automated pre-integration checks. ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details. After integration, the commit message for the final commit will be:
You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed. At the time when this comment was updated there had been 877 new commits pushed to the
As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details. As you do not have Committer status in this project an existing Committer must agree to sponsor your change. Possible candidates are the reviewers of this PR (@prrace) but any other Committer may sponsor as well. ➡️ To flag this PR as ready for integration with the above commit message, type |
return (((int) bits) ^ ((int) (bits >> 32))); | ||
} | ||
|
||
/** | ||
* Returns a hash code for the given value, with negative zero | ||
* collapsed into to the single positive zero. |
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.
Should I fix this trivial typo before the merge? ("into to" → "to").
/integrate |
@desruisseaux |
@desruisseaux This pull request has been inactive for more than 4 weeks and will be automatically closed if another 4 weeks passes without any activity. To avoid this, simply add a new comment to the pull request. Feel free to ask for assistance if you need help with progressing this pull request towards integration! |
A ping for preventing this merge request to be automatically closed. This MR has been approved in August 11 and is ready for integration by a committer (if no more comment). |
/sponsor |
Going to push as commit 5c030cc.
Your commit was automatically rebased without conflicts. |
@jayathirthrao @desruisseaux Pushed as commit 5c030cc. 💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored. |
AffineTransform.equals(Object)
andhashCode()
break two contracts:A.equals(A)
returnsfalse
if at least one affine transform coefficient is NaN.A.equals(B)
should implyA.hashCode() == B.hashCode()
, but it is not the case if a coefficient is zero with an opposite sign in A and B.This patch preserves the current behaviour regarding 0 (i.e. -0 is considered equal to +0) for backward compatibility reason. Instead the
hashCode()
method is updated for being consistent withequals(Object)
behaviour.Progress
Issue
Reviewers
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk pull/9121/head:pull/9121
$ git checkout pull/9121
Update a local copy of the PR:
$ git checkout pull/9121
$ git pull https://git.openjdk.org/jdk pull/9121/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 9121
View PR using the GUI difftool:
$ git pr show -t 9121
Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/9121.diff