So in other words the musl "exp2f" implementation seems incorrect yes? Is the following code used :
https://github.com/rofl0r/musl/blob/master/src/math/exp2f.c Should we do a bug report? Or do you consider using musl "exp2f" in optimized mode in Emcripten is the problem in the first place? Thanks. Stéphane Letz Le jeudi 29 janvier 2015 21:03:00 UTC+1, Alon Zakai a écrit : > > Ok, that is very surprising, so I did more checking. It looks like your > original results were optimized? I tried without any optimization flags, > which leads to good results. But when I optimize, I see the same as you. > > What's going on is that when not optimizing, the emitted code uses > Math_pow. But when optimizing, LLVM emits an exp2f libc call. We implement > generic pow using Math.pow, but exp2f using the musl libc. And it turns out > that in musl exp2f, not having proper float32 precision leads to inaccuracy > that causes the bad results. > > In other words, we are running different code for pow when optimizing and > when not. This sort of makes sense, as I do see the musl methods as being > faster, but perhaps we should reconsider that? Regardless, when building > with PRECISE_F32=1 (not 0 or 2) there is a guarantee of proper float32 > precision, and the results are as they should be. > > In this case here, which is best for your app depends on whether > performance or precision is most important. If you get decent speed with > your option 2, I would go with that (use your normal C code, build with > PRECISE_F32 support, but I would use 1 and not 2 in this case, as some > browsers will not have fround, and will get the bad results with option 2). > > - Alon > > > > On Wed, Jan 28, 2015 at 11:19 PM, Stéphane Letz <[email protected] > <javascript:>> wrote: > >> Problem occurring on both Chrome 40.0.2214.93 (64-bit) and Firefox >> 35.0.1 on OSX 10.8.5. >> >> I wasn't aware of this PRECISE_F32 flag, thanks. But I'm a but confused >> here, the documentation says : >> >> ar PRECISE_F32 = 0; // 0: Use JS numbers for floating-point values. >> These are 64-bit and do not model C++ >> >> // floats exactly, which are 32-bit. >> >> Now if I use the following JS code instead of C in the first place, it >> works: >> >> midiToFreq = function (note) >> >> { >> >> return 440.0 * Math.pow(2.0, (note - 69.0) / 12.0); >> } >> >> Then using -s PRECISE_F32=1 or -s PRECISE_F32=2 works, and I read >> that PRECISE_F32=2 is preferable. So now what is the best option: >> >> 1) just use the "double" midiToFreq version in the original C code and >> emcripten >> >> 2) or use the "float" version in the C original C code, emcripten >> and -s PRECISE_F32=2 >> >> 3) to just avoid the C midiToFreq and use the pure JS midiToFreq version >> instead? >> >> Thanks. >> >> Stéphane >> >> Le jeudi 29 janvier 2015 00:30:32 UTC+1, Alon Zakai a écrit : >>> >>> Which platform and which JS engine is that? >>> >>> There are several possible issues here. The JS engine might be using the >>> system libc pow, but it might have it's own implementation (e.g. sin and >>> cos have been implemented in browsers), and different libcs and so forth >>> can be more or less precise. Also, since there are floats here, building >>> with -s PRECISE_F32=1 can make the results more like native. With that I >>> get almost identical results, but still some tiny rounding errors. But even >>> without it, the errors are much smaller than yours. >>> >>> - Alon >>> >>> >>> >>> On Wed, Jan 28, 2015 at 1:43 PM, Stéphane Letz <[email protected]> wrote: >>> >>>> The following code : >>>> >>>> >>>> double midiToFreq(double note) >>>> >>>> { >>>> >>>> return 440.0 * pow(2.0, (note-69.0)/12.0); >>>> >>>> } >>>> >>>> >>>> float midiToFreq2(float note) >>>> >>>> { >>>> >>>> return 440.0f * powf(2.0f, (note-69.0f)/12.0f); >>>> >>>> } >>>> >>>> >>>> int main() >>>> >>>> { >>>> >>>> for (int i = 48; i < 84; i++) { >>>> >>>> printf("pitch %d %f\n", i, midiToFreq(i)); >>>> >>>> printf("pitch %d %f\n", i, midiToFreq2(i)); >>>> >>>> } >>>> >>>> } >>>> >>>> correctly gives : >>>> >>>> pitch 48 130.812783 >>>> pitch 48 130.812775 >>>> pitch 49 138.591315 >>>> pitch 49 138.591324 >>>> pitch 50 146.832384 >>>> pitch 50 146.832382 >>>> pitch 51 155.563492 >>>> pitch 51 155.563492 >>>> pitch 52 164.813778 >>>> pitch 52 164.813782 >>>> pitch 53 174.614116 >>>> …. >>>> >>>> when compiled with a C compiler and incorrectly gives the following >>>> when compiled with emcc and displayed in JS : >>>> >>>> pitch 48 130.812783 >>>> pitch 48 130.812783 >>>> pitch 49 138.591315 >>>> pitch 49 136.604359 >>>> pitch 50 146.832384 >>>> pitch 50 148.968110 >>>> pitch 51 155.563492 >>>> pitch 51 155.563492 >>>> pitch 52 164.813778 >>>> pitch 52 162.450876 >>>> pitch 53 174.614116 >>>> pitch 53 177.153937 >>>> pitch 54 184.997211 >>>> >>>> When could be the reason for this strange behavior of the powf function >>>> ? >>>> >>>> Thanks. >>>> >>>> Stéphane Letz >>>> >>>> -- >>>> You received this message because you are subscribed to the Google >>>> Groups "emscripten-discuss" group. >>>> To unsubscribe from this group and stop receiving emails from it, send >>>> an email to [email protected]. >>>> For more options, visit https://groups.google.com/d/optout. >>>> >>> >>> -- >> You received this message because you are subscribed to the Google Groups >> "emscripten-discuss" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to [email protected] <javascript:>. >> For more options, visit https://groups.google.com/d/optout. >> > > -- You received this message because you are subscribed to the Google Groups "emscripten-discuss" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
