# Math.sincos(x)? Classic List Threaded 10 messages Reply | Threaded
Open this post in threaded view
|

## Math.sincos(x)?

 [Preamble: this is my first post to es-discuss -- if this isn't the right place to suggest language extensions, please let me know. Thanks. - rdp] How often have you seen code that calls Math.sin() and Math.cos() with the same argument, e.g:    x = r * Math.cos(theta);    y = r * Math.sin(theta); ?  This trope is repeated for polar coordinates, complex arithmetic, FTTs, etc. However, most implementations for cos(theta) actually generate sin(theta) as a "byproduct" (and vice-versa).  Since trigonometric functions are relatively expensive, and this is a common pattern, wouldn't it make sense to define a function that returns cos(theta) and sin(theta) at the same time?  A polyfill might look like this:    function sincos(theta) {       return { sin: sin(theta), cos: cos(theta) };    } (or whatever the preferred style is for returning multiple values), but a real implementation would make a single call to the underlying trigonometric routine. - rdp _______________________________________________ es-discuss mailing list [hidden email] https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

## Re: Math.sincos(x)?

 If you think that performance of cos is too big (did you measure it?) than just calculate cos from sin with the formula sin^2 + con^2 = 1```jsfunction sincos (a) {    const sin = Math.sin(a)    const cos = (1 - sin**2)**0.5    return {sin, cos}}```2017-06-22 21:02 GMT+03:00 Robert Poor :[Preamble: this is my first post to es-discuss -- if this isn't the right place to suggest language extensions, please let me know. Thanks. - rdp] How often have you seen code that calls Math.sin() and Math.cos() with the same argument, e.g:    x = r * Math.cos(theta);    y = r * Math.sin(theta); ?  This trope is repeated for polar coordinates, complex arithmetic, FTTs, etc. However, most implementations for cos(theta) actually generate sin(theta) as a "byproduct" (and vice-versa).  Since trigonometric functions are relatively expensive, and this is a common pattern, wouldn't it make sense to define a function that returns cos(theta) and sin(theta) at the same time?  A polyfill might look like this:    function sincos(theta) {       return { sin: sin(theta), cos: cos(theta) };    } (or whatever the preferred style is for returning multiple values), but a real implementation would make a single call to the underlying trigonometric routine. - rdp _______________________________________________ es-discuss mailing list [hidden email] https://mail.mozilla.org/listinfo/es-discuss _______________________________________________ es-discuss mailing list [hidden email] https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

## Re: Math.sincos(x)?

 In reply to this post by Robert Poor On 6/22/17 2:02 PM, Robert Poor wrote: > However, most implementations for cos(theta) actually generate > sin(theta) as a "byproduct" (and vice-versa). At first glance, the v8 implementation of cos typically uses a Taylor series and does not compute sin. And the SpiderMonkey implementation of cos looks like it just calls the C standard library cos, so also doesn't compute sin(theta) in a way visible to it. -Boris _______________________________________________ es-discuss mailing list [hidden email] https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

## Re: Math.sincos(x)?

 In reply to this post by Алексей On 6/22/17 2:13 PM, Алексей wrote: > function sincos (a) { >     const sin = Math.sin(a) >     const cos = (1 - sin**2)**0.5 This will completely fail for a near pi/2.  It will return zero instead of the correct small but nonzero value it should be returning. -Boris _______________________________________________ es-discuss mailing list [hidden email] https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

## Re: Math.sincos(x)?

 Also the sign of the `cos` component is wrong for a bunch of inputs. On Thursday, June 22, 2017 8:16:21 PM CEST Boris Zbarsky wrote: > On 6/22/17 2:13 PM, Алексей wrote: > > function sincos (a) { > > > >     const sin = Math.sin(a) > >     const cos = (1 - sin**2)**0.5 > > This will completely fail for a near pi/2.  It will return zero instead > of the correct small but nonzero value it should be returning. > > -Boris > _______________________________________________ > es-discuss mailing list > [hidden email] > https://mail.mozilla.org/listinfo/es-discuss_______________________________________________ es-discuss mailing list [hidden email] https://mail.mozilla.org/listinfo/es-discuss signature.asc (849 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

## Re: Math.sincos(x)?

 In reply to this post by Robert Poor Hi Robert, On Thu, Jun 22, 2017 at 6:02 PM, Robert Poor <[hidden email]> wrote: > How often have you seen code that calls Math.sin() and Math.cos() with > the same argument, e.g: > >    x = r * Math.cos(theta); >    y = r * Math.sin(theta); > > ?  This trope is repeated for polar coordinates, complex arithmetic, FTTs, etc. > > However, most implementations for cos(theta) actually generate > sin(theta) as a "byproduct" (and vice-versa).  Since trigonometric > functions are relatively expensive, and this is a common pattern, > wouldn't it make sense to define a function that returns cos(theta) > and sin(theta) at the same time? For your information, the optimizing compiler of SpiderMonkey already try to optimize consecutive calls to cos and sin by the sincos function when possible. I do not know if other optimizing compilers are doing this optimization as well, but I would expect that it would be quite easy to add. http://searchfox.org/mozilla-central/rev/3291398f10dcbe192fb52e74974b172616c018aa/js/src/jit/Ion.cpp#1310On Thu, Jun 22, 2017 at 6:02 PM, Robert Poor <[hidden email]> wrote: >  A polyfill might look like this: > >    function sincos(theta) { >       return { sin: sin(theta), cos: cos(theta) }; >    } I would expect all engines to use escape analysis to remove this object allocation, when this function is inlined. Until this code gets inlined, by allocating an object this code will add pressure to the nursery of the garbage collector. This will also add memory writes/reads to/from memory. Both are not desirable when you are doing math-intensive operations. -- Nicolas B. Pierron _______________________________________________ es-discuss mailing list [hidden email] https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

## Re: Math.sincos(x)?

 I previously wrote:>> most implementations for cos(theta) actually generate sin(theta) as a "byproduct"As others several have pointed out, that's not really true.  V8, for example, uses a (different) Taylor series approximation for sin and cos.  But given the amount of work that goes into reducing theta to a small interval, it still might make sense.  (See comment about SpiderMonkey below...)@Nicolas:> SpiderMonkey already try to optimize consecutive calls to cos and sinVery cool!  >  `return { sin: sin(theta), cos: cos(theta) };` will add pressure to the nursery of the garbage collector.True -- forgive my ignorance, but is there a way to return multiple values that does not cause heap allocation?  That was my intention.Another possible optimization: cache theta with its interval-reduced equivalent.  If you get a subsequent call with the same theta, you've already done half the work.On Fri, Jun 23, 2017 at 3:00 AM, Nicolas B. Pierron wrote:Hi Robert, On Thu, Jun 22, 2017 at 6:02 PM, Robert Poor <[hidden email]> wrote: > How often have you seen code that calls Math.sin() and Math.cos() with > the same argument, e.g: > >    x = r * Math.cos(theta); >    y = r * Math.sin(theta); > > ?  This trope is repeated for polar coordinates, complex arithmetic, FTTs, etc. > > However, most implementations for cos(theta) actually generate > sin(theta) as a "byproduct" (and vice-versa).  Since trigonometric > functions are relatively expensive, and this is a common pattern, > wouldn't it make sense to define a function that returns cos(theta) > and sin(theta) at the same time? For your information, the optimizing compiler of SpiderMonkey already try to optimize consecutive calls to cos and sin by the sincos function when possible. I do not know if other optimizing compilers are doing this optimization as well, but I would expect that it would be quite easy to add. http://searchfox.org/mozilla-central/rev/3291398f10dcbe192fb52e74974b172616c018aa/js/src/jit/Ion.cpp#1310 On Thu, Jun 22, 2017 at 6:02 PM, Robert Poor <[hidden email]> wrote: >  A polyfill might look like this: > >    function sincos(theta) { >       return { sin: sin(theta), cos: cos(theta) }; >    } I would expect all engines to use escape analysis to remove this object allocation, when this function is inlined. Until this code gets inlined, by allocating an object this code will add pressure to the nursery of the garbage collector. This will also add memory writes/reads to/from memory. Both are not desirable when you are doing math-intensive operations. -- Nicolas B. Pierron _______________________________________________ es-discuss mailing list [hidden email] https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

## Re: Math.sincos(x)?

 On Fri, Jun 23, 2017 at 10:38 AM, Robert Poor <[hidden email]> wrote: >>  `return { sin: sin(theta), cos: cos(theta) };` will add pressure to the >> nursery of the garbage collector. > > True -- forgive my ignorance, but is there a way to return multiple values > that does not cause heap allocation?  That was my intention. The only one I know, is by setting the properties of an object given as arguments, assuming that the property do exists, and that the object is reused for multiple calls. > Another possible optimization: cache theta with its interval-reduced > equivalent.  If you get a subsequent call with the same theta, you've > already done half the work. As far as I know the spec does not provide any mean to specify an acceptable precision to math operations so having an interval-reduced equivalent would not be compliant with the spec. -- Nicolas B. Pierron _______________________________________________ es-discuss mailing list [hidden email] https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

## Re: Math.sincos(x)?

 In reply to this post by Robert Poor On Thu, Jun 22, 2017 at 8:02 PM, Robert Poor wrote:    function sincos(theta) {       return { sin: sin(theta), cos: cos(theta) };    }Allocating, filling, accessing and GC'ing the return object will take more time than calling the underlying C library function which emits the machine code for the processor to consult his trigonometric functions.  _______________________________________________ es-discuss mailing list [hidden email] https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

## Re: Math.sincos(x)?

 > Allocating, filling, accessing and GC'ing the return object will take more time than calling the underlying C That seems like the nail in the coffin for this suggestion.  Thanks.  I don't have anything to add.On Fri, Jun 23, 2017 at 9:34 AM, Florian Bösch wrote:On Thu, Jun 22, 2017 at 8:02 PM, Robert Poor wrote:    function sincos(theta) {       return { sin: sin(theta), cos: cos(theta) };    }Allocating, filling, accessing and GC'ing the return object will take more time than calling the underlying C library function which emits the machine code for the processor to consult his trigonometric functions.  _______________________________________________ es-discuss mailing list [hidden email] https://mail.mozilla.org/listinfo/es-discuss