kirkagur ·
hi
is there any fast log10 approximation??
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].