Why not then simply print a big warning when compiling the problematic case, and suggest to use the PRECISE_F32 flag for proper results?
Stéphane Le vendredi 30 janvier 2015 19:48:43 UTC+1, azakai a écrit : > > exp2f in MUSL is correct, but it *does* depend on precise float32 > semantics. Doing the operations in JavaScript doubles leads to imprecision > and errors. That's why building with PRECISE_F32 makes it work. > > The confusing thing is that LLVM only switches to exp2f when optimizing. > But that is correct as well, exp2f is power of 2, which is faster to > compute than a generic Math.pow(x, y) with arbitrary x. So this made the > bug harder to track down, but LLVM is also doing the right thing here. > > Perhaps the only thing that is "wrong" is that emscripten does not have > PRECISE_F32 on by default. However, it increases code size by some 4% (on > bullet, which I tested now), and while its optimized well in firefox, it > still isn't in other browsers (box2d is almost 2x slower in chrome, 10% > slower in safari), so we should wait on them to improve before turning it > on by default. > > However, an argument could be made that we should turn PRECISE_F32 on in > debug builds or -O0 or something like that, so -O0 is guaranteed to have > the right semantics. But I'm not sure that's the right thing either. > Thoughts? > > - Alon > > > On Fri, Jan 30, 2015 at 6:40 AM, Stéphane Letz <[email protected] > <javascript:>> wrote: > >> 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]> 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]. >>>> 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.
