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

±0 handling #14

Open
hax opened this issue Nov 14, 2024 · 6 comments
Open

±0 handling #14

hax opened this issue Nov 14, 2024 · 6 comments

Comments

@hax
Copy link

hax commented Nov 14, 2024

As the current draft:

8. If value is -0𝔽 and min is +0𝔽, return min.
9. If value is +0𝔽 and min is -0𝔽, return min.
10. If value < min, return min.
11. If value is -0𝔽 and max is +0𝔽, return max.
12. If value is +0𝔽 and max is -0𝔽, return max.

The behavior is:

Math.clamp(-0, 0, Infinity) // +0
Math.clamp(0, -0, Infinity) // -0 -- why?
Math.clamp(-0, -Infinity, 0) // +0 -- why?
Math.clamp(0, -Infinity, -0) // -0

I couldn't find the discussion about the behavior related to ±0, and I'm also curious about the rationale behind it.

BTW, I also suggest change the spec text to make the return value much clear:

8. If value is -0𝔽 and min is +0𝔽, return +0𝔽.
9. If value is +0𝔽 and min is -0𝔽, return -0𝔽.
10. If value < min, return min.
11. If value is -0𝔽 and max is +0𝔽, return +0𝔽.
12. If value is +0𝔽 and max is -0𝔽, return -0𝔽.
@ljharb
Copy link

ljharb commented Nov 14, 2024

I would indeed expect:

Math.clamp(-0, 0, Infinity) // +0
Math.clamp(0, -0, Infinity) // +0, because it's greater than -0
Math.clamp(-0, -Infinity, 0) // -0, because it's less than +0
Math.clamp(0, -Infinity, -0) // -0

@theScottyJam
Copy link

Another possible option would be to treat -0 and 0 as equal. If the value being clamped is equal to one of the bounds, prefer returning the value being clamped as opposed to the bounds.

Which means:

Math.clamp(-0, 0, Infinity) // -0, because it's the first argument
Math.clamp(0, -0, Infinity) // +0, because it's the first argument
Math.clamp(-0, -Infinity, 0) // -0, because it's the first argument
Math.clamp(0, -Infinity, -0) // -0, because it's the first argument

It also means the following, by the same logic:

Math.clamp(0, -0, -0); // +0
Math.clamp(0, 0, -0); // +0

This last one, Math.clamp(0, 0, -0), has an intuitive result under this mental model. I'm not really sure what we would want it to return if we wanted to treat -0 as pseudo-less-than +0.

@ljharb
Copy link

ljharb commented Nov 15, 2024

They're not equal, though - if you divide them into 1, you get opposite signed results.

@theScottyJam
Copy link

Depends on the definition of equals. And less than. And greater than.

I would personally expect Math.clamp()'s semantics to be fairly similar to the built-in comparison operators, < and >, which don't treat -0 as different from +0 (while the equality operator does treat them as equal). I don't think we've ever had a spot in the language that compared -0 as less than +0, and it's slightly off-putting to introduce that comparison.

That's at least my gut reaction to this. I'm going to try and see if I can come up with an actual use-case for Math.clamp() with +/-0 arguments - I might not be successful though :).

@theScottyJam
Copy link

Finding a real use-case for this sort of thing turns out to be really hard.

But what I did find out, was that Math.min() and Math.max() do treat -0 as less than +0. So I'm changing my mind - it makes sense to me to have Math.clamp() behave in a similar fashion to Math.min()/Math.max().

I do think it would be good to explicitly decide what the following will return:


I'd assume that we'd want this behavior:

Math.clamp(0, -0, -0); // => -0
Math.clamp(-0, 0, 0); // => 0

And for these, I have no idea:

Math.clamp(0, 0, -0); // => ??
Math.clamp(-0, 0, -0); // => ??

@ljharb
Copy link

ljharb commented Nov 15, 2024

providing an upper bound that's less than the lower bound throws a RangeError, so both would throw.

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

No branches or pull requests

3 participants