Asp Forum
Home | Login | Register | Search

Forums >

# comp.lang.javascript

## Impact of implicit arrays...

### unknown

6/11/2016 5:53:00 PM

I created a little complex number library for some new
fractal encryption techniques I am going to put online.
I am a bit worried about all of the arrays I am using in
the following code:
______________________________
"use strict";

{
return [c0[0] + c1[0], c0[1] + c1[1]];
}

function ct_complex_sub(c0, c1) {
return [c0[0] - c1[0], c0[1] - c1[1]];
}

function ct_complex_abs(c)
{
return Math.sqrt(c[0] * c[0] + c[1] * c[1]);
}

function ct_complex_mul(c0, c1)
{
return [c0[0] * c1[0] - c0[1] * c1[1],
c0[0] * c1[1] + c0[1] * c1[0]];
}

function ct_complex_mul_real(c0, c)
{
return [c0[0] * c, c0[1] * c];
}

function ct_complex_pow(c, p)
{
var l = ct_complex_abs(c);
var s = Math.pow(l, p);
var a = Math.atan2(c[1], c[0]) * p;

return [Math.cos(a) * s, Math.sin(a) * s];
}

function ct_complex_roots(c, p)
{
var l = ct_complex_abs(c);
var s = Math.pow(l, 1.0 / p);
var a = Math.atan2(c[1], c[0]) / p;

var n = Math.ceil(Math.abs(p));
var as = (Math.PI * 2) / p;
var roots = [];

for (var i = 0; i < n; ++i)
{
roots.push([Math.cos(a + as * i) * s,
Math.sin(a + as * i) * s]);
}

return roots;
}
______________________________

If I call any of the functions above in a large
iteration, will memory start to explode and stress
out the garbage collector? I mean will there be
millions of arrays that are allocated during heavy
load? This is purely functional implementation. Can
an intrusive technique give better performance?

Thank you.

### Thomas 'PointedEars' Lahn

6/12/2016 10:16:00 AM

 0

Chris M. Thomasson wrote:

> [â?¦]
> {
> return [c0[0] + c1[0], c0[1] + c1[1]];
> }
> [â?¦]
> function ct_complex_sub(c0, c1) {
> return [c0[0] - c1[0], c0[1] - c1[1]];
> }
> [â?¦]
> ______________________________
>
>
> If I call any of the functions above in a large
> iteration, will memory start to explode and stress
> out the garbage collector? I mean will there be
> millions of arrays that are allocated during heavy

a small example and see how the approach scales in various runtime
environments. You might see a pattern emerging if the same ECMAScript
implementation is used.

> This is purely functional implementation. Can
> an intrusive technique give better performance?

Mu.

I referred to my JSX:math/complex.js before, so you are reinventing the
wheel (but you might do it better), but the only real difference to your
approach is that mine is *more* object-oriented: there are Complex instances
(arrays *are* objects too, so your approach is _not_ â??purely functionalâ?)
because new Complex instances are created as the result of operations.

Creating new objects when operating on complex values (literally and
figuratively) can only be avoided if an operation function modifies the
object and returns a reference to the modified object. Or one can, with
loss of precision and performance, operate only on string representations,
hoping that the script engine does not create objects from them unless
necessary, i.e. unless String methods are called. Is one of those what you
mean by â??an intrusive techniqueâ??

--
PointedEars
FAQ: <http://PointedEars.... | SVN: <http://PointedEars.de...
Twitter: @PointedEars2 | ES Matrix: <http://PointedEars.de/es-...
Please do not cc me. / Bitte keine Kopien per E-Mail.

### unknown

6/13/2016 7:23:00 PM

 0

> Chris M. Thomasson wrote:
> [â?¦]
> {
> return [c0[0] + c1[0], c0[1] + c1[1]];
> }
> [â?¦]
> function ct_complex_sub(c0, c1) {
> return [c0[0] - c1[0], c0[1] - c1[1]];
> }
> [â?¦]
> ______________________________
>
>
> If I call any of the functions above in a large
> iteration, will memory start to explode and stress
> out the garbage collector? I mean will there be
> millions of arrays that are allocated during heavy

> > "Thomas 'PointedEars' Lahn" wrote:

> > The only good answer to such questions is â??try and seeâ?. You can start
> > with
> > a small example and see how the approach scales in various runtime
> > environments. You might see a pattern emerging if the same ECMAScript
> > implementation is used.

Excellent advise. So far it seems to be okay, but I have
the feeling that it can still blow up.

> This is purely functional implementation. Can
> an intrusive technique give better performance?

> > Mu.

