Re: [LAD] Is -ffast-math safe for audio?
On Sat, Nov 24, 2018 at 10:49:46AM +, Will Godfrey wrote: > >The safe way is of course: > > > >int i = (int) floorf (p); > >float f = p - i; > I'd been mulling over *exactly* that point for some time. My reasoning being > that in the latter case, if the integer was slightly wrong then using it for > the subtraction should give a remainder that was also slightly wrong, but in a > direction that tends to compensate for the error. How can an int be 'slightly wrong' ? :-) The advantage of the 'safe' way is that you always have p == i + f. > The other thing, is why do we need the floorf? Or in the original example > (which was taken from working code) truncf? > A straight cast to int seems to give exactly the same result, and is at least > twice as fast with -O3 and about 4 times as fast unoptimised. We want f >= 0, so rounding must be towards -inf. Casting will truncate (i.e. round towards zero). This gives the correct result only if p >= 0. That may be all you need, but I wouldn't like to depend on it. There is a way to avoid all float to int conversions, at least outside the per-sample loops. Suppose you have a wavetable of size L, current position is float p, and increment is float f. To generate N samples you'd have something like: for (i = 0; i < N; i++) { k = floorf (p); u = p - k; // use k, u to interpolate in wavetable p += f; if (p >= L) p -= L; } To avoid floorf() inside the loop, instead of maintaining p and f as floats, split both of them from the start into an integer and float part: k = floorf (p); u = p - k; kf = floorf (f); uf = f - kf; for (i = 0; i < N; i++) { // use k, u to interpolate in wavetable k += kf; u += uf; if (u >= 1.0f) { k += 1; u -= 1; } if (k >= L) k -= L; // or k &= L-1 if L is a power of 2. } Ciao, -- FA ___ Linux-audio-dev mailing list Linux-audio-dev@lists.linuxaudio.org https://lists.linuxaudio.org/listinfo/linux-audio-dev
Re: [LAD] Is -ffast-math safe for audio?
On Sat, 24 Nov 2018 11:14:06 +0100 Fons Adriaensen wrote: >The dangerous thing to do is: > >// given float p > >int i = (int) floorf (p); >float f = fmodf (p, 1.0f); > >as you could end up with i + f != p. > >The safe way is of course: > >int i = (int) floorf (p); >float f = p - i; > > >Ciao, > Thanks very much for that Fons :) I'd been mulling over *exactly* that point for some time. My reasoning being that in the latter case, if the integer was slightly wrong then using it for the subtraction should give a remainder that was also slightly wrong, but in a direction that tends to compensate for the error. The other thing, is why do we need the floorf? Or in the original example (which was taken from working code) truncf? A straight cast to int seems to give exactly the same result, and is at least twice as fast with -O3 and about 4 times as fast unoptimised. -- Will J Godfrey http://www.musically.me.uk Say you have a poem and I have a tune. Exchange them and we can both have a poem, a tune, and a song. ___ Linux-audio-dev mailing list Linux-audio-dev@lists.linuxaudio.org https://lists.linuxaudio.org/listinfo/linux-audio-dev
Re: [LAD] Is -ffast-math safe for audio?
On Thu, Nov 22, 2018 at 11:29:11PM +0100, Robin Gareus wrote: > A simpler example to show this is > > #include > #include > int main (int argc, char** argv) { > float a = 0; > for (int i = 0; i < 100; ++i) { > a += 0.1f; > a -= 0.05f; > a = fmodf (a, 1.f); > } > printf ("%f\n", a); > return 0; > } > > using gcc 6.3.0-18+deb9u1, x86_64, this > prints 1.00 (when compiled with -O0) > and0.01 (when compiled with -O2 --fast-math) Actually 0.99940 and 0.00596. The 1.00 would imply that the fmodf (a, 1.0f) would be plain wrong, but it isn't. The examples shown in this thread all involve converting floats to ints. Typical application of this in audio is to convert a float index into a wavetable to an int index and a float < 1 interpolation argument. The dangerous thing to do is: // given float p int i = (int) floorf (p); float f = fmodf (p, 1.0f); as you could end up with i + f != p. The safe way is of course: int i = (int) floorf (p); float f = p - i; Ciao, -- FA ___ Linux-audio-dev mailing list Linux-audio-dev@lists.linuxaudio.org https://lists.linuxaudio.org/listinfo/linux-audio-dev