-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathMath.signbit.bs
150 lines (113 loc) · 4.73 KB
/
Math.signbit.bs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
<pre class='metadata'>
Title: Math.signbit
Shortname: Math.signbit
Revision: 0
Status: Stage1
Group: TC39
!Source: <a href="https://github.com/tc39/proposal-Math.signbit/blob/master/Math.signbit.bs">github.com/tc39/proposal-Math.signbit/blob/master//Math.signbit.bs</a>
Editor: JF Bastien, Apple, jfbastien@apple.com
ED:
Abstract:
Date: 2017-01-26
Markup Shorthands: markdown yes
</pre>
IEEE 754 has a precise meaning for *sign bit*. JavaScript's `Math.sign` falls
short on `-0.0` and `+0.0`. This is a shortcoming of a "batteries included"
approach to language design.
Correctly obtaining the sign bit of a Number in JavaScript is somewhat
unintuitive: the naïve `x < 0` approach fails if `x` is `-0.0` because `0.0` and
`-0.0` compare equal to each other.
One can instead rely on division by zero returning one of `-Infinity` or
`+Infinity`: `1.0 / x < 0`. This now has the interesting caveat of returning
`NaN` if `x` was `NaN`. It's also highly counter-intuitive.
JavaScript aficionado will know that `Object.is(-0, x)` will return `true` when
`x` is `-0` but not when it's `0`. This is surprising for developers who are
more numerics-oriented than object-—dare I say prototype-?—oriented. These
developers just want the sign bit, IEEE 754 has a very precise definition of
what the sign bit is, and why can't JavaScript just give them the sign bit?
This issue [has been discussed previously](https://esdiscuss.org/topic/math-sign-vs-0)
but was never addressed. We believe that this proposal can fix this
oft-encountered problem once and for all.
Revision History {#rev}
================
* Presented at the [2017-01](https://github.com/tc39/tc39-notes/blob/master/meetings/2017-01/jan-25.md#13id-seeking-stage--00-for-ieee-754-sign-bit) TC39 meeting and moved to Stage 1.
Background {#bg}
==========
IEEE 754 {#ieee754}
--------
[[IEEE754]] section 5.5.1 defines *sign bit operations*. These operations are
quiet-computational operations which only affect the sign bit of the arithmetic
format. The operations treat floating-point numbers and NaNs alike, and signal
no exception. As defined, they may propagate non-canonical encodings.
The following operations are defined:
* `copy`
* `negate`
* `abs`
C / C++ {#cpp}
-------
[[C]] and [[Cpp]] define `signbit` in `<math.h>` and `<cmath>` respectively. It
returns a nonzero `int` value if and only if the sign of its argument value is
negative. The `signbit` macro reports the sign of all values, including
infinities, zeros, and NaNs.
Go {#go}
---
[[Go]]'s math package defines `Signbit` as `true` if `x` is negative or negative
zero. While the specification is silent on NaN,
[the implementation](https://golang.org/src/math/signbit.go) clearly extracts the
sign bit regardless of NaN-ness.
`Math.sign` {#sign}
-----------
JavaScript provides `Math.sign` which is specified as follows:
<blockquote>
Returns the sign of the x, indicating whether x is positive, negative or zero.
* If `x` is `NaN`, the result is `NaN`.
* If `x` is `-0`, the result is `-0`.
* If `x` is `+0`, the result is `+0`.
* If `x` is negative and not `-0`, the result is `-1`.
* If `x` is positive and not `+0`, the result is `+1`.
</blockquote>
This falls short when dealing with `-0` and `+0` since these values both compare
equal.
Proposal {#proposal}
========
Given existing precedent as well as common hardware support, we propose adding
`Math.signbit` to JavaScript as follows.
`Math.signbit(x)` {#spec}
-----------------
Returns whether the sign bit of `x` is set.
1. If `n` is `NaN`, the result is `false`.
1. If `n` is `-0`, the result is `true`.
1. If `n` is negative, the result is `true`.
1. Otherwise, the result is `false`.
Note: The "Function Properties of the Math Object" section already states:
"Each of the following `Math` object functions applies the `ToNumber` abstract
operation to each of its argument."
Alternatives {#alts}
------------
This proposal makes decisions which TC39 may want to consider modifying:
* Coercison `ToNumber`.
* The return type is Boolean.
* NaN is equivalent to a positive number.
<pre class=biblio>
{
"IEEE754": {
"href": "https://standards.ieee.org/standard/754-2019.html",
"title": "IEEE 754-2019",
"publisher": "IEEE Computer Society"
},
"C": {
"href": "http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf",
"title": "Programming Languages — C",
"publisher": "ISO/IEC JTC1 SC22 WG14"
},
"Cpp": {
"href": "http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3797.pdf",
"title": "Programming Languages — C++",
"publisher": "ISO/IEC JTC1 SC22 WG21"
},
"Go": {
"href": "https://golang.org/pkg/math/",
"title": "The Go Programming Language — Package math"
}
}
</pre>