how about more args for Math.hypot

# Roger Andrews (12 years ago)

For 3D geometry etc it would be nice if Math.hypot was variadic: Math.hypot(x,y,z,...)

This is easy to implement just by finding the largest argument in order to avoid overflow.

# Luke Hoban (12 years ago)

Replying to the four proposals you sent in one mail for easier discussion:

*** Make Math.hypot(x,y,z,...) variadic *** This sounds like a reasonable extension. Oddly, I haven't seen any other libraries support a variadic hypot function, but the use cases seem obvious enough.

*** Math.cbrt *** This was considered, but wasn't above the line of what was in the proposed Math extensions. What use case do you have in mind?

*** Rename Math.sign to Math.signum *** There isn't overwhelming precedent in either direction here. Java and Matlab are signum, .NET and Python (numpy) and Mathematica are sign. C has a different but related copysign. To the extent there is precedent, it seems slightly in favor of 'sign', and it's slightly less cryptic.

*** More constants on Number *** EPSILON would be a sensible addition - I am aware of use cases in estimating error bounds. For MIN_NORMAL, MAX_INTEGER and MAX_POWTWO, what use cases do you have in mind?

Luke

# alawatthe (12 years ago)

There are already Strawmans for Number.MAX_INTEGER and Number.EPSILON: strawman:number_max_integer, strawman:number_epsilon

*** Make Math.hypot(x,y,z,...) variadic *** This sounds like a reasonable extension. Oddly, I haven't seen any other libraries support a variadic hypot function, but the use cases seem obvious enough.

Just yesterday I released my JavaScript library for mathematical computations alawatthe/MathLib It supports more than two arguments in it's hypot function. So there is at least one library supporting variadic hypot functions :-)

Regarding Math.sign versus Math.signum In (written) mathematics "sgn" is often used. But I think Math.sign is fine as well. In my opinion sign and sine aren't similar enough to be confused.

Alex

P.S.: There might be other use cases for Number.EPSILON, but comparing numbers with a tolerance of Number.EPSILON isn't working that good. Number.EPSILON is in many cases to small. Right now I'm using 3e-15.

# Roger Andrews (12 years ago)

Replying to the four proposals you sent in one mail for easier discussion:

OK. I've replied to your replies in this thread as 4 short posts.

*** Make Math.hypot(x,y,z,...) variadic *** This sounds like a reasonable extension. Oddly, I haven't seen any other libraries support a variadic hypot function, but the use cases seem obvious enough.

Thanks. I also posted a top-level thread "explicit detail of Math.hypot", but this post doesn't seem to have arrived. Perhaps it's awaiting moderation(?). Anyway the two paragraphs are repeated below...

The documentation of Math.hypot should point out that hypot avoids overflow and minimises cancellation (& rounding) errors. Otherwise people might be tempted to naively use Math.sqrt. This is easily implemented by dividing through by the largest argument then multiplying back at the end in the obvious way.

The existing doc of Math.hypot describes the result of Math.hypot as NaN if x or y is NaN. IEEE754 defines hypot of Infinity with anything (even NaN) as Infinity, thus: hypot(Infinity,NaN) == hypot(NaN,-Infinity) == ... == Infinity Note that JavaScript already correctly deals with the indefinite number NaN in Math.pow: Math.pow(NaN,0) == 1 (This is correct since pow(x,0)==1 for all x.)

# Roger Andrews (12 years ago)

Replying to the four proposals you sent in one mail for easier discussion:

OK. I've replied to your replies in this thread as 4 short posts.

*** Math.cbrt *** This was considered, but wasn't above the line of what was in the proposed Math extensions. What use case do you have in mind?

I don't have specific use cases, but observe that cbrt is very useful in maths - comparable with sqrt. Cubic equations seem to be nearly as frequent as quadratic (and can be solved by Cardano's Method like the famous quadratic solution).

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 - forcing the user to check and correct before invoking.
  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;

// 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)); };

# Roger Andrews (12 years ago)

Replying to the four proposals you sent in one mail for easier discussion:

OK. I've replied to your replies in this thread as 4 short posts.