> > I referred to my JSX:math/complex.js before, so you are reinventing the
> > wheel (but you might do it better), but the only real difference to your
> > approach is that mine is *more* object-oriented: there are Complex
> > instances
> > (arrays *are* objects too, so your approach is _not_ â??purely
> > functionalâ?)
> > because new Complex instances are created as the result of operations.

:^D Yeah, I am a C programmer at heart, so this type of
(ct_complex_xxx) function naming scheme is natural to me.
Also, so is returning arrays that do not need to be allocated.
That's the main source of my worry.

> > Creating new objects when operating on complex values (literally and
> > figuratively) can only be avoided if an operation function modifies the
> > object and returns a reference to the modified object. Or one can, with
> > loss of precision and performance, operate only on string
> > representations,
> > hoping that the script engine does not create objects from them unless
> > necessary, i.e. unless String methods are called. Is one of those what
> > you
> > mean by â??an intrusive techniqueâ??

YES! Intrusive means to change the inputs from (input only)
to (input/output) parameters. So, take the snippet of my
code you saved wrt (ct_complex_add). The intrusive analog
of this could be:

// IMVHO, functional...
> {
> return [c0[0] + c1[0], c0[1] + c1[1]];
> }

IMHO, this following code is not so functional!
Its intrusive... ;^o
______________________________
{
c0[0] += c1[0];
c0[1] += c1[1];
return c0;
}
______________________________

I can do this, but it requires the caller needs to respect the
fact that actual function parameters will be changed. However,
there will be no chance of a new array being created on each
call to this function wrt intrusive design.

;^)

### Michael Haufe (\"TNO\")

6/14/2016 5:00:00 AM

 0

On Saturday, June 11, 2016 at 12:52:43 PM UTC-5, Chris M. Thomasson wrote:
> I created a little complex number library for some new
> fractal encryption techniques I am going to put online.
> I am a bit worried about all of the arrays I am using in
> the following code:
> ______________________________
> "use strict";
>
> {
> return [c0[0] + c1[0], c0[1] + c1[1]];
> }
>
> function ct_complex_sub(c0, c1) {
> return [c0[0] - c1[0], c0[1] - c1[1]];
> }
>
> function ct_complex_abs(c)
> {
> return Math.sqrt(c[0] * c[0] + c[1] * c[1]);
> }
>
> function ct_complex_mul(c0, c1)
> {
> return [c0[0] * c1[0] - c0[1] * c1[1],
> c0[0] * c1[1] + c0[1] * c1[0]];
> }
>
> function ct_complex_mul_real(c0, c)
> {
> return [c0[0] * c, c0[1] * c];
> }
>
> function ct_complex_pow(c, p)
> {
> var l = ct_complex_abs(c);
> var s = Math.pow(l, p);
> var a = Math.atan2(c[1], c[0]) * p;
>
> return [Math.cos(a) * s, Math.sin(a) * s];
> }
>
> function ct_complex_roots(c, p)
> {
> var l = ct_complex_abs(c);
> var s = Math.pow(l, 1.0 / p);
> var a = Math.atan2(c[1], c[0]) / p;
>
> var n = Math.ceil(Math.abs(p));
> var as = (Math.PI * 2) / p;
> var roots = [];
>
> for (var i = 0; i < n; ++i)
> {
> roots.push([Math.cos(a + as * i) * s,
> Math.sin(a + as * i) * s]);
> }
>
> return roots;
> }
> ______________________________
>
>
> If I call any of the functions above in a large
> iteration, will memory start to explode and stress
> out the garbage collector? I mean will there be
> millions of arrays that are allocated during heavy
> load? This is purely functional implementation. Can
> an intrusive technique give better performance?
>
> Thank you.

Potentially, yes.

You want to avoid the intermediate data structures obviously, but the question is how? Sadly since JavaScript uses CBV evaluation semantics, you won't get any help there [1]. Which means it's up to you to do some creative thinking in your data structures.

Looking at what you have thus far, I don't think there is much you can do to improve things at this level of discourse, at best I think you might get a constant factor speedup at the significant expense of readability. (Bit fiddling and Math.foo() alternatives...)

I think what I would do is evaluate how the application is developing and at that stage try to discover some form of higher level rules that you can exploit. For example, for manipulating sums:

1 + 2 + 3 + ... + n = (n*(n+1)) / 2

Another thought is to switch to polar coordinates instead of Cartesian coordinates as it would simplify multiplication and division at least. With fractal based work this might be more intuitive anyway, yes?

[1] <https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by...

### unknown

6/15/2016 12:17:00 AM

 0

> "Michael Haufe (TNO)" wrote in message

