C++ equivalent of Java's Math.floorMod()?

Viewed 854

In Java, we have two different modulo (and remiander) operations, % and Math.floorMod(). The difference is in the area of the mapping destination, which can either depend on the sign of the first or the sign of the second operand. This page explains the difference nicely.

Is there an equivalent (fast) operation in C++ with the same effect as Math.floorMod()?

I currently go with the following (and for performance reasons it's not even fully equivalent to Math.floorMod()):

inline int floor_mod(int x, int y) {
    x %= y;

    if (x < 0) {
        x += y;
    }

    return x;
}

I think there might be an intrinsic or something similar which compiles to only 1 instruction on some CPUs.

3 Answers

Well...

I'm afraid you'll have to make one yourself. A one-liner is a custom floorModulo, however one if-test might be faster (and more readable) if you're expecting an unsigned int& as divisor.

#include <iostream>

int myCustomModulo(const int& a, const int& b);

int main()
{
    std::cout
        << "| mod & +divisor | mod & -divisor |\n"
        << "| :------------- | -------------- |\n"
        ;
    int b{ 3 };
    for (int a{ -5 }; a < 0; ++a)
        std::cout
            << "| " << a << " mod " << b << "  =  " << myCustomModulo(a, b) << " "
            << "| " << a << " mod " << -b << " = " << myCustomModulo(a, -b) << " |"
            << std::endl
            ;
    for (int a{ 0 }; a < 6; ++a)
        std::cout
            << "|  " << a << " mod " << b << "  =  " << myCustomModulo(a, b) << " "
            << "|  " << a << " mod " << -b << " = " << myCustomModulo(a, -b) << " |"
            << std::endl
            ;
}

int myCustomModulo(const int& a, const int& b)
{
    return (a % b + b) % b;
}

Output:

| mod & +divisor | mod & -divisor |
| :------------- | -------------- |
| -5 mod 3  =  1 | -5 mod -3 = -2 |
| -4 mod 3  =  2 | -4 mod -3 = -1 |
| -3 mod 3  =  0 | -3 mod -3 = 0 |
| -2 mod 3  =  1 | -2 mod -3 = -2 |
| -1 mod 3  =  2 | -1 mod -3 = -1 |
|  0 mod 3  =  0 |  0 mod -3 = 0 |
|  1 mod 3  =  1 |  1 mod -3 = -2 |
|  2 mod 3  =  2 |  2 mod -3 = -1 |
|  3 mod 3  =  0 |  3 mod -3 = 0 |
|  4 mod 3  =  1 |  4 mod -3 = -2 |
|  5 mod 3  =  2 |  5 mod -3 = -1 |

Correct results from your link:

| mod & +divisor | mod & -divisor |
| :------------- | :--------------|
| -5 mod 3 =  1  | -5 mod -3 = -2 |
| -4 mod 3 =  2  | -4 mod -3 = -1 |
| -3 mod 3 =  0  | -3 mod -3 =  0 |
| -2 mod 3 =  1  | -2 mod -3 = -2 |
| -1 mod 3 =  2  | -1 mod -3 = -1 |
|  0 mod 3 =  0  |  0 mod -3 =  0 |
|  1 mod 3 =  1  |  1 mod -3 = -2 |
|  2 mod 3 =  2  |  2 mod -3 = -1 |
|  3 mod 3 =  0  |  3 mod -3 =  0 |
|  4 mod 3 =  1  |  4 mod -3 = -2 |
|  5 mod 3 =  2  |  5 mod -3 = -1 |

The remainder() function in the cmath header file is similar to math.floorMod() for integer operations

#include <cmath>
remainder(dividend, divisor)

The remainder function can be recreated as follows

int floor_mod(int x, int y)
{   
   return  x-(x/y)*y  ;  
}

While I'm not aware of any intrinsic capable of performing such operation, I'd like to modify the asker's implementation to better mimic the Java function Math.floorMod(dividend,divisor)

constexpr int floor_mod(int dividend, int divisor)
{
    return [divisor, remainder = dividend % divisor] {
        return remainder && (remainder < 0 != divisor < 0)
            ? remainder + divisor
            : remainder;
    } ();
}

Here this function is tested for some trivial inputs.

The overhead due to the extra operations seems to be less than the one needed by an extra modulo (See e.g. those quick benchmarks: (1) or (2)).

Related