Re: Fast fmodf(..., 1.0f)



On Jun 29, 7:47 pm, "jason.cipri...@xxxxxxxxx"
<jason.cipri...@xxxxxxxxx> wrote:
On Jun 29, 4:50 pm, pete <pfil...@xxxxxxxxxxxxxx> wrote:
I would expect modff to be faster at breaking a float
into integer and fractional parts, simply because,
unlikefmodf, it can't be used for anything else.

Thanks! I didn't know about this function. I'll see if it improves the
speed when I get a chance to test. To make it work with negative
numbers like I want it to, it will be (using doubles, although in
reality I'm doing this in C++ and using the C++ std::modf version that
works with floats) something like this:

It seems that modff is significantly slower than fmodf, taking about
1.5 to 2 times longer -- I'm imagining it has something to do with the
fact that it returns both the fractional AND integer parts. The
program I used to time it is at the end of this message. If you run it
provide a non-zero argument, fmodf is significantly slower when you
pass 0.0f to it for some reason.

Compiled with MinGW GCC 3.4.5:

gcc -std=c99 -O0 fmodtest.c

Results, in performance counter ticks (actual units here are
arbitrary, relative values are meaningful), Intel T2600 at 2.16 GHz:

$ ./a.exe -1.5
fmodf = 1514
modff = 2482
$ ./a.exe 0
fmodf = 2176
modff = 2409
$ ./a.exe 1.5
fmodf = 1411
modff = 2411

Differences when the value is in or out of the range [-1,1] are
negligible.

Program follows; if you aren't using Windows you'll have to fill in
something appropriate for timerval_t, tick(), and tickdiff(). You can
use gettimeofday() on Linux.

Jason

======== modtest.c =========

#include <math.h>
#include <stdio.h>
#include <stdlib.h>

/* do what you need to do here */
#ifdef _WIN32
# include <windows.h>
typedef LARGE_INTEGER timerval_t;
# define tick QueryPerformanceCounter
# define tickdiff(a,b) ((b).QuadPart - (a).QuadPart)
#else
/* typedef ... timerval_t;
void tick (timerval_t *t) { ... }
timerval_t tickdiff (timerval_t a, timerval_t b) { ... } */
#endif

#define ITERS 1000


inline float mymoda (float v) {
if (v >= 0.0f)
return fmodf(v, 1.0f);
else
return 1.0f - fmodf(-v, 1.0f);
}


inline float mymodb (float v) {
float ipart;
if (v >= 0.0f)
return modff(v, &ipart);
else
return 1.0f - modff(-v, &ipart);
}


int main (int argc, char **argv) {

timerval_t a1, a2, b1, b2;
float v, s = 0.0f;
unsigned n;
unsigned long at, bt;

/* v is non-constant to prevent optimizations with > -O0 */
v = atof(argv[1]);
printf("using value %f\n", v);

tick(&a1);
for (n = 0; n < ITERS; ++ n) {
s += mymoda(v);
s += mymoda(v);
s += mymoda(v);
s += mymoda(v);
s += mymoda(v);
s += mymoda(v);
s += mymoda(v);
s += mymoda(v);
s += mymoda(v);
s += mymoda(v);
}
tick(&a2);

tick(&b1);
for (n = 0; n < ITERS; ++ n) {
s += mymodb(v);
s += mymodb(v);
s += mymodb(v);
s += mymodb(v);
s += mymodb(v);
s += mymodb(v);
s += mymodb(v);
s += mymodb(v);
s += mymodb(v);
s += mymodb(v);
}
tick(&b2);

at = (unsigned long)tickdiff(a1, a2);
bt = (unsigned long)tickdiff(b1, b2);
printf("fmodf = %lu\nmodff = %lu\n", at, bt);

/* prevent calculations from being optimized away with > -O0 */
return (int)s;

}
.



Relevant Pages

  • Re: Fast fmodf(..., 1.0f)
    ... It seems that modff is significantly slower than fmodf, ... inline float mymoda { ...   float ipart; ...
    (comp.lang.c)
  • Re: Floating point arithmetic.
    ... > double fmod ... > float fmodf ... > long double fmodl ...
    (comp.lang.cpp)
  • Re: Fast fmodf(..., 1.0f)
    ... I don't know the input range, ... I would expect modff to be faster at breaking a float ... unlike fmodf, it can't be used for anything else. ... double ipart; ...
    (comp.lang.c)
  • Re: Fast fmodf(..., 1.0f)
    ... fastest way to compute the fractional part of a float? ... I don't know the input range, ... Oops, ... to wrap around, too, so, unlike fmodf, I'm looking for: ...
    (comp.lang.c)