>> On Saturday, June 11, 2016 at 12:52:43 PM UTC-5, Chris M. Thomasson
>> wrote:
>> I created a little complex number library for some new
>> fractal encryption techniques I am going to put online.
>> I am a bit worried about all of the arrays I am using in
>> the following code:
>> ______________________________
>> "use strict";
[...]
>> function ct_complex_mul(c0, c1)
>> {
>> return [c0[0] * c1[0] - c0[1] * c1[1],
>> c0[0] * c1[1] + c0[1] * c1[0]];
>> }
[...]
>> function ct_complex_pow(c, p)
>> {
>> var l = ct_complex_abs(c);
>> var s = Math.pow(l, p);
>> var a = Math.atan2(c[1], c[0]) * p;
>>
>> return [Math.cos(a) * s, Math.sin(a) * s];
>> }
>>
>> function ct_complex_roots(c, p)
>> {
>> var l = ct_complex_abs(c);
>> var s = Math.pow(l, 1.0 / p);
>> var a = Math.atan2(c[1], c[0]) / p;
>>
>> var n = Math.ceil(Math.abs(p));
>> var as = (Math.PI * 2) / p;
>> var roots = [];
>>
>> for (var i = 0; i < n; ++i)
>> {
>> roots.push([Math.cos(a + as * i) * s,
>> Math.sin(a + as * i) * s]);
>> }
>>
>> return roots;
>> }
>> ______________________________
>>
>>
>> If I call any of the functions above in a large
>> iteration, will memory start to explode and stress
>> out the garbage collector?
[...]

> Potentially, yes.

Yup. I agree. Its behaving okay for some stuff, but
I do not trust it under prolonged sustained load.

> You want to avoid the intermediate data structures
> obviously, but the question is how? Sadly since
> JavaScript uses CBV evaluation semantics, you won't
> get any help there [1]. Which means it's up to you
> to do some creative thinking in your data structures.

Agreed. For instance, intrusive function design should
work well here. Lets focus on converting the functional
complex multiplication function:
_______________________________________
>> function ct_complex_mul(c0, c1)
>> {
>> return [c0[0] * c1[0] - c0[1] * c1[1],
>> c0[0] * c1[1] + c0[1] * c1[0]];
>> }
_______________________________________

into an intrusive form:
_______________________________________
function ct_complex_mul(c0, c1)
{
var x = c0[0] * c1[0] - c0[1] * c1[1];
c0[1] = c0[0] * c1[1] + c0[1] * c1[0];
c0[0] = x;

return c0;
}
_______________________________________

Now, this will modify (c0), effectively turning it into
an input/output parameter. To call it in a loop could
look like:
_______________________________________
function foo_with_intrusive()
{
var z = [1, 1];
var c = [2, 2];

for (var i = 0; i < 10; ++i)
{
z = ct_complex_mul(z, c);
}
}
_______________________________________

Also, we can do this another way that involves an explicit
output parameter to the function. Something like:
_______________________________________
function ct_complex_mul(c0, c1, out)
{
out[0] = c0[0] * c1[0] - c0[1] * c1[1];
out[1] = c0[0] * c1[1] + c0[1] * c1[0];

return out;
}
_______________________________________

To call it in a loop could look like:
_______________________________________
function foo_with_out()
{
var out = [0, 0];
var z = [1, 1];
var c = [2, 2];

for (var i = 0; i < 10; ++i)
{
out = ct_complex_mul(z, c);
z[0] = out[0];
z[1] = out[1];
}
}
_______________________________________

Notice that both approaches have caveats, but both of them
will not have a chance to create a shi% load of objects!
Do you have some better ideas here?

> Looking at what you have thus far, I don't think
> there is much you can do to improve things at this
> level of discourse, at best I think you might get a
> constant factor speedup at the significant expense
> of readability. (Bit fiddling and Math.foo()
> alternatives...)

FWIW, check out this sqrt estimation algorithm:

http://forums.parallax.com/discussion/147522/dog-leg-hypotenuse-app...

;^)

> I think what I would do is evaluate how the application
> is developing and at that stage try to discover some
> form of higher level rules that you can exploit. For
> example, for manipulating sums:

> 1 + 2 + 3 + ... + n = (n*(n+1)) / 2

Indeed.

> Another thought is to switch to polar coordinates
> instead of Cartesian coordinates as it would simplify
> multiplication and division at least. With fractal based
> work this might be more intuitive anyway, yes?

Right. However, I think that converting Polar into Cartesian
in order to add/subtract is the simplest route correct?

### Thomas 'PointedEars' Lahn

6/15/2016 4:53:00 AM

 0

Chris M. Thomasson wrote:

