[fxtf-drafts] [geometry-1] Is a specific handling for Infinity implied by "NaN-safe minimum/maximum"? (#556)

towerofnix has just created a new issue for https://github.com/w3c/fxtf-drafts:

== [geometry-1] Is a specific handling for Infinity implied by "NaN-safe minimum/maximum"? ==
[Document conventions](https://drafts.fxtf.org/geometry/#conventions) includes the following description for *NaN-safe minimum* and *NaN-safe maximum:*

> The ***NaN-safe minimum*** of a non-empty list of [`unrestricted double`](https://webidl.spec.whatwg.org/#idl-unrestricted-double) values is NaN if any member of the list is NaN, or the minimum of the list otherwise.
>
> Analogously, the ***NaN-safe maximum*** of a non-empty list of [`unrestricted double`](https://webidl.spec.whatwg.org/#idl-unrestricted-double) values is NaN if any member of the list is NaN, or the maximum of the list otherwise.

This was introduced in #395 following discussion in #222 and mailing lists (quoted in the latter issue).

Although Infinity is explicitly mentioned in the (quoted) mailing list, it isn't in the spec or issue discussion.

> On Sat, Oct 15, 2016 at 2:47 PM, Simon Fraser [smfr@me.com](mailto:smfr@me.com) wrote: **(excerpt)**
> Using unrestricted doubles forces implementors to handle NaN and Inf values for x, y, width and height, and to correctly **propagate NaN and Inf** through steps used to calculate left, top, right, bottom (assuming IEEE rules, though the spec does not make this explicit). […] Is the complexity worth it?

> On Oct 16, 2016, at 9:34 AM, Rik Cabanier [cabanier@gmail.com](mailto:cabanier@gmail.com) wrote: **(excerpt, emphasis mine)**
> yes. We allowed this so NaN and Inf would signal when matrix calculations hit edge conditions.
> Instead of throwing or giving inaccurate result, it was decided to **allow the values so authors can check for those.** The alternative would be to throw and we feared that this would break a lot of code since people don't test with exceptions. […]

So I just wanted to ask, is the behavior for Infinity currently defined? At the moment we're using the verb "if ... is NaN" to specify the special behavior ("the NaN-safe minimum … is NaN"), and the default behavior is otherwise only "the minimum of" the list of terms. I don't see definitions or references for what "is NaN" and "the minimum of" mean within this spec, which seems like potentially undefined behavior to me.

<details>
<summary>Test script to observe behavior of infinity on various edges and areas:</summary>

```js
rects = {
  infinityTowardsRight: new DOMRect(0, 0, Infinity, 0),
  infinityTowardsLeft: new DOMRect(0, 0, -Infinity, 0),
  infinityAtRight: new DOMRect(Infinity, 0, 0, 0),
  infinityAtLeft: new DOMRect(-Infinity, 0, 0, 0),
  infinityLeftToRight: new DOMRect(-Infinity, 0, Infinity, 0),
  infinityRightToLeft: new DOMRect(Infinity, 0, -Infinity, 0),

  infinityTowardsBottom: new DOMRect(0, 0, 0, Infinity),
  infinityTowardsTop: new DOMRect(0, 0, 0, -Infinity),
  infinityAtBottom: new DOMRect(0, Infinity, 0, 0),
  infinityAtTop: new DOMRect(0, -Infinity, 0, 0),
  infinityTopToBottom: new DOMRect(0, -Infinity, 0, Infinity),
  infinityBottomToTop: new DOMRect(0, Infinity, 0, -Infinity),

  bottomRightQuadrant: new DOMRect(0, 0, Infinity, Infinity),
  bottomLeftQuadrant: new DOMRect(0, 0, -Infinity, Infinity),
  topRightQuadrant: new DOMRect(0, 0, Infinity, -Infinity),
  topLeftQuadrant: new DOMRect(0, 0, -Infinity, Infinity),

  planeTopBottomLeftRight: new DOMRect(-Infinity, -Infinity, Infinity, Infinity),
  planeTopBottomRightLeft: new DOMRect(Infinity, -Infinity, -Infinity, Infinity),
  planeBottomTopLeftRight: new DOMRect(Infinity, -Infinity, Infinity, -Infinity),
  planeBottomTopRightLeft: new DOMRect(Infinity, Infinity, -Infinity, -Infinity),
};

props = ['x', 'y', 'width', 'height', 'left', 'right', 'top', 'bottom'];

console.log(`Rectangle,` + props.join(','));
for (const [name, rect] of Object.entries(rects)) {
  console.log(`${name},${props.map(p => rect[p]).join(',')}`);
}
```
</details>

<details><summary>Results are conveniently identical in Safari 17.4, Firefox 123, Chrome 122:</summary>

| Rectangle               | x         | y         | width     | height    | left      | right     | top       | bottom    |
|-------------------------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|
| infinityTowardsRight    | 0         | 0         | Infinity  | 0         | 0         | Infinity  | 0         | 0         |
| infinityTowardsLeft     | 0         | 0         | -Infinity | 0         | -Infinity | 0         | 0         | 0         |
| infinityAtRight         | Infinity  | 0         | 0         | 0         | Infinity  | Infinity  | 0         | 0         |
| infinityAtLeft          | -Infinity | 0         | 0         | 0         | -Infinity | -Infinity | 0         | 0         |
| infinityLeftToRight     | -Infinity | 0         | Infinity  | 0         | NaN       | NaN       | 0         | 0         |
| infinityRightToLeft     | Infinity  | 0         | -Infinity | 0         | NaN       | NaN       | 0         | 0         |
| infinityTowardsBottom   | 0         | 0         | 0         | Infinity  | 0         | 0         | 0         | Infinity  |
| infinityTowardsTop      | 0         | 0         | 0         | -Infinity | 0         | 0         | -Infinity | 0         |
| infinityAtBottom        | 0         | Infinity  | 0         | 0         | 0         | 0         | Infinity  | Infinity  |
| infinityAtTop           | 0         | -Infinity | 0         | 0         | 0         | 0         | -Infinity | -Infinity |
| infinityTopToBottom     | 0         | -Infinity | 0         | Infinity  | 0         | 0         | NaN       | NaN       |
| infinityBottomToTop     | 0         | Infinity  | 0         | -Infinity | 0         | 0         | NaN       | NaN       |
| bottomRightQuadrant     | 0         | 0         | Infinity  | Infinity  | 0         | Infinity  | 0         | Infinity  |
| bottomLeftQuadrant      | 0         | 0         | -Infinity | Infinity  | -Infinity | 0         | 0         | Infinity  |
| topRightQuadrant        | 0         | 0         | Infinity  | -Infinity | 0         | Infinity  | -Infinity | 0         |
| topLeftQuadrant         | 0         | 0         | -Infinity | Infinity  | -Infinity | 0         | 0         | Infinity  |
| planeTopBottomLeftRight | -Infinity | -Infinity | Infinity  | Infinity  | NaN       | NaN       | NaN       | NaN       |
| planeTopBottomRightLeft | Infinity  | -Infinity | -Infinity | Infinity  | NaN       | NaN       | NaN       | NaN       |
| planeBottomTopLeftRight | Infinity  | -Infinity | Infinity  | -Infinity | Infinity  | Infinity  | -Infinity | -Infinity |
| planeBottomTopRightLeft | Infinity  | Infinity  | -Infinity | -Infinity | NaN       | NaN       | NaN       | NaN       |
</details>

The consistent behavior is obviously a good sign, but I'd like to know if the spec is already explicit enough and browsers are strictly following it, or if they've just settled on identical behavior here by happenstance.

Also relevant are the definitions for top/left/right/bottom (bottom of [3. The DOMRect interfaces](https://drafts.fxtf.org/geometry/#DOMRect)):

> The top attribute, on getting, must return the [NaN-safe minimum](https://drafts.fxtf.org/geometry/#nan-safe-minimum) of the [y coordinate](https://drafts.fxtf.org/geometry/#rectangle-y-coordinate) and the sum of the y coordinate and the [height dimension](https://drafts.fxtf.org/geometry/#rectangle-height-dimension).
>
> The right attribute, on getting, must return the [NaN-safe maximum](https://drafts.fxtf.org/geometry/#nan-safe-maximum) of the [x coordinate](https://drafts.fxtf.org/geometry/#rectangle-x-coordinate) and the sum of the x coordinate and the [width dimension](https://drafts.fxtf.org/geometry/#rectangle-width-dimension).
>
> The bottom attribute, on getting, must return the [NaN-safe maximum](https://drafts.fxtf.org/geometry/#nan-safe-maximum) of the [y coordinate](https://drafts.fxtf.org/geometry/#rectangle-y-coordinate) and the sum of the y coordinate and the [height dimension](https://drafts.fxtf.org/geometry/#rectangle-height-dimension).
>
> The left attribute, on getting, must return the [NaN-safe minimum](https://drafts.fxtf.org/geometry/#nan-safe-minimum) of the [x coordinate](https://drafts.fxtf.org/geometry/#rectangle-x-coordinate) and the sum of the x coordinate and the [width dimension](https://drafts.fxtf.org/geometry/#rectangle-width-dimension).

Note use of "the sum of".

x, y, width, height are all unrestricted doubles, which ["is a floating point numeric type that corresponds to the set of all possible double-precision 64-bit IEEE 754 floating point numbers, finite, non-finite, and special "not a number" values (NaNs)"](https://webidl.spec.whatwg.org/#idl-unrestricted-double).

I'm not acquainted with IEEE 754 to know if it specifically defines computations for minimum/maximum (which would include details for Infinity, e.g. "the minimum of any set of numbers, not including NaN, and including negative infinity, is negative infinity"), but given the previous concern over NaN propagation being addressed within this spec (rather than externally or implicitly), I'm wondering if Infinity should receive similar treatment.

I also don't know if "is NaN" is explicit enough as-is to imply "is the exact value NaN" (i.e. synonymous with JavaScript [`Number.isNaN`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN)) - I understand it not to imply "infinity is NaN", but this isn't explicit in the spec.

Please view or discuss this issue at https://github.com/w3c/fxtf-drafts/issues/556 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Saturday, 9 March 2024 15:49:20 UTC