Modulo Function in C++, That Behaves Like Mod in Matlab

I do a simulation with a lot of particles (up to 100000) in periodic domain(box), and in order particles to stay inside the box, I use modulo function with float or double numbers.

In Matlab everything works great with mod function. However in C++ I found out, that function fmod is not completely equal to Matlab's mod function:

mod(-0.5,10)=9.5 - I want this result in C++

fmod(-0.5,10)=-0.5 - I don't want this.

I, of course, can solve my problem with if statements. However, i think, it will affect efficiency (if statement in critical loop). Is there a way to implement this function without if statement? May be some other function?

Thanks.

5 Answers

Just use a conditional. It will not meaningfully affect efficiency.

inline double realmod (x, y)
{
  result = fmod(x, y);
  return result >= 0 ? result : result + y;
}

fmod() calls assembly instruction FPREM which takes 16-64 cycles (according to the Pentium manual, ). The jump instructions for the conditional and the floating point addition only amount to 5 or so.

When your code has floating point division, you don't need to sweat the small stuff.

4

Either use floor and regular division:

float modulo(float a, float q)
{
    float b = a / q;
    return (b - floor(b)) * q;
}

or you can add the divisor to the result of fmod without branching:

float modulo(float a, float q)
{
    float m = fmod(a, q);
    return m + q * (m < 0.f);
}    

Based on Matlab mod(a, m) documentation and @QuestionC's answer -

A general solution that behaves exactly like Matlab - also for negative and zero divisor.

Tested against multiple values :

static inline double MatlabMod(double q, double m)
{
  if(m == 0)
    return q;

  double result = fmod(q, m);
  return ((result >= 0 && m > 0) || (q <= 0 && m < 0)) ? result : (result + m);
}

Tested with matlab for :

(q, m) -> result

(54, 321) -> 54

(-50, 512) -> 462

(54, -152) -> -98

(-53, -500) -> -53

(-500, 300) -> 100

(-5000, 400) -> 200

(-1000, -360) -> -280

(500, 360) -> 140

(1000, 360) -> 280

(-1000, 360) -> 80

(-5051, 0) -> -5051

(512, 0) -> 512

(0, 52) -> 0

(0, -58) -> 0

Just add the divisor to the number you want to keep in the interval before you apply the modulo operator:

return fmod(a+q,q);

this requires no branching at all.

If you have to worry about a exeeding -q between two updates, you can make it more robust by e.g.:

return fmod(a+q*10,q);

which would work for a >= -10*q

1

The most straightforward with working for both floats and ints without any branching.

// b = MOD(a, m)
int a = a - m * floor(a / m) + m; 
int b = a - m * floor(a / m);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Alexander Ross

Alexander Ross

Gaming, Esports & Interactive Media Writer

Alexander Ross has covered the video game industry for a decade, writing deep dives on game design, esports tournaments, VR developments, and gaming culture.

Share this article
Twitter Facebook Pinterest