archives

« Bugzilla Issues Index

#309 — Community Feedback on Harmony Math functions proposal


This item is for tracking community feedback and feature requests relating to the the Harmony Math related proposals (http://wiki.ecmascript.org/doku.php?id=harmony:more_math_functions and others ).

Anybody with such feedback should record it as a comment on this bug.



> This item is for tracking community feedback and feature requests relating to
> the the Harmony Math related proposals
> (http://wiki.ecmascript.org/doku.php?id=harmony:more_math_functions and others
> ).
>
> Anybody with such feedback should record it as a comment on this bug.

Has anyone considered setting limits for the maximum error of different functions?

Most of the added functions in that proposal are quite a bit less useful unless the results are guaranteed to be better than just implementing them in JS. Accuracy currently varies a bit between browsers (and platforms) which is a bit annoying.


(In reply to comment #1)
> Has anyone considered setting limits for the maximum error of different
> functions?
>
> Most of the added functions in that proposal are quite a bit less useful unless
> the results are guaranteed to be better than just implementing them in JS.
> Accuracy currently varies a bit between browsers (and platforms) which is a bit
> annoying.

Agreed.

The whole point of Math.log2, Math.log10, Math.log1p, Math.expm1 is to be more accurate than the user could achieve with a simplistic approach.
Math.hypot too should accurately control cancellation errors (as well as avoiding overflow and managing Infinity).
Math.cbrt (if it comes to pass) also manages accuracy.

It should be possible to make a 1 ULP guarantee to most (all?) Math functions, though the exact nature of this issue is assumed to be a "hard problem" in computer science.

See also the Table Maker's Dilemma:
http://en.wikipedia.org/wiki/Rounding#The_table-maker.27s_dilemma


(In reply to comment #2)
> (In reply to comment #1)
> > Has anyone considered setting limits for the maximum error of different
> > functions?
> >
> > Most of the added functions in that proposal are quite a bit less useful unless
> > the results are guaranteed to be better than just implementing them in JS.
> > Accuracy currently varies a bit between browsers (and platforms) which is a bit
> > annoying.
>
> Agreed.
>
> The whole point of Math.log2, Math.log10, Math.log1p, Math.expm1 is to be more
> accurate than the user could achieve with a simplistic approach.
> Math.hypot too should accurately control cancellation errors (as well as
> avoiding overflow and managing Infinity).
> Math.cbrt (if it comes to pass) also manages accuracy.
>
> It should be possible to make a 1 ULP guarantee to most (all?) Math functions,
> though the exact nature of this issue is assumed to be a "hard problem" in
> computer science.
>
> See also the Table Maker's Dilemma:
> http://en.wikipedia.org/wiki/Rounding#The_table-maker.27s_dilemma

While it is correct that the "Table Maker's Dilemma" is a problem for general transcendental functions, I think that the ones currently proposed could be correctly rounded; I did a quick check through the IEEE 754-2008 standard and most (if not all) functions are on 'Recommended correctly rounded functions 9.2.0' list.


Re: Special Values in the es6libraryextensions.pdf document

Note that sometimes the text has "if x is +0 or -0" other times both cases are enumerated even if the result is the same. Maybe choose one style or the other for consistency.

This document has a couple of issues in the Special Values of new Math functions:

Math.acosh
add new line "If x is -Inf, the result is +Inf"
Math.expm1(−Inf) -> −1
as already noted in Harmony bug 262
Math.hypot
the statement "the result is y" is incorrect, result should be abs(y);
also, the check for infinite x or y should be done before the check for NaN
for IEEE754 conformance (see below)


IEEE754 has hypot of +/-Infinity with anything (even NaN) as +Infinity:
hypot(Infinity,NaN) == hypot(NaN,-Infinity) == ... == Infinity

This is similar to the existing Math.pow which conforms to IEEE754 handling of the indefinite number NaN:
Math.pow(NaN,0) -> 1
(which is correct since pow(x,0)==1 for all x).


Re: Math.hypot

There seems to be agreement on making Math.hypot variadic: Math.hypot(x,y,z,...)

The use cases in 3D geometry etc are obvious.

Probably the function's arity should remain 2 (Math.hypot.length==2). If given no arguments the return value should probably be 0 (not NaN), although what meaning does the Euclidean distance have in a 0-dimensional space?


The documentation of Math.hypot should point out that hypot avoids overflow
and minimises rounding errors. Otherwise people might be tempted to naively use Math.sqrt on the sum of the squares. This is easily implemented by dividing through by the largest argument then multiplying back at the end (see pseudocode below).

As noted in comment 4 above, the hypot of +/-Infinity with anything (even NaN) should be +Infinity.

Pseudocode implementation:
scan the arguments noting the maximum absolute value, maxabs;
if (maxabs is infinite) return Infinity;
if (any of the arguments was NaN) return NaN;
if (maxabs == 0) return 0;
divide each argument by maxabs;
take the sqrt of the sum of the squares of the arguments, r;
return r * maxabs;

There are a couple of speedups possible, such as the early detection of arguments.length being 0 or 1. Otherwise take care of the value of maxabs if there are no arguments. You might also want to sum the squared arguments from smallest to largest in an attempt to squeeze a little extra precision.


Re: proposed new function Math.cbrt

Several math libraries have the cube-root elementary function: cbrt.
The proposal is for JavaScript to follow suit.

cbrt is more accurate than pow(x,1/3) and does not have a domain error for x<0.
Unlike pow() it has the special values:
Math.cbrt(-0) -> -0
Math.cbrt(-Infinity) -> -Infinity
because it is an odd function and therefore has rotational symmetry about the Origin (like sin(), tan(), etc).

Specific use cases were not given, but observe that cbrt is arguably almost as generally useful as sqrt. cbrt handles a negative domain (x<0) with no nasty drama, unlike pow which returns NaN - forcing the user to check and correct before invoking.


Comparing against Math.pow:
1) cbrt is more explicit about -0 and -Infinity, whereas pow deals with the
general case. (Note that sqrt is also explicit about -0.)
2) cbrt correctly handles a negative domain (x<0) with no nasty drama,
whereas pow returns NaN.
3) Obviously, cbrt is more accurate than pow since 1/3 is not exact in
floating-point, and the error compounds internally.


I offer the following implementation of Math.cbrt ...

Math.cbrt = function (x)
{
x = +x; // guard against non-numeric

// handle NaN, infinities, zeroes -- thus avoid Inf/Inf and 0/0

if (isNaN( x/x )) return x;

// estimate the cube root well;
// then improve by Halley's Method (more accurate ULP than Newton's!)

var r = Math.pow( Math.abs(x), 1/3 );
var t = x/r/r; // safe!
return r + (r * (t-r) / (2*r + t));
};


Re: rename Math.sign to Math.signum

There isn't overwhelming precedent in either direction here. To the extent there is precedent, it seems slightly in favor of 'sign', and it's slightly less cryptic.

One could argue that it's an advantage to be slightly more cryptic while remaining within well-accepted norms, see point 2 below.

The sign function complements the abs (magnitude) function.


The case for 'signum':

1) Clearly the word "sign" has meaning on the Real line, but think of the Complex plane where the range of the "sign" function is the union of a circle of Unit Magnitude (note: UM) and the zeroes. A complex number, z, in polar coordinates has a magnitude/modulus/amplitude, r, and an argument/phase, theta; where r=abs(z) and theta=sign[um](z).