*** Rename Math.sign to Math.signum *** There isn't overwhelming precedent in either direction here. Java and Matlab are signum, .NET and Python (numpy) and Mathematica are sign. C has a different but related copysign. To the extent there is precedent, it seems slightly in favor of 'sign', and it's slightly less cryptic.

The sign function complements the abs (magnitude) function. (copySign is an invention of IEEE754, which also has copyAbs - these are explicit in the face of IEEE "signaling NaNs".)

Clearly the word "sign" has meaning on the Real line, but think of the Complex plane where the range of the sign function is a circle of unit magnitude (or a zero). A complex number, z, in polar coordinates has a magnitude/modulus/amplitude, r, and an argument/phase, theta; where r=abs(z) and theta=signum.

Also, the so-called "sign" function returns information about the magnitude as well as the +/- sign when the magnitude is a 0: Math.signum==-0 Math.signum==0.

This is pretty vague, but the word "signum" just feels to me better than "sign", in the light of the above.

Here is an implementation that works with +0 and -0 and NaN ...

Math.signum = function(x) { return (x>0)? 1 : (x<0)? -1 : x; }
# Roger Andrews (12 years ago)

Replying to the four proposals you sent in one mail for easier discussion:

OK. I've replied to your replies in this thread as 4 short posts.

*** More constants on Number *** EPSILON would be a sensible addition - I am aware of use cases in estimating error bounds. For MIN_NORMAL, MAX_INTEGER and MAX_POWTWO, what use cases do you have in mind?

EPSILON (defined as 2^-52) is the least-significant bit of the significand of an IEEE binary64 floating-point number (e.g. JS's Number). This makes it easy to find the next larger or smaller representable number. All the bits below EPSILON are rounded in the significand to form the EPSILON bit.

MAX_INTEGER is useful when working with integers e.g. prime numbers, factorials, fibonacci numbers - just as MAX_VALUE is useful. If an integer calculation goes over MAX_INTEGER then the result is not properly significant.

MIN_NORMAL is the smallest floating-point number that retains full significance. If a calculation goes below this number then the final result is known not to be fully significant but has underflowed (gracefully). (If a calculation overflows then we know about it like a punch in the face because the final result is Infinity.) Functions like ulp, nextUp, nextDown need to handle numbers below MIN_NORMAL carefully. Also see scaling below.

MAX_POWTWO is the most significant bit in a Number. This is useful for upwardly scaling a number x<1, whereas MIN_NORMAL is useful for downwardly scaling a number x>1. It is also useful when taking the ulp of a very large

number x>9e307 which cannot be calculated with the usual trick due to

overflow (admittedly very few people will get excited by this).

Here's an example of scaling using MAX_POWTWO and MIN_NORMAL:

// multiply x by 2^n, first taking care for large |n| if (isFinite( n )) { while (n > 1023 && 1/x != 0) { x *= MAX_POWTWO; n -= 1023; } while (n < -1022 && x != 0) { x *= MIN_NORMAL; n += 1022; } } result = x * Math.pow( 2, n )

# Allen Wirfs-Brock (12 years ago)

Roger and Alex,

Have you reviewed the math library related proposals for ES.next :

harmony:more_math_functions

and in particular harmony:es6libraryextensions.pdf

I would be very useful to have feedback on these from numerical computation experts.

# Roger Andrews (12 years ago)

There are already Strawmans for Number.MAX_INTEGER and Number.EPSILON:

strawman:number_max_integer

That page has MAX_INTEGER as 2^53. While strictly correct in floating-point, it is conventional to have (2^n)-1 for a n-bit integer. IEEE binary64 numbers have 53 bits of precision (including the "hidden" bit), so I prefer MAX_INTEGER = 2^53-1 = 9007199254740991.

(As a power-of-two 2^53 has a "funny" representation -- its significand is all 0s except for the unstored hidden bit. Whereas 2^53-1 has a representation that looks very similar to almost all other integers.)

Regarding Math.sign versus Math.signum In (written) mathematics "sgn" is often used. But I think Math.sign is fine as well. In my opinion sign and sine aren't similar enough to be confused.

Doesn't Java use signum? JavaScript seems to follow Java's philosophy in many ways. Another vote for "signum" in addition to my previous points IMHO.

There might be other use cases for Number.EPSILON, but comparing numbers with a tolerance of Number.EPSILON isn't working that good. Number.EPSILON is in many cases to small. Right now I'm using 3e-15.

Comparing numbers with a tolerance is not what EPSILON is for. For that see the bible: D.Knuth "The Art of Computer Programming : Seminumerical Algorithms" section 4.2.2 "Accuracy of Floating Point Arithmetic". When comparing any number x>=2, EPSILON is effectively 0.

3e15 is approx 2^-48 thus discriminates the lower 6 bits of numbers in the range [1,2); (all significands are in this range). 3e15 is effectively 0 when trying to discriminate numbers >=2^6.

An exact mathematical value lies between floating-point number x and x+EPSILON or x-EPSILON when scaled to the exponent (i.e. normalised). EPSILON bounds the rounding error in the significand.

# Jens Nockert (12 years ago)

On Mar 15, 2012, at 12:42 PM, alawatthe wrote:

Just yesterday I released my JavaScript library for mathematical computations alawatthe/MathLib It supports more than two arguments in it's hypot function. So there is at least one library supporting variadic hypot functions :-)

Except that a variadic hypot function is non-trivial to implement (in a way that people expect it to behave), the one implemented above is essentially just sugar and can overflow even though the result is inside the range of a double.

Usually hypot is implemented something like |x| * sqrt(1 + (y / x)^2) (|x| > |y|) instead, but such a formula for a variadic hypot is probably non-trivial.

# Brendan Eich (12 years ago)

Roger Andrews wrote:

That page has MAX_INTEGER as 2^53. While strictly correct in floating-point, it is conventional to have (2^n)-1 for a n-bit integer. IEEE binary64 numbers have 53 bits of precision (including the "hidden" bit), so I prefer MAX_INTEGER = 2^53-1 = 9007199254740991.

Good catch -- MAX should mean (and does mean, in Mozilla code I oversee) maximum value in the set, not the fencepost one beyond.

# Christian Mayer (12 years ago)

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256

Am 15.03.2012 16:30, schrieb Allen Wirfs-Brock:

particular harmony:es6libraryextensions.pdf

harmony:es6libraryextensions.pdf

I would be very useful to have feedback on these from numerical computation experts.

The hypot is nice and probably well used by beginners. But in numerics you can and will use very often the squared value as that saves you taking most of the time taking an unnecessary square root.

E.g. checking the distance won't be done by checking the hypot, but by comparing the scalar product (which is the hypot squared) against the squared value of the distance.

So I suggest adding a Math.hypot2 as well.

Christian

-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux)

