dart-lang / sdk

The Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.
https://dart.dev
BSD 3-Clause "New" or "Revised" License
10.22k stars 1.57k forks source link

Add ES6 Math Functions #29623

Open lexaknyazev opened 7 years ago

lexaknyazev commented 7 years ago

ECMAScript 6 has some new Math functions:

Math.acosh(x)
Math.asinh(x)
Math.atanh(x)
Math.cbrt(x)
Math.clz32(x)
Math.cosh(x)
Math.expm1(x)
Math.fround(x)
Math.hypot(value1, value2, ...)
Math.imul(x, y)
Math.log1p(x)
Math.log10(x)
Math.log2(x)
Math.sign(x)
Math.sinh(x)
Math.tanh(x)

It would be great to have those exposed in dart:math, especially given that all modern browsers already support them (only IE11 needs polyfill).

rakudrama commented 7 years ago

Can you recommend a polyfill for IE11?

If the implementation of the other 'intrinsics' on the VM is a guide, this is quite a lot of effort. To make these operations 'mesh' nicely with the surrounding arithmetic requires some work to be done for each architecture.

imul and clz32 do not really make sense on the Dart VM.

lexaknyazev commented 7 years ago

Right now, dart:math has full feature parity with JS Math of ECMAScript 5.1 (with few differences in semantics of Random and rounding).

Since ES6 version of JS Math is supported in all major browsers (except IE11), I think that support of these functions in Dart could be expected by developers. Of course, it doesn't have to precisely follow ECMA semantics: Math.sign(x) is clearly redundant in Dart.

In terms of implementation, these functions could be grouped in two categories:

Mathematical

Math.acosh(x)
Math.cosh(x)
Math.asinh(x)
Math.sinh(x)
Math.atanh(x)
Math.tanh(x)

Math.cbrt(x)
Math.expm1(x)
Math.log1p(x)
Math.log10(x)
Math.log2(x)

Math.hypot(value1, value2, ...)

For these, ECMAScript 6.0 spec says that they're implementation-dependent (as are regular trigonometric functions):

The behavior of the functions acos, acosh, asin, asinh, atan, atanh, atan2, cbrt, cos, cosh, exp, expm1, hypot, log, log1p, log2, log10, pow, random, sin, sinh, sqrt, tan, and tanh is not precisely specified here except to require specific results for certain argument values that represent boundary cases of interest. For other argument values, these functions are intended to compute approximations to the results of familiar mathematical functions, but some latitude is allowed in the choice of approximation algorithms. The general intent is that an implementer should be able to use the same mathematical library for ECMAScript on a given hardware platform that is available to C programmers on that platform.

Although the choice of algorithms is left to the implementation, it is recommended (but not specified by this standard) that implementations use the approximation algorithms for IEEE 754-2008 arithmetic contained in fdlibm, the freely distributable mathematical library from Sun Microsystems (http://www.netlib.org/fdlibm).

Other

Math.imul(x, y) and Math.clz32(x) - seem to be added for Emscripten-based workflow, I don't see much value in them for Dart.

Math.fround(x) - useful when working with floating-point data from binary buffers. Typical emulation is to write a value to Float32List and read it back immediately.


Speaking of polyfills, there're simple examples on MDN, but they don't follow native behavior in some cases.

MattConflitti commented 4 years ago

Any update on this? Math.tanh is a must for me.

rakudrama commented 3 years ago

@lrhn Can we consider adding these functions to dart:math as part of a small release? The biggest work would be adding the functions to the VM, but now that FFI is more mature, perhaps a simple solution is possible.

lrhn commented 3 years ago

Adding top-level functions is something that can technically be breaking, especially if they're lower-cased. (If anyone import dart:math and refers to a superclass member named asin with an unqualified identifier, then they'll now target the one from dart:math instead).

The names are rather unique, and it requires importing dart:math without a prefix, so I don't think it's a big risk. We likely will have to go through the breaking change process and do a little survey to see if something known is going to break.

Otherwise I'm fine with it, except for clz32 and imul.

mraleph commented 3 years ago

now that FFI is more mature, perhaps a simple solution is possible.

FFI is not yet at the stage where we can bind to these functions efficiently (at the same level of efficiency as sin and cos right now). #43889 is tracking part of the effort to switch SDK internal functions to FFI.

lexaknyazev commented 3 years ago

Otherwise I'm fine with it, except for clz32 and imul.

JS runtime may still benefit from using Math.clz32 even if that function is not exposed externally: https://github.com/dart-lang/sdk/blob/f8b2d9e7f319629a3d0537948b5966ff82838c80/sdk/lib/_internal/js_runtime/lib/js_number.dart#L533-L536