I was looking at the section ToLength, and compared it and ToInteger to the algorithm for Math.floor, and I was wondering: isn't it basically this? It seems like an odd duplication here considering it's basically simple clamping.
Abstract Operation ToLength(x)
- Let num be ToNumber(x).
- If num is NaN, return +0.
- Return max(0, min(floor(num), 2^53 - 1)).
I'm not sure what you're asking - are you suggesting a simplification of the ToLength algorithm?
Specifically thinking about the edge cases:
| input | current ToLength | proposed ToLength |
| --- | --- | --- |
| +0 | +0 | +0 |
| -0 | +0 | 0 (not sure if positive or negative) |
| +∞ | 2^53 - 1 | not sure, because https://tc39.github.io/ecma262/#sec-mathematical-operations does not clearly define to me how floor works with infinity |
| -∞ | +0 | same as above |
| NaN | +0 | +0 |
| 2^53 - 1 | 2^53 - 1 | 2^53 - 1 |
| 2^53 | 2^53 - 1 | 2^53 - 1 |
| -2^53 - 1 | +0 | 0 (not sure if positive or negative) |
| -2^53 | +0 | 0 (not sure if positive or negative) |
In other words, with your suggestion and the current definition of floor(), and given that if it is +0 or -0 then the corresponding mathematical value is simply 0, I'm not sure what happens with the infinities, nor am I sure what happens with the zeroes.
Explicit steps added to your suggestion could certainly account for these explicitly, for example:
Let num be ? ToNumber(x).
If num is NaN, return +0.
if num <= +0, return +0.
if num is +∞, return 2^53 - 1.
Return max(0, min(floor(num), 2^53 - 1)).
but at that point it's repeating some of the edge cases ToInteger already handles.
What do you think?
@ljharb
I'm not sure what you're asking - are you suggesting a simplification of the ToLength algorithm?
Specifically thinking about the edge cases: [...]
In other words, with your suggestion and the current definition offloor(), and given thatif it is +0 or -0 then the corresponding mathematical value is simply 0, I'm not sure what happens with the infinities, nor am I sure what happens with the zeroes.Explicit steps added to your suggestion could certainly account for these explicitly, for example:
Let num be ? ToNumber(x).
If num is NaN, return +0.
if num <= +0, return +0.
if num is +∞, return 2^53 - 1.
Return max(0, min(floor(num), 2^53 - 1)).but at that point it's repeating some of the edge cases ToInteger already handles.
What do you think?
That's probably more what I'm going for. If you created a Max(a, b) and a Min(a, b) that carried the semantics of Math.max + Math.min, you could use those for the more correct simplification. Adding those would tie into #1422, too, so I might go for an editorial PR that combines these two.
@isiahmeadows If you created a Max(_a_, _b_) and a Min(_a_, _b_) that carried the semantics of
Math.max+Math.min...
In that case, don’t call them Max(_a_, _b_) / Min(_a_, _b_), but NumberMax(_a_, _b_) / NumberMin(_a_, _b_), to make clear that they’re concerning Number values; because max()/min() might be used in context where Number values and real numbers don’t match (specifically, outside the set of nonnegative integers not larger than 253).
In addition to what Claude said, the functions defined in 5.2.5 Mathematical Operations are also not defined for non-finite values and -0/+0 are collapsed into a single 0 value.
@claudepache @anba Yeah, I'm finding this out. I'm just suggesting abstract operations that sugar over these mathematical operations for the relevant methods should exist. They'd simplify some of the more math-y stuff like ToLength and friends.
Most helpful comment
In addition to what Claude said, the functions defined in 5.2.5 Mathematical Operations are also not defined for non-finite values and -0/+0 are collapsed into a single 0 value.