iEYEAREIAAYFAk9iLU4ACgkQoWM1JLkHou2e2wCdGep1VhK7Ed/ozdL3su8eovdj BK0An1ff6P5iXxdebb45Q4SFrrTkVRjB =RiXV -----END PGP SIGNATURE-----

# Brendan Eich (12 years ago)

Christian Mayer wrote:

So I suggest adding a Math.hypot2 as well. +1

# alawatthe (12 years ago)

Thanks for your feedback for my library, I will look into this issue more closely soon.

The hypot is nice and probably well used by beginners. But in numerics you can and will use very often the squared value as that saves you taking most of the time taking an unnecessary square root.

E.g. checking the distance won't be done by checking the hypot, but by comparing the scalar product (which is the hypot squared) against the squared value of the distance.

So I suggest adding a Math.hypot2 as well.

I agree with you, that you can use the scalar product to compare lengths. So +1 for Math.hypot2 But I see also use cases for calculating the actual length. So I would definitely include both methods.

alex

P.S I had problems with my mail program this afternoon. Sorry if someone got my previous mail twice. I think I made some chaos in the mailing list...

# Luke Hoban (12 years ago)

So I suggest adding a Math.hypot2 as well. +1

Agreed, I've added hypot2 to the proposal as well as making both hypot and hypot2 variadic.

Luke

# Luke Hoban (12 years ago)

Usually hypot is implemented something like |x| * sqrt(1 + (y / x)^2) (|x| > |y|) instead, but such a formula for a variadic hypot is probably non-trivial.

I believe, as Roger noted on another branch, the variadic version of this formula just divides all arguments by the maximum of the arguments before doing the sum of squares, then multiples by the maximum after taking the sqrt.

Luke