blob: 83d86d76117e8f69ff69cbdcad82dfbae861508a [file] [log] [blame]
#!/bin/sh
#
# Input a file where each line has an x-value followed by a series of
# y-values in sorted order. Output a line containing the x-value, the
# average, min, and max of the good data, the number of good data values,
# and the number of original data values. This script uses a variant of
# the old Sonatech data-cleaning algorithm, but incorporates the assumption
# that the smallest data values are good. Similar algorithms have been
# used by Dave Mills in NTP and by Larry McVoy in lmbench.
#
# This script takes the following arguments:
#
# --divisor: Reciprocal of the leading fraction of data assumed
# to be good, defaults to 3 (for one-third of the data).
# --relerr: Relative error inherent in the data, defaults to 0.01.
# --trendbreak: Multiple of average difference deemed to constitute
# a trend break. Defaults to 2.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, you can access it online at
# http://www.gnu.org/licenses/gpl-2.0.html.
#
# Copyright (C) IBM Corporation, 2012
#
# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
divisor=3
relerr=0.01
trendbreak=10
while test $# -gt 0
do
case "$1" in
--divisor)
shift
divisor=$1
;;
--relerr)
shift
relerr=$1
;;
--trendbreak)
shift
trendbreak=$1
;;
esac
shift
done
# echo divisor: $divisor relerr: $relerr trendbreak: $trendbreak
awk -v divisor=$divisor -v relerr=$relerr -v trendbreak=$trendbreak '{
for (i = 2; i <= NF; i++)
d[i - 1] = $i;
asort(d);
i = int((NF + divisor - 1) / divisor);
delta = d[i] - d[1];
maxdelta = delta * divisor;
maxdelta1 = delta + d[i] * relerr;
if (maxdelta1 > maxdelta)
maxdelta = maxdelta1;
for (j = i + 1; j < NF; j++) {
if (j <= 2)
maxdiff = d[NF - 1] - d[1];
else
maxdiff = trendbreak * (d[j - 1] - d[1]) / (j - 2);
# print "i: " i, "j: " j, "maxdelta: " maxdelta, "maxdiff: " maxdiff, "d[j] - d[j - 1]: " d[j] - d[j - 1]
if (d[j] - d[1] > maxdelta && d[j] - d[j - 1] > maxdiff)
break;
}
n = sum = 0;
for (k = 1; k < j; k++) {
sum += d[k];
n++;
}
min = d[1];
max = d[j - 1];
avg = sum / n;
print $1, avg, min, max, n, NF - 1;
}'