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.

Reply via email to