4

Does the standard (or boost) provide a method for incrementing an integer ensuring that it doesn't carry over and start back at zero but keeps the value at max? Or would I simply have to create my own (this really does seem like a little utility function that should be included).

template<typename T>
void Increment(T& x)
{
    if(x != std::numeric_limits<T>::max()) ++x;
}
user3901459
  • 824
  • 3
  • 11
  • 18

1 Answers1

4

As far as I know there is no such utility, so you would need to build you own.

There is a good article that covers saturating arithmetic: Branchfree Saturating Arithmetic and they cover all the arithmetic operations. Their examples are in C but should not be difficult to translate.

For your case we would be looking at addition. They assume the following:

#include <limits.h>

typedef unsigned u32b;

typedef signed s32b;

and for unsigned addition they provide the following code:

u32b sat_addu32b(u32b x, u32b y)
{
    u32b res = x + y;
    res |= -(res < x);

    return res;
}

and for signed addition:

s32b sat_adds32b(s32b x, s32b y)
{
    u32b ux = x;
    u32b uy = y;
    u32b res = ux + uy;

    /* Calculate overflowed result. (Don't change the sign bit of ux) */
    ux = (ux >> 31) + INT_MAX;

    /* Force compiler to use cmovns instruction */
    if ((s32b) ((ux ^ uy) | ~(uy ^ res)) >= 0)
    {
        res = ux;
    }

    return res;
}

As Pascal Cuoq notes in a comment the unsigned case assumes twos complement which should be fine for the vast majority of the cases but the standard does not make assumptions on the underlying representation.

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
  • Do you mean the signed case assumes two's-complement? The unsigned case assumes modular arithmetic, which the Standard mandates for unsigned int, though not necessarily for smaller unsigned types (addition is generally safe even for those, but in a nasty implementation even incrementing an unsigned short could yield Undefined Behavior even if it has the same range as unsigned int. – supercat Nov 03 '15 at 00:34
  • @supercat you know I am not sure, it looks like he is assuming promotion to a signed type but it does not seem like this should be the case. – Shafik Yaghmour Nov 03 '15 at 01:12
  • Subtracting a larger unsigned value from a smaller one yields (UINT_MAX+1) minus the difference. – supercat Nov 03 '15 at 02:37