// SPDX-License-Identifier: GPL-2.0
#include <kunit/test.h>

#include "mean_and_variance.h"

#define MAX_SQR (SQRT_U64_MAX*SQRT_U64_MAX)

static void mean_and_variance_basic_test(struct kunit *test)
{
	struct mean_and_variance s = {};

	mean_and_variance_update(&s, 2);
	mean_and_variance_update(&s, 2);

	KUNIT_EXPECT_EQ(test, mean_and_variance_get_mean(s), 2);
	KUNIT_EXPECT_EQ(test, mean_and_variance_get_variance(s), 0);
	KUNIT_EXPECT_EQ(test, s.n, 2);

	mean_and_variance_update(&s, 4);
	mean_and_variance_update(&s, 4);

	KUNIT_EXPECT_EQ(test, mean_and_variance_get_mean(s), 3);
	KUNIT_EXPECT_EQ(test, mean_and_variance_get_variance(s), 1);
	KUNIT_EXPECT_EQ(test, s.n, 4);
}

/*
 * Test values computed using a spreadsheet from the psuedocode at the bottom:
 * https://fanf2.user.srcf.net/hermes/doc/antiforgery/stats.pdf
 */

static void mean_and_variance_weighted_test(struct kunit *test)
{
	struct mean_and_variance_weighted s = { };

	mean_and_variance_weighted_update(&s, 10, false, 2);
	KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_mean(s, 2), 10);
	KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_variance(s, 2), 0);

	mean_and_variance_weighted_update(&s, 20, true, 2);
	KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_mean(s, 2), 12);
	KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_variance(s, 2), 18);

	mean_and_variance_weighted_update(&s, 30, true, 2);
	KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_mean(s, 2), 16);
	KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_variance(s, 2), 72);

	s = (struct mean_and_variance_weighted) { };

	mean_and_variance_weighted_update(&s, -10, false, 2);
	KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_mean(s, 2), -10);
	KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_variance(s, 2), 0);

	mean_and_variance_weighted_update(&s, -20, true, 2);
	KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_mean(s, 2), -12);
	KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_variance(s, 2), 18);

	mean_and_variance_weighted_update(&s, -30, true, 2);
	KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_mean(s, 2), -16);
	KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_variance(s, 2), 72);
}

static void mean_and_variance_weighted_advanced_test(struct kunit *test)
{
	struct mean_and_variance_weighted s = { };
	bool initted = false;
	s64 i;

	for (i = 10; i <= 100; i += 10) {
		mean_and_variance_weighted_update(&s, i, initted, 8);
		initted = true;
	}

	KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_mean(s, 8), 11);
	KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_variance(s, 8), 107);

	s = (struct mean_and_variance_weighted) { };
	initted = false;

	for (i = -10; i >= -100; i -= 10) {
		mean_and_variance_weighted_update(&s, i, initted, 8);
		initted = true;
	}

	KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_mean(s, 8), -11);
	KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_variance(s, 8), 107);
}

static void do_mean_and_variance_test(struct kunit *test,
				      s64 initial_value,
				      s64 initial_n,
				      s64 n,
				      unsigned weight,
				      s64 *data,
				      s64 *mean,
				      s64 *stddev,
				      s64 *weighted_mean,
				      s64 *weighted_stddev)
{
	struct mean_and_variance mv = {};
	struct mean_and_variance_weighted vw = { };

	for (unsigned i = 0; i < initial_n; i++) {
		mean_and_variance_update(&mv, initial_value);
		mean_and_variance_weighted_update(&vw, initial_value, false, weight);

		KUNIT_EXPECT_EQ(test, mean_and_variance_get_mean(mv),		initial_value);
		KUNIT_EXPECT_EQ(test, mean_and_variance_get_stddev(mv),		0);
		KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_mean(vw, weight),	initial_value);
		KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_stddev(vw, weight),0);
	}

	for (unsigned i = 0; i < n; i++) {
		mean_and_variance_update(&mv, data[i]);
		mean_and_variance_weighted_update(&vw, data[i], true, weight);

		KUNIT_EXPECT_EQ(test, mean_and_variance_get_mean(mv),		mean[i]);
		KUNIT_EXPECT_EQ(test, mean_and_variance_get_stddev(mv),		stddev[i]);
		KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_mean(vw, weight),	weighted_mean[i]);
		KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_stddev(vw, weight),weighted_stddev[i]);
	}

	KUNIT_EXPECT_EQ(test, mv.n, initial_n + n);
}

/* Test behaviour with a single outlier, then back to steady state: */
static void mean_and_variance_test_1(struct kunit *test)
{
	s64 d[]			= { 100, 10, 10, 10, 10, 10, 10 };
	s64 mean[]		= {  22, 21, 20, 19, 18, 17, 16 };
	s64 stddev[]		= {  32, 29, 28, 27, 26, 25, 24 };
	s64 weighted_mean[]	= {  32, 27, 22, 19, 17, 15, 14 };
	s64 weighted_stddev[]	= {  38, 35, 31, 27, 24, 21, 18 };

	do_mean_and_variance_test(test, 10, 6, ARRAY_SIZE(d), 2,
			d, mean, stddev, weighted_mean, weighted_stddev);
}

