Trivial %d -> %zu format string fix
[paraslash.git] / time.c
1 #include "para.h"
2 /** \file time.c helper functions for dealing with timeouts */
3
4 /**
5 * convert struct timeval to milliseconds
6 *
7 * \param tv the value to convert
8 *
9 * \return The number off milliseconds in \a tv
10 */
11 long unsigned tv2ms(const struct timeval *tv)
12 {
13 return tv->tv_sec * 1000 + (tv->tv_usec + 500)/ 1000;
14 }
15
16 /**
17 * convert milliseconds to struct timeval
18 *
19 * \param n the number of milliseconds
20 * \param tv will be filled in by the function
21 */
22 void ms2tv(long unsigned n, struct timeval *tv)
23 {
24 tv->tv_sec = n / 1000;
25 tv->tv_usec = (n % 1000) * 1000;
26 }
27
28 /**
29 * convert double to struct timeval
30 *
31 * \param x the value to convert
32 * \param tv converted value is stored here
33 */
34 void d2tv(double x, struct timeval *tv)
35 {
36 tv->tv_sec = x;
37 tv->tv_usec = (x - (double)tv->tv_sec) * 1000.0 * 1000.0 + 0.5;
38 }
39
40 /**
41 * compute the difference of two time values
42 *
43 * \param b minuend
44 * \param a subtrahend
45 * \param diff difference is stored here
46 *
47 * \return If b > a, compute b - a and return 1. if b < a
48 * compute a - b and return -1. If \a diff is not \p NULL, \a diff gets
49 * filled in with the absolute value |b - a|.
50 */
51 int tv_diff(const struct timeval *b, const struct timeval *a, struct timeval *diff)
52 {
53 int ret = 1;
54
55 if ((b->tv_sec < a->tv_sec) ||
56 ((b->tv_sec == a->tv_sec) && (b->tv_usec < a->tv_usec))) {
57 const struct timeval *tmp = a;
58 a = b;
59 b = tmp;
60 ret = -1;
61 }
62 if (!diff)
63 return ret;
64 diff->tv_sec = b->tv_sec - a->tv_sec;
65 if (b->tv_usec < a->tv_usec) {
66 diff->tv_sec--;
67 diff->tv_usec = 1000 * 1000 - a->tv_usec + b->tv_usec;
68 } else
69 diff->tv_usec = b->tv_usec - a->tv_usec;
70 return ret;
71 }
72
73 /**
74 * add two structs of type timeval
75 *
76 * \param a first addend
77 * \param b second addend
78 * \param sum holds the sum upon return
79 */
80 void tv_add(const struct timeval *a, const struct timeval *b,
81 struct timeval *sum)
82 {
83 sum->tv_sec = a->tv_sec + b->tv_sec;
84 if (a->tv_usec + b->tv_usec >= 1000 * 1000) {
85 sum->tv_sec++;
86 sum->tv_usec = a->tv_usec + b->tv_usec - 1000 * 1000;
87 } else
88 sum->tv_usec = a->tv_usec + b->tv_usec;
89 }
90
91 /**
92 * compute integer multiple of given struct timeval
93 *
94 * \param mult the integer value to multiply with
95 * \param tv the timevalue to multiply
96 * \param result holds mult * tv upon return
97 */
98 void tv_scale(const unsigned long mult, const struct timeval *tv,
99 struct timeval *result)
100 {
101 result->tv_sec = mult * tv->tv_sec;
102 result->tv_sec += tv->tv_usec * mult / 1000 / 1000;
103 result->tv_usec = tv->tv_usec * mult % (1000 * 1000);
104 }
105
106 /**
107 * compute fraction of given struct timeval
108 *
109 * \param divisor the integer value to divide by
110 * \param tv the timevalue to divide
111 * \param result holds (1 / mult) * tv upon return
112 */
113 void tv_divide(const unsigned long divisor, const struct timeval *tv,
114 struct timeval *result)
115 {
116 long unsigned q;
117
118 if (!divisor) {
119 PARA_EMERG_LOG("%s\n", "division by zero");
120 exit(EXIT_FAILURE);
121 }
122 q = tv->tv_usec / divisor;
123 result->tv_sec = tv->tv_sec / divisor;
124 result->tv_usec = (tv->tv_sec - result->tv_sec * divisor)
125 * 1000 * 1000 / divisor;
126 if (result->tv_usec + q >= 1000 * 1000) {
127 result->tv_sec++;
128 result->tv_usec = 1000 * 1000 - result->tv_usec - q;
129 } else
130 result->tv_usec += q;
131 }
132
133 /**
134 * compute a convex combination of two time values
135 *
136 * \param a the first coefiicent
137 * \param tv1 the first time value
138 * \param b the second coefiicent
139 * \param tv2 the second time value
140 * \param result holds the convex combination upon return
141 *
142 * compute x := (a * tv1 + b * tv2) / (|a| + |b|). a, b may be negative.
143 * returns sign(x) and stores |x| in the result pointer.
144 */
145 int tv_convex_combination(const long a, const struct timeval *tv1,
146 const long b, const struct timeval *tv2,
147 struct timeval *result)
148 {
149 struct timeval tmp1, tmp2, tmp3;
150 int ret = 1, subtract = ((a > 0 && b < 0) || (a < 0 && b > 0));
151 unsigned long a1 = PARA_ABS(a), b1 = PARA_ABS(b);
152
153 tv_scale(a1, tv1, &tmp1);
154 tv_scale(b1, tv2, &tmp2);
155 if (subtract)
156 ret = tv_diff(&tmp1, &tmp2, &tmp3);
157 else
158 tv_add(&tmp1, &tmp2, &tmp3);
159 if (a1 + b1)
160 tv_divide(a1 + b1, &tmp3, result);
161 else {
162 result->tv_sec = 0;
163 result->tv_usec = 0;
164 }
165 if (!a || !b) {
166 if (a + b < 0)
167 ret = -1;
168 } else
169 if (a < 0)
170 ret = -ret;
171 return ret;
172 }