From 957ca005886fb29489de483068761a87e0c9c6b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 14 Feb 2020 23:42:01 +0100 Subject: [PATCH] [yul-phaser] Common: Add mean() and meanSquaredError() --- test/yulPhaser/Common.h | 51 +++++++++++++++++++++++++++++++++++ test/yulPhaser/CommonTest.cpp | 29 ++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/test/yulPhaser/Common.h b/test/yulPhaser/Common.h index 8a7bc9afe..a5881d329 100644 --- a/test/yulPhaser/Common.h +++ b/test/yulPhaser/Common.h @@ -27,3 +27,54 @@ */ #pragma once + +#include +#include + +namespace solidity::phaser::test +{ + +// STATISTICAL UTILITIES + +/// Calculates the mean value of a series of samples given in a vector. +/// +/// Supports any integer and real type as a convenience but the precision of the result is limited +/// to the precision of type @a double as all the values are internally converted to it. +/// +/// This is a very simple, naive implementation that's more than enough for tests where we usually +/// deal with relatively short sequences of small, positive integers. It's not numerically stable +/// in more complicated cases. Don't use in production. +template +double mean(std::vector const& _samples) +{ + assert(_samples.size() > 0); + + double sum = 0; + for (T const& sample: _samples) + sum += static_cast(sample); + + return sum / _samples.size(); +} + +/// Calculates the sum of squared differences between @a _expectedValue and the values of a series +/// of samples given in a vector. +/// +/// Supports any integer and real type as a convenience but the precision of the result is limited +/// to the precision of type @a double as all the values are internally converted to it. +/// +/// This is a very simple, naive implementation that's more than enough for tests where we usually +/// deal with relatively short sequences of small, positive integers. It's not numerically stable +/// in more complicated cases. Don't use in production. +template +double meanSquaredError(std::vector const& _samples, double _expectedValue) +{ + assert(_samples.size() > 0); + + double sumOfSquaredDifferences = 0; + for (T const& sample: _samples) + sumOfSquaredDifferences += (sample - _expectedValue) * (sample - _expectedValue); + + return sumOfSquaredDifferences / _samples.size(); +} + +} diff --git a/test/yulPhaser/CommonTest.cpp b/test/yulPhaser/CommonTest.cpp index 55ddc4633..f86d963bd 100644 --- a/test/yulPhaser/CommonTest.cpp +++ b/test/yulPhaser/CommonTest.cpp @@ -15,14 +15,43 @@ along with solidity. If not, see . */ +#include + #include +using namespace boost::test_tools; + namespace solidity::phaser::test { BOOST_AUTO_TEST_SUITE(Phaser) BOOST_AUTO_TEST_SUITE(CommonTest) +BOOST_AUTO_TEST_CASE(mean_should_calculate_statistical_mean) +{ + BOOST_TEST(mean({0}) == 0.0); + BOOST_TEST(mean({0, 0, 0, 0}) == 0.0); + BOOST_TEST(mean({5, 5, 5, 5}) == 5.0); + BOOST_TEST(mean({0, 1, 2, 3}) == 1.5); + BOOST_TEST(mean({-4, -3, -2, -1, 0, 1, 2, 3}) == -0.5); + + BOOST_TEST(mean({1.3, 1.1, 0.0, 1.5, 1.1, 2.0, 1.5, 1.5}) == 1.25); +} + +BOOST_AUTO_TEST_CASE(meanSquaredError_should_calculate_average_squared_difference_between_samples_and_expected_value) +{ + BOOST_TEST(meanSquaredError({0}, 0.0) == 0.0); + BOOST_TEST(meanSquaredError({0}, 1.0) == 1.0); + BOOST_TEST(meanSquaredError({0, 0, 0, 0}, 0.0) == 0.0); + BOOST_TEST(meanSquaredError({0, 0, 0, 0}, 1.0) == 1.0); + BOOST_TEST(meanSquaredError({0, 0, 0, 0}, 2.0) == 4.0); + BOOST_TEST(meanSquaredError({5, 5, 5, 5}, 1.0) == 16.0); + BOOST_TEST(meanSquaredError({0, 1, 2, 3}, 2.0) == 1.5); + BOOST_TEST(meanSquaredError({-4, -3, -2, -1, 0, 1, 2, 3}, -4.0) == 17.5); + + BOOST_TEST(meanSquaredError({1.3, 1.1, 0.0, 1.5, 1.1, 2.0, 1.5, 1.5}, 1.0) == 0.3575, tolerance(0.0001)); +} + BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()