> Also, we can do this another way that involves an explicit
> output parameter to the function. Something like:
> _______________________________________
> function ct_complex_mul(c0, c1, out)
^^^
> {
> out[0] = c0[0] * c1[0] - c0[1] * c1[1];
> out[1] = c0[0] * c1[1] + c0[1] * c1[0];
>
> return out;
> }
> _______________________________________
>
>
> To call it in a loop could look like:
> _______________________________________
> function foo_with_out()
> {
> var out = [0, 0];
> var z = [1, 1];
> var c = [2, 2];
>
> for (var i = 0; i < 10; ++i)
> {
> out = ct_complex_mul(z, c);
^^
> z[0] = out[0];
> z[1] = out[1];
> }
> }
> _______________________________________

No, that would be pointless. In fact, the function SHOULD NOT *return* the
changed value then.

But this non-idempotent, non-reentrant code is not thread-safe â?? it is not
suited for animations.

>> Another thought is to switch to polar coordinates
>> instead of Cartesian coordinates as it would simplify
>> multiplication and division at least. With fractal based
>> work this might be more intuitive anyway, yes?
>
> Right. However, I think that converting Polar into Cartesian
> in order to add/subtract is the simplest route correct?

Yes. UTSL.

<http://www.interhack.net/pubs/munging-ha...
<http://tools.ietf.org/html/rfc5536#section...

You should also avoid the troll server, aioe.org.

F'up2 poster

--
PointedEars
FAQ: <http://PointedEars.... | SVN: <http://PointedEars.de...
Twitter: @PointedEars2 | ES Matrix: <http://PointedEars.de/es-...
Please do not cc me. / Bitte keine Kopien per E-Mail.

### Thomas 'PointedEars' Lahn

6/15/2016 4:55:00 AM

 0

Chris M. Thomasson wrote:

> Also, we can do this another way that involves an explicit
> output parameter to the function. Something like:
> _______________________________________
> function ct_complex_mul(c0, c1, out)
^^^
> {
> out[0] = c0[0] * c1[0] - c0[1] * c1[1];
> out[1] = c0[0] * c1[1] + c0[1] * c1[0];
>
> return out;
> }
> _______________________________________
>
>
> To call it in a loop could look like:
> _______________________________________
> function foo_with_out()
> {
> var out = [0, 0];
> var z = [1, 1];
> var c = [2, 2];
>
> for (var i = 0; i < 10; ++i)
> {
> out = ct_complex_mul(z, c);
^^
> z[0] = out[0];
> z[1] = out[1];
> }
> }
> _______________________________________

No, that would be pointless. In fact, the function SHOULD NOT *return* the
changed value then.

But this non-idempotent, non-reentrant code is not thread-safe â?? it is not
suited for animations.

>> Another thought is to switch to polar coordinates
>> instead of Cartesian coordinates as it would simplify
>> multiplication and division at least. With fractal based
>> work this might be more intuitive anyway, yes?
>
> Right. However, I think that converting Polar into Cartesian
> in order to add/subtract is the simplest route correct?

Yes. UTSL.

<http://www.interhack.net/pubs/munging-ha...
<http://tools.ietf.org/html/rfc5536#section...
<http://tools.ietf.org/html/rfc5536#secti...

You should also avoid the troll server, aioe.org.

F'up2 poster

--
PointedEars
FAQ: <http://PointedEars.... | SVN: <http://PointedEars.de...
Twitter: @PointedEars2 | ES Matrix: <http://PointedEars.de/es-...
Please do not cc me. / Bitte keine Kopien per E-Mail.

### John B. Matthews

6/15/2016 5:20:00 AM

 0

On 6/14/2016 5:17 PM, Chris M. Thomasson wrote:
[...]
> Also, we can do this another way that involves an explicit
> output parameter to the function. Something like:
> _______________________________________
> function ct_complex_mul(c0, c1, out)
> {
> out[0] = c0[0] * c1[0] - c0[1] * c1[1];
> out[1] = c0[0] * c1[1] + c0[1] * c1[0];
>
> return out;
> }
> _______________________________________
>
>
> To call it in a loop could look like:
> _______________________________________
> function foo_with_out()
> {
> var out = [0, 0];
> var z = [1, 1];
> var c = [2, 2];
>
> for (var i = 0; i < 10; ++i)
> {
> out = ct_complex_mul(z, c);
> z[0] = out[0];
> z[1] = out[1];
> }
> }
> _______________________________________

I have a nasty typo in there. Let me correct that:
_______________________________________
function ct_complex_mul(c0, c1, out)
{
out[0] = c0[0] * c1[0] - c0[1] * c1[1];
out[1] = c0[0] * c1[1] + c0[1] * c1[0];
}

function foo_with_out()
{
var out = [0, 0];
var z = [1, 1];
var c = [2, 2];

for (var i = 0; i < 10; ++i)
{
ct_complex_mul(z, c, out);
z[0] = out[0];
z[1] = out[1];
}
}
_______________________________________