2) Also, the so-called "sign" function actually returns information about the magnitude as well as the +/- sign when the magnitude is a 0, and always implicitly returns the zero/nonzero status of the magnitude:
Math.sign[um](-0) -> -0
Math.sign[um](0) -> 0

3) JavaScript often seems to follow Java's philosophy, and Java has 'signum'.

4) Wikipedia says 'signum' is to avoid confusion with the sine function, (but maybe it isn't sufficiently confusing!):
http://en.wikipedia.org/wiki/Sign_function


The case for 'sign':

5) It is the actual mathematical name for the function.

6) The function is already currently called 'sign', just stick with that.

7) Fewer characters to type.

8) Less cryptic.


This is pretty vague, but 'signum' just feels to me better than 'sign', in the light of the above. (But it is a 50-50 call!)


PS:
Here is an implementation that works with +0 and -0 and NaN and non-numerics ...

function(x) { return (x>0)? 1 : (x<0)? -1 : +x; }


(In reply to comment #5)
> Re: Math.hypot
>
> There seems to be agreement on making Math.hypot variadic:
> Math.hypot(x,y,z,...)
>
> The use cases in 3D geometry etc are obvious.
>
> Probably the function's arity should remain 2 (Math.hypot.length==2). If given
> no arguments the return value should probably be 0 (not NaN), although what
> meaning does the Euclidean distance have in a 0-dimensional space?
>
>
> The documentation of Math.hypot should point out that hypot avoids overflow
> and minimises rounding errors. Otherwise people might be tempted to naively
> use Math.sqrt on the sum of the squares. This is easily implemented by
> dividing through by the largest argument then multiplying back at the end (see
> pseudocode below).
>
> As noted in comment 4 above, the hypot of +/-Infinity with anything (even NaN)
> should be +Infinity.
>
> Pseudocode implementation:
> scan the arguments noting the maximum absolute value, maxabs;
> if (maxabs is infinite) return Infinity;
> if (any of the arguments was NaN) return NaN;
> if (maxabs == 0) return 0;
> divide each argument by maxabs;
> take the sqrt of the sum of the squares of the arguments, r;
> return r * maxabs;
>
> There are a couple of speedups possible, such as the early detection of
> arguments.length being 0 or 1. Otherwise take care of the value of maxabs if
> there are no arguments. You might also want to sum the squared arguments from
> smallest to largest in an attempt to squeeze a little extra precision.

I am still against it, mildly, only because the name does no longer make sense in my opinion. It does no longer calculate the hypotenuse of a right-angled triangle. Why not add both hypot (2-arity) and norm2 with an array argument?

Possibly adding at the same time, add some more vector functions from BLAS L1. They have fast implementations on all platforms and many of them are quite obviously useful for games.


Re: variadic Math.hypot

> I am still against it, mildly, only because the name does no longer make sense
> in my opinion. It does no longer calculate the hypotenuse of a right-angled
> triangle. Why not add both hypot (2-arity) and norm2 with an array argument?
>
> Possibly adding at the same time, add some more vector functions from BLAS L1.
> They have fast implementations on all platforms and many of them are quite
> obviously useful for games.

The Math library contains the elementary mathematical functions (plus a couple of numeric functions that sneaked in).

I would love to see a BLAS library, and LAPACK, taking array-like vectors & matrices as arguments. But not in the 'Math' namespace. (If you know of a BLAS lib please private-email me.)

3-adic 'hypot' (or whatever it's called) is useful in basic 3D geometry for those who don't want to go the whole Linear Algebra route. Not least in converting rectangular x-y-z coordinates into spherical lat-lng-alt -- [this is nice for dealing with other 3D spaces such as colorspace, map grid conversion, astronomy (especially heliocentric coordinates), others?].

I'd be happy with a 'hypot' that is restricted to have either 2 or 3 arguments.


The name "hypot" is well-established in 2D and could easily be extended to 3D, but what would you call it?

The word "norm2" invites people to think of general vectors not coordinates (i.e. position vectors). And it sounds a bit funny when it takes 3 arguments (cf. 'atan2'). It also invites the question: if you've got 2-norms why not 1-norms and Inf-norms and ...

Other words could be based on "Euclidean distance" or "radius vector" or even "proper length". But nothing really jumps out as very pleasant or better than boring old standard "hypot".

I've seen 3-adic 'hypot' called "hypot3" in places. But why invent a new name when JavaScript easily copes with variable arguments?

Would you really want a different name for the 3D version of the simple 2D sqrt(x*x+y*y) concept?


(In reply to comment #4)
> Re: Special Values in the es6libraryextensions.pdf document
>
> Math.acosh
> add new line "If x is -Inf, the result is +Inf"

Whoops, that line should not be added (I was thinking of cosh).
acosh(-Inf) is of course a domain error (x<1).


(In reply to comment #9)
> Re: variadic Math.hypot
>
> The Math library contains the elementary mathematical functions (plus a couple
> of numeric functions that sneaked in).
>
> I would love to see a BLAS library, and LAPACK, taking array-like vectors &
> matrices as arguments. But not in the 'Math' namespace. (If you know of a
> BLAS lib please private-email me.)

I agree, vectors should not be stuck in Math. (And probably would depend on something like Typed Arrays)

> 3-adic 'hypot' (or whatever it's called) is useful in basic 3D geometry for
> those who don't want to go the whole Linear Algebra route. Not least in
> converting rectangular x-y-z coordinates into spherical lat-lng-alt -- [this is
> nice for dealing with other 3D spaces such as colorspace, map grid conversion,
> astronomy (especially heliocentric coordinates), others?].
>
> I'd be happy with a 'hypot' that is restricted to have either 2 or 3 arguments.

It is definitely a useful operation.

> The name "hypot" is well-established in 2D and could easily be extended to 3D,
> but what would you call it?
>
> The word "norm2" invites people to think of general vectors not coordinates
> (i.e. position vectors). And it sounds a bit funny when it takes 3 arguments
> (cf. 'atan2'). It also invites the question: if you've got 2-norms why not
> 1-norms and Inf-norms and ...

That was the intention and was just something I was throwing around together with L1 BLAS, which would add those other norms etc.

> Other words could be based on "Euclidean distance" or "radius vector" or even
> "proper length". But nothing really jumps out as very pleasant or better than
> boring old standard "hypot".

I agree, if there is nothing significantly better than that, then 'hypot' is a good compromise.

> I've seen 3-adic 'hypot' called "hypot3" in places. But why invent a new name
> when JavaScript easily copes with variable arguments?
>
> Would you really want a different name for the 3D version of the simple 2D
> sqrt(x*x+y*y) concept?

I agree that there is no point in creating an additional 'hypot3' because then we just create a confusing variadic 'hypot' with a weird implementation.


> The name "hypot" is well-established in 2D and could easily be extended to 3D,
> but what would you call it?
The hypot function is sometimes also called Pythagorean sum/addition.
(http://en.wikipedia.org/wiki/Pythagorean_addition)
Moler and Morrison (They found an algorithm for hypot without taking square roots, link to their paper in the Wikipedia article) call this function "pythag". But I don't like this name very much, I'd stick with hypot and make it variadic (even if hypotenuse isn't making sense for three or more arguments).

> I'd be happy with a 'hypot' that is restricted to have either 2 or 3 arguments.
Moler and Morrison made an other interesting point in their paper; they calculate the hypot function with more than two arguments recursively
hypot(a, b, c) = hypot(a, hypot(b, c))
and discuss the advantages of doing it this way.
So if we have a good implementation of hypot(a, b), it should be no problem to support 3 or more arguments. Therefore I see no reason of being restricted to 2 or 3 arguments.
Of course one problem with this approach is speed, because we have to call hypot n-1 times for n arguments.


(In reply to comment #12)
Re: Math.hypot implementation technique
> Moler and Morrison (They found an algorithm for hypot without taking square
> roots, link to their paper in the Wikipedia article) call this function
> "pythag".

Nice find.

However Moler & Morrison's pythag is less accurate than the sqrt technique:
pythag(3,4) == 5.000000000000001 == 5 + 2^-50
4*sqrt(1+3/4*3/4) == 5 == sqrt(3*3+4*4) // not just because 4 is 2^2

Presumably this is because sqrt is well-implemented to better than 1 ULP and then suffers from a single multiply; whereas pythag accumulates several rounding errors in the "p" variable, significantly worse than 1 ULP.

Also note that sqrt is typically a basic function of hardware floating-point units. Hence fast (and internally calculated to extended precision too) on decent systems with a hardware FPU.

In 1983 Moler & Morrison were only concerned with avoiding "excessive" rounding errors, not achieving 1 ULP within the confines of machine precision.


> Moler and Morrison made an other interesting point in their paper; they
> calculate the hypot function with more than two arguments recursively
> hypot(a, b, c) = hypot(a, hypot(b, c))
> and discuss the advantages of doing it this way.
> So if we have a good implementation of hypot(a, b), it should be no problem to
> support 3 or more arguments. Therefore I see no reason of being restricted to > 2 or 3 arguments.
> Of course one problem with this approach is speed, because we have to call
> hypot n-1 times for n arguments.

The rounding error accumulates quite badly as the number of arguments increases. In 1983 Moler & Morrison didn't consider this "excessive", but we can do better now.


(In reply to comment #13)

> However Moler & Morrison's pythag is less accurate than the sqrt technique:
> pythag(3,4) == 5.000000000000001 == 5 + 2^-50
> 4*sqrt(1+3/4*3/4) == 5 == sqrt(3*3+4*4) // not just because 4 is 2^2
>
> Presumably this is because sqrt is well-implemented to better than 1 ULP and
> then suffers from a single multiply; whereas pythag accumulates several
> rounding errors in the "p" variable, significantly worse than 1 ULP.
>
> …
>
> In 1983 Moler & Morrison were only concerned with avoiding "excessive" rounding
> errors, not achieving 1 ULP within the confines of machine precision.

The number 1 here seems magic, if the specification should demand anything, it should probably follow the IEEE 754-2008 recommendation that the hypot function (for arguments of length 2) should be correctly rounded.

> The rounding error accumulates quite badly as the number of arguments
> increases. In 1983 Moler & Morrison didn't consider this "excessive", but we
> can do better now.

A recommendation that it should use an algorithm that provides a good trade-off between accuracy, performance and over-/underflow (for arguments of longer length than 2) should be enough. I doubt that most BLAS NRM2 implementations are accurate for especially evil inputs.


Re: summary of variadic Math.hypot

This is hopefully a summary of the recent interesting Math.hypot discussion.

Math.hypot should take either 2 or 3 arguments, rather than being fully variadic. 2 is normal, 3 is a straightforward extension to 3D geometry. (Otherwise we get into over-complicated issues with vector 2-norms, etc.)

Math.hypot's arity should be 2 (the normal case), i.e. Math.hypot.length==2.

It should remain named "hypot", which has become standard terminology, even though the diagonal of a cuboid is not really a "hypotenuse".

Math.hypot of +/-Infinity with anything (even NaN) is +Infinity:
hypot(Infinity,NaN) == hypot(NaN,-Infinity,NaN) == ... == Infinity

The documentation should point out that Math.hypot:
1) always avoids underflow,
2) avoids overflow if possible,
3) minimises rounding errors.

In the documentation: the incorrect statement "the result is y" should be fixed.


Re: implementation of 'log1p' and 'expm1'

There are a couple of simple implementations of 'log1p' -- has anyone analysed their accuracy considering the hard work in a polynomial approximation (to better than 1ULP)?
(http://en.wikipedia.org/wiki/Approximation_theory#Remez.27_algorithm)

log1p(x) = function(x) {
if (isNaN( x ) || x == Infinity || x == 0) return x;
var xp1 = x+1;
return (xp1 == 0)? -Infinity : Math.log(xp1) - ((xp1-1)-x)/xp1; // (1)
return (xp1 == 1)? x : Math.log(xp1) * (x/(xp1-1)); // (2)
};

Version (2) is believed accurate to a few ULP. Version (1) seems better.
They both seem suspiciously simple.


For 'expm1', is it necessary to find a polynomial approximation, or is evaluating the 'exp' power series without the first term good enough?


(With a good 'expm1' the hyperbolic functions can be good;
with a good 'log1p' the inverse hyperbolic functions can be good.)


Re: Number.isNaN & Number.isFinite

If 'isNaN' and 'isFinite' are being carried over from the global namespace into
'Number', then we could take the opportunity likewise to carry 'parseFloat' and
'parseInt' for completeness:
isNaN -> Number.isNaN
isFinite -> Number.isFinite
parseInt -> Number.parseInt
parseFloat -> Number.parse

See Bug 314's 6th comment for more on the possible improvements to parseFloat.


I've uploaded a new draft of proposed ES6 library extensions spec
(http://wiki.ecmascript.org/doku.php?do=show&id=harmony%3Amore_math_functions).

This so far addresses the following asks from this thread:
- Support for 2- and 3- arg variants of hypot
- Adds hypot2 which computes sum of squares
- Adds cbrt
- Addresses bugs and editorial inconsistency in description of special values

Other topics raised here, including specification of accuracy and under/overflow requirements, will be discussed at TC39 f2f this week.


I have quite a few times been annoyed by the lack of a fused multiply-add function in ES, and wondered if anyone have any arguments against adding it? It is available in the C99 standard, and most non-x86 hardware has support for it.

It is useful for a lot of things, but mainly when implementing high-precision double-double arithmetic, to increase accuracy when calculating dot products, matrix operations, evaluating polynomials or when trying to implement other transcendental functions.

The current solution of faking it is a bit suboptimal performance-wise.


(In reply to comment #19)
> I have quite a few times been annoyed by the lack of a fused multiply-add
> function in ES, and wondered if anyone have any arguments against adding it? It
> is available in the C99 standard, and most non-x86 hardware has support for it.
>
> It is useful for a lot of things, but mainly when implementing high-precision
> double-double arithmetic, to increase accuracy when calculating dot products,
> matrix operations, evaluating polynomials or when trying to implement other
> transcendental functions.
>
> The current solution of faking it is a bit suboptimal performance-wise.

+1.
A fused multiply-add (FMA) facility would improve IEEE754 conformance, but it needn't be a named function.

For comments about FMA ("a mixed blessing") see page 5 of William Kahan's 1997 lecture notes on IEEE754:
http://www.cs.berkeley.edu/~wkahan/ieee754status/IEEE754.PDF

He suggests using parentheses to decide when to use FMA in arithmetic:
(a*b+c) // FMA
(a*b+c*d) // no FMA
(a*b+(c*d)) // FMA
((a*b)+c*d) // FMA

FMA should be available in a conforming hardware FPU.


> A fused multiply-add (FMA) facility would improve IEEE754 conformance, but it
> needn't be a named function.
>
> For comments about FMA ("a mixed blessing") see page 5 of William Kahan's 1997
> lecture notes on IEEE754:
> http://www.cs.berkeley.edu/~wkahan/ieee754status/IEEE754.PDF
>
> He suggests using parentheses to decide when to use FMA in arithmetic:
> (a*b+c) // FMA
> (a*b+c*d) // no FMA
> (a*b+(c*d)) // FMA
> ((a*b)+c*d) // FMA

This changes the semantics of existing programs, so in my opinion it is a _really_ bad idea. A function allows us to stay backwards compatible with older applications that depend on the current version of the language.

In addition, performance would probably suffer since the most common platform (x86) does generally _not_ have hardware FMA (but you can do it easily in software, and AMD Bulldozer and Intel's upcoming Haswell provide competing FMA implementations.)


(In reply to comment #18)
> I've uploaded a new draft of proposed ES6 library extensions spec
> (http://wiki.ecmascript.org/doku.php?do=show&id=harmony%3Amore_math_functions).
>
> This so far addresses the following asks from this thread:
> - Adds hypot2 which computes sum of squares
>[snip]

Thanks for the feedback. A couple of questions on the new spec.

What's the point of Math.hypot2?
The sum of squares is easily computed arithmetically, and there is no chance of avoiding overflow (unlike plain hypot). The name looks funny when the '2' means 'squared' not 'takes 2 arguments' (cf. Math.atan2).

Why Number.parseFloat not Number.parse?
Just thinking of Date.parse which parses a Date, so Number.parse would parse a Number, and Foo.parse parse a Foo. Whereas Number.parseInt parses a special sort of Number.


(In reply to comment #21)
> > He suggests using parentheses to decide when to use FMA in arithmetic:
>
> This changes the semantics of existing programs, so in my opinion it is a
> _really_ bad idea. A function allows us to stay backwards compatible with older
> applications that depend on the current version of the language.
>
> In addition, performance would probably suffer since the most common platform
> (x86) does generally _not_ have hardware FMA (but you can do it easily in
> software, and AMD Bulldozer and Intel's upcoming Haswell provide competing FMA
> implementations.)

Fair enough.

May I suggest it is called Number.muladd or Number.FMA -- in the Number namespace since it is arithmetic:
Number.muladd(a,b,c) // returns a+(b*c)


Re: String.prototype.repeat

Should String.prototype.repeat limit the repetition count, to avoid >8 gigabyte string results?
What if the count is negative?


Re: String.prototype.reverse

The steps are numbered from 8 not 1.
The description refers to an Array not a String.


Since a String.prototype.reverse function is being carried over from Array, do you want to invent String.prototype.splice too?


Re: String.prototype.endsWith

The description for String.prototype.endsWith has a typo: "endPoisition"


Re: String.prototype.contains

obj.contains( searchString, position )
is equivalent to
(obj.indexOf( searchString, position ) >= 0)

Why define a new function for this simple procedure?


Re: String.prototype.toArray

str.toArray()
is equivalent to
str.split('')

Why define a new function for this simple procedure?


Re: Number.EPSILON & Number.MAX_INTEGER

The descriptions of these refer to Number.MAX_VALUE not these properties.


Thanks for great feedback. I've updated the draft.

Re: String.prototype.repeat
I've updated the spec text to use ToUInt32. This matches spec convention for things like new Array(len).

Re: String.prototype.reverse
This was actually intended to be removed, based on previous TC39 feedback about issues with reversing surrogate pairs.

Re: String.prototype.endsWith
Typo corrected.

Re: String.prototype.contains
Re: String.prototype.toArray
These are developer conveniences based on frequent requests and expectations from other programming languages and developer platforms.

Re: Number.EPSILON & Number.MAX_INTEGER
Type fixed.


(In reply to comment #29)
> Thanks for great feedback. I've updated the draft.

Looking at es6libraryextensions-3-28-12.2.pdf ...


Re: Number.MAX_INTEGER

In the PDF there is a large space between "MAX_INTEGER is the largest".


Re: String.prototype.repeat

Much nicer.
But still allows the programmers to easily specify enormous strings with length len*count. Maybe that's OK, after all they can easily shoot themselves in the foot in other ways e.g. an infinite loop like 'for i=1 to 2^54 step 1'.

What happens to "longstring".repeat(0xFFFFFFFF) -- do they wait a long time until memory runs out? Maybe that's better than imposing an arbitrary limit.


Re: Math.hypot2

Repeating comment 22.
What's the point of Math.hypot2?
The sum of squares is easily computed arithmetically, and there is no chance of
avoiding overflow (unlike plain hypot). The name looks funny when the '2'
means 'squared' not 'takes 2 arguments' (cf. Math.atan2).


Re: Number.parseFloat

Rephrasing comment 22.
Why Number.parseFloat not Number.parse? (ala Date.parse)

Will there be a new Number.parse which can parse fractions/infinity in any base [2-36]? Then the parser would be able to decode any format that the formatters can produce, just like Date.parse can. And Number.parseFloat would really mean parseDecimal.


Re: Number.isNaN description

The note after Number.isNaN says the function is equivalent to X!==X,
this is not quite correct:
x = new Number(NaN)
isNaN(x) // is true
Number.isNaN(x) // is true
x!==x // is false
however:
+x!==x // is true

Also:
x = "123"
isNaN(x) // is false
Number.isNaN(x) // is true
x!==x // is false
+x!==x // is true
And:
x = "abc"
isNaN(x) // is true
Number.isNaN(x) // is true
x!==x // is false
+x!==x // is true

The global isNaN(x) is equivalent to (+x!=x).
Number.isNaN(x) is equivalent to (+x!==x).


Re: Unicode surrogates and String.prototype.toArray, also ~.reverse;
introducing new StringError

As described, String.prototype.toArray splits Unicode surrogate pairs; the reason given for not doing ~.reverse is that it would break surrogates if implemented naively.

Sooner or later a programmer is going to reverse a string by using 'toArray' followed by an Array reverse, thus hurting themselves when it doesn't work on surrogate pairs.

We can avoid these problems by making 'toArray' split the string into Unicode codepoints not UTF-16 codeunits -- normal chars would become single array elements, surrogate pairs would become single array elements (of 2 UTF-16 codeunits).

What to do with unpaired surrogates in an ill-formed string? I suggest throwing an exception, just like encodeURI & encodeURIComponent do. (It is not 'toArray's job to undertake surrogate corrective descisions/actions.)

Following this pattern, String.prototype.reverse could also work on well-formed strings, treating surrogate pairs as Unicode codepoints too. Implemented natively this would be faster than converting to an array, reversing, and joining.

The exception could be a new Error type: say 'StringError'.
This would be used in other cases where a surrogate problem is detected and rejected aborting further processing.
It would be sensible to use this new Error in encodeURI & encodeURIComponent too (currently they throw URIError).

... to be continued with new String.prototype.repair ...


Re: new String.prototype.repair

Following on from comment 32, it would be nice to have a function that repairs ill-formed strings. Then the programmer could either 1) preemptively force strings to be well-formed, or 2) catch a StringError exception and decide to repair & retry or simply abandon further processing.

Suggested API: String.prototype.repair( replacechar_opt )
where unpaired surrogates in this string are replaced by 'replacechar_opt' if its given or otherwise U+FFFD (the Unicode replacement character).
If 'replacechar_opt' is the empty string then unpaired surrogates are simply deleted.

I believe the following implementation using RegExps would work (the RegExp is split over 2 lines for readability):


var re_badsurrogate = /[\uD800-\uDBFF](?![\uDC00-\uDFFF])
|([^\uD800-\uDBFF])[\uDC00-\uDFFF]|^[\uDC00-\uDFFF]/g;

String.prototype.repair(replchar)
{
if (arguments.length == 0) replchar = "\uFFFD";

return this.replace( re_badsurrogate, "$1"+replchar );
};


(In reply to comment #31)
> Re: Number.isNaN description
>
> The note after Number.isNaN says the function is equivalent to X!==X,
> this is not quite correct:

the note was removed in the May 4, 2012 drafrt


(In reply to comment #30)
> (In reply to comment #29)
> > Thanks for great feedback. I've updated the draft.
>
> Looking at es6libraryextensions-3-28-12.2.pdf ...
>
>
> Re: Number.MAX_INTEGER
>
> In the PDF there is a large space between "MAX_INTEGER is the largest".
>
Fixed in May 4 2012 draft


>
> Re: String.prototype.repeat
>
> Much nicer.
> But still allows the programmers to easily specify enormous strings with length
> len*count. Maybe that's OK, after all they can easily shoot themselves in the
> foot in other ways e.g. an infinite loop like 'for i=1 to 2^54 step 1'.
>
> What happens to "longstring".repeat(0xFFFFFFFF) -- do they wait a long time
> until memory runs out? Maybe that's better than imposing an arbitrary limit.
>

In general the ES spec. does place arbitrary limits to try to prevent resource exhaustion errors. that is left to implementations




>
> Re: Math.hypot2
>

It's now gone. Killed at March TC39 meeting


Bulk closing all Harmony bugs. Proposals should be tracked on GitHub. The ES wiki is completely defunct at this point.