|
@@ -8,6 +8,7 @@
|
|
|
#include <linux/module.h>
|
|
|
#include <linux/average.h>
|
|
|
#include <linux/bug.h>
|
|
|
+#include <linux/log2.h>
|
|
|
|
|
|
/**
|
|
|
* DOC: Exponentially Weighted Moving Average (EWMA)
|
|
@@ -24,18 +25,21 @@
|
|
|
* ewma_init() - Initialize EWMA parameters
|
|
|
* @avg: Average structure
|
|
|
* @factor: Factor to use for the scaled up internal value. The maximum value
|
|
|
- * of averages can be ULONG_MAX/(factor*weight).
|
|
|
+ * of averages can be ULONG_MAX/(factor*weight). For performance reasons
|
|
|
+ * factor has to be a power of 2.
|
|
|
* @weight: Exponential weight, or decay rate. This defines how fast the
|
|
|
- * influence of older values decreases. Has to be bigger than 1.
|
|
|
+ * influence of older values decreases. For performance reasons weight has
|
|
|
+ * to be a power of 2.
|
|
|
*
|
|
|
* Initialize the EWMA parameters for a given struct ewma @avg.
|
|
|
*/
|
|
|
void ewma_init(struct ewma *avg, unsigned long factor, unsigned long weight)
|
|
|
{
|
|
|
- WARN_ON(weight <= 1 || factor == 0);
|
|
|
+ WARN_ON(!is_power_of_2(weight) || !is_power_of_2(factor));
|
|
|
+
|
|
|
+ avg->weight = ilog2(weight);
|
|
|
+ avg->factor = ilog2(factor);
|
|
|
avg->internal = 0;
|
|
|
- avg->weight = weight;
|
|
|
- avg->factor = factor;
|
|
|
}
|
|
|
EXPORT_SYMBOL(ewma_init);
|
|
|
|
|
@@ -49,9 +53,9 @@ EXPORT_SYMBOL(ewma_init);
|
|
|
struct ewma *ewma_add(struct ewma *avg, unsigned long val)
|
|
|
{
|
|
|
avg->internal = avg->internal ?
|
|
|
- (((avg->internal * (avg->weight - 1)) +
|
|
|
- (val * avg->factor)) / avg->weight) :
|
|
|
- (val * avg->factor);
|
|
|
+ (((avg->internal << avg->weight) - avg->internal) +
|
|
|
+ (val << avg->factor)) >> avg->weight :
|
|
|
+ (val << avg->factor);
|
|
|
return avg;
|
|
|
}
|
|
|
EXPORT_SYMBOL(ewma_add);
|