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

Support numeric/binary hash comparison for floats derived from Variants (as well as existing semantic comparison) #74588

Merged
merged 1 commit into from
Sep 27, 2023

Conversation

puchik
Copy link
Contributor

@puchik puchik commented Mar 8, 2023

Hash scalar compare for Variants which are floats no longer considers two NaN values as equal.

Hash comparison for Variant continues to perform semantic/logical comparison with NaN's considered equal by default (to prevent #16114, #7354, #6947, #8081, #16031), but now optionally allows for numeric comparison that does not consider NaN's equal to support proper value comparison (for #72222)

  • Added a semantic_comparison argument to existing hash_compare implementation(s) that is set to true by default.
  • Added a hash_comparison_base macro to support existing hash_compare values with default semantic comparison.
  • Dictionary value and arrays use non-semantic/numeric/binary comparisons for floats.

Closes #72222

@puchik puchik requested a review from a team as a code owner March 8, 2023 03:42
@Chaosus Chaosus added this to the 4.1 milestone Mar 8, 2023
@akien-mga akien-mga requested a review from hpvb March 8, 2023 08:20
@akien-mga
Copy link
Member

CC @hpvb who introduced this code back in 2017 with #7815 (+ #8393).

The behavior for Dictionary with NAN keys was then later changed with #16114 to fix #16031. Would this PR reintroduce that bug?

@AThousandShips
Copy link
Member

AThousandShips commented Mar 8, 2023

Because of macros I would keep the parentheses around the values, just to be safe

For example: hash_compare_scalar(a&b,c) would break, not that it's likely to happen but macros are confusing

@AThousandShips
Copy link
Member

Maybe we should add a hash compare that treats NaN as equal and use it for dictionary, where we technically care about binary equality

@vnen
Copy link
Member

vnen commented Mar 8, 2023

I believe this will reintroduce the bug as it is.

@puchik puchik force-pushed the float-variant-nan-inequality branch from deab627 to 759f05b Compare March 11, 2023 20:38
@puchik
Copy link
Contributor Author

puchik commented Mar 11, 2023

Looks like this was quite a controversial series of bugs and decisions 🙂

It does look like to support both the best way I can think of is two functions. I pushed a change that addresses this with I think the least code duplication as possible and doesn't break compatibility.

I tested with the original target issue (#72222) and previous issues (#16114, #7354, #6947, #8081, #16031) and all cases seem covered.

image

@puchik puchik changed the title Do not consider NaNs equal in float values derived from Variant Support numeric/binary hash comparison for floats derived from Variants (as well as existing semantic comparison) Mar 11, 2023
@akien-mga akien-mga modified the milestones: 4.1, 4.2 Jun 19, 2023
Copy link
Member

@Calinou Calinou left a comment

Choose a reason for hiding this comment

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

Tested locally (rebased on top of master b0c3c00), it works as expected.

PR output

1
=======================
false
false
=======================
(-3, 2)
=======================

master output

1
=======================
false
true
=======================
(-3, 2)
=======================

Code

extends Node


func _ready():
	var d = {}
	d[Vector2(NAN, NAN)] = 0
	d[Vector2(NAN, NAN)] = 0
	print(d.size())

	print("=======================")

	var foo = { foo = NAN }
	var bar = { foo = NAN }
	print(foo.foo == bar.foo)  # false
	print(foo == bar)  # true

	print("=======================")

	Vector2(3, -2)
	print(Vector2(-3, 2))

	print("=======================")

	var x = 200 * cos(2 * PI / (0))
	var y = 200 * sin(2 * PI / (0))

@Calinou
Copy link
Member

Calinou commented Jun 22, 2023

PS: In the future, when posting a screenshot of code, please include it in Markdown as well between triple backticks (and the gdscript syntax highlighting language) so that other people can test it easily. (This is also more accessible to screen readers.)

@akien-mga akien-mga requested a review from reduz August 17, 2023 09:51
@puchik puchik force-pushed the float-variant-nan-inequality branch from 759f05b to c9356f3 Compare August 18, 2023 05:17
@reduz
Copy link
Member

reduz commented Aug 18, 2023

This makes sense to me, but hard to know if it will break something. Probably better to give it a go and be very attentive to see what happens.

@puchik puchik requested a review from AThousandShips August 31, 2023 05:19
Hash comparison for Variant continues to perform semantic/logical comparison with NaN's considered equal by default (to prevent godotengine#16114, godotengine#7354, godotengine#6947, godotengine#8081), but now optionally allows for numeric comparison that does not consider NaN's equal to support proper value comparison (for godotengine#72222)
@puchik puchik force-pushed the float-variant-nan-inequality branch from c9356f3 to ee27254 Compare August 31, 2023 16:36
@puchik
Copy link
Contributor Author

puchik commented Sep 1, 2023

I'm not sure if the memory error is a problem with the workflow. Especially because all I changed was the order of the if conditions and it seems to be connected to Vulkan, plus I'm not able to reproduce it.

@akien-mga
Copy link
Member

That's a race condition unrelated to this PR, it happens every now and then. I restarted the build.

@puchik
Copy link
Contributor Author

puchik commented Sep 1, 2023

I see. Thanks!

@akien-mga akien-mga merged commit 737c308 into godotengine:master Sep 27, 2023
@akien-mga
Copy link
Member

Thanks!

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.

Dictionary equality and float equality is inconsistent with NaN values
7 participants