|
1 | 1 | #ifndef _LINUX_AVERAGE_H
|
2 | 2 | #define _LINUX_AVERAGE_H
|
3 | 3 |
|
4 |
| -/* Exponentially weighted moving average (EWMA) */ |
| 4 | +/* |
| 5 | + * Exponentially weighted moving average (EWMA) |
| 6 | + * |
| 7 | + * This implements a fixed-precision EWMA algorithm, with both the |
| 8 | + * precision and fall-off coefficient determined at compile-time |
| 9 | + * and built into the generated helper funtions. |
| 10 | + * |
| 11 | + * The first argument to the macro is the name that will be used |
| 12 | + * for the struct and helper functions. |
| 13 | + * |
| 14 | + * The second argument, the precision, expresses how many bits are |
| 15 | + * used for the fractional part of the fixed-precision values. |
| 16 | + * |
| 17 | + * The third argument, the weight reciprocal, determines how the |
| 18 | + * new values will be weighed vs. the old state, new values will |
| 19 | + * get weight 1/weight_rcp and old values 1-1/weight_rcp. Note |
| 20 | + * that this parameter must be a power of two for efficiency. |
| 21 | + */ |
5 | 22 |
|
6 |
| -#define DECLARE_EWMA(name, _factor, _weight) \ |
| 23 | +#define DECLARE_EWMA(name, _precision, _weight_rcp) \ |
7 | 24 | struct ewma_##name { \
|
8 | 25 | unsigned long internal; \
|
9 | 26 | }; \
|
10 | 27 | static inline void ewma_##name##_init(struct ewma_##name *e) \
|
11 | 28 | { \
|
12 |
| - BUILD_BUG_ON(!__builtin_constant_p(_factor)); \ |
13 |
| - BUILD_BUG_ON(!__builtin_constant_p(_weight)); \ |
14 |
| - BUILD_BUG_ON_NOT_POWER_OF_2(_factor); \ |
15 |
| - BUILD_BUG_ON_NOT_POWER_OF_2(_weight); \ |
| 29 | + BUILD_BUG_ON(!__builtin_constant_p(_precision)); \ |
| 30 | + BUILD_BUG_ON(!__builtin_constant_p(_weight_rcp)); \ |
| 31 | + /* \ |
| 32 | + * Even if you want to feed it just 0/1 you should have \ |
| 33 | + * some bits for the non-fractional part... \ |
| 34 | + */ \ |
| 35 | + BUILD_BUG_ON((_precision) > 30); \ |
| 36 | + BUILD_BUG_ON_NOT_POWER_OF_2(_weight_rcp); \ |
16 | 37 | e->internal = 0; \
|
17 | 38 | } \
|
18 | 39 | static inline unsigned long \
|
19 | 40 | ewma_##name##_read(struct ewma_##name *e) \
|
20 | 41 | { \
|
21 |
| - BUILD_BUG_ON(!__builtin_constant_p(_factor)); \ |
22 |
| - BUILD_BUG_ON(!__builtin_constant_p(_weight)); \ |
23 |
| - BUILD_BUG_ON_NOT_POWER_OF_2(_factor); \ |
24 |
| - BUILD_BUG_ON_NOT_POWER_OF_2(_weight); \ |
25 |
| - return e->internal >> ilog2(_factor); \ |
| 42 | + BUILD_BUG_ON(!__builtin_constant_p(_precision)); \ |
| 43 | + BUILD_BUG_ON(!__builtin_constant_p(_weight_rcp)); \ |
| 44 | + BUILD_BUG_ON((_precision) > 30); \ |
| 45 | + BUILD_BUG_ON_NOT_POWER_OF_2(_weight_rcp); \ |
| 46 | + return e->internal >> (_precision); \ |
26 | 47 | } \
|
27 | 48 | static inline void ewma_##name##_add(struct ewma_##name *e, \
|
28 | 49 | unsigned long val) \
|
29 | 50 | { \
|
30 | 51 | unsigned long internal = ACCESS_ONCE(e->internal); \
|
31 |
| - unsigned long weight = ilog2(_weight); \ |
32 |
| - unsigned long factor = ilog2(_factor); \ |
| 52 | + unsigned long weight_rcp = ilog2(_weight_rcp); \ |
| 53 | + unsigned long precision = _precision; \ |
33 | 54 | \
|
34 |
| - BUILD_BUG_ON(!__builtin_constant_p(_factor)); \ |
35 |
| - BUILD_BUG_ON(!__builtin_constant_p(_weight)); \ |
36 |
| - BUILD_BUG_ON_NOT_POWER_OF_2(_factor); \ |
37 |
| - BUILD_BUG_ON_NOT_POWER_OF_2(_weight); \ |
| 55 | + BUILD_BUG_ON(!__builtin_constant_p(_precision)); \ |
| 56 | + BUILD_BUG_ON(!__builtin_constant_p(_weight_rcp)); \ |
| 57 | + BUILD_BUG_ON((_precision) > 30); \ |
| 58 | + BUILD_BUG_ON_NOT_POWER_OF_2(_weight_rcp); \ |
38 | 59 | \
|
39 | 60 | ACCESS_ONCE(e->internal) = internal ? \
|
40 |
| - (((internal << weight) - internal) + \ |
41 |
| - (val << factor)) >> weight : \ |
42 |
| - (val << factor); \ |
| 61 | + (((internal << weight_rcp) - internal) + \ |
| 62 | + (val << precision)) >> weight_rcp : \ |
| 63 | + (val << precision); \ |
43 | 64 | }
|
44 | 65 |
|
45 | 66 | #endif /* _LINUX_AVERAGE_H */
|
0 commit comments