/* Test behaviour where we switch from one steady state to another: */
static void mean_and_variance_test_2(struct kunit *test)
{
	s64 d[]			= { 100, 100, 100, 100, 100 };
	s64 mean[]		= {  22,  32,  40,  46,  50 };
	s64 stddev[]		= {  32,  39,  42,  44,  45 };
	s64 weighted_mean[]	= {  32,  49,  61,  71,  78 };
	s64 weighted_stddev[]	= {  38,  44,  44,  41,  38 };

	do_mean_and_variance_test(test, 10, 6, ARRAY_SIZE(d), 2,
			d, mean, stddev, weighted_mean, weighted_stddev);
}

static void mean_and_variance_fast_divpow2(struct kunit *test)
{
	s64 i;
	u8 d;

	for (i = 0; i < 100; i++) {
		d = 0;
		KUNIT_EXPECT_EQ(test, fast_divpow2(i, d), div_u64(i, 1LLU << d));
		KUNIT_EXPECT_EQ(test, abs(fast_divpow2(-i, d)), div_u64(i, 1LLU << d));
		for (d = 1; d < 32; d++) {
			KUNIT_EXPECT_EQ_MSG(test, abs(fast_divpow2(i, d)),
					    div_u64(i, 1 << d), "%lld %u", i, d);
			KUNIT_EXPECT_EQ_MSG(test, abs(fast_divpow2(-i, d)),
					    div_u64(i, 1 << d), "%lld %u", -i, d);
		}
	}
}

static void mean_and_variance_u128_basic_test(struct kunit *test)
{
	u128_u a  = u64s_to_u128(0, U64_MAX);
	u128_u a1 = u64s_to_u128(0, 1);
	u128_u b  = u64s_to_u128(1, 0);
	u128_u c  = u64s_to_u128(0, 1LLU << 63);
	u128_u c2 = u64s_to_u128(U64_MAX, U64_MAX);

	KUNIT_EXPECT_EQ(test, u128_hi(u128_add(a, a1)), 1);
	KUNIT_EXPECT_EQ(test, u128_lo(u128_add(a, a1)), 0);
	KUNIT_EXPECT_EQ(test, u128_hi(u128_add(a1, a)), 1);
	KUNIT_EXPECT_EQ(test, u128_lo(u128_add(a1, a)), 0);

	KUNIT_EXPECT_EQ(test, u128_lo(u128_sub(b, a1)), U64_MAX);
	KUNIT_EXPECT_EQ(test, u128_hi(u128_sub(b, a1)), 0);

	KUNIT_EXPECT_EQ(test, u128_hi(u128_shl(c, 1)), 1);
	KUNIT_EXPECT_EQ(test, u128_lo(u128_shl(c, 1)), 0);

	KUNIT_EXPECT_EQ(test, u128_hi(u128_square(U64_MAX)), U64_MAX - 1);
	KUNIT_EXPECT_EQ(test, u128_lo(u128_square(U64_MAX)), 1);

	KUNIT_EXPECT_EQ(test, u128_lo(u128_div(b, 2)), 1LLU << 63);

	KUNIT_EXPECT_EQ(test, u128_hi(u128_div(c2, 2)), U64_MAX >> 1);
	KUNIT_EXPECT_EQ(test, u128_lo(u128_div(c2, 2)), U64_MAX);

	KUNIT_EXPECT_EQ(test, u128_hi(u128_div(u128_shl(u64_to_u128(U64_MAX), 32), 2)), U32_MAX >> 1);
	KUNIT_EXPECT_EQ(test, u128_lo(u128_div(u128_shl(u64_to_u128(U64_MAX), 32), 2)), U64_MAX << 31);
}

static struct kunit_case mean_and_variance_test_cases[] = {
	KUNIT_CASE(mean_and_variance_fast_divpow2),
	KUNIT_CASE(mean_and_variance_u128_basic_test),
	KUNIT_CASE(mean_and_variance_basic_test),
	KUNIT_CASE(mean_and_variance_weighted_test),
	KUNIT_CASE(mean_and_variance_weighted_advanced_test),
	KUNIT_CASE(mean_and_variance_test_1),
	KUNIT_CASE(mean_and_variance_test_2),
	{}
};

static struct kunit_suite mean_and_variance_test_suite = {
	.name		= "mean and variance tests",
	.test_cases	= mean_and_variance_test_cases
};

kunit_test_suite(mean_and_variance_test_suite);

MODULE_AUTHOR("Daniel B. Hill");
MODULE_DESCRIPTION("bcachefs filesystem mean and variance unit tests");
MODULE_LICENSE("GPL");
