Function Properties of the Math Object has a header which says
Each of the following Math object functions applies the ToNumber abstract operation to each of its arguments (in left-to-right order if there is more than one). If ToNumber returns an abrupt completion, that Completion Record is immediately returned. Otherwise, the function performs a computation on the resulting Number value(s). The value returned by each function is a Number.
And then the actual functions are typically defined not using algorithm steps, but rather with a prose description such as
Returns the integral part of the number x, removing any fractional digits. If x is already an integer, the result is x.
followed by some descriptions of edge-case behavior.
I think it would be clearer if these were defined with prose steps which explicitly called ToNumber on each argument, in order, and then handled each edge case in turn, and then had a prose description (or, when possible, precise algorithm) for the usual case.
More context for those who are coming here looking for a good first patch:
Compare the definitions of Math functions in §20.3.2 with a more typical definition: Object.prototype.hasOwnProperty in §19.1.3.2.
A typical definition of an ECMAScript function is given by a sequence of algorithm steps. Sometimes, these definitions also include a human-readable summary of the function's purpose and description/type of its parameters.
The Math functions are defined in an odd way. The Math functions have a summary at the top that is defining normative requirements. Then there's a bulleted list of exceptions to the preceding description. Additionally, there's a rule all the way up in the section header that says ToNumber has to be applied to each argument in order. We'd like to define the Math functions more like how Object.prototype.hasOwnProperty is defined. This means we can leave a loose description of what it does in the summary, but we need to have algorithm steps that can be followed in order to arrive at the return value for any input. In most (if not all) cases, this will mean starting with steps that call ToNumber on each parameter, followed by steps that handle each of the exceptional cases, followed by a step (or steps) that performs the common behaviour that's currently in the summary position.
As far as the markup goes, you should be able to basically follow the pattern you see in the definitions of other functions like hasOwnProperty. If you want to learn more about the <emu-*> tags, you can read more about them in the ecmarkup documentation, but I don't expect you'll need that if you're good at following the pattern of what's already there. Run npm install and npm run build to build the spec locally and review your changes as you go.
can i try tackle this one?
@felipedotcom Of course! Let us know if you start working on it or if you need any further direction.
Something along this line?
When the Math.abs method is called with argument x, The following steps are taken:
1. Let `x` be? ToNumber(x)
2. If Type(x) is Undefined, return **NaN**.
im kinda struggling to find what happen after we call toNumber on x
I started looking at this as well. Here's what I came up with but I'm unclear on the expectations as well.
<emu-clause id="sec-math.abs">
<h1>Math.abs ( _x_ )</h1>
<p>Returns the absolute value of _x_; the result has the same magnitude as _x_ but has positive sign.</p>
<emu-alg>
1. Let _N_ be ? ToNumber(_x_).
1. If _N_ is *NaN*, Return *NaN*.
1. If _N_ is *-0*, Return *+0*.
1. If _N_ is *-∞*, Return *+∞*.
1. Return the absolute value of _N_.
</emu-alg>
</emu-clause>
Which renders as:

@felipedotcom - happy to collab with you on this if you'd like!
I’d probably expect, rather than “the absolute value of”, explicit steps saying something like, if it’s < 0, return -x, else return x
I considered that in this example but it gets rather complex in the others (e.g. Math.atanh). Is it worth spelling out the simple cases but leave the ones mentioned in the "Note" with a more general description?
@michaelficarra said:
followed by a step (or steps) that performs the common behaviour that's currently in the summary position.
So in this case, that final step might be:
1. Return the Number value that has the same magnitude as _N_ but has positive sign.
(Maybe not the best, but it's a possible approach.)
Also:
Return should be lower-case return._N_ should maybe be _n_. (The spec isn't entirely consistent on this, but it generally prefers alias names that start with a lower-case letter.)we could also take this opportunity to explore bigint support, although the changes would require committee time.
i think bigint support should be separate from this attempt to deprose these operations.
@ryanjduffy i would personally prefer dozens of steps, to being concise yet vague :-)
I think it's worth spelling out all the cases which are currently spelled out, although they can be combined where appropriate. For example, for Math.atanh, I would expect something like
Returns an implementation-approximated value representing the arc tangent of _x_. The result is expressed in radians and ranges from -π / 2 to +π / 2.
<emu-alg>
1. Let _n_ be ? ToNumber(_x_).
1. If _n_ is *NaN*, *+0*, or *-0*, return _n_.
1. If _n_ is *+∞*, return an implementation-approximated value representing +π / 2.
1. If _n_ is *-∞*, return an implementation-approximated value representing -π / 2.
1. Return an implementation-approximated value representing the arc tangent of _n_.
</emu-alg>
@ryanjduffy sure :)
How about this:
Returns the absolute value of x; the result has the same magnitude as x but has positive sign.
1. Let _n_ be ? ToNumber(_x_).
2. If Number.isNaN( _n_ ), return true
3. If _n_ is *-0*, return *+0*
4. If _n_ is *-∞*, return *+∞*
5. If _n_ < 0, return ((_n_) * (-1))
Else return _n_
Started a draft PR to provide a place to get some feedback.
Couple questions:
Number.isNaN(_n_) based on the comment above (and @ljharb's :+1:). In other places (e.g. 6.1.6.1.3), the convention appears to be is *NaN*. Which is preferred?@felipedotcom - I've invited you as a collaborator as well.
@ryanjduffy i commented on the PR; we can't observably call into Number.isNaN, and "is NaN" should be sufficient to check for that.
@ryanjduffy I will work on the cbrt up to floor, i forked the repo but I will only be able to work on them tomorrow
Most helpful comment
@ryanjduffy sure :)
How about this: