SynthMaker

fast log10

Archive · 2008 33 old posts

From the original SynthMaker forum (2004–2014), with its members’ names and dates.

kirkagur ·

hi

is there any fast log10 approximation??

infuzion ·

I'm not sure if you can get significantly faster than Code's log10(x), aside from dropping the extra movaps before & after in the ASM, but you can look here for ideas: http://www.embeddedrelated.com/usenet/e ... 1447-2.php

TomC ·

kirkagur wrote: hi

is there any fast log10 approximation??

I use this one, but actually never measured if it's 'fast' at all.

Give it a try:

[Edit]: This will always be the final version with all corrections applied, so there's no need to download anything further down the thread.

aliasant ·

Hey TomC

Nice little thing.

I made a small change to place the / primitive inside the code like this and on my mac it uses 30cycles. Is that good or bad? What should I compare with?

streamin x; streamin log; streamout y;

float x2;

x2 = x*x;

y = (x-0.5*x2+x*x2/3+0.25*x2*x2)/log;

exonerate ·

aliasant wrote: What should I compare with?

The log10 function like this...

streamin x; streamout y;

y = log10(x);

By the way you can avoid the divide in the code module by inverting (1/x )the value in the green domain first, then using a multiply instead of the divide.

oh and thanks for the approximation TomC should come in handy. 🙂

Cheers 😉

Exo

kirkagur ·

thanks all

for the comments & the code!

aliasant ·

exonerate wrote: aliasant wrote: What should I compare with?

The log10 function like this...

streamin x; streamout y;

y = log10(x);

By the way you can avoid the divide in the code module by inverting (1/x )the value in the green domain first, then using a multiply instead of the divide.

oh and thanks for the approximation TomC should come in handy. 🙂

Cheers 😉

Exo

Well.

I did compare them and they are nothing alike.

TomC's thing, whatever it is , uses 30 cycles and the log10 Code uses about 310 cycles. And they output very different numbers so... TomC. What is your code really? 🙂

TomC ·

aliasant wrote: exonerate wrote: I did compare them and they are nothing alike.

TomC's thing, whatever it is , uses 30 cycles and the log10 Code uses about 310 cycles. And they output very different numbers so... TomC. What is your code really? 🙂

Mea culpa, I forgot a part of the formula.

I'm a bit swamped by work right know, but I'll post a corrected version in the next couple of days.

Sorry for the confusion.

Tom

TomC ·

TomC wrote: Mea culpa, I forgot a part of the formula.

I'm a bit swamped by work right know, but I'll post a corrected version in the next couple of days.

Sorry for the confusion.

Tom

Okay, I'm too proud to let this thingy uncorrected, so here's a version which

a) is correct b) a little longer than the first one, but c) much more precise

Enjoy:

aliasant ·

=)

Gonna check it soon.

infuzion ·

TomC wrote: Okay, I'm too proud to let this thingy uncorrected, so here's a version which a) is correct b) a little longer than the first one, but c) much more precise

Very good! Bootsy & I helped make it: a) faster (-29 cycles on Core2Duo, likely -40 cycles on AMD64) b) sexier (newer version later)

bootsy ·

Don't forget the two divisions (through 3 and 5) which can be replaced by multiply...

TomC ·

bootsy wrote: Don't forget the two divisions (through 3 and 5) which can be replaced by multiply...

Don't worry too much, I'll post an assembler optimized version in a couple of days anyway.

Tom

infuzion ·

bootsy wrote: Don't forget the two divisions (through 3 and 5) which can be replaced by multiply...

Arrg, I did forget; thanks 🙂 Updated OSM above; saved another 20 cycles!

TomC ·

So, I've made an optimized SSE assembler version (needs half as much cycles), corrected infuzion's, ahem, slightly wrong comment (log(x) = ln(x) * log(e), NOT divided by log(e)) and made it a bit more sexy inside (no, there are no Halle pix inside, sorry guys 🙂 )

BTW, it's interesting to see HOW much x/3 differes from x*0.3333333, but for most purposes (0.1 <= x <= 7) the precision should be good enough.

Enjoy.

Tom

exonerate ·

TomC wrote: So, I've made an optimized SSE assembler version (needs half as much cycles), corrected infuzion's, ahem, slightly wrong comment (log(x) = ln(x) * log(e), NOT divided by log(e)) and made it a bit more sexy inside (no, there are no Halle pix inside, sorry guys 🙂 )

BTW, it's interesting to see HOW much x/3 differes from x*0.3333333, but for most purposes (0.1 <= x <= 7) the precision should be good enough.

Enjoy.

Tom

Great work, would it be ok to add this to the Developer toolkit ?

Cheers 😉

Exo

TomC ·

exonerate wrote: Great work, would it be ok to add this to the Developer toolkit ?

Cheers 😉

Exo

Sure, that's what it was made for!

Tom

exonerate ·

TomC wrote: exonerate wrote: Great work, would it be ok to add this to the Developer toolkit ?

Cheers 😉

Exo

Sure, that's what it was made for!

Tom

Excellent, thanks 😀

infuzion ·

oopsy, math isn't my strongest ability 😊 I like your coding; very fast running & a good teaching tool on how to ASM math. I'm wondering, how did you get 0.4342994481 for log10(Euler)? I got 0.4342945239647 with a online calculator. I'm more likely to be wrong; I just want to know the better way. I found how to save a cycle or 3; here is a "compressed" version:

streamin x;streamout y;float log=.4342945;float F1=1;float F2=2;float FP33=.3333333;float FP2=.2; movaps xmm0,x;movaps xmm1,F1;movaps xmm2,xmm0;subps xmm0,xmm1;addps xmm1,xmm2;divps xmm0,xmm1; movaps xmm1,xmm0;mulps xmm1,xmm0;mulps xmm0,F2;movaps xmm2,xmm1;mulps xmm2,FP33;mulps xmm1,xmm1; mulps xmm1,FP2;addps xmm1,xmm2;addps xmm1,F1;mulps xmm1,xmm0;mulps xmm1,log;movaps y,xmm1; //V1.6 log(x) approximation by TomC, helped: bootsy,infuzion edit: more compressed, correct log

TomC ·

infuzion wrote: I'm wondering, how did you get 0.4342994481 for log10(Euler)? I got 0.4342945239647 with a online calculator.

Nope, you're right, the second '9' was a typo, I shouldn't do such things when I'm tired. The rest (at least according to my calculator) should be fine

Find attached a new version with the correct constant:

infuzion ·

Cool, thanks for the reply! BTW, in the future, might be better to simply remove & re-upload revised version in the previous posting, or atleast remove the older versions, so people aren't downloading 5 versions, eating up bandwidth, adding confusion, etc 🙂 I've edited my "compressed" version above.

TomC ·

infuzion wrote: Cool, thanks for the reply! BTW, in the future, might be better to simply remove & re-upload revised version in the previous posting, or atleast remove the older versions, so people aren't downloading 5 versions, eating up bandwidth, adding confusion, etc 🙂 I've edited my "compressed" version above.

Yeah, good point. I've added the last version + a comment to my first reply and try to avoid multiple uploaded versions in the future. Makes sense...

Tom

infuzion ·

Thanks again TomC for your great ASM-fu; nice to know that you & Exo have joined the ASM Army! 😇

martinvicanek ·

Fast ln(x), absolute error < 3e-8 for all x, which is better than the built-in log10(x) function. Uses the floating point representation

x = man*2^exp

where -127 <= exp <= 128 is a whole number and 1 <= man < 2 is the mantissa. The logarithm is

ln(x) = ln(man) + exp*ln(2)

The ln(man) term is efficiently and accurately evaluated using a polynomial approximation (Abramowitz&Stegun). The exp term requires only some bit shifting and a multiplication by the constant ln(2).

I am sure you guys can make it still faster. 😉 E.g. most applications will require only mono but I'm not that good at optimizing. P.s. I should mention that Cyto's excellent tools (cytoTools (part 1)) have been extremely helpful for understanding the bit shifting part.

treacherousumbrella ·

Any chance of the OSM for the fast log?

martinvicanek ·

Oh, uhm - yes, of course, I forgot... 😊

treacherousumbrella ·

😀 no worries, assumed it was an oversight very nice, thanks

RRSounds ·

The subject here says "fast log10" but it looks like the .osm I downloaded actually does a natural log. Is this correct?

David

martinvicanek ·

Yup, that's correct, the OSM implements the natural logarithm ln(x). Sorry if that's confusing but I didn't want to start a new thread since the two logs are easily converted,

ln(x) = ln(10)*log10(x) = 2.3026*log10(x)

A similar relation holds for the dual log:

ln(x) = ln(2)*log2(x) = 0.693*log2(x)

BTW I have used both relations in the OSM.

trogluddite ·

Great work, as ever, Martin - and thanks for the explanation too, I can never resist a good example of bit-bashing!

Such a shame we don't have the 'psrld' opcode - we have 'pslld', so it seems daft that the SSE channels have to be split just to shift in the other direction!

EDIT) Or maybe not - I'm not mathematical enough to know for sure that I haven't screwed the accuracy - but here's an optimisation - I just replaced the shifting with a multiply by 2^-23 after converting the exponent to a float. Has worked so far with every number I've thrown at it - but maybe that's just the float box rounding masking any errors?

trogluddite ·

...and another few CPU cycles saved with some 'out-of-order' trickery...

EDIT NB) This optimisation is very CPU dependent - it won't ever make things worse, but on some processors, it might not be any better than the previous version.

martinvicanek ·

trogluddite wrote: I can never resist a good example of bit-bashing!

Hehe, I knew you would bite! 😈

trogluddite wrote: Such a shame we don't have the 'psrld' opcode - we have 'pslld', so it seems daft that the SSE channels have to be split just to shift in the other direction!

Indeed, daft and time consuming at that.

trogluddite wrote: here's an optimisation - I just replaced the shifting with a multiply by 2^-23 after converting the exponent to a float.

So simple and so elegant! 😍 Trog, you are a genius!

infuzion ·

martinvicanek wrote: trogluddite wrote: I can never resist a good example of bit-bashing!

Hehe, I knew you would bite! 😈

Switch the leads around to the analyzers; their results seem to vary by location in my i7 CPU. I can hack martin's a little to save a few cycles, but I think troggie's is still a bit faster. Congrats!

Wrote something here? To have a post removed or your name hidden, write to [email protected].

Before your first post

A few rules keep this a friendly place. You agree to them once.

Shown next to what you post, here and in the app. It doesn’t have to be your real name: 3–24 lower-case letters, digits or _ (capitals become lower case, spaces become _).

    Then your post goes up straight away.

    Delete this reply?

    Open it in SynthMaker?

    It goes on the track you’re editing there, in place of that track’s sound, and into My sounds. Your other tracks stay as they are.

    Want to keep that track’s sound? Start a new song in SynthMaker first (Song › New song), then open this.

    Report this reply?

    Only the developer reads reports. The person isn’t told who reported them.

    What’s wrong with it?

    Block this person?

    You won’t see their posts and replies here any more. They aren’t told, and you can unblock them at any time.

    People you’ve blocked

    Their posts and replies are hidden from you. Unblock someone to see them again.

    The community rules

    A few rules keep this a friendly place. Everyone agrees to them once, before their first post.