discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

How to find the product of all elements in a list?

T
TLC123
Sun, Dec 6, 2020 11:36 AM

Is there a neat hack to multiply all the numbers in a list other than
recursive methods?

--
Sent from: http://forum.openscad.org/

Is there a neat hack to multiply all the numbers in a list other than recursive methods? -- Sent from: http://forum.openscad.org/
A
adrianv
Sun, Dec 6, 2020 1:35 PM

TLC123 wrote

Is there a neat hack to multiply all the numbers in a list other than
recursive methods?

If you're goal is "avoid recursion" I think you could do it with a C-style
for loop.  However, in my experience, the C-style for loops are slower than
recursion, so their only potential advantage would be avoiding recursion
depth limits.

You could take the log of the items in the list, multiply by a vector of all
ones to sum, and then apply exp.

function prod(v) =
let(
logv = [for(item=v) ln(item)],
ones = [for(i=[0:1:len(v)-1]) 1]
)
exp(logv*ones);

--
Sent from: http://forum.openscad.org/

TLC123 wrote > Is there a neat hack to multiply all the numbers in a list other than > recursive methods? If you're goal is "avoid recursion" I think you could do it with a C-style for loop. However, in my experience, the C-style for loops are slower than recursion, so their only potential advantage would be avoiding recursion depth limits. You could take the log of the items in the list, multiply by a vector of all ones to sum, and then apply exp. function prod(v) = let( logv = [for(item=v) ln(item)], ones = [for(i=[0:1:len(v)-1]) 1] ) exp(logv*ones); -- Sent from: http://forum.openscad.org/
T
TLC123
Sun, Dec 6, 2020 2:23 PM

Thanks
function prod(v) = exp([for(i=v) ln(i)]* [for(i=v) 1]);
Sure does satisfy neat if not speed.  :)

--
Sent from: http://forum.openscad.org/

Thanks ```function prod(v) = exp([for(i=v) ln(i)]* [for(i=v) 1]);``` Sure does satisfy neat if not speed. :) -- Sent from: http://forum.openscad.org/
A
adrianv
Sun, Dec 6, 2020 2:55 PM

TLC123 wrote

Thanks
function prod(v) = exp([for(i=v) ln(i)]* [for(i=v) 1]);
Sure does satisfy neat if not speed.  :)

I've done tons of timing tests on OpenSCAD code and I'm pretty sure this is
the fastest way to compute a product.  The question is whether you care
about speed, actually.    Also, how long is your list?  Because products of
long lists are either zero or infinity unless they are very specially formed
lists.

I did a quick time test against the recursive approach to demonstrate this
(and I'm not at all surprised to see that this code is about 4-6 times
faster than the recursive approach):

On length 100k lists:

recursive method: 450 ms
log method: 80ms

On length 1000 lists:

recursive:  4ms
log method: 0.8 ms

length 10 lists:
recursive: 50 microseconds
log method: 12 microseconds

The real issue I see with this code is accuracy and of course the inability
to handle inputs less than zero.  It can produce non-integer output for
integer input, for example.  (Note, it appears that exp(log(0))=0.  Does
that always work?)

--
Sent from: http://forum.openscad.org/

TLC123 wrote > Thanks > ```function prod(v) = exp([for(i=v) ln(i)]* [for(i=v) 1]);``` > Sure does satisfy neat if not speed. :) I've done tons of timing tests on OpenSCAD code and I'm pretty sure this is the fastest way to compute a product. The question is whether you care about speed, actually. Also, how long is your list? Because products of long lists are either zero or infinity unless they are very specially formed lists. I did a quick time test against the recursive approach to demonstrate this (and I'm not at all surprised to see that this code is about 4-6 times faster than the recursive approach): On length 100k lists: recursive method: 450 ms log method: 80ms On length 1000 lists: recursive: 4ms log method: 0.8 ms length 10 lists: recursive: 50 microseconds log method: 12 microseconds The real issue I see with this code is accuracy and of course the inability to handle inputs less than zero. It can produce non-integer output for integer input, for example. (Note, it appears that exp(log(0))=0. Does that always work?) -- Sent from: http://forum.openscad.org/