A Euclidian Modulus function for C++

May 3, 2013 at 12:59am
For anyone who has tried to apply a modulus operator with negative numbers, you have probably discovered that the c++ "%" operator and fmod functions don't really cut it, as they are truncated modulus functions that tend to have poor representativeness.

I wasn't able to find a proper euclidian modulus operator for floating point operations, so I wrote a small function that I have tested (only for floating point types).

1
2
3
4
5
6
7
template <typename T> T const EucFMod(T const dividend,T const divisor)
{
  assert(divisor > 0.0);
  T const quotient = std::ceil(dividend / divisor);
  T const remainder = divisor * (1 + dividend / divisor - quotient);
  return remainder == divisor ? 0.0 : remainder;
}


Any observations or recommendations would be appreciated. Or if you know of some inbuilt/more efficient alternative please let me know.
Last edited on May 3, 2013 at 1:05am
May 3, 2013 at 2:32am
What exactly is representativeness?
May 5, 2013 at 1:06pm
The tendency of a construct to be representative. The mod function in c++ was designed to quickly and efficiently restrict the magnitude of an unsigned integer to some range for the purpose of (presumably) indexing some array or contiguous series of objects. Its representativeness in natural, mathematical, or physical situations however is poor though, as the truncated modulus is unable to represent a continuous loop across the series of all signed integers, which is what I'm trying to achieve with the euclidean mod.
May 5, 2013 at 2:46pm
remainder == divisor Floating point comparsion problem could arise.
Actually remainder > divisor can return true because of rounding problems before.
May 6, 2013 at 2:16am
The assembly instruction for modulus is actually the exact same instruction for division. The CPU performs the operation, the quotient goes into one part of, or another register (depending on the size of the type), and the remainder into another.

I believe it's up to the hardware how the behavior is defined.
Last edited on May 6, 2013 at 7:02am
May 6, 2013 at 5:21am
I believe it's up to the hardware how the behavior is defined.
What a wonderful idea to have mathematic formula result change depending on hardware you launch it.
Last edited on May 6, 2013 at 5:21am
May 6, 2013 at 6:53am
If both operands are nonnegative then the remainder is nonnegative; If if not, the sign of the remainder is implementation-defined.

http://stackoverflow.com/questions/7594508/modulo-operator-with-negative-values

Modulus is very efficient. It's the same operation as division, although division can be optimized by turning it into multiplication. Since it's a direct CPU instruction, it is very very fast. Much faster than a software algorithm. It is strange though for operands of different signs, the sign of the result is implementation defined.
Last edited on May 6, 2013 at 7:01am
May 6, 2013 at 7:21am
It is strange though for operands of different signs, the sign of the result is implementation defined.
That is because this operation works different on different processors, and it should be fast low-level operation.

Still It would be a disaster to have undefined result of math operation, so we have to fall to software algorithms
For example this is formula for always positive remainder, used in day of week calculation in C++:
1
2
3
4
remainder = (divid % divis + divis) % divis;
//or
int temp = divid % divis;
remainder = (temp < 0)?(temp + divis):temp;

The same formula in Python: remainder = divid % divis
Because Python defines result of nonpositive modlus operation
May 6, 2013 at 5:08pm
Opinion: use a combination of MiiNiPaa and ausairman:
1
2
3
4
5
6
7
template <typename T> T const EucFMod(T const dividend,T const divisor)
{ assert(divisor > 0); //note we compare to 0, not 0.0
  T result = dividend % divisor;
  if (result<0)
    result+=divisor;
  return result;
}


Note: I am against taking moduli with respect to negative numbers. This calls for a programming mathematical error.
Also, I prefer that the comparison be to 0, not to 0.0: if I am to use with a LargeInteger class, I don't want to compare LargeInteger to doubles.

This solution will produce effective code with integers, but will also work great with far more complex data structures, say, one-variable polynomials over the rationals.
Last edited on May 6, 2013 at 5:13pm
May 6, 2013 at 5:28pm
This calls for a programming mathematical error.
Use of "round result of division with remainder towards —∞, remainder is always non-negative and in range of [0; divisor)" is considered default between my country mathematicians because it allows for continuous stable series in regards for both positive and negative function arguments and generalizes some relations on numbers ∈ ℝ.
Last edited on May 6, 2013 at 5:29pm
Topic archived. No new replies allowed.