#!/bin/sh
#
# Usage: timeskewsummary.sh < timeskew-output
#
# The purpose of this script is to give a first-cut exploration of
# data generated by the timeskew program.  It also compares a median of
# differences to a difference of medians, with results thus far confirming
# that the former is preferable.
#
# 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) Facebook, 2022
#
# Authors: Paul E. McKenney <paulmck@kernel.org>

gawk '
BEGIN {
	n = 0;
}

$1 + 0 != 0 {
	wc_mono[n] = $5;
	wc_mono_sum += $5;
	if (wc_mono_max < $5 || wc_mono_max == "")
		wc_mono_max = $5;
	if (wc_mono_min > $5 || wc_mono_min == "")
		wc_mono_min = $5;

	mono1_mono[n] = $6;
	mono1_mono_sum += $6;
	if (mono1_mono_max < $6 || mono1_mono_max == "")
		mono1_mono_max = $6;
	if (mono1_mono_min > $6 || mono1_mono_min == "")
		mono1_mono_min = $6;

	mono2_mono1[n] = $7;
	mono2_mono1_sum += $7;
	if (mono2_mono1_max < $7 || mono2_mono1_max == "")
		mono2_mono1_max = $7;
	if (mono2_mono1_min > $7 || mono2_mono1_min == "")
		mono2_mono1_min = $7;

	if (mono1_mono[n] < mono2_mono1[n])
		backwards++;

	wc_ovhd[n] = mono1_mono[n] - mono2_mono1[n];
	wc_ovhd_sum += wc_ovhd[n];
	if (wc_ovhd_max < wc_ovhd[n] || wc_ovhd_max == "")
		wc_ovhd_max = wc_ovhd[n];
	if (wc_ovhd_min > wc_ovhd[n] || wc_ovhd_min == "")
		wc_ovhd_min = wc_ovhd[n];

	n++;
}

END {
	print "n = " n "  backwards = " backwards " (" 100. * backwards / n "%)";
	print "";
	asort(wc_mono);
	asort(mono1_mono);
	asort(mono2_mono1);
	asort(wc_ovhd);
	if (int(n / 2) * 2 == n) {
		wc_mono_median = (wc_mono[n / 2] + wc_mono[n / 2 - 1]) / 2;
		mono1_mono_median = (mono1_mono[n / 2] + mono1_mono[n / 2 - 1]) / 2;
		mono2_mono1_median = (mono2_mono1[n / 2] + mono2_mono1[n / 2 - 1]) / 2;
		wc_ovhd_median = (wc_ovhd[n / 2] + wc_ovhd[n / 2 - 1]) / 2;
	} else {
		wc_mono_median = wc_mono[int(n / 2)];
		mono1_mono_median = mono1_mono[int(n / 2)];
		mono2_mono1_median = mono2_mono1[int(n / 2)];
		wc_ovhd_median = wc_ovhd[int(n / 2)];
	}
	printf "        %14s %14s %14s %14s\n", "wc-mono", "mono1-mono",  "mono2-mono1", "wc_ovhd";
	printf "min:    %#14.2e %#14.2e %#14.2e %#14.2e\n", wc_mono_min, mono1_mono_min, mono2_mono1_min, wc_ovhd_min;
	printf "max:    %#14.2e %#14.2e %#14.2e %#14.2e\n", wc_mono_max, mono1_mono_max, mono2_mono1_max, wc_ovhd_max;
	printf "mean:   %#14.2e %#14.2e %#14.2e %#14.2e\n", wc_mono_sum / n, mono1_mono_sum / n, mono2_mono1_sum / n, wc_ovhd_sum / n;
	printf "median: %#14.2e %#14.2e %#14.2e %#14.2e\n", wc_mono_median, mono1_mono_median, mono2_mono1_median, wc_ovhd_median;
	print "";
	printf "Median of differences: %#9.2e\n", wc_ovhd_median;
	printf "Difference of medians: %#9.2e  %+g%%\n",  mono1_mono_median - mono2_mono1_median, 100 * (mono1_mono_median - mono2_mono1_median - wc_ovhd_median) / wc_ovhd_median;
}'
