Skip to content

Instantly share code, notes, and snippets.

@vchernov
Last active November 1, 2020 07:46
Show Gist options
  • Select an option

  • Save vchernov/4774682 to your computer and use it in GitHub Desktop.

Select an option

Save vchernov/4774682 to your computer and use it in GitHub Desktop.
timeval arithmetic
// calculates addition of positive arguments
void add(const timeval& a, const timeval& b, timeval& result)
{
result.tv_sec = a.tv_sec + b.tv_sec;
result.tv_usec = a.tv_usec + b.tv_usec;
if (result.tv_usec >= 1000000)
{
result.tv_sec++;
result.tv_usec -= 1000000;
}
}
// addition
timeval operator+(const timeval& a, const timeval& b)
{
// is the "a" negative
bool nega = (a.tv_sec < 0) || (a.tv_usec < 0);
// absolute value of the "a"
timeval absa;
absa.tv_sec = labs(a.tv_sec);
absa.tv_usec = labs(a.tv_usec);
// is the "b" negative
bool negb = (b.tv_sec < 0) || (b.tv_usec < 0);
// absolute value of the "b"
timeval absb;
absb.tv_sec = labs(b.tv_sec);
absb.tv_usec = labs(b.tv_usec);
timeval result;
bool negative; // sign of the result
if (nega)
{
if (negb)
{
add(absa, absb, result);
negative = true;
}
else
negative = sub(absb, absa, result);
}
else
{
if (negb)
negative = sub(absa, absb, result);
else
{
add(absa, absb, result);
negative = false;
}
}
if (negative)
{
// making the result negative
if (result.tv_sec != 0)
result.tv_sec = -result.tv_sec;
else
result.tv_usec = -result.tv_usec;
}
return result;
}
for (long a = -3000000; a <= 3000000; a += 10000)
{
for (long b = -3000000; b <= 3000000; b += 10000)
{
timeval ta;
ta.tv_sec = a / 1000000;
ta.tv_usec = a % 1000000;
timeval tb;
tb.tv_sec = b / 1000000;
tb.tv_usec = b % 1000000;
timeval tp = ta + tb;
long long pr = labs(tp.tv_sec) * 1000000 + labs(tp.tv_usec);
if ((tp.tv_sec < 0) || (tp.tv_usec < 0))
pr = -pr;
long long p = a + b;
assert(p == pr);
assert(labs(tp.tv_usec) < 1000000);
timeval tm = ta - tb;
long long mr = labs(tm.tv_sec) * 1000000 + labs(tm.tv_usec);
if ((tm.tv_sec < 0) || (tm.tv_usec < 0))
mr = -mr;
long long m = a - b;
assert(m == mr);
assert(labs(tm.tv_usec) < 1000000);
}
}
struct timeval
{
__time_t tv_sec; /* Seconds. */
__suseconds_t tv_usec; /* Microseconds. */
};
// calculates subtraction of positive arguments, returns true if the result is negative
bool sub(const timeval& a, const timeval& b, timeval& result)
{
bool negative;
if (a.tv_sec > b.tv_sec)
{
negative = false;
if (a.tv_usec >= b.tv_usec)
{
result.tv_sec = a.tv_sec - b.tv_sec;
result.tv_usec = a.tv_usec - b.tv_usec;
}
else
{
result.tv_sec = a.tv_sec - b.tv_sec - 1;
result.tv_usec = 1000000 - b.tv_usec + a.tv_usec;
}
}
else if (a.tv_sec < b.tv_sec)
{
negative = true;
if (a.tv_usec > b.tv_usec)
{
result.tv_sec = b.tv_sec - a.tv_sec - 1;
result.tv_usec = 1000000 - a.tv_usec + b.tv_usec;
}
else
{
result.tv_sec = b.tv_sec - a.tv_sec;
result.tv_usec = b.tv_usec - a.tv_usec;
}
}
else
{
result.tv_sec = 0;
if (a.tv_usec >= b.tv_usec)
{
negative = false;
result.tv_usec = a.tv_usec - b.tv_usec;
}
else
{
negative = true;
result.tv_usec = b.tv_usec - a.tv_usec;
}
}
return negative;
}
// subtraction
timeval operator-(const timeval& a, const timeval& b)
{
// is the "a" negative
bool nega = (a.tv_sec < 0) || (a.tv_usec < 0);
// absolute value of the "a"
timeval absa;
absa.tv_sec = labs(a.tv_sec);
absa.tv_usec = labs(a.tv_usec);
// is the "b" negative
bool negb = (b.tv_sec < 0) || (b.tv_usec < 0);
// absolute value of the "b"
timeval absb;
absb.tv_sec = labs(b.tv_sec);
absb.tv_usec = labs(b.tv_usec);
timeval result;
bool negative; // sign of the result
if (nega)
{
if (negb)
negative = sub(absb, absa, result);
else
{
add(absa, absb, result);
negative = true;
}
}
else
{
if (negb)
{
add(absa, absb, result);
negative = false;
}
else
negative = sub(absa, absb, result);
}
if (negative)
{
// making the result negative
if (result.tv_sec != 0)
result.tv_sec = -result.tv_sec;
else
result.tv_usec = -result.tv_usec;
}
return result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment