#ifndef _COUNTER_H_
#define _COUNTER_H_
+#include <string.h>
+
/*
- * 32 bit should be enough for now
+ * 32 bit should be enough for most cases
*/
+#ifndef STAT_CNT_NUM
#define STAT_CNT_NUM 1
+#endif
typedef struct _counter_t {
unsigned cnt[STAT_CNT_NUM];
}
/**
- * decreace a counter
+ * decrease a counter
*/
static INLINE void cnt_dec(counter_t *cnt)
{
int i, carry = 0;
for (i = 0; i < STAT_CNT_NUM; ++i) {
- unsigned a = dst->cnt[i] + src->cnt[i] + carry;
+ unsigned x = dst->cnt[i];
+ unsigned y = src->cnt[i];
+ unsigned a = x + y + carry;
- if (carry)
- carry = a <= dst->cnt[i];
- else
- carry = a < dst->cnt[i];
+ carry = (int)((x & y) | ((x | y) & ~a)) < 0 ? 1 : 0;
dst->cnt[i] = a;
-
- if (! carry)
- break;
}
}
/**
- * add an integer to an counter
+ * add an (positive) integer to an counter
*/
static INLINE void cnt_add_i(counter_t *dst, int src)
{
int i;
- unsigned a = dst->cnt[0] + src;
- unsigned carry = a < dst->cnt[0];
-
- dst->cnt[0] = a;
- if (! carry)
- return;
+ unsigned carry = src;
- for (i = 1; i < STAT_CNT_NUM; ++i) {
+ for (i = 0; i < STAT_CNT_NUM; ++i) {
unsigned a = dst->cnt[i] + carry;
carry = a < dst->cnt[i];
int i;
unsigned va, vb;
-
for (i = STAT_CNT_NUM - 1 ; i >= 0; --i) {
va = a->cnt[i];
vb = b->cnt[i];
return 0;
}
+/**
+ * convert a counter into a double
+ */
+static INLINE double cnt_to_dbl(const counter_t *a)
+{
+ int i;
+ double res = 0.0, scale = 1.0, tmp;
+
+ i = (1 << (sizeof(a->cnt[i]) * 4));
+ tmp = ((double)i) * ((double)i);
+
+ for (i = 0; i < STAT_CNT_NUM; ++i) {
+ res += scale * (double)a->cnt[i];
+
+ scale *= tmp;
+ }
+ return res;
+}
+
+/**
+ * check, if a counter is equal to an unsigned
+ */
+static INLINE int cnt_eq(const counter_t *a, unsigned value)
+{
+ int i;
+
+ for (i = 1; i < STAT_CNT_NUM; ++i)
+ if (a->cnt[i])
+ return 0;
+
+ return a->cnt[0] == value;
+}
+
+/**
+ * check, if a counter as greater than an unsigned
+ */
+static INLINE int cnt_gt(const counter_t *a, unsigned value)
+{
+ int i;
+
+ for (i = 1; i < STAT_CNT_NUM; ++i)
+ if (a->cnt[i])
+ return 1;
+
+ return a->cnt[0] > value;
+}
+
+
#endif /* _COUNTER_H_ */