forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
lib: Add generic exponentially weighted moving average (EWMA) function
This adds generic functions for calculating Exponentially Weighted Moving Averages (EWMA). This implementation makes use of a structure which keeps the EWMA parameters and a scaled up internal representation to reduce rounding errors. The original idea for this implementation came from the rt2x00 driver (rt2x00link.c). I would like to use it in several places in the mac80211 and ath5k code and I hope it can be useful in many other places in the kernel code. Signed-off-by: Bruno Randolf <[email protected]> Reviewed-by: KOSAKI Motohiro <[email protected]> Signed-off-by: John W. Linville <[email protected]>
- Loading branch information
Showing
4 changed files
with
94 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
#ifndef _LINUX_AVERAGE_H | ||
#define _LINUX_AVERAGE_H | ||
|
||
#include <linux/kernel.h> | ||
|
||
/* Exponentially weighted moving average (EWMA) */ | ||
|
||
/* For more documentation see lib/average.c */ | ||
|
||
struct ewma { | ||
unsigned long internal; | ||
unsigned long factor; | ||
unsigned long weight; | ||
}; | ||
|
||
extern void ewma_init(struct ewma *avg, unsigned long factor, | ||
unsigned long weight); | ||
|
||
extern struct ewma *ewma_add(struct ewma *avg, unsigned long val); | ||
|
||
/** | ||
* ewma_read() - Get average value | ||
* @avg: Average structure | ||
* | ||
* Returns the average value held in @avg. | ||
*/ | ||
static inline unsigned long ewma_read(const struct ewma *avg) | ||
{ | ||
return DIV_ROUND_CLOSEST(avg->internal, avg->factor); | ||
} | ||
|
||
#endif /* _LINUX_AVERAGE_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -210,4 +210,7 @@ config GENERIC_ATOMIC64 | |
config LRU_CACHE | ||
tristate | ||
|
||
config AVERAGE | ||
bool | ||
|
||
endmenu |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
/* | ||
* lib/average.c | ||
* | ||
* This source code is licensed under the GNU General Public License, | ||
* Version 2. See the file COPYING for more details. | ||
*/ | ||
|
||
#include <linux/module.h> | ||
#include <linux/average.h> | ||
#include <linux/bug.h> | ||
|
||
/** | ||
* DOC: Exponentially Weighted Moving Average (EWMA) | ||
* | ||
* These are generic functions for calculating Exponentially Weighted Moving | ||
* Averages (EWMA). We keep a structure with the EWMA parameters and a scaled | ||
* up internal representation of the average value to prevent rounding errors. | ||
* The factor for scaling up and the exponential weight (or decay rate) have to | ||
* be specified thru the init fuction. The structure should not be accessed | ||
* directly but only thru the helper functions. | ||
*/ | ||
|
||
/** | ||
* 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). | ||
* @weight: Exponential weight, or decay rate. This defines how fast the | ||
* influence of older values decreases. Has to be bigger than 1. | ||
* | ||
* 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); | ||
avg->internal = 0; | ||
avg->weight = weight; | ||
avg->factor = factor; | ||
} | ||
EXPORT_SYMBOL(ewma_init); | ||
|
||
/** | ||
* ewma_add() - Exponentially weighted moving average (EWMA) | ||
* @avg: Average structure | ||
* @val: Current value | ||
* | ||
* Add a sample to the average. | ||
*/ | ||
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); | ||
return avg; | ||
} | ||
EXPORT_SYMBOL(ewma_add); |