Exp function
Monkey Forums/Monkey Programming/Exp function
| ||
Hi guys i need to implement an optimized exp function... now my exp function is like this: const E:Float = 2.78281828 function exp:Float(power:Float) return Pow(E, power) end function some better (optimized) code ? no need for extreme accurancy... thanks. |
| ||
for starters, e = 2.71828183... It's very odd that there's no built-in exp function. Import mojo Function cfexp#(z#) Return 1+2*z/((2-z)+(z*z/6)/(z+(z*z/60)/(1+(z*z/140)/(1+(z*z/252)/(1+z*z/396))))) End Function taylorexp#(z#) Return 1 + z/1 + z*z/2 + z*z*z/6 + z*z*z*z/24 + z*z*z*z*z/120 + z*z*z*z*z*z/720 + z*z*z*z*z*z*z/5040 + z*z*z*z*z*z*z*z/40320 + z*z*z*z*z*z*z*z*z/362880 + z*z*z*z*z*z*z*z*z*z/3628800 End Const e#=2.71828183 Function powexp#(z#) Return Pow(e,z) End Function Main() New App Local c,start,finish Print "Starting" start=Millisecs() err=0 For c=1 To 10000000 cfexp(Rnd(20)) Next finish=Millisecs() Print (finish-start)+"ms: continued fraction" Print "Starting" start=Millisecs() err=0 For c=1 To 10000000 taylorexp(Rnd(20)) Next finish=Millisecs() Print (finish-start)+"ms: taylor series approximation" Print "Starting" start=Millisecs() err=0 For c=1 To 10000000 powexp(Rnd(20)) Next finish=Millisecs() Print (finish-start)+"ms: pow function" End So it looks like the function taylorexp, based on the Taylor approximation, is fastest. |
| ||
Also, the Taylor series gives you a greater control of what kind of heuristic you want (in terms of speed versus accuracy). |
| ||
thanks guys! i hope that this optimizations will be effective also on Android, ios and wp7 devices. thanks again! |
| ||
Interesting -- in HTML5, I get very different results with these depending on the browser I use. Chrome 11: Starting 1442ms: continued fraction Starting 1432ms: taylor series approximation Starting 1879ms: pow function Internet Explorer 9: Starting 5157ms: continued fraction Starting 8891ms: taylor series approximation Starting 3727ms: pow function So... Taylor approximation is the fastest choice in Chrome for me, but in IE it takes much longer than the other two. |
| ||
Performance of this sort of thing will always vary widely across the platforms. The code above has a few problems though. The continued fraction implementation seems to have errors, but also the timing code includes the cost of the randomise function, which will vary across platforms. It's not really possible to do micro-optimisation at the Monkey level that is applicable to all targets, but I've made a few tweaks that help on most targets to some extent. It's pretty academic as unless you're doing thousands of these operations in your game loop it's likely to be completely unnoticeable. Example timings with 1,000,000 values Chrome: Starting continued fraction orig(ms): 336 continued fraction opt(ms): 81 taylor series orig(ms): 103 taylor series opt(ms): 45 pow function(ms): 167 IE9: Starting continued fraction orig(ms): 440 continued fraction opt(ms): 230 taylor series orig(ms): 1013 taylor series opt(ms): 284 pow function(ms): 364 Android: 09-04 13:50:06.127: INFO/[Monkey](2761): Starting 09-04 13:50:07.947: INFO/[Monkey](2761): continued fraction orig(ms): 1818 09-04 13:50:09.157: INFO/[Monkey](2761): continued fraction opt(ms): 1207 09-04 13:50:12.487: INFO/[Monkey](2761): taylor series orig(ms): 3330 09-04 13:50:14.097: INFO/[Monkey](2761): taylor series opt(ms): 1609 09-04 13:50:32.327: INFO/[Monkey](2761): pow function(ms): 18231 Edit: After playing around a bit, I've noticed that Chrome seems to have some pronounced start-up costs that handicap whichever function is timed first. The other targets I've tried don't show this to any great extent, but it's probably also worth looping over the entire test set two or three times if you want to avoid this problem. Example second loop timings for Chrome: Starting continued fraction orig(ms): 129 continued fraction opt(ms): 79 taylor series orig(ms): 101 taylor series opt(ms): 46 pow function(ms): 167 |
| ||
Avoid this unless numerical accuracy is utterly irrelevant. The Taylor series up to z^10 is acceptable only for very small values of z. But it gets worse as z grows and is already down to one significant digit at z = 7: 1096.633 exp(7) "exact" float value 988.592 Taylor up to z^10, note error is about 10%. And it is completely ridiculous at z = -7, unless you take care to use 1/taylorexp(7). Then the error is back to being only 10%. |
| ||
Hi, Exp will be added to the next version. Sorry for the oversight, it's just one of those things I never use myself so keeps slipping my mind... |
| ||
oh thanks mark! |