The problematic case is our default - it seems troubling to have a big warning on our default compilation settings. Yet, for the reasons mentioned above, I'm not sure we can change that default.
I did add an entry on this to the FAQ meanwhile. - Alon On Sat, Jan 31, 2015 at 6:49 AM, Stéphane Letz <[email protected]> wrote: > 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]> 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]. >>> 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]. For more options, visit https://groups.google.com/d/optout.
