Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to detect the difference between a wrapping counter and large negative value in C language

Tags:

c++

c

x86

32-bit

rtp

Apologies for my imbecility as this is my first post on this forum. I am trying to detect the difference between a wrapping unsigned 32-bit counter and a large negative Jump with the help of following code but the compiler give me error:

error: comparison is always true due to limited range of data type [-Werror=type-limits]

Here is my code snippet:

#define MAX_BACKWARD_JUMP -4294959295 //UINT_MAX - 8000
#define MIN_BACKWARD_JUMP -3600
#define MAX_FORWARD_JUMP   4800000

signed int rtpDelta; //Signed 32-bit
unsigned int currRTPTs, prevRTPTs; //unsigned 32-bit

rtpDelta = currRTPTs - prevRTPTs;

  if ((rtpDelta > MAX_BACKWARD_JUMP && rtpDelta < MIN_BACKWARD_JUMP) 
        || (rtpDelta > MAX_FORWARD_JUMP))
        {
          printf("Delta in Timestamps too large\n",rtpDelta);
        }

The idea here is to catch the invalid large Deltas in RTP timestamps. We have a current TimeStamp and a previous Timestamp receiving from peer RTP client. The boundary limits for invalid values of RTP Timestamps are -4294959295 < rtpDelta < -3600 that is it should throw an Error if the Delta is less than -3600 and greater than -4294959295 because the values closer to UMAX_INT will be considered as roll-over. What am I doing wrong here?

like image 976
Black_Zero Avatar asked Oct 20 '22 14:10

Black_Zero


1 Answers

In general, if you have two unsigned counters a and b, with values between 0 and LIMIT-1, inclusive, with the data type capable of representing 2*LIMIT-1, you can use modulo arithmetic with the split point in the middle:

difference = (a + LIMIT - b) % LIMIT;
if (difference <= LIMIT/2) {
    /* a = b + difference */
} else {
    /* b = a + (LIMIT - difference) */
}

It is common to have LIMIT be a power of two, in which case the modulo operator (% LIMIT) can be replaced with a binary AND (& (LIMIT-1)), which is much faster on current processors.

For C, unsigned integer types are defined in the standards as having modulo arithmetic (C99, C11 6.2.5p9), so a - b using any unsigned integer type for a and b will yield the correct results, with LIMIT being the corresponding Utype_MAX macro defined in "limits.h" header file. For example,

const unsigned int  d = (unsigned int)a - (unsigned int)b;
if (d <= UINT_MAX/2)
    /* a >= b, a = b + d */
else
    /* a < b,  b = a + UINT_MAX - (d - 1) */
like image 160
Nominal Animal Avatar answered Oct 27 '22 12:10

Nominal Animal