#include <cmath>
#include <boost/test/unit_test.hpp>
#include "rfr/util.hpp"

BOOST_AUTO_TEST_CASE(merge_feature_vectors_test){

	double v1[4] = {1,2,3,nan("")};
	double v2[4] = {nan(""), nan(""), 4, 5};
	double v3[4] = {nan(""), nan(""), nan(""), nan("")};

	rfr::util::merge_two_vectors(v1,v2,v3,4);

	BOOST_REQUIRE(v3[0] == 1);
	BOOST_REQUIRE(v3[1] == 2);
	BOOST_REQUIRE(v3[2] == 4);
	BOOST_REQUIRE(v3[3] == 5);

	BOOST_REQUIRE_THROW(rfr::util::merge_two_vectors(v1,v1,v3,4), std::runtime_error);
}

BOOST_AUTO_TEST_CASE(test_running_statistics){

	double values[] = {61, 99, 125, 222, 34, 208, 247, 156, 59, 2, 226, 116, 203, 213, 123, 250, 209, 124, 218, 20, 43, 66, 154, 142, 223, 117, 252, 249, 105, 42, 2, 248, 69, 180, 142, 196, 237, 124, 25, 53, 76, 5, 9, 219, 114, 251, 21, 247, 183, 83, 147, 202, 16, 101, 192, 209, 140, 207, 225, 34, 160, 171, 173, 188, 161, 76, 242, 97, 104, 10, 163, 32, 243, 140, 204, 211, 106, 212, 199, 14, 115, 116, 196, 120, 87, 50, 204, 28, 158, 191, 127, 110, 210, 224, 162, 105, 68, 236, 25, 142, 80, 196, 235, 219, 140, 251, 113, 240, 81, 9, 133, 219, 186, 153, 55, 35, 166, 9, 238, 125, 233, 69, 181, 109, 63, 34, 193, 240, 174, 194, 213, 165, 26, 210, 167, 21, 168, 167, 55, 135, 170, 206, 13, 91, 225, 159, 253, 127, 196, 140, 144, 222, 190, 15, 158, 22, 185, 79, 11, 106, 57, 94, 78, 116, 183, 128, 161, 212, 38, 242, 157, 41, 253, 192, 184, 6, 163, 17, 66, 128, 245, 80, 194, 208, 73, 181, 91, 93, 38, 123, 213, 197, 109, 231, 36, 168, 199, 172, 211, 180, 246, 111, 45, 249, 73, 187, 42, 255, 83, 103, 45, 76, 145, 10, 59, 84, 179, 168, 251, 77, 218, 109, 221, 237, 135, 154, 94, 69, 49, 79, 102, 254, 77, 40, 107, 13, 226, 84, 78, 128, 35, 177, 4, 123, 172, 55, 174, 46, 176, 43, 77, 110, 43, 37, 148, 237};

	rfr::util::running_statistics<double> stat1, stat2;

	for (auto &v: values){
		stat1.push(v);

		stat2.push(v+1e9);
	}

	BOOST_REQUIRE(stat1.number_of_points() == 256);
	BOOST_REQUIRE_CLOSE(stat1.mean(),134.5078125,1e-6);
	BOOST_REQUIRE_CLOSE(stat1.variance_population(),5481.3124389648438,1e-6);
	BOOST_REQUIRE_CLOSE(stat1.sum_of_squares(), 6034858, 1e-6);

	BOOST_REQUIRE(stat2.number_of_points() == 256);
	BOOST_REQUIRE_CLOSE(stat2.mean(),134.5078125+1e9,1e-6);
	BOOST_REQUIRE_CLOSE(stat2.variance_population(),5481.3124389648438,1e-6);
}

BOOST_AUTO_TEST_CASE(test_running_statistics_operators){
	int N = 1024;
	double values[] = {187, 277, 299, 202, 190, 425, 214, 163, 441, 401, 464, 379, 427, 345, 168, 484, 258, 224, 481, 109, 331, 419, 47, 101, 52, 250, 228, 350, 455, 507, 91, 184, 250, 59, 55, 495, 504, 52, 336, 101, 482, 148, 94, 340, 137, 14, 132, 429, 418, 22, 208, 25, 453, 483, 333, 437, 83, 170, 464, 100, 299, 356, 223, 348, 464, 317, 31, 62, 52, 336, 385, 148, 74, 101, 202, 51, 402, 280, 485, 246, 107, 347, 269, 450, 95, 164, 82, 475, 144, 173, 197, 420, 222, 72, 378, 389, 418, 266, 331, 495, 386, 300, 124, 470, 268, 372, 416, 462, 426, 176, 214, 280, 207, 396, 245, 255, 128, 90, 437, 39, 361, 153, 334, 442, 241, 94, 491, 346, 184, 420, 119, 158, 99, 98, 512, 216, 461, 497, 54, 317, 257, 77, 486, 414, 443, 403, 385, 500, 229, 278, 435, 175, 159, 490, 136, 337, 357, 460, 149, 423, 488, 429, 213, 302, 414, 316, 16, 331, 177, 360, 294, 218, 300, 166, 505, 327, 276, 403, 424, 330, 409, 224, 283, 407, 433, 257, 456, 420, 229, 17, 307, 434, 210, 165, 391, 27, 505, 164, 201, 267, 94, 132, 264, 256, 5, 368, 178, 429, 308, 421, 279, 144, 422, 155, 419, 397, 306, 35, 104, 310, 447, 168, 139, 146, 172, 357, 468, 226, 437, 390, 35, 234, 460, 49, 288, 218, 95, 384, 25, 162, 56, 375, 115, 70, 223, 456, 145, 119, 194, 436, 470, 212, 484, 449, 412, 210, 256, 226, 253, 144, 461, 322, 101, 172, 107, 360, 115, 53, 122, 287, 32, 146, 466, 411, 232, 471, 15, 168, 26, 224, 105, 150, 94, 98, 502, 74, 55, 490, 424, 379, 449, 264, 410, 128, 17, 16, 185, 129, 51, 31, 310, 397, 511, 248, 175, 366, 461, 36, 291, 210, 193, 384, 147, 248, 33, 245, 245, 127, 224, 352, 438, 438, 456, 76, 78, 348, 117, 135, 427, 76, 43, 76, 404, 379, 246, 76, 79, 396, 74, 391, 438, 288, 61, 45, 231, 346, 476, 27, 368, 173, 367, 462, 236, 461, 291, 106, 80, 35, 373, 112, 164, 484, 114, 372, 365, 422, 206, 395, 149, 407, 415, 439, 364, 395, 101, 147, 266, 129, 333, 384, 2, 211, 122, 143, 210, 162, 368, 222, 154, 205, 197, 495, 233, 359, 459, 258, 284, 46, 91, 470, 179, 124, 207, 131, 262, 171, 15, 269, 216, 94, 22, 311, 178, 381, 433, 187, 158, 191, 79, 432, 228, 67, 100, 403, 315, 57, 401, 121, 244, 429, 67, 394, 279, 11, 84, 138, 221, 271, 11, 205, 402, 18, 500, 207, 34, 244, 466, 341, 206, 300, 139, 277, 131, 292, 403, 77, 419, 242, 329, 223, 262, 452, 451, 387, 218, 282, 355, 251, 196, 75, 400, 107, 118, 43, 65, 402, 413, 346, 508, 117, 103, 243, 329, 196, 5, 447, 395, 267, 353, 346, 59, 358, 455, 351, 381, 319, 252, 463, 165, 503, 296, 198, 144, 248, 88, 94, 466, 164, 98, 290, 329, 24, 123, 84, 383, 346, 243, 488, 346, 425, 12, 472, 159, 468, 37, 186, 18, 31, 222, 64, 309, 74, 131, 256, 425, 342, 441, 223, 470, 134, 104, 458, 119, 477, 153, 181, 112, 88, 338, 303, 199, 190, 389, 214, 507, 503, 25, 308, 213, 309, 301, 163, 152, 428, 243, 509, 344, 255, 47, 38, 296, 57, 37, 131, 8, 159, 55, 28, 75, 377, 44, 33, 75, 496, 256, 483, 54, 239, 331, 134, 192, 133, 38, 218, 472, 313, 138, 401, 462, 34, 203, 99, 40, 365, 100, 411, 96, 408, 380, 212, 245, 61, 80, 194, 271, 9, 208, 347, 512, 88, 462, 445, 121, 183, 45, 119, 415, 1, 459, 55, 176, 255, 308, 332, 5, 432, 249, 81, 107, 213, 96, 310, 506, 153, 168, 337, 165, 125, 326, 202, 347, 309, 410, 214, 281, 377, 219, 122, 263, 270, 204, 462, 475, 238, 285, 432, 235, 143, 458, 204, 402, 211, 284, 133, 495, 384, 80, 81, 183, 40, 171, 237, 314, 501, 236, 155, 373, 57, 178, 51, 443, 144, 64, 173, 160, 282, 287, 148, 263, 79, 260, 247, 35, 161, 339, 429, 10, 98, 257, 488, 329, 456, 331, 344, 337, 452, 237, 400, 49, 119, 256, 187, 40, 82, 24, 510, 251, 223, 232, 72, 207, 113, 473, 75, 211, 324, 52, 426, 3, 355, 358, 109, 38, 423, 124, 376, 204, 11, 244, 120, 380, 291, 210, 471, 33, 319, 503, 182, 62, 494, 330, 440, 38, 219, 108, 82, 31, 229, 319, 404, 89, 118, 120, 322, 195, 144, 160, 385, 221, 231, 365, 88, 81, 403, 186, 241, 360, 379, 36, 206, 197, 457, 155, 493, 271, 484, 508, 505, 363, 80, 31, 54, 192, 257, 65, 121, 329, 148, 327, 486, 290, 427, 493, 386, 480, 94, 62, 65, 275, 328, 31, 107, 482, 468, 196, 328, 353, 117, 318, 422, 184, 269, 475, 307, 53, 82, 355, 507, 15, 0, 336, 222, 489, 175, 160, 384, 229, 13, 162, 512, 72, 497, 185, 245, 247, 261, 427, 282, 304, 52, 107, 227, 344, 92, 100, 461, 203, 195, 162, 403, 140, 351, 490, 345, 317, 507, 436, 161, 185, 121, 455, 257, 500, 382, 37, 338, 462, 228, 321, 60, 407, 144, 34, 114, 338, 437, 29, 191, 344, 211, 141, 283, 169, 20, 416, 206, 155, 275, 343, 51, 145, 396, 392, 123, 69, 380, 476, 142, 11, 204, 445, 301, 280, 124, 390, 42, 355, 81, 492, 93, 427, 510, 2, 317, 160, 43, 207, 291, 347, 146, 499, 505, 143, 207, 182, 120, 209, 488, 494, 415, 121, 69, 392, 451, 51, 416, 273, 364, 121, 459, 51, 318, 139, 135, 261, 497, 27, 510, 121, 222, 461, 237, 437, 479, 360, 334, 297, 68, 482, 235, 43, 334, 7, 411, 361, 271, 197, 319, 480, 289, 162, 260, 152, 155, 269, 183, 16, 480, 150, 105, 284, 273, 233, 221, 185, 120, 424, 214, 333, 116, 174, 384, 197, 348, 358, 272, 363, 397, 207, 491, 441, 13, 326, 70};

	rfr::util::running_statistics<double> stat_total;

	for (auto i=0u; i<N; ++i)
		stat_total.push(values[i]);

	for (auto i=10u; i<N-10; ++i){
		rfr::util::running_statistics<double> stat1, stat2, stat3;

		for(auto j=0u; j<i; ++j)
			stat1.push(values[j]);

		for(auto j=i; j<N; ++j)
			stat2.push(values[j]);

		BOOST_REQUIRE(stat_total.numerically_equal(stat1+stat2, 1e-6));
		BOOST_REQUIRE(stat1.numerically_equal(stat_total-stat2, 1e-6));
		BOOST_REQUIRE(stat2.numerically_equal(stat_total-stat1, 1e-6));

		stat3 = stat1 + stat2;

		BOOST_REQUIRE_THROW(stat1-stat3, std::runtime_error);
		BOOST_REQUIRE_THROW(stat1-=stat3, std::runtime_error);

	}

	{
		rfr::util::running_statistics<double> stat1, stat2;
		stat1.push(values[0]);
		BOOST_REQUIRE_THROW(stat1.pop(values[0]), std::runtime_error);

		stat2.push(values[0]);
		stat2.push(values[1]);

		BOOST_REQUIRE_THROW(stat2.pop(512), std::runtime_error);
	}

	{
		rfr::util::running_statistics<double> stat1, stat2, stat3, stat4, stat5;

		double factor = 1.2345;
		double offset = 6.7890;

		for (auto i=0u; i<N; ++i){
			stat1.push(values[i]);
			stat2.push(factor*values[i]);
			stat3.push(values[i]+offset);
			stat4.push(factor*values[i]+offset);
			stat5.push(values[i]-offset);
		}

		BOOST_REQUIRE(stat2.numerically_equal(stat1*factor, 1e-4));
		BOOST_REQUIRE(stat3.numerically_equal(stat1+offset, 1e-4));
		BOOST_REQUIRE(stat4.numerically_equal(stat1*factor+offset, 1e-4));
		BOOST_REQUIRE(stat5.numerically_equal(stat1-offset, 1e-4));
	}
}

BOOST_AUTO_TEST_CASE(test_running_covariance){
	int N = 1024;
	double v1[] = {187, 277, 299, 202, 190, 425, 214, 163, 441, 401, 464, 379, 427, 345, 168, 484, 258, 224, 481, 109, 331, 419, 47, 101, 52, 250, 228, 350, 455, 507, 91, 184, 250, 59, 55, 495, 504, 52, 336, 101, 482, 148, 94, 340, 137, 14, 132, 429, 418, 22, 208, 25, 453, 483, 333, 437, 83, 170, 464, 100, 299, 356, 223, 348, 464, 317, 31, 62, 52, 336, 385, 148, 74, 101, 202, 51, 402, 280, 485, 246, 107, 347, 269, 450, 95, 164, 82, 475, 144, 173, 197, 420, 222, 72, 378, 389, 418, 266, 331, 495, 386, 300, 124, 470, 268, 372, 416, 462, 426, 176, 214, 280, 207, 396, 245, 255, 128, 90, 437, 39, 361, 153, 334, 442, 241, 94, 491, 346, 184, 420, 119, 158, 99, 98, 512, 216, 461, 497, 54, 317, 257, 77, 486, 414, 443, 403, 385, 500, 229, 278, 435, 175, 159, 490, 136, 337, 357, 460, 149, 423, 488, 429, 213, 302, 414, 316, 16, 331, 177, 360, 294, 218, 300, 166, 505, 327, 276, 403, 424, 330, 409, 224, 283, 407, 433, 257, 456, 420, 229, 17, 307, 434, 210, 165, 391, 27, 505, 164, 201, 267, 94, 132, 264, 256, 5, 368, 178, 429, 308, 421, 279, 144, 422, 155, 419, 397, 306, 35, 104, 310, 447, 168, 139, 146, 172, 357, 468, 226, 437, 390, 35, 234, 460, 49, 288, 218, 95, 384, 25, 162, 56, 375, 115, 70, 223, 456, 145, 119, 194, 436, 470, 212, 484, 449, 412, 210, 256, 226, 253, 144, 461, 322, 101, 172, 107, 360, 115, 53, 122, 287, 32, 146, 466, 411, 232, 471, 15, 168, 26, 224, 105, 150, 94, 98, 502, 74, 55, 490, 424, 379, 449, 264, 410, 128, 17, 16, 185, 129, 51, 31, 310, 397, 511, 248, 175, 366, 461, 36, 291, 210, 193, 384, 147, 248, 33, 245, 245, 127, 224, 352, 438, 438, 456, 76, 78, 348, 117, 135, 427, 76, 43, 76, 404, 379, 246, 76, 79, 396, 74, 391, 438, 288, 61, 45, 231, 346, 476, 27, 368, 173, 367, 462, 236, 461, 291, 106, 80, 35, 373, 112, 164, 484, 114, 372, 365, 422, 206, 395, 149, 407, 415, 439, 364, 395, 101, 147, 266, 129, 333, 384, 2, 211, 122, 143, 210, 162, 368, 222, 154, 205, 197, 495, 233, 359, 459, 258, 284, 46, 91, 470, 179, 124, 207, 131, 262, 171, 15, 269, 216, 94, 22, 311, 178, 381, 433, 187, 158, 191, 79, 432, 228, 67, 100, 403, 315, 57, 401, 121, 244, 429, 67, 394, 279, 11, 84, 138, 221, 271, 11, 205, 402, 18, 500, 207, 34, 244, 466, 341, 206, 300, 139, 277, 131, 292, 403, 77, 419, 242, 329, 223, 262, 452, 451, 387, 218, 282, 355, 251, 196, 75, 400, 107, 118, 43, 65, 402, 413, 346, 508, 117, 103, 243, 329, 196, 5, 447, 395, 267, 353, 346, 59, 358, 455, 351, 381, 319, 252, 463, 165, 503, 296, 198, 144, 248, 88, 94, 466, 164, 98, 290, 329, 24, 123, 84, 383, 346, 243, 488, 346, 425, 12, 472, 159, 468, 37, 186, 18, 31, 222, 64, 309, 74, 131, 256, 425, 342, 441, 223, 470, 134, 104, 458, 119, 477, 153, 181, 112, 88, 338, 303, 199, 190, 389, 214, 507, 503, 25, 308, 213, 309, 301, 163, 152, 428, 243, 509, 344, 255, 47, 38, 296, 57, 37, 131, 8, 159, 55, 28, 75, 377, 44, 33, 75, 496, 256, 483, 54, 239, 331, 134, 192, 133, 38, 218, 472, 313, 138, 401, 462, 34, 203, 99, 40, 365, 100, 411, 96, 408, 380, 212, 245, 61, 80, 194, 271, 9, 208, 347, 512, 88, 462, 445, 121, 183, 45, 119, 415, 1, 459, 55, 176, 255, 308, 332, 5, 432, 249, 81, 107, 213, 96, 310, 506, 153, 168, 337, 165, 125, 326, 202, 347, 309, 410, 214, 281, 377, 219, 122, 263, 270, 204, 462, 475, 238, 285, 432, 235, 143, 458, 204, 402, 211, 284, 133, 495, 384, 80, 81, 183, 40, 171, 237, 314, 501, 236, 155, 373, 57, 178, 51, 443, 144, 64, 173, 160, 282, 287, 148, 263, 79, 260, 247, 35, 161, 339, 429, 10, 98, 257, 488, 329, 456, 331, 344, 337, 452, 237, 400, 49, 119, 256, 187, 40, 82, 24, 510, 251, 223, 232, 72, 207, 113, 473, 75, 211, 324, 52, 426, 3, 355, 358, 109, 38, 423, 124, 376, 204, 11, 244, 120, 380, 291, 210, 471, 33, 319, 503, 182, 62, 494, 330, 440, 38, 219, 108, 82, 31, 229, 319, 404, 89, 118, 120, 322, 195, 144, 160, 385, 221, 231, 365, 88, 81, 403, 186, 241, 360, 379, 36, 206, 197, 457, 155, 493, 271, 484, 508, 505, 363, 80, 31, 54, 192, 257, 65, 121, 329, 148, 327, 486, 290, 427, 493, 386, 480, 94, 62, 65, 275, 328, 31, 107, 482, 468, 196, 328, 353, 117, 318, 422, 184, 269, 475, 307, 53, 82, 355, 507, 15, 0, 336, 222, 489, 175, 160, 384, 229, 13, 162, 512, 72, 497, 185, 245, 247, 261, 427, 282, 304, 52, 107, 227, 344, 92, 100, 461, 203, 195, 162, 403, 140, 351, 490, 345, 317, 507, 436, 161, 185, 121, 455, 257, 500, 382, 37, 338, 462, 228, 321, 60, 407, 144, 34, 114, 338, 437, 29, 191, 344, 211, 141, 283, 169, 20, 416, 206, 155, 275, 343, 51, 145, 396, 392, 123, 69, 380, 476, 142, 11, 204, 445, 301, 280, 124, 390, 42, 355, 81, 492, 93, 427, 510, 2, 317, 160, 43, 207, 291, 347, 146, 499, 505, 143, 207, 182, 120, 209, 488, 494, 415, 121, 69, 392, 451, 51, 416, 273, 364, 121, 459, 51, 318, 139, 135, 261, 497, 27, 510, 121, 222, 461, 237, 437, 479, 360, 334, 297, 68, 482, 235, 43, 334, 7, 411, 361, 271, 197, 319, 480, 289, 162, 260, 152, 155, 269, 183, 16, 480, 150, 105, 284, 273, 233, 221, 185, 120, 424, 214, 333, 116, 174, 384, 197, 348, 358, 272, 363, 397, 207, 491, 441, 13, 326, 70};
	double v2[] = {187, 219, 410, 218, 295, 338, 390, 313, 279, 289, 88, 213, 274, 52, 119, 506, 17, 132, 57, 16, 444, 339, 385, 283, 323, 60, 336, 507, 65, 483, 333, 159, 22, 299, 491, 209, 323, 491, 190, 348, 184, 185, 80, 252, 444, 180, 56, 279, 382, 293, 491, 255, 329, 105, 37, 68, 216, 183, 418, 458, 69, 301, 27, 169, 35, 426, 99, 282, 169, 56, 98, 442, 81, 113, 450, 41, 360, 180, 329, 421, 233, 245, 379, 338, 169, 11, 246, 234, 88, 17, 173, 477, 500, 437, 179, 140, 176, 8, 425, 296, 238, 404, 157, 0, 278, 369, 426, 235, 470, 172, 378, 475, 59, 309, 269, 329, 201, 253, 212, 143, 274, 180, 125, 180, 224, 373, 323, 275, 166, 150, 13, 348, 454, 455, 406, 317, 401, 231, 389, 64, 320, 16, 195, 271, 9, 406, 38, 80, 149, 489, 256, 191, 385, 174, 235, 196, 203, 229, 220, 479, 311, 121, 165, 478, 140, 435, 182, 146, 246, 27, 450, 368, 448, 162, 101, 14, 161, 502, 264, 375, 160, 276, 382, 157, 1, 174, 192, 158, 269, 365, 54, 307, 479, 37, 177, 399, 278, 392, 469, 486, 322, 130, 346, 15, 371, 107, 20, 252, 58, 348, 81, 234, 192, 5, 216, 356, 146, 251, 467, 510, 313, 239, 384, 405, 124, 461, 507, 200, 498, 163, 104, 391, 259, 196, 408, 154, 264, 221, 347, 418, 60, 118, 418, 161, 471, 165, 202, 432, 220, 503, 44, 381, 5, 250, 294, 109, 299, 86, 342, 512, 47, 382, 103, 106, 18, 441, 260, 115, 201, 341, 153, 210, 333, 237, 166, 409, 48, 242, 463, 469, 302, 415, 5, 263, 80, 341, 120, 262, 43, 433, 340, 436, 224, 502, 31, 360, 449, 421, 261, 71, 55, 141, 478, 122, 270, 253, 486, 346, 100, 377, 417, 251, 159, 408, 348, 268, 499, 237, 125, 319, 345, 25, 141, 481, 241, 394, 508, 138, 264, 448, 328, 267, 382, 160, 113, 62, 415, 359, 414, 35, 50, 157, 229, 109, 466, 90, 164, 355, 431, 272, 213, 156, 194, 82, 322, 490, 83, 56, 212, 277, 412, 299, 120, 292, 477, 360, 16, 459, 127, 366, 389, 47, 401, 446, 467, 473, 471, 62, 198, 25, 358, 337, 492, 162, 59, 120, 286, 211, 275, 43, 502, 26, 295, 60, 70, 324, 112, 4, 304, 394, 154, 411, 248, 350, 102, 9, 77, 482, 156, 80, 502, 123, 381, 255, 352, 128, 7, 345, 250, 496, 67, 379, 374, 118, 211, 318, 92, 309, 347, 447, 334, 173, 137, 459, 422, 479, 288, 90, 395, 19, 504, 2, 46, 474, 238, 363, 498, 338, 242, 104, 310, 14, 318, 244, 456, 87, 424, 265, 201, 419, 62, 166, 223, 219, 104, 146, 398, 237, 441, 416, 478, 256, 218, 250, 322, 100, 507, 358, 131, 433, 115, 358, 5, 119, 479, 127, 69, 495, 420, 335, 366, 170, 467, 87, 383, 416, 313, 442, 152, 486, 58, 496, 484, 23, 169, 219, 231, 147, 226, 255, 314, 306, 58, 97, 475, 507, 4, 367, 460, 38, 122, 27, 113, 139, 113, 290, 323, 227, 399, 53, 414, 236, 390, 358, 213, 209, 65, 84, 202, 66, 502, 238, 21, 39, 185, 113, 324, 37, 378, 379, 345, 65, 137, 74, 511, 169, 332, 30, 407, 73, 391, 499, 317, 474, 350, 347, 389, 506, 108, 288, 205, 415, 100, 207, 12, 174, 86, 477, 278, 36, 198, 506, 54, 247, 92, 407, 237, 494, 395, 301, 163, 401, 272, 220, 243, 509, 396, 204, 435, 58, 501, 443, 389, 512, 195, 282, 80, 221, 81, 476, 198, 49, 276, 180, 84, 8, 244, 481, 309, 237, 310, 180, 8, 126, 251, 52, 231, 153, 109, 274, 473, 141, 22, 278, 241, 472, 339, 90, 457, 203, 215, 329, 91, 365, 346, 397, 407, 193, 67, 193, 459, 26, 57, 23, 122, 26, 134, 495, 311, 98, 101, 190, 29, 270, 331, 84, 237, 99, 379, 287, 479, 134, 459, 60, 77, 62, 395, 494, 280, 204, 484, 332, 391, 212, 309, 478, 172, 422, 192, 489, 507, 385, 130, 249, 501, 500, 37, 207, 383, 203, 292, 45, 253, 415, 338, 266, 398, 368, 199, 442, 40, 40, 375, 74, 92, 265, 15, 123, 441, 180, 367, 95, 504, 366, 56, 508, 26, 475, 30, 236, 258, 292, 505, 487, 320, 148, 74, 78, 375, 309, 219, 445, 402, 277, 178, 165, 61, 397, 78, 483, 414, 64, 105, 224, 45, 512, 159, 41, 136, 271, 352, 151, 505, 49, 364, 61, 105, 158, 453, 191, 164, 114, 120, 467, 477, 303, 99, 186, 347, 19, 209, 237, 6, 301, 79, 326, 366, 502, 499, 330, 219, 437, 328, 347, 506, 33, 139, 217, 340, 51, 403, 288, 272, 191, 22, 73, 176, 407, 68, 247, 407, 117, 416, 235, 176, 78, 443, 276, 187, 44, 175, 196, 234, 197, 435, 281, 391, 336, 44, 185, 170, 384, 83, 90, 25, 96, 206, 159, 464, 378, 404, 321, 343, 139, 451, 470, 308, 408, 505, 210, 157, 329, 267, 85, 293, 191, 245, 128, 388, 402, 142, 197, 2, 215, 232, 201, 233, 418, 129, 502, 220, 398, 28, 116, 498, 287, 450, 8, 70, 140, 382, 202, 280, 5, 56, 406, 161, 54, 371, 222, 87, 293, 325, 167, 402, 494, 83, 163, 386, 51, 263, 381, 33, 168, 83, 80, 504, 105, 325, 209, 463, 248, 10, 310, 376, 239, 341, 498, 499, 372, 355, 416, 29, 294, 51, 177, 440, 282, 12, 214, 144, 376, 510, 188, 205, 228, 325, 512, 195, 237, 137, 9, 256, 147, 175, 92, 39, 409, 438, 151, 375, 280, 400, 383, 405, 355, 351, 488, 4, 372, 244, 493, 419, 62, 15, 493, 209, 336, 295, 266, 110, 454, 209, 237, 158, 280, 79, 23, 307, 92, 384, 7, 33, 321, 476, 359, 462, 292, 333, 415, 476, 210, 69, 148, 484, 80, 280, 397, 365, 146, 303, 72, 61, 263, 287, 16, 207, 471, 167, 197, 414, 89, 411, 242, 503, 120, 28, 216, 400, 47, 23, 414, 236, 347};

	rfr::util::running_statistics<double> stat1, stat2;
	rfr::util::running_covariance<double> cov;

	for (auto i = 0; i<N; i++){
		cov.push(v1[i], v2[i]);
		stat1.push(v1[i]);
		stat2.push(v2[i]);
	}
	BOOST_REQUIRE_CLOSE(stat1.mean(),253.3232421875, 1e-6);
	BOOST_REQUIRE_CLOSE(stat1.variance_sample(),21532.3323625, 1e-6);

	BOOST_REQUIRE_CLOSE(stat2.mean(),253.830078125,1e-6);
	BOOST_REQUIRE_CLOSE(stat2.variance_sample(),22307.58986666, 1e-6);
	BOOST_REQUIRE_CLOSE(cov.covariance(),  -80.89516702, 1e-6);
}

BOOST_AUTO_TEST_CASE(test_weighted_running_statistics_push){

	unsigned int N = 255;
	double values[] = {  61,    99,   125,   222,   34,   208,   247,   156,    59,     2,   226,   116,   203,   213,   123,   250,   209,   124,   218,    20,    43,    66,   154,   142,   223,   117,   252,   249,   105,    42,     2,   248,    69,   180,   142,   196,   237,   124,    25,    53,    76,     5,     9,   219,   114,   251,    21,   247,   183,    83,   147,   202,    16,   101,   192,   209,   140,   207,   225,    34,   160,  171,   173,   188,   161,    76,   242,    97,   104,    10,   163,    32,   243,  140,  204,   211,   106,   212,   199,    14,   115,   116,   196,   120,    87,    50,   204,  28,  158,   191,   127,   110,  210,   224,  162,   105,    68,   236,    25,   142,    80,   196,   235,   219,   140,   251,   113,   240,    81,     9,   133,   219,   186,   153,    55,   35,   166,    9,   238,   125,   233,   69,   181,  109,    63,    34,   193,   240,   174,   194,   213,   165,    26,   210,   167,   21,   168,   167,    55,   135,   170,   206,    13,    91,   225,   159,  253,   127,   196,   140,   144,   222,   190,   15,    22,   185,    79,    11,   106,    57,    94,    78,   116,   183,  128,   161,   212,    38,  242,   157,    41,   253,   192,   184,     6,   163,    17,    66,   128,   245,    80,   194,   208,    73,   181,    91,    93,    38,   123,   213,   197,  109,   231,    36,   168,   199,   172,   211,   180,   246,   111,    45,   249,    73,   187,    42,   255,    83,   103,   45,    76,   145,    10,    59,  84,   179,   168,  251,  77,   218,   109,   221,   237,   135,   154,    94,    69,    49,    79,   102,   254,    77,    40,   107,    13,   226,    84,    78,   128,    35,   177,    4,  123,   172,    55,   174,    46,  176,    43,    77,   110,    43,  37,   148,  237};
	double weights[]= {0.07, 0.985, 0.056, 0.089, 0.18, 0.619, 0.267, 0.528, 0.138, 0.468, 0.666, 0.858, 0.204, 0.126, 0.116, 0.739, 0.484, 0.311, 0.598, 0.947, 0.499, 0.777, 0.434, 0.976, 0.109, 0.267, 0.758, 0.455, 0.841, 0.028, 0.328, 0.426, 0.072, 0.508, 0.771, 0.197, 0.551, 0.656, 0.152, 0.207, 0.765, 0.315, 0.112, 0.095, 0.743, 0.262, 0.865, 0.361, 0.276, 0.035, 0.208, 0.307, 0.212, 0.894, 0.246, 0.716, 0.573, 0.929, 0.173, 0.077, 0.982, 0.68, 0.954, 0.009, 0.417, 0.255, 0.211, 0.586, 0.608, 0.844, 0.311, 0.702, 0.474, 0.98, 0.89, 0.658, 0.293, 0.973, 0.104, 0.333, 0.187, 0.532, 0.899, 0.364, 0.618, 0.768, 0.683, 0.8, 0.85, 0.221, 0.212, 0.048, 0.73, 0.477, 0.84, 0.817, 0.729, 0.825, 0.927, 0.934, 0.586, 0.482, 0.023, 0.282, 0.454, 0.255, 0.197, 0.529, 0.692, 0.092, 0.809, 0.316, 0.914, 0.221, 0.091, 0.04, 0.791, 0.82, 0.205, 0.698, 0.455, 0.02, 0.842, 0.14, 0.005, 0.968, 0.486, 0.463, 0.992, 0.426, 0.147, 0.591, 0.262, 0.276, 0.299, 0.64, 0.607, 0.165, 0.907, 0.342, 0.413, 0.413, 0.202, 0.103, 0.167, 0.996, 0.35, 0.291, 0.184, 0.538, 0.921, 0.556, 0.772, 0.88, 0.982, 0.398, 0.917, 0.329, 0.961, 0.714, 0.064, 0.237, 0.735, 0.531, 0.27, 0.098, 0.565, 0.699, 0.32, 0.452, 0.002, 0.699, 0.888, 0.516, 0.404, 0.464, 0.051, 0.304, 0.178, 0.919, 0.503, 0.667, 0.628, 0.079, 0.864, 0.827, 0.363, 0.644, 0.551, 0.846, 0.641, 0.07, 0.346, 0.505, 0.672, 0.143, 0.083, 0.881, 0.398, 0.787, 0.662, 0.799, 0.354, 0.477, 0.506, 0.124, 0.233, 0.963, 0.529, 0.54, 0.781, 0.935, 0.025, 0.475, 0.3, 0.837, 0.409, 0.38, 0.7, 0.575, 0.487, 0.432, 0.967, 0.017, 0.449, 0.513, 0.245, 0.834, 0.138, 0.751, 0.969, 0.183, 0.526, 0.813, 0.583, 0.759, 0.527, 0.675, 0.142, 0.007, 0.075, 0.85, 0.97, 0.567, 0.048, 0.121, 0.281, 0.65, 0.455, 0.936, 0.055, 0.709, 0.7, 0.384, 0.99};
		rfr::util::weighted_running_statistics<double> stat1, stat2;

	for (auto i=0u; i<N; i++){
		stat1.push(values[i], 1);
		stat2.push(values[i], weights[i]);

	}

	BOOST_REQUIRE_CLOSE(stat1.sum_of_weights()     , (double) N  , 1e-6);
	BOOST_REQUIRE_CLOSE(stat1.mean()               ,134.415686275,1e-6);
	BOOST_REQUIRE_CLOSE(stat1.variance_population(),5500.63504806,1e-6);
	BOOST_REQUIRE_CLOSE(stat1.sum_of_squares()     , 6009894     ,1e-6);   

	BOOST_REQUIRE_CLOSE(stat2.sum_of_weights()		,125.273	,1e-6);
	BOOST_REQUIRE_CLOSE(stat2.mean()				,136.6691945,1e-6);
	BOOST_REQUIRE_CLOSE(stat2.variance_population()	,5340.296298,1e-6);
	BOOST_REQUIRE_CLOSE(stat2.sum_of_squares()      ,3008902.75 ,1e-6);

	BOOST_REQUIRE_THROW(stat1.push(0.1, 0), std::runtime_error);
	BOOST_REQUIRE_THROW(stat1.push(0.1, -2), std::runtime_error);
}

BOOST_AUTO_TEST_CASE(test_weighted_running_statistics_throws){

	unsigned int N = 255;
	double values[] = {  61,    99,   125,   222,   34,   208,   247,   156,    59,     2,   226,   116,   203,   213,   123,   250,   209,   124,   218,    20,    43,    66,   154,   142,   223,   117,   252,   249,   105,    42,     2,   248,    69,   180,   142,   196,   237,   124,    25,    53,    76,     5,     9,   219,   114,   251,    21,   247,   183,    83,   147,   202,    16,   101,   192,   209,   140,   207,   225,    34,   160,  171,   173,   188,   161,    76,   242,    97,   104,    10,   163,    32,   243,  140,  204,   211,   106,   212,   199,    14,   115,   116,   196,   120,    87,    50,   204,  28,  158,   191,   127,   110,  210,   224,  162,   105,    68,   236,    25,   142,    80,   196,   235,   219,   140,   251,   113,   240,    81,     9,   133,   219,   186,   153,    55,   35,   166,    9,   238,   125,   233,   69,   181,  109,    63,    34,   193,   240,   174,   194,   213,   165,    26,   210,   167,   21,   168,   167,    55,   135,   170,   206,    13,    91,   225,   159,  253,   127,   196,   140,   144,   222,   190,   15,    22,   185,    79,    11,   106,    57,    94,    78,   116,   183,  128,   161,   212,    38,  242,   157,    41,   253,   192,   184,     6,   163,    17,    66,   128,   245,    80,   194,   208,    73,   181,    91,    93,    38,   123,   213,   197,  109,   231,    36,   168,   199,   172,   211,   180,   246,   111,    45,   249,    73,   187,    42,   255,    83,   103,   45,    76,   145,    10,    59,  84,   179,   168,  251,  77,   218,   109,   221,   237,   135,   154,    94,    69,    49,    79,   102,   254,    77,    40,   107,    13,   226,    84,    78,   128,    35,   177,    4,  123,   172,    55,   174,    46,  176,    43,    77,   110,    43,  37,   148,  237};
	double weights[]= {0.07, 0.985, 0.056, 0.089, 0.18, 0.619, 0.267, 0.528, 0.138, 0.468, 0.666, 0.858, 0.204, 0.126, 0.116, 0.739, 0.484, 0.311, 0.598, 0.947, 0.499, 0.777, 0.434, 0.976, 0.109, 0.267, 0.758, 0.455, 0.841, 0.028, 0.328, 0.426, 0.072, 0.508, 0.771, 0.197, 0.551, 0.656, 0.152, 0.207, 0.765, 0.315, 0.112, 0.095, 0.743, 0.262, 0.865, 0.361, 0.276, 0.035, 0.208, 0.307, 0.212, 0.894, 0.246, 0.716, 0.573, 0.929, 0.173, 0.077, 0.982, 0.68, 0.954, 0.009, 0.417, 0.255, 0.211, 0.586, 0.608, 0.844, 0.311, 0.702, 0.474, 0.98, 0.89, 0.658, 0.293, 0.973, 0.104, 0.333, 0.187, 0.532, 0.899, 0.364, 0.618, 0.768, 0.683, 0.8, 0.85, 0.221, 0.212, 0.048, 0.73, 0.477, 0.84, 0.817, 0.729, 0.825, 0.927, 0.934, 0.586, 0.482, 0.023, 0.282, 0.454, 0.255, 0.197, 0.529, 0.692, 0.092, 0.809, 0.316, 0.914, 0.221, 0.091, 0.04, 0.791, 0.82, 0.205, 0.698, 0.455, 0.02, 0.842, 0.14, 0.005, 0.968, 0.486, 0.463, 0.992, 0.426, 0.147, 0.591, 0.262, 0.276, 0.299, 0.64, 0.607, 0.165, 0.907, 0.342, 0.413, 0.413, 0.202, 0.103, 0.167, 0.996, 0.35, 0.291, 0.184, 0.538, 0.921, 0.556, 0.772, 0.88, 0.982, 0.398, 0.917, 0.329, 0.961, 0.714, 0.064, 0.237, 0.735, 0.531, 0.27, 0.098, 0.565, 0.699, 0.32, 0.452, 0.002, 0.699, 0.888, 0.516, 0.404, 0.464, 0.051, 0.304, 0.178, 0.919, 0.503, 0.667, 0.628, 0.079, 0.864, 0.827, 0.363, 0.644, 0.551, 0.846, 0.641, 0.07, 0.346, 0.505, 0.672, 0.143, 0.083, 0.881, 0.398, 0.787, 0.662, 0.799, 0.354, 0.477, 0.506, 0.124, 0.233, 0.963, 0.529, 0.54, 0.781, 0.935, 0.025, 0.475, 0.3, 0.837, 0.409, 0.38, 0.7, 0.575, 0.487, 0.432, 0.967, 0.017, 0.449, 0.513, 0.245, 0.834, 0.138, 0.751, 0.969, 0.183, 0.526, 0.813, 0.583, 0.759, 0.527, 0.675, 0.142, 0.007, 0.075, 0.85, 0.97, 0.567, 0.048, 0.121, 0.281, 0.65, 0.455, 0.936, 0.055, 0.709, 0.7, 0.384, 0.99};
		rfr::util::weighted_running_statistics<double> stat1, stat2;

	for (auto i=0u; i<N; i++){
		stat1.push(values[i], 1);
		stat2.push(values[i], weights[i]);

	}

	BOOST_REQUIRE_THROW(stat1.pop(0.1, 0), std::runtime_error);
	BOOST_REQUIRE_THROW(stat1.pop(0.1, -2), std::runtime_error);

	BOOST_REQUIRE_THROW(stat1.pop(0.1, 1e20), std::runtime_error);

	BOOST_REQUIRE_THROW(stat2-stat1, std::runtime_error);
	BOOST_REQUIRE_THROW(stat2-=stat1, std::runtime_error);

	for (auto i=0u; i<N-2; i++){
		stat1.pop(values[i], 1);
		stat2.pop(values[i], weights[i]);
	}

	BOOST_REQUIRE_THROW(stat1.pop(values[N-1], 1), std::runtime_error);
	BOOST_REQUIRE_THROW(stat2.pop(values[N-1], weights[N-1]), std::runtime_error);

}

BOOST_AUTO_TEST_CASE(test_weighted_running_statistics_pop){

	unsigned int N = 255;
	double values[] = {  61,    99,   125,   222,   34,   208,   247,   156,    59,     2,   226,   116,   203,   213,   123,   250,   209,   124,   218,    20,    43,    66,   154,   142,   223,   117,   252,   249,   105,    42,     2,   248,    69,   180,   142,   196,   237,   124,    25,    53,    76,     5,     9,   219,   114,   251,    21,   247,   183,    83,   147,   202,    16,   101,   192,   209,   140,   207,   225,    34,   160,  171,   173,   188,   161,    76,   242,    97,   104,    10,   163,    32,   243,  140,  204,   211,   106,   212,   199,    14,   115,   116,   196,   120,    87,    50,   204,  28,  158,   191,   127,   110,  210,   224,  162,   105,    68,   236,    25,   142,    80,   196,   235,   219,   140,   251,   113,   240,    81,     9,   133,   219,   186,   153,    55,   35,   166,    9,   238,   125,   233,   69,   181,  109,    63,    34,   193,   240,   174,   194,   213,   165,    26,   210,   167,   21,   168,   167,    55,   135,   170,   206,    13,    91,   225,   159,  253,   127,   196,   140,   144,   222,   190,   15,    22,   185,    79,    11,   106,    57,    94,    78,   116,   183,  128,   161,   212,    38,  242,   157,    41,   253,   192,   184,     6,   163,    17,    66,   128,   245,    80,   194,   208,    73,   181,    91,    93,    38,   123,   213,   197,  109,   231,    36,   168,   199,   172,   211,   180,   246,   111,    45,   249,    73,   187,    42,   255,    83,   103,   45,    76,   145,    10,    59,  84,   179,   168,  251,  77,   218,   109,   221,   237,   135,   154,    94,    69,    49,    79,   102,   254,    77,    40,   107,    13,   226,    84,    78,   128,    35,   177,    4,  123,   172,    55,   174,    46,  176,    43,    77,   110,    43,  37,   148,  237};
	double weights[]= {0.07, 0.985, 0.056, 0.089, 0.18, 0.619, 0.267, 0.528, 0.138, 0.468, 0.666, 0.858, 0.204, 0.126, 0.116, 0.739, 0.484, 0.311, 0.598, 0.947, 0.499, 0.777, 0.434, 0.976, 0.109, 0.267, 0.758, 0.455, 0.841, 0.028, 0.328, 0.426, 0.072, 0.508, 0.771, 0.197, 0.551, 0.656, 0.152, 0.207, 0.765, 0.315, 0.112, 0.095, 0.743, 0.262, 0.865, 0.361, 0.276, 0.035, 0.208, 0.307, 0.212, 0.894, 0.246, 0.716, 0.573, 0.929, 0.173, 0.077, 0.982, 0.68, 0.954, 0.009, 0.417, 0.255, 0.211, 0.586, 0.608, 0.844, 0.311, 0.702, 0.474, 0.98, 0.89, 0.658, 0.293, 0.973, 0.104, 0.333, 0.187, 0.532, 0.899, 0.364, 0.618, 0.768, 0.683, 0.8, 0.85, 0.221, 0.212, 0.048, 0.73, 0.477, 0.84, 0.817, 0.729, 0.825, 0.927, 0.934, 0.586, 0.482, 0.023, 0.282, 0.454, 0.255, 0.197, 0.529, 0.692, 0.092, 0.809, 0.316, 0.914, 0.221, 0.091, 0.04, 0.791, 0.82, 0.205, 0.698, 0.455, 0.02, 0.842, 0.14, 0.005, 0.968, 0.486, 0.463, 0.992, 0.426, 0.147, 0.591, 0.262, 0.276, 0.299, 0.64, 0.607, 0.165, 0.907, 0.342, 0.413, 0.413, 0.202, 0.103, 0.167, 0.996, 0.35, 0.291, 0.184, 0.538, 0.921, 0.556, 0.772, 0.88, 0.982, 0.398, 0.917, 0.329, 0.961, 0.714, 0.064, 0.237, 0.735, 0.531, 0.27, 0.098, 0.565, 0.699, 0.32, 0.452, 0.002, 0.699, 0.888, 0.516, 0.404, 0.464, 0.051, 0.304, 0.178, 0.919, 0.503, 0.667, 0.628, 0.079, 0.864, 0.827, 0.363, 0.644, 0.551, 0.846, 0.641, 0.07, 0.346, 0.505, 0.672, 0.143, 0.083, 0.881, 0.398, 0.787, 0.662, 0.799, 0.354, 0.477, 0.506, 0.124, 0.233, 0.963, 0.529, 0.54, 0.781, 0.935, 0.025, 0.475, 0.3, 0.837, 0.409, 0.38, 0.7, 0.575, 0.487, 0.432, 0.967, 0.017, 0.449, 0.513, 0.245, 0.834, 0.138, 0.751, 0.969, 0.183, 0.526, 0.813, 0.583, 0.759, 0.527, 0.675, 0.142, 0.007, 0.075, 0.85, 0.97, 0.567, 0.048, 0.121, 0.281, 0.65, 0.455, 0.936, 0.055, 0.709, 0.7, 0.384, 0.99};
	rfr::util::weighted_running_statistics<double> stat_ref, stat1;

	for (auto i=0u; i<N; ++i){
		stat_ref.push(values[i], weights[i]);
	}

	BOOST_REQUIRE_CLOSE(stat_ref.sum_of_weights()		,125.273	,1e-6);
	BOOST_REQUIRE_CLOSE(stat_ref.mean()					,136.6691945,1e-6);
	BOOST_REQUIRE_CLOSE(stat_ref.variance_population()	,5340.296298,1e-6);

	for (auto i=16u; i<N; ++i){

		stat1 = stat_ref;
		rfr::util::weighted_running_statistics<double> stat2;

		for (auto j=0u; j < i; ++j){
			stat1.push(values[j], weights[N-1-j]);
			stat2.push(values[j], weights[N-1-j]);
		}

		BOOST_REQUIRE(stat1.numerically_equal( stat_ref+stat2, 1e-6));
		BOOST_REQUIRE(stat_ref.numerically_equal( stat1-stat2, 1e-6));

		for (auto j=0u; j < i; ++j)
			stat1.pop(values[j], weights[N-1-j]);

		BOOST_REQUIRE_CLOSE(stat1.sum_of_weights()		,125.273	,1e-6);
		BOOST_REQUIRE_CLOSE(stat1.mean()				,136.6691945,1e-6);
		BOOST_REQUIRE_CLOSE(stat1.variance_population()	,5340.296298,1e-6);
	}

}

BOOST_AUTO_TEST_CASE(test_weighted_running_statistics_operators){
	unsigned int N = 255;
	double values[] = {  61,    99,   125,   222,   34,   208,   247,   156,    59,     2,   226,   116,   203,   213,   123,   250,   209,   124,   218,    20,    43,    66,   154,   142,   223,   117,   252,   249,   105,    42,     2,   248,    69,   180,   142,   196,   237,   124,    25,    53,    76,     5,     9,   219,   114,   251,    21,   247,   183,    83,   147,   202,    16,   101,   192,   209,   140,   207,   225,    34,   160,  171,   173,   188,   161,    76,   242,    97,   104,    10,   163,    32,   243,  140,  204,   211,   106,   212,   199,    14,   115,   116,   196,   120,    87,    50,   204,  28,  158,   191,   127,   110,  210,   224,  162,   105,    68,   236,    25,   142,    80,   196,   235,   219,   140,   251,   113,   240,    81,     9,   133,   219,   186,   153,    55,   35,   166,    9,   238,   125,   233,   69,   181,  109,    63,    34,   193,   240,   174,   194,   213,   165,    26,   210,   167,   21,   168,   167,    55,   135,   170,   206,    13,    91,   225,   159,  253,   127,   196,   140,   144,   222,   190,   15,    22,   185,    79,    11,   106,    57,    94,    78,   116,   183,  128,   161,   212,    38,  242,   157,    41,   253,   192,   184,     6,   163,    17,    66,   128,   245,    80,   194,   208,    73,   181,    91,    93,    38,   123,   213,   197,  109,   231,    36,   168,   199,   172,   211,   180,   246,   111,    45,   249,    73,   187,    42,   255,    83,   103,   45,    76,   145,    10,    59,  84,   179,   168,  251,  77,   218,   109,   221,   237,   135,   154,    94,    69,    49,    79,   102,   254,    77,    40,   107,    13,   226,    84,    78,   128,    35,   177,    4,  123,   172,    55,   174,    46,  176,    43,    77,   110,    43,  37,   148,  237};
	double weights[]= {0.07, 0.985, 0.056, 0.089, 0.18, 0.619, 0.267, 0.528, 0.138, 0.468, 0.666, 0.858, 0.204, 0.126, 0.116, 0.739, 0.484, 0.311, 0.598, 0.947, 0.499, 0.777, 0.434, 0.976, 0.109, 0.267, 0.758, 0.455, 0.841, 0.028, 0.328, 0.426, 0.072, 0.508, 0.771, 0.197, 0.551, 0.656, 0.152, 0.207, 0.765, 0.315, 0.112, 0.095, 0.743, 0.262, 0.865, 0.361, 0.276, 0.035, 0.208, 0.307, 0.212, 0.894, 0.246, 0.716, 0.573, 0.929, 0.173, 0.077, 0.982, 0.68, 0.954, 0.009, 0.417, 0.255, 0.211, 0.586, 0.608, 0.844, 0.311, 0.702, 0.474, 0.98, 0.89, 0.658, 0.293, 0.973, 0.104, 0.333, 0.187, 0.532, 0.899, 0.364, 0.618, 0.768, 0.683, 0.8, 0.85, 0.221, 0.212, 0.048, 0.73, 0.477, 0.84, 0.817, 0.729, 0.825, 0.927, 0.934, 0.586, 0.482, 0.023, 0.282, 0.454, 0.255, 0.197, 0.529, 0.692, 0.092, 0.809, 0.316, 0.914, 0.221, 0.091, 0.04, 0.791, 0.82, 0.205, 0.698, 0.455, 0.02, 0.842, 0.14, 0.005, 0.968, 0.486, 0.463, 0.992, 0.426, 0.147, 0.591, 0.262, 0.276, 0.299, 0.64, 0.607, 0.165, 0.907, 0.342, 0.413, 0.413, 0.202, 0.103, 0.167, 0.996, 0.35, 0.291, 0.184, 0.538, 0.921, 0.556, 0.772, 0.88, 0.982, 0.398, 0.917, 0.329, 0.961, 0.714, 0.064, 0.237, 0.735, 0.531, 0.27, 0.098, 0.565, 0.699, 0.32, 0.452, 0.002, 0.699, 0.888, 0.516, 0.404, 0.464, 0.051, 0.304, 0.178, 0.919, 0.503, 0.667, 0.628, 0.079, 0.864, 0.827, 0.363, 0.644, 0.551, 0.846, 0.641, 0.07, 0.346, 0.505, 0.672, 0.143, 0.083, 0.881, 0.398, 0.787, 0.662, 0.799, 0.354, 0.477, 0.506, 0.124, 0.233, 0.963, 0.529, 0.54, 0.781, 0.935, 0.025, 0.475, 0.3, 0.837, 0.409, 0.38, 0.7, 0.575, 0.487, 0.432, 0.967, 0.017, 0.449, 0.513, 0.245, 0.834, 0.138, 0.751, 0.969, 0.183, 0.526, 0.813, 0.583, 0.759, 0.527, 0.675, 0.142, 0.007, 0.075, 0.85, 0.97, 0.567, 0.048, 0.121, 0.281, 0.65, 0.455, 0.936, 0.055, 0.709, 0.7, 0.384, 0.99};

	{
		rfr::util::weighted_running_statistics<double> stat1, stat2, stat3, stat4;

		double factor = 1.2345;
		double offset = 6.7890;

		for (auto i=0u; i<N; ++i){
			stat1.push(values[i], weights[i]);
			stat2.push(factor*values[i], weights[i]);
			stat3.push(values[i]+offset, weights[i]);
			stat4.push(factor*values[i]+offset, weights[i]);
		}

		BOOST_REQUIRE(stat2.numerically_equal(stat1*factor, 1e-4));
		BOOST_REQUIRE(stat3.numerically_equal(stat1+offset, 1e-4));
		BOOST_REQUIRE(stat4.numerically_equal(stat1*factor+offset, 1e-4));
	}

	{
		rfr::util::weighted_running_statistics<double> stat1, stat2;

		double factor = 1.2345;

		for (auto i=0u; i<N; ++i){
			stat1.push(values[i], weights[i]);
			stat2.push(values[i], factor*weights[i]);
		}

		BOOST_REQUIRE_CLOSE(stat1.mean(), stat2.mean(), 1e-6);
		BOOST_REQUIRE_CLOSE(stat1.variance_population(), stat2.variance_population(), 1e-6);

		auto stat3 = stat1.multiply_weights_by(factor);
		BOOST_REQUIRE(stat2.numerically_equal(stat3, 1e-4));
	}

}

BOOST_AUTO_TEST_CASE(test_subspace_cardinality){

	std::vector<std::vector<double> > subspace;
	std::vector<unsigned int> types;

	subspace.push_back(std::vector<double> ({-1,1}));
	types.emplace_back(0);

	BOOST_REQUIRE_EQUAL(2, rfr::util::subspace_cardinality(subspace, types) );

	subspace.push_back(std::vector<double> ({0,1,2,3,4,5}));
	types.emplace_back(6);

	BOOST_REQUIRE_EQUAL(12, rfr::util::subspace_cardinality(subspace, types) );

	subspace.push_back(std::vector<double> ({0,1,2,4,5}));
	types.emplace_back(6);

	BOOST_REQUIRE_EQUAL(60, rfr::util::subspace_cardinality(subspace, types) );

}

BOOST_AUTO_TEST_CASE(test_boolean_vector_helper){

	std::vector<double> features(8,NAN);

	auto indices = rfr::util::get_non_NAN_indices(features);

	BOOST_REQUIRE_EQUAL(0, indices.size());

	features[2] = 2;

	indices = rfr::util::get_non_NAN_indices(features);

	BOOST_REQUIRE_EQUAL(1, indices.size());
	BOOST_REQUIRE_EQUAL(2, indices[0]);

	features[4] = 4;

	indices = rfr::util::get_non_NAN_indices(features);

	BOOST_REQUIRE_EQUAL(2, indices.size());
	BOOST_REQUIRE_EQUAL(2, indices[0]);
	BOOST_REQUIRE_EQUAL(4, indices[1]);

	std::vector<bool> bit_vector (8, false);
	BOOST_REQUIRE_EQUAL(false, rfr::util::any_true(bit_vector, indices));

	bit_vector[3] = true;
	BOOST_REQUIRE_EQUAL(false, rfr::util::any_true(bit_vector, indices));

	bit_vector[2] = true;
	BOOST_REQUIRE_EQUAL(true, rfr::util::any_true(bit_vector, indices));

	std::vector<bool> another_bit_vector(6,false);
	rfr::util::disjunction(bit_vector, another_bit_vector);

	BOOST_REQUIRE_EQUAL(bit_vector.size(), another_bit_vector.size());
	BOOST_REQUIRE(bit_vector == another_bit_vector);

}
#include <cmath>
#include <boost/test/unit_test.hpp>
#include "rfr/util.hpp"

BOOST_AUTO_TEST_CASE(merge_feature_vectors_test){
	
	double v1[4] = {1,2,3,nan("")};
	double v2[4] = {nan(""), nan(""), 4, 5};
	double v3[4] = {nan(""), nan(""), nan(""), nan("")};
	
	rfr::util::merge_two_vectors(v1,v2,v3,4);
	
	BOOST_REQUIRE(v3[0] == 1);
	BOOST_REQUIRE(v3[1] == 2);
	BOOST_REQUIRE(v3[2] == 4);
	BOOST_REQUIRE(v3[3] == 5);
	
	BOOST_REQUIRE_THROW(rfr::util::merge_two_vectors(v1,v1,v3,4), std::runtime_error);
}



BOOST_AUTO_TEST_CASE(test_running_statistics){
	
	// 256 random ints in [0,256)
	double values[] = {61, 99, 125, 222, 34, 208, 247, 156, 59, 2, 226, 116, 203, 213, 123, 250, 209, 124, 218, 20, 43, 66, 154, 142, 223, 117, 252, 249, 105, 42, 2, 248, 69, 180, 142, 196, 237, 124, 25, 53, 76, 5, 9, 219, 114, 251, 21, 247, 183, 83, 147, 202, 16, 101, 192, 209, 140, 207, 225, 34, 160, 171, 173, 188, 161, 76, 242, 97, 104, 10, 163, 32, 243, 140, 204, 211, 106, 212, 199, 14, 115, 116, 196, 120, 87, 50, 204, 28, 158, 191, 127, 110, 210, 224, 162, 105, 68, 236, 25, 142, 80, 196, 235, 219, 140, 251, 113, 240, 81, 9, 133, 219, 186, 153, 55, 35, 166, 9, 238, 125, 233, 69, 181, 109, 63, 34, 193, 240, 174, 194, 213, 165, 26, 210, 167, 21, 168, 167, 55, 135, 170, 206, 13, 91, 225, 159, 253, 127, 196, 140, 144, 222, 190, 15, 158, 22, 185, 79, 11, 106, 57, 94, 78, 116, 183, 128, 161, 212, 38, 242, 157, 41, 253, 192, 184, 6, 163, 17, 66, 128, 245, 80, 194, 208, 73, 181, 91, 93, 38, 123, 213, 197, 109, 231, 36, 168, 199, 172, 211, 180, 246, 111, 45, 249, 73, 187, 42, 255, 83, 103, 45, 76, 145, 10, 59, 84, 179, 168, 251, 77, 218, 109, 221, 237, 135, 154, 94, 69, 49, 79, 102, 254, 77, 40, 107, 13, 226, 84, 78, 128, 35, 177, 4, 123, 172, 55, 174, 46, 176, 43, 77, 110, 43, 37, 148, 237};

	rfr::util::running_statistics<double> stat1, stat2;

	for (auto &v: values){
		stat1.push(v);
		// second values are all shifted by a large number, which makes 'naive' algorithms fail
		stat2.push(v+1e9);
	}

	// reference computed with numpy, so should be fine
	BOOST_REQUIRE(stat1.number_of_points() == 256);
	BOOST_REQUIRE_CLOSE(stat1.mean(),134.5078125,1e-6);
	BOOST_REQUIRE_CLOSE(stat1.variance_population(),5481.3124389648438,1e-6);
	BOOST_REQUIRE_CLOSE(stat1.sum_of_squares(), 6034858, 1e-6);
	

	BOOST_REQUIRE(stat2.number_of_points() == 256);
	BOOST_REQUIRE_CLOSE(stat2.mean(),134.5078125+1e9,1e-6);
	BOOST_REQUIRE_CLOSE(stat2.variance_population(),5481.3124389648438,1e-6);
}


BOOST_AUTO_TEST_CASE(test_running_statistics_operators){
	int N = 1024;
	double values[] = {187, 277, 299, 202, 190, 425, 214, 163, 441, 401, 464, 379, 427, 345, 168, 484, 258, 224, 481, 109, 331, 419, 47, 101, 52, 250, 228, 350, 455, 507, 91, 184, 250, 59, 55, 495, 504, 52, 336, 101, 482, 148, 94, 340, 137, 14, 132, 429, 418, 22, 208, 25, 453, 483, 333, 437, 83, 170, 464, 100, 299, 356, 223, 348, 464, 317, 31, 62, 52, 336, 385, 148, 74, 101, 202, 51, 402, 280, 485, 246, 107, 347, 269, 450, 95, 164, 82, 475, 144, 173, 197, 420, 222, 72, 378, 389, 418, 266, 331, 495, 386, 300, 124, 470, 268, 372, 416, 462, 426, 176, 214, 280, 207, 396, 245, 255, 128, 90, 437, 39, 361, 153, 334, 442, 241, 94, 491, 346, 184, 420, 119, 158, 99, 98, 512, 216, 461, 497, 54, 317, 257, 77, 486, 414, 443, 403, 385, 500, 229, 278, 435, 175, 159, 490, 136, 337, 357, 460, 149, 423, 488, 429, 213, 302, 414, 316, 16, 331, 177, 360, 294, 218, 300, 166, 505, 327, 276, 403, 424, 330, 409, 224, 283, 407, 433, 257, 456, 420, 229, 17, 307, 434, 210, 165, 391, 27, 505, 164, 201, 267, 94, 132, 264, 256, 5, 368, 178, 429, 308, 421, 279, 144, 422, 155, 419, 397, 306, 35, 104, 310, 447, 168, 139, 146, 172, 357, 468, 226, 437, 390, 35, 234, 460, 49, 288, 218, 95, 384, 25, 162, 56, 375, 115, 70, 223, 456, 145, 119, 194, 436, 470, 212, 484, 449, 412, 210, 256, 226, 253, 144, 461, 322, 101, 172, 107, 360, 115, 53, 122, 287, 32, 146, 466, 411, 232, 471, 15, 168, 26, 224, 105, 150, 94, 98, 502, 74, 55, 490, 424, 379, 449, 264, 410, 128, 17, 16, 185, 129, 51, 31, 310, 397, 511, 248, 175, 366, 461, 36, 291, 210, 193, 384, 147, 248, 33, 245, 245, 127, 224, 352, 438, 438, 456, 76, 78, 348, 117, 135, 427, 76, 43, 76, 404, 379, 246, 76, 79, 396, 74, 391, 438, 288, 61, 45, 231, 346, 476, 27, 368, 173, 367, 462, 236, 461, 291, 106, 80, 35, 373, 112, 164, 484, 114, 372, 365, 422, 206, 395, 149, 407, 415, 439, 364, 395, 101, 147, 266, 129, 333, 384, 2, 211, 122, 143, 210, 162, 368, 222, 154, 205, 197, 495, 233, 359, 459, 258, 284, 46, 91, 470, 179, 124, 207, 131, 262, 171, 15, 269, 216, 94, 22, 311, 178, 381, 433, 187, 158, 191, 79, 432, 228, 67, 100, 403, 315, 57, 401, 121, 244, 429, 67, 394, 279, 11, 84, 138, 221, 271, 11, 205, 402, 18, 500, 207, 34, 244, 466, 341, 206, 300, 139, 277, 131, 292, 403, 77, 419, 242, 329, 223, 262, 452, 451, 387, 218, 282, 355, 251, 196, 75, 400, 107, 118, 43, 65, 402, 413, 346, 508, 117, 103, 243, 329, 196, 5, 447, 395, 267, 353, 346, 59, 358, 455, 351, 381, 319, 252, 463, 165, 503, 296, 198, 144, 248, 88, 94, 466, 164, 98, 290, 329, 24, 123, 84, 383, 346, 243, 488, 346, 425, 12, 472, 159, 468, 37, 186, 18, 31, 222, 64, 309, 74, 131, 256, 425, 342, 441, 223, 470, 134, 104, 458, 119, 477, 153, 181, 112, 88, 338, 303, 199, 190, 389, 214, 507, 503, 25, 308, 213, 309, 301, 163, 152, 428, 243, 509, 344, 255, 47, 38, 296, 57, 37, 131, 8, 159, 55, 28, 75, 377, 44, 33, 75, 496, 256, 483, 54, 239, 331, 134, 192, 133, 38, 218, 472, 313, 138, 401, 462, 34, 203, 99, 40, 365, 100, 411, 96, 408, 380, 212, 245, 61, 80, 194, 271, 9, 208, 347, 512, 88, 462, 445, 121, 183, 45, 119, 415, 1, 459, 55, 176, 255, 308, 332, 5, 432, 249, 81, 107, 213, 96, 310, 506, 153, 168, 337, 165, 125, 326, 202, 347, 309, 410, 214, 281, 377, 219, 122, 263, 270, 204, 462, 475, 238, 285, 432, 235, 143, 458, 204, 402, 211, 284, 133, 495, 384, 80, 81, 183, 40, 171, 237, 314, 501, 236, 155, 373, 57, 178, 51, 443, 144, 64, 173, 160, 282, 287, 148, 263, 79, 260, 247, 35, 161, 339, 429, 10, 98, 257, 488, 329, 456, 331, 344, 337, 452, 237, 400, 49, 119, 256, 187, 40, 82, 24, 510, 251, 223, 232, 72, 207, 113, 473, 75, 211, 324, 52, 426, 3, 355, 358, 109, 38, 423, 124, 376, 204, 11, 244, 120, 380, 291, 210, 471, 33, 319, 503, 182, 62, 494, 330, 440, 38, 219, 108, 82, 31, 229, 319, 404, 89, 118, 120, 322, 195, 144, 160, 385, 221, 231, 365, 88, 81, 403, 186, 241, 360, 379, 36, 206, 197, 457, 155, 493, 271, 484, 508, 505, 363, 80, 31, 54, 192, 257, 65, 121, 329, 148, 327, 486, 290, 427, 493, 386, 480, 94, 62, 65, 275, 328, 31, 107, 482, 468, 196, 328, 353, 117, 318, 422, 184, 269, 475, 307, 53, 82, 355, 507, 15, 0, 336, 222, 489, 175, 160, 384, 229, 13, 162, 512, 72, 497, 185, 245, 247, 261, 427, 282, 304, 52, 107, 227, 344, 92, 100, 461, 203, 195, 162, 403, 140, 351, 490, 345, 317, 507, 436, 161, 185, 121, 455, 257, 500, 382, 37, 338, 462, 228, 321, 60, 407, 144, 34, 114, 338, 437, 29, 191, 344, 211, 141, 283, 169, 20, 416, 206, 155, 275, 343, 51, 145, 396, 392, 123, 69, 380, 476, 142, 11, 204, 445, 301, 280, 124, 390, 42, 355, 81, 492, 93, 427, 510, 2, 317, 160, 43, 207, 291, 347, 146, 499, 505, 143, 207, 182, 120, 209, 488, 494, 415, 121, 69, 392, 451, 51, 416, 273, 364, 121, 459, 51, 318, 139, 135, 261, 497, 27, 510, 121, 222, 461, 237, 437, 479, 360, 334, 297, 68, 482, 235, 43, 334, 7, 411, 361, 271, 197, 319, 480, 289, 162, 260, 152, 155, 269, 183, 16, 480, 150, 105, 284, 273, 233, 221, 185, 120, 424, 214, 333, 116, 174, 384, 197, 348, 358, 272, 363, 397, 207, 491, 441, 13, 326, 70};

	rfr::util::running_statistics<double> stat_total;

	for (auto i=0u; i<N; ++i)
		stat_total.push(values[i]);


	for (auto i=10u; i<N-10; ++i){
		rfr::util::running_statistics<double> stat1, stat2, stat3;

		for(auto j=0u; j<i; ++j)
			stat1.push(values[j]);

		for(auto j=i; j<N; ++j)
			stat2.push(values[j]);

		BOOST_REQUIRE(stat_total.numerically_equal(stat1+stat2, 1e-6));
		BOOST_REQUIRE(stat1.numerically_equal(stat_total-stat2, 1e-6));
		BOOST_REQUIRE(stat2.numerically_equal(stat_total-stat1, 1e-6));

		stat3 = stat1 + stat2;

		BOOST_REQUIRE_THROW(stat1-stat3, std::runtime_error);
		BOOST_REQUIRE_THROW(stat1-=stat3, std::runtime_error);


	}

	{
		rfr::util::running_statistics<double> stat1, stat2;
		stat1.push(values[0]);
		BOOST_REQUIRE_THROW(stat1.pop(values[0]), std::runtime_error);

		stat2.push(values[0]);
		stat2.push(values[1]);

		BOOST_REQUIRE_THROW(stat2.pop(512), std::runtime_error);
	}

	{
		rfr::util::running_statistics<double> stat1, stat2, stat3, stat4, stat5;
		
		double factor = 1.2345;
		double offset = 6.7890;
		
		for (auto i=0u; i<N; ++i){
			stat1.push(values[i]);
			stat2.push(factor*values[i]);
			stat3.push(values[i]+offset);
			stat4.push(factor*values[i]+offset);
			stat5.push(values[i]-offset);
		}
		
		BOOST_REQUIRE(stat2.numerically_equal(stat1*factor, 1e-4));
		BOOST_REQUIRE(stat3.numerically_equal(stat1+offset, 1e-4));
		BOOST_REQUIRE(stat4.numerically_equal(stat1*factor+offset, 1e-4));
		BOOST_REQUIRE(stat5.numerically_equal(stat1-offset, 1e-4));
	}
}


BOOST_AUTO_TEST_CASE(test_running_covariance){
	int N = 1024;
	double v1[] = {187, 277, 299, 202, 190, 425, 214, 163, 441, 401, 464, 379, 427, 345, 168, 484, 258, 224, 481, 109, 331, 419, 47, 101, 52, 250, 228, 350, 455, 507, 91, 184, 250, 59, 55, 495, 504, 52, 336, 101, 482, 148, 94, 340, 137, 14, 132, 429, 418, 22, 208, 25, 453, 483, 333, 437, 83, 170, 464, 100, 299, 356, 223, 348, 464, 317, 31, 62, 52, 336, 385, 148, 74, 101, 202, 51, 402, 280, 485, 246, 107, 347, 269, 450, 95, 164, 82, 475, 144, 173, 197, 420, 222, 72, 378, 389, 418, 266, 331, 495, 386, 300, 124, 470, 268, 372, 416, 462, 426, 176, 214, 280, 207, 396, 245, 255, 128, 90, 437, 39, 361, 153, 334, 442, 241, 94, 491, 346, 184, 420, 119, 158, 99, 98, 512, 216, 461, 497, 54, 317, 257, 77, 486, 414, 443, 403, 385, 500, 229, 278, 435, 175, 159, 490, 136, 337, 357, 460, 149, 423, 488, 429, 213, 302, 414, 316, 16, 331, 177, 360, 294, 218, 300, 166, 505, 327, 276, 403, 424, 330, 409, 224, 283, 407, 433, 257, 456, 420, 229, 17, 307, 434, 210, 165, 391, 27, 505, 164, 201, 267, 94, 132, 264, 256, 5, 368, 178, 429, 308, 421, 279, 144, 422, 155, 419, 397, 306, 35, 104, 310, 447, 168, 139, 146, 172, 357, 468, 226, 437, 390, 35, 234, 460, 49, 288, 218, 95, 384, 25, 162, 56, 375, 115, 70, 223, 456, 145, 119, 194, 436, 470, 212, 484, 449, 412, 210, 256, 226, 253, 144, 461, 322, 101, 172, 107, 360, 115, 53, 122, 287, 32, 146, 466, 411, 232, 471, 15, 168, 26, 224, 105, 150, 94, 98, 502, 74, 55, 490, 424, 379, 449, 264, 410, 128, 17, 16, 185, 129, 51, 31, 310, 397, 511, 248, 175, 366, 461, 36, 291, 210, 193, 384, 147, 248, 33, 245, 245, 127, 224, 352, 438, 438, 456, 76, 78, 348, 117, 135, 427, 76, 43, 76, 404, 379, 246, 76, 79, 396, 74, 391, 438, 288, 61, 45, 231, 346, 476, 27, 368, 173, 367, 462, 236, 461, 291, 106, 80, 35, 373, 112, 164, 484, 114, 372, 365, 422, 206, 395, 149, 407, 415, 439, 364, 395, 101, 147, 266, 129, 333, 384, 2, 211, 122, 143, 210, 162, 368, 222, 154, 205, 197, 495, 233, 359, 459, 258, 284, 46, 91, 470, 179, 124, 207, 131, 262, 171, 15, 269, 216, 94, 22, 311, 178, 381, 433, 187, 158, 191, 79, 432, 228, 67, 100, 403, 315, 57, 401, 121, 244, 429, 67, 394, 279, 11, 84, 138, 221, 271, 11, 205, 402, 18, 500, 207, 34, 244, 466, 341, 206, 300, 139, 277, 131, 292, 403, 77, 419, 242, 329, 223, 262, 452, 451, 387, 218, 282, 355, 251, 196, 75, 400, 107, 118, 43, 65, 402, 413, 346, 508, 117, 103, 243, 329, 196, 5, 447, 395, 267, 353, 346, 59, 358, 455, 351, 381, 319, 252, 463, 165, 503, 296, 198, 144, 248, 88, 94, 466, 164, 98, 290, 329, 24, 123, 84, 383, 346, 243, 488, 346, 425, 12, 472, 159, 468, 37, 186, 18, 31, 222, 64, 309, 74, 131, 256, 425, 342, 441, 223, 470, 134, 104, 458, 119, 477, 153, 181, 112, 88, 338, 303, 199, 190, 389, 214, 507, 503, 25, 308, 213, 309, 301, 163, 152, 428, 243, 509, 344, 255, 47, 38, 296, 57, 37, 131, 8, 159, 55, 28, 75, 377, 44, 33, 75, 496, 256, 483, 54, 239, 331, 134, 192, 133, 38, 218, 472, 313, 138, 401, 462, 34, 203, 99, 40, 365, 100, 411, 96, 408, 380, 212, 245, 61, 80, 194, 271, 9, 208, 347, 512, 88, 462, 445, 121, 183, 45, 119, 415, 1, 459, 55, 176, 255, 308, 332, 5, 432, 249, 81, 107, 213, 96, 310, 506, 153, 168, 337, 165, 125, 326, 202, 347, 309, 410, 214, 281, 377, 219, 122, 263, 270, 204, 462, 475, 238, 285, 432, 235, 143, 458, 204, 402, 211, 284, 133, 495, 384, 80, 81, 183, 40, 171, 237, 314, 501, 236, 155, 373, 57, 178, 51, 443, 144, 64, 173, 160, 282, 287, 148, 263, 79, 260, 247, 35, 161, 339, 429, 10, 98, 257, 488, 329, 456, 331, 344, 337, 452, 237, 400, 49, 119, 256, 187, 40, 82, 24, 510, 251, 223, 232, 72, 207, 113, 473, 75, 211, 324, 52, 426, 3, 355, 358, 109, 38, 423, 124, 376, 204, 11, 244, 120, 380, 291, 210, 471, 33, 319, 503, 182, 62, 494, 330, 440, 38, 219, 108, 82, 31, 229, 319, 404, 89, 118, 120, 322, 195, 144, 160, 385, 221, 231, 365, 88, 81, 403, 186, 241, 360, 379, 36, 206, 197, 457, 155, 493, 271, 484, 508, 505, 363, 80, 31, 54, 192, 257, 65, 121, 329, 148, 327, 486, 290, 427, 493, 386, 480, 94, 62, 65, 275, 328, 31, 107, 482, 468, 196, 328, 353, 117, 318, 422, 184, 269, 475, 307, 53, 82, 355, 507, 15, 0, 336, 222, 489, 175, 160, 384, 229, 13, 162, 512, 72, 497, 185, 245, 247, 261, 427, 282, 304, 52, 107, 227, 344, 92, 100, 461, 203, 195, 162, 403, 140, 351, 490, 345, 317, 507, 436, 161, 185, 121, 455, 257, 500, 382, 37, 338, 462, 228, 321, 60, 407, 144, 34, 114, 338, 437, 29, 191, 344, 211, 141, 283, 169, 20, 416, 206, 155, 275, 343, 51, 145, 396, 392, 123, 69, 380, 476, 142, 11, 204, 445, 301, 280, 124, 390, 42, 355, 81, 492, 93, 427, 510, 2, 317, 160, 43, 207, 291, 347, 146, 499, 505, 143, 207, 182, 120, 209, 488, 494, 415, 121, 69, 392, 451, 51, 416, 273, 364, 121, 459, 51, 318, 139, 135, 261, 497, 27, 510, 121, 222, 461, 237, 437, 479, 360, 334, 297, 68, 482, 235, 43, 334, 7, 411, 361, 271, 197, 319, 480, 289, 162, 260, 152, 155, 269, 183, 16, 480, 150, 105, 284, 273, 233, 221, 185, 120, 424, 214, 333, 116, 174, 384, 197, 348, 358, 272, 363, 397, 207, 491, 441, 13, 326, 70};
	double v2[] = {187, 219, 410, 218, 295, 338, 390, 313, 279, 289, 88, 213, 274, 52, 119, 506, 17, 132, 57, 16, 444, 339, 385, 283, 323, 60, 336, 507, 65, 483, 333, 159, 22, 299, 491, 209, 323, 491, 190, 348, 184, 185, 80, 252, 444, 180, 56, 279, 382, 293, 491, 255, 329, 105, 37, 68, 216, 183, 418, 458, 69, 301, 27, 169, 35, 426, 99, 282, 169, 56, 98, 442, 81, 113, 450, 41, 360, 180, 329, 421, 233, 245, 379, 338, 169, 11, 246, 234, 88, 17, 173, 477, 500, 437, 179, 140, 176, 8, 425, 296, 238, 404, 157, 0, 278, 369, 426, 235, 470, 172, 378, 475, 59, 309, 269, 329, 201, 253, 212, 143, 274, 180, 125, 180, 224, 373, 323, 275, 166, 150, 13, 348, 454, 455, 406, 317, 401, 231, 389, 64, 320, 16, 195, 271, 9, 406, 38, 80, 149, 489, 256, 191, 385, 174, 235, 196, 203, 229, 220, 479, 311, 121, 165, 478, 140, 435, 182, 146, 246, 27, 450, 368, 448, 162, 101, 14, 161, 502, 264, 375, 160, 276, 382, 157, 1, 174, 192, 158, 269, 365, 54, 307, 479, 37, 177, 399, 278, 392, 469, 486, 322, 130, 346, 15, 371, 107, 20, 252, 58, 348, 81, 234, 192, 5, 216, 356, 146, 251, 467, 510, 313, 239, 384, 405, 124, 461, 507, 200, 498, 163, 104, 391, 259, 196, 408, 154, 264, 221, 347, 418, 60, 118, 418, 161, 471, 165, 202, 432, 220, 503, 44, 381, 5, 250, 294, 109, 299, 86, 342, 512, 47, 382, 103, 106, 18, 441, 260, 115, 201, 341, 153, 210, 333, 237, 166, 409, 48, 242, 463, 469, 302, 415, 5, 263, 80, 341, 120, 262, 43, 433, 340, 436, 224, 502, 31, 360, 449, 421, 261, 71, 55, 141, 478, 122, 270, 253, 486, 346, 100, 377, 417, 251, 159, 408, 348, 268, 499, 237, 125, 319, 345, 25, 141, 481, 241, 394, 508, 138, 264, 448, 328, 267, 382, 160, 113, 62, 415, 359, 414, 35, 50, 157, 229, 109, 466, 90, 164, 355, 431, 272, 213, 156, 194, 82, 322, 490, 83, 56, 212, 277, 412, 299, 120, 292, 477, 360, 16, 459, 127, 366, 389, 47, 401, 446, 467, 473, 471, 62, 198, 25, 358, 337, 492, 162, 59, 120, 286, 211, 275, 43, 502, 26, 295, 60, 70, 324, 112, 4, 304, 394, 154, 411, 248, 350, 102, 9, 77, 482, 156, 80, 502, 123, 381, 255, 352, 128, 7, 345, 250, 496, 67, 379, 374, 118, 211, 318, 92, 309, 347, 447, 334, 173, 137, 459, 422, 479, 288, 90, 395, 19, 504, 2, 46, 474, 238, 363, 498, 338, 242, 104, 310, 14, 318, 244, 456, 87, 424, 265, 201, 419, 62, 166, 223, 219, 104, 146, 398, 237, 441, 416, 478, 256, 218, 250, 322, 100, 507, 358, 131, 433, 115, 358, 5, 119, 479, 127, 69, 495, 420, 335, 366, 170, 467, 87, 383, 416, 313, 442, 152, 486, 58, 496, 484, 23, 169, 219, 231, 147, 226, 255, 314, 306, 58, 97, 475, 507, 4, 367, 460, 38, 122, 27, 113, 139, 113, 290, 323, 227, 399, 53, 414, 236, 390, 358, 213, 209, 65, 84, 202, 66, 502, 238, 21, 39, 185, 113, 324, 37, 378, 379, 345, 65, 137, 74, 511, 169, 332, 30, 407, 73, 391, 499, 317, 474, 350, 347, 389, 506, 108, 288, 205, 415, 100, 207, 12, 174, 86, 477, 278, 36, 198, 506, 54, 247, 92, 407, 237, 494, 395, 301, 163, 401, 272, 220, 243, 509, 396, 204, 435, 58, 501, 443, 389, 512, 195, 282, 80, 221, 81, 476, 198, 49, 276, 180, 84, 8, 244, 481, 309, 237, 310, 180, 8, 126, 251, 52, 231, 153, 109, 274, 473, 141, 22, 278, 241, 472, 339, 90, 457, 203, 215, 329, 91, 365, 346, 397, 407, 193, 67, 193, 459, 26, 57, 23, 122, 26, 134, 495, 311, 98, 101, 190, 29, 270, 331, 84, 237, 99, 379, 287, 479, 134, 459, 60, 77, 62, 395, 494, 280, 204, 484, 332, 391, 212, 309, 478, 172, 422, 192, 489, 507, 385, 130, 249, 501, 500, 37, 207, 383, 203, 292, 45, 253, 415, 338, 266, 398, 368, 199, 442, 40, 40, 375, 74, 92, 265, 15, 123, 441, 180, 367, 95, 504, 366, 56, 508, 26, 475, 30, 236, 258, 292, 505, 487, 320, 148, 74, 78, 375, 309, 219, 445, 402, 277, 178, 165, 61, 397, 78, 483, 414, 64, 105, 224, 45, 512, 159, 41, 136, 271, 352, 151, 505, 49, 364, 61, 105, 158, 453, 191, 164, 114, 120, 467, 477, 303, 99, 186, 347, 19, 209, 237, 6, 301, 79, 326, 366, 502, 499, 330, 219, 437, 328, 347, 506, 33, 139, 217, 340, 51, 403, 288, 272, 191, 22, 73, 176, 407, 68, 247, 407, 117, 416, 235, 176, 78, 443, 276, 187, 44, 175, 196, 234, 197, 435, 281, 391, 336, 44, 185, 170, 384, 83, 90, 25, 96, 206, 159, 464, 378, 404, 321, 343, 139, 451, 470, 308, 408, 505, 210, 157, 329, 267, 85, 293, 191, 245, 128, 388, 402, 142, 197, 2, 215, 232, 201, 233, 418, 129, 502, 220, 398, 28, 116, 498, 287, 450, 8, 70, 140, 382, 202, 280, 5, 56, 406, 161, 54, 371, 222, 87, 293, 325, 167, 402, 494, 83, 163, 386, 51, 263, 381, 33, 168, 83, 80, 504, 105, 325, 209, 463, 248, 10, 310, 376, 239, 341, 498, 499, 372, 355, 416, 29, 294, 51, 177, 440, 282, 12, 214, 144, 376, 510, 188, 205, 228, 325, 512, 195, 237, 137, 9, 256, 147, 175, 92, 39, 409, 438, 151, 375, 280, 400, 383, 405, 355, 351, 488, 4, 372, 244, 493, 419, 62, 15, 493, 209, 336, 295, 266, 110, 454, 209, 237, 158, 280, 79, 23, 307, 92, 384, 7, 33, 321, 476, 359, 462, 292, 333, 415, 476, 210, 69, 148, 484, 80, 280, 397, 365, 146, 303, 72, 61, 263, 287, 16, 207, 471, 167, 197, 414, 89, 411, 242, 503, 120, 28, 216, 400, 47, 23, 414, 236, 347};

	rfr::util::running_statistics<double> stat1, stat2;
	rfr::util::running_covariance<double> cov;
	
	for (auto i = 0; i<N; i++){
		cov.push(v1[i], v2[i]);
		stat1.push(v1[i]);
		stat2.push(v2[i]);
	}
	BOOST_REQUIRE_CLOSE(stat1.mean(),253.3232421875, 1e-6);
	BOOST_REQUIRE_CLOSE(stat1.variance_sample(),21532.3323625, 1e-6);
	
	BOOST_REQUIRE_CLOSE(stat2.mean(),253.830078125,1e-6);
	BOOST_REQUIRE_CLOSE(stat2.variance_sample(),22307.58986666, 1e-6);
	BOOST_REQUIRE_CLOSE(cov.covariance(),  -80.89516702, 1e-6);
}


BOOST_AUTO_TEST_CASE(test_weighted_running_statistics_push){
	
	// 256 random ints in [0,256)
	unsigned int N = 255;
	double values[] = {  61,    99,   125,   222,   34,   208,   247,   156,    59,     2,   226,   116,   203,   213,   123,   250,   209,   124,   218,    20,    43,    66,   154,   142,   223,   117,   252,   249,   105,    42,     2,   248,    69,   180,   142,   196,   237,   124,    25,    53,    76,     5,     9,   219,   114,   251,    21,   247,   183,    83,   147,   202,    16,   101,   192,   209,   140,   207,   225,    34,   160,  171,   173,   188,   161,    76,   242,    97,   104,    10,   163,    32,   243,  140,  204,   211,   106,   212,   199,    14,   115,   116,   196,   120,    87,    50,   204,  28,  158,   191,   127,   110,  210,   224,  162,   105,    68,   236,    25,   142,    80,   196,   235,   219,   140,   251,   113,   240,    81,     9,   133,   219,   186,   153,    55,   35,   166,    9,   238,   125,   233,   69,   181,  109,    63,    34,   193,   240,   174,   194,   213,   165,    26,   210,   167,   21,   168,   167,    55,   135,   170,   206,    13,    91,   225,   159,  253,   127,   196,   140,   144,   222,   190,   15,    22,   185,    79,    11,   106,    57,    94,    78,   116,   183,  128,   161,   212,    38,  242,   157,    41,   253,   192,   184,     6,   163,    17,    66,   128,   245,    80,   194,   208,    73,   181,    91,    93,    38,   123,   213,   197,  109,   231,    36,   168,   199,   172,   211,   180,   246,   111,    45,   249,    73,   187,    42,   255,    83,   103,   45,    76,   145,    10,    59,  84,   179,   168,  251,  77,   218,   109,   221,   237,   135,   154,    94,    69,    49,    79,   102,   254,    77,    40,   107,    13,   226,    84,    78,   128,    35,   177,    4,  123,   172,    55,   174,    46,  176,    43,    77,   110,    43,  37,   148,  237};
	double weights[]= {0.07, 0.985, 0.056, 0.089, 0.18, 0.619, 0.267, 0.528, 0.138, 0.468, 0.666, 0.858, 0.204, 0.126, 0.116, 0.739, 0.484, 0.311, 0.598, 0.947, 0.499, 0.777, 0.434, 0.976, 0.109, 0.267, 0.758, 0.455, 0.841, 0.028, 0.328, 0.426, 0.072, 0.508, 0.771, 0.197, 0.551, 0.656, 0.152, 0.207, 0.765, 0.315, 0.112, 0.095, 0.743, 0.262, 0.865, 0.361, 0.276, 0.035, 0.208, 0.307, 0.212, 0.894, 0.246, 0.716, 0.573, 0.929, 0.173, 0.077, 0.982, 0.68, 0.954, 0.009, 0.417, 0.255, 0.211, 0.586, 0.608, 0.844, 0.311, 0.702, 0.474, 0.98, 0.89, 0.658, 0.293, 0.973, 0.104, 0.333, 0.187, 0.532, 0.899, 0.364, 0.618, 0.768, 0.683, 0.8, 0.85, 0.221, 0.212, 0.048, 0.73, 0.477, 0.84, 0.817, 0.729, 0.825, 0.927, 0.934, 0.586, 0.482, 0.023, 0.282, 0.454, 0.255, 0.197, 0.529, 0.692, 0.092, 0.809, 0.316, 0.914, 0.221, 0.091, 0.04, 0.791, 0.82, 0.205, 0.698, 0.455, 0.02, 0.842, 0.14, 0.005, 0.968, 0.486, 0.463, 0.992, 0.426, 0.147, 0.591, 0.262, 0.276, 0.299, 0.64, 0.607, 0.165, 0.907, 0.342, 0.413, 0.413, 0.202, 0.103, 0.167, 0.996, 0.35, 0.291, 0.184, 0.538, 0.921, 0.556, 0.772, 0.88, 0.982, 0.398, 0.917, 0.329, 0.961, 0.714, 0.064, 0.237, 0.735, 0.531, 0.27, 0.098, 0.565, 0.699, 0.32, 0.452, 0.002, 0.699, 0.888, 0.516, 0.404, 0.464, 0.051, 0.304, 0.178, 0.919, 0.503, 0.667, 0.628, 0.079, 0.864, 0.827, 0.363, 0.644, 0.551, 0.846, 0.641, 0.07, 0.346, 0.505, 0.672, 0.143, 0.083, 0.881, 0.398, 0.787, 0.662, 0.799, 0.354, 0.477, 0.506, 0.124, 0.233, 0.963, 0.529, 0.54, 0.781, 0.935, 0.025, 0.475, 0.3, 0.837, 0.409, 0.38, 0.7, 0.575, 0.487, 0.432, 0.967, 0.017, 0.449, 0.513, 0.245, 0.834, 0.138, 0.751, 0.969, 0.183, 0.526, 0.813, 0.583, 0.759, 0.527, 0.675, 0.142, 0.007, 0.075, 0.85, 0.97, 0.567, 0.048, 0.121, 0.281, 0.65, 0.455, 0.936, 0.055, 0.709, 0.7, 0.384, 0.99};
		rfr::util::weighted_running_statistics<double> stat1, stat2;

	for (auto i=0u; i<N; i++){
		stat1.push(values[i], 1);
		stat2.push(values[i], weights[i]);
		
	}

	// reference computed with numpy, so should be fine
	BOOST_REQUIRE_CLOSE(stat1.sum_of_weights()     , (double) N  , 1e-6);
	BOOST_REQUIRE_CLOSE(stat1.mean()               ,134.415686275,1e-6);
	BOOST_REQUIRE_CLOSE(stat1.variance_population(),5500.63504806,1e-6);
	BOOST_REQUIRE_CLOSE(stat1.sum_of_squares()     , 6009894     ,1e-6);   

	BOOST_REQUIRE_CLOSE(stat2.sum_of_weights()		,125.273	,1e-6);
	BOOST_REQUIRE_CLOSE(stat2.mean()				,136.6691945,1e-6);
	BOOST_REQUIRE_CLOSE(stat2.variance_population()	,5340.296298,1e-6);
	BOOST_REQUIRE_CLOSE(stat2.sum_of_squares()      ,3008902.75 ,1e-6);

	// only positive weights
	BOOST_REQUIRE_THROW(stat1.push(0.1, 0), std::runtime_error);
	BOOST_REQUIRE_THROW(stat1.push(0.1, -2), std::runtime_error);
}


BOOST_AUTO_TEST_CASE(test_weighted_running_statistics_throws){

	// 256 random ints in [0,256)
	unsigned int N = 255;
	double values[] = {  61,    99,   125,   222,   34,   208,   247,   156,    59,     2,   226,   116,   203,   213,   123,   250,   209,   124,   218,    20,    43,    66,   154,   142,   223,   117,   252,   249,   105,    42,     2,   248,    69,   180,   142,   196,   237,   124,    25,    53,    76,     5,     9,   219,   114,   251,    21,   247,   183,    83,   147,   202,    16,   101,   192,   209,   140,   207,   225,    34,   160,  171,   173,   188,   161,    76,   242,    97,   104,    10,   163,    32,   243,  140,  204,   211,   106,   212,   199,    14,   115,   116,   196,   120,    87,    50,   204,  28,  158,   191,   127,   110,  210,   224,  162,   105,    68,   236,    25,   142,    80,   196,   235,   219,   140,   251,   113,   240,    81,     9,   133,   219,   186,   153,    55,   35,   166,    9,   238,   125,   233,   69,   181,  109,    63,    34,   193,   240,   174,   194,   213,   165,    26,   210,   167,   21,   168,   167,    55,   135,   170,   206,    13,    91,   225,   159,  253,   127,   196,   140,   144,   222,   190,   15,    22,   185,    79,    11,   106,    57,    94,    78,   116,   183,  128,   161,   212,    38,  242,   157,    41,   253,   192,   184,     6,   163,    17,    66,   128,   245,    80,   194,   208,    73,   181,    91,    93,    38,   123,   213,   197,  109,   231,    36,   168,   199,   172,   211,   180,   246,   111,    45,   249,    73,   187,    42,   255,    83,   103,   45,    76,   145,    10,    59,  84,   179,   168,  251,  77,   218,   109,   221,   237,   135,   154,    94,    69,    49,    79,   102,   254,    77,    40,   107,    13,   226,    84,    78,   128,    35,   177,    4,  123,   172,    55,   174,    46,  176,    43,    77,   110,    43,  37,   148,  237};
	double weights[]= {0.07, 0.985, 0.056, 0.089, 0.18, 0.619, 0.267, 0.528, 0.138, 0.468, 0.666, 0.858, 0.204, 0.126, 0.116, 0.739, 0.484, 0.311, 0.598, 0.947, 0.499, 0.777, 0.434, 0.976, 0.109, 0.267, 0.758, 0.455, 0.841, 0.028, 0.328, 0.426, 0.072, 0.508, 0.771, 0.197, 0.551, 0.656, 0.152, 0.207, 0.765, 0.315, 0.112, 0.095, 0.743, 0.262, 0.865, 0.361, 0.276, 0.035, 0.208, 0.307, 0.212, 0.894, 0.246, 0.716, 0.573, 0.929, 0.173, 0.077, 0.982, 0.68, 0.954, 0.009, 0.417, 0.255, 0.211, 0.586, 0.608, 0.844, 0.311, 0.702, 0.474, 0.98, 0.89, 0.658, 0.293, 0.973, 0.104, 0.333, 0.187, 0.532, 0.899, 0.364, 0.618, 0.768, 0.683, 0.8, 0.85, 0.221, 0.212, 0.048, 0.73, 0.477, 0.84, 0.817, 0.729, 0.825, 0.927, 0.934, 0.586, 0.482, 0.023, 0.282, 0.454, 0.255, 0.197, 0.529, 0.692, 0.092, 0.809, 0.316, 0.914, 0.221, 0.091, 0.04, 0.791, 0.82, 0.205, 0.698, 0.455, 0.02, 0.842, 0.14, 0.005, 0.968, 0.486, 0.463, 0.992, 0.426, 0.147, 0.591, 0.262, 0.276, 0.299, 0.64, 0.607, 0.165, 0.907, 0.342, 0.413, 0.413, 0.202, 0.103, 0.167, 0.996, 0.35, 0.291, 0.184, 0.538, 0.921, 0.556, 0.772, 0.88, 0.982, 0.398, 0.917, 0.329, 0.961, 0.714, 0.064, 0.237, 0.735, 0.531, 0.27, 0.098, 0.565, 0.699, 0.32, 0.452, 0.002, 0.699, 0.888, 0.516, 0.404, 0.464, 0.051, 0.304, 0.178, 0.919, 0.503, 0.667, 0.628, 0.079, 0.864, 0.827, 0.363, 0.644, 0.551, 0.846, 0.641, 0.07, 0.346, 0.505, 0.672, 0.143, 0.083, 0.881, 0.398, 0.787, 0.662, 0.799, 0.354, 0.477, 0.506, 0.124, 0.233, 0.963, 0.529, 0.54, 0.781, 0.935, 0.025, 0.475, 0.3, 0.837, 0.409, 0.38, 0.7, 0.575, 0.487, 0.432, 0.967, 0.017, 0.449, 0.513, 0.245, 0.834, 0.138, 0.751, 0.969, 0.183, 0.526, 0.813, 0.583, 0.759, 0.527, 0.675, 0.142, 0.007, 0.075, 0.85, 0.97, 0.567, 0.048, 0.121, 0.281, 0.65, 0.455, 0.936, 0.055, 0.709, 0.7, 0.384, 0.99};
		rfr::util::weighted_running_statistics<double> stat1, stat2;

	for (auto i=0u; i<N; i++){
		stat1.push(values[i], 1);
		stat2.push(values[i], weights[i]);
		
	}

	// only positive weights
	BOOST_REQUIRE_THROW(stat1.pop(0.1, 0), std::runtime_error);
	BOOST_REQUIRE_THROW(stat1.pop(0.1, -2), std::runtime_error);

	// remove too much weight
	BOOST_REQUIRE_THROW(stat1.pop(0.1, 1e20), std::runtime_error);

	// cannon subtract statistics with larger weight
	BOOST_REQUIRE_THROW(stat2-stat1, std::runtime_error);
	BOOST_REQUIRE_THROW(stat2-=stat1, std::runtime_error);


	// see what happens if we try to pop all but one element
	for (auto i=0u; i<N-2; i++){
		stat1.pop(values[i], 1);
		stat2.pop(values[i], weights[i]);
	}
	// due to rounding, the squared distance to the mean will be slightly negative!
	BOOST_REQUIRE_THROW(stat1.pop(values[N-1], 1), std::runtime_error);
	BOOST_REQUIRE_THROW(stat2.pop(values[N-1], weights[N-1]), std::runtime_error);

}


BOOST_AUTO_TEST_CASE(test_weighted_running_statistics_pop){
	
	// 255 random ints in [0,256)
	unsigned int N = 255;
	double values[] = {  61,    99,   125,   222,   34,   208,   247,   156,    59,     2,   226,   116,   203,   213,   123,   250,   209,   124,   218,    20,    43,    66,   154,   142,   223,   117,   252,   249,   105,    42,     2,   248,    69,   180,   142,   196,   237,   124,    25,    53,    76,     5,     9,   219,   114,   251,    21,   247,   183,    83,   147,   202,    16,   101,   192,   209,   140,   207,   225,    34,   160,  171,   173,   188,   161,    76,   242,    97,   104,    10,   163,    32,   243,  140,  204,   211,   106,   212,   199,    14,   115,   116,   196,   120,    87,    50,   204,  28,  158,   191,   127,   110,  210,   224,  162,   105,    68,   236,    25,   142,    80,   196,   235,   219,   140,   251,   113,   240,    81,     9,   133,   219,   186,   153,    55,   35,   166,    9,   238,   125,   233,   69,   181,  109,    63,    34,   193,   240,   174,   194,   213,   165,    26,   210,   167,   21,   168,   167,    55,   135,   170,   206,    13,    91,   225,   159,  253,   127,   196,   140,   144,   222,   190,   15,    22,   185,    79,    11,   106,    57,    94,    78,   116,   183,  128,   161,   212,    38,  242,   157,    41,   253,   192,   184,     6,   163,    17,    66,   128,   245,    80,   194,   208,    73,   181,    91,    93,    38,   123,   213,   197,  109,   231,    36,   168,   199,   172,   211,   180,   246,   111,    45,   249,    73,   187,    42,   255,    83,   103,   45,    76,   145,    10,    59,  84,   179,   168,  251,  77,   218,   109,   221,   237,   135,   154,    94,    69,    49,    79,   102,   254,    77,    40,   107,    13,   226,    84,    78,   128,    35,   177,    4,  123,   172,    55,   174,    46,  176,    43,    77,   110,    43,  37,   148,  237};
	double weights[]= {0.07, 0.985, 0.056, 0.089, 0.18, 0.619, 0.267, 0.528, 0.138, 0.468, 0.666, 0.858, 0.204, 0.126, 0.116, 0.739, 0.484, 0.311, 0.598, 0.947, 0.499, 0.777, 0.434, 0.976, 0.109, 0.267, 0.758, 0.455, 0.841, 0.028, 0.328, 0.426, 0.072, 0.508, 0.771, 0.197, 0.551, 0.656, 0.152, 0.207, 0.765, 0.315, 0.112, 0.095, 0.743, 0.262, 0.865, 0.361, 0.276, 0.035, 0.208, 0.307, 0.212, 0.894, 0.246, 0.716, 0.573, 0.929, 0.173, 0.077, 0.982, 0.68, 0.954, 0.009, 0.417, 0.255, 0.211, 0.586, 0.608, 0.844, 0.311, 0.702, 0.474, 0.98, 0.89, 0.658, 0.293, 0.973, 0.104, 0.333, 0.187, 0.532, 0.899, 0.364, 0.618, 0.768, 0.683, 0.8, 0.85, 0.221, 0.212, 0.048, 0.73, 0.477, 0.84, 0.817, 0.729, 0.825, 0.927, 0.934, 0.586, 0.482, 0.023, 0.282, 0.454, 0.255, 0.197, 0.529, 0.692, 0.092, 0.809, 0.316, 0.914, 0.221, 0.091, 0.04, 0.791, 0.82, 0.205, 0.698, 0.455, 0.02, 0.842, 0.14, 0.005, 0.968, 0.486, 0.463, 0.992, 0.426, 0.147, 0.591, 0.262, 0.276, 0.299, 0.64, 0.607, 0.165, 0.907, 0.342, 0.413, 0.413, 0.202, 0.103, 0.167, 0.996, 0.35, 0.291, 0.184, 0.538, 0.921, 0.556, 0.772, 0.88, 0.982, 0.398, 0.917, 0.329, 0.961, 0.714, 0.064, 0.237, 0.735, 0.531, 0.27, 0.098, 0.565, 0.699, 0.32, 0.452, 0.002, 0.699, 0.888, 0.516, 0.404, 0.464, 0.051, 0.304, 0.178, 0.919, 0.503, 0.667, 0.628, 0.079, 0.864, 0.827, 0.363, 0.644, 0.551, 0.846, 0.641, 0.07, 0.346, 0.505, 0.672, 0.143, 0.083, 0.881, 0.398, 0.787, 0.662, 0.799, 0.354, 0.477, 0.506, 0.124, 0.233, 0.963, 0.529, 0.54, 0.781, 0.935, 0.025, 0.475, 0.3, 0.837, 0.409, 0.38, 0.7, 0.575, 0.487, 0.432, 0.967, 0.017, 0.449, 0.513, 0.245, 0.834, 0.138, 0.751, 0.969, 0.183, 0.526, 0.813, 0.583, 0.759, 0.527, 0.675, 0.142, 0.007, 0.075, 0.85, 0.97, 0.567, 0.048, 0.121, 0.281, 0.65, 0.455, 0.936, 0.055, 0.709, 0.7, 0.384, 0.99};
	rfr::util::weighted_running_statistics<double> stat_ref, stat1;

	for (auto i=0u; i<N; ++i){
		stat_ref.push(values[i], weights[i]);
	}
	// reference computed with numpy, so should be fine
	BOOST_REQUIRE_CLOSE(stat_ref.sum_of_weights()		,125.273	,1e-6);
	BOOST_REQUIRE_CLOSE(stat_ref.mean()					,136.6691945,1e-6);
	BOOST_REQUIRE_CLOSE(stat_ref.variance_population()	,5340.296298,1e-6);



	for (auto i=16u; i<N; ++i){

		stat1 = stat_ref;
		rfr::util::weighted_running_statistics<double> stat2;
		
		// add points to the statistics
		for (auto j=0u; j < i; ++j){
			stat1.push(values[j], weights[N-1-j]);
			stat2.push(values[j], weights[N-1-j]);
		}

		BOOST_REQUIRE(stat1.numerically_equal( stat_ref+stat2, 1e-6));
		BOOST_REQUIRE(stat_ref.numerically_equal( stat1-stat2, 1e-6));
		
		// remove the points again
		for (auto j=0u; j < i; ++j)
			stat1.pop(values[j], weights[N-1-j]);

		// make sure nothing has changed
		BOOST_REQUIRE_CLOSE(stat1.sum_of_weights()		,125.273	,1e-6);
		BOOST_REQUIRE_CLOSE(stat1.mean()				,136.6691945,1e-6);
		BOOST_REQUIRE_CLOSE(stat1.variance_population()	,5340.296298,1e-6);
	}
	
}


BOOST_AUTO_TEST_CASE(test_weighted_running_statistics_operators){
	unsigned int N = 255;
	double values[] = {  61,    99,   125,   222,   34,   208,   247,   156,    59,     2,   226,   116,   203,   213,   123,   250,   209,   124,   218,    20,    43,    66,   154,   142,   223,   117,   252,   249,   105,    42,     2,   248,    69,   180,   142,   196,   237,   124,    25,    53,    76,     5,     9,   219,   114,   251,    21,   247,   183,    83,   147,   202,    16,   101,   192,   209,   140,   207,   225,    34,   160,  171,   173,   188,   161,    76,   242,    97,   104,    10,   163,    32,   243,  140,  204,   211,   106,   212,   199,    14,   115,   116,   196,   120,    87,    50,   204,  28,  158,   191,   127,   110,  210,   224,  162,   105,    68,   236,    25,   142,    80,   196,   235,   219,   140,   251,   113,   240,    81,     9,   133,   219,   186,   153,    55,   35,   166,    9,   238,   125,   233,   69,   181,  109,    63,    34,   193,   240,   174,   194,   213,   165,    26,   210,   167,   21,   168,   167,    55,   135,   170,   206,    13,    91,   225,   159,  253,   127,   196,   140,   144,   222,   190,   15,    22,   185,    79,    11,   106,    57,    94,    78,   116,   183,  128,   161,   212,    38,  242,   157,    41,   253,   192,   184,     6,   163,    17,    66,   128,   245,    80,   194,   208,    73,   181,    91,    93,    38,   123,   213,   197,  109,   231,    36,   168,   199,   172,   211,   180,   246,   111,    45,   249,    73,   187,    42,   255,    83,   103,   45,    76,   145,    10,    59,  84,   179,   168,  251,  77,   218,   109,   221,   237,   135,   154,    94,    69,    49,    79,   102,   254,    77,    40,   107,    13,   226,    84,    78,   128,    35,   177,    4,  123,   172,    55,   174,    46,  176,    43,    77,   110,    43,  37,   148,  237};
	double weights[]= {0.07, 0.985, 0.056, 0.089, 0.18, 0.619, 0.267, 0.528, 0.138, 0.468, 0.666, 0.858, 0.204, 0.126, 0.116, 0.739, 0.484, 0.311, 0.598, 0.947, 0.499, 0.777, 0.434, 0.976, 0.109, 0.267, 0.758, 0.455, 0.841, 0.028, 0.328, 0.426, 0.072, 0.508, 0.771, 0.197, 0.551, 0.656, 0.152, 0.207, 0.765, 0.315, 0.112, 0.095, 0.743, 0.262, 0.865, 0.361, 0.276, 0.035, 0.208, 0.307, 0.212, 0.894, 0.246, 0.716, 0.573, 0.929, 0.173, 0.077, 0.982, 0.68, 0.954, 0.009, 0.417, 0.255, 0.211, 0.586, 0.608, 0.844, 0.311, 0.702, 0.474, 0.98, 0.89, 0.658, 0.293, 0.973, 0.104, 0.333, 0.187, 0.532, 0.899, 0.364, 0.618, 0.768, 0.683, 0.8, 0.85, 0.221, 0.212, 0.048, 0.73, 0.477, 0.84, 0.817, 0.729, 0.825, 0.927, 0.934, 0.586, 0.482, 0.023, 0.282, 0.454, 0.255, 0.197, 0.529, 0.692, 0.092, 0.809, 0.316, 0.914, 0.221, 0.091, 0.04, 0.791, 0.82, 0.205, 0.698, 0.455, 0.02, 0.842, 0.14, 0.005, 0.968, 0.486, 0.463, 0.992, 0.426, 0.147, 0.591, 0.262, 0.276, 0.299, 0.64, 0.607, 0.165, 0.907, 0.342, 0.413, 0.413, 0.202, 0.103, 0.167, 0.996, 0.35, 0.291, 0.184, 0.538, 0.921, 0.556, 0.772, 0.88, 0.982, 0.398, 0.917, 0.329, 0.961, 0.714, 0.064, 0.237, 0.735, 0.531, 0.27, 0.098, 0.565, 0.699, 0.32, 0.452, 0.002, 0.699, 0.888, 0.516, 0.404, 0.464, 0.051, 0.304, 0.178, 0.919, 0.503, 0.667, 0.628, 0.079, 0.864, 0.827, 0.363, 0.644, 0.551, 0.846, 0.641, 0.07, 0.346, 0.505, 0.672, 0.143, 0.083, 0.881, 0.398, 0.787, 0.662, 0.799, 0.354, 0.477, 0.506, 0.124, 0.233, 0.963, 0.529, 0.54, 0.781, 0.935, 0.025, 0.475, 0.3, 0.837, 0.409, 0.38, 0.7, 0.575, 0.487, 0.432, 0.967, 0.017, 0.449, 0.513, 0.245, 0.834, 0.138, 0.751, 0.969, 0.183, 0.526, 0.813, 0.583, 0.759, 0.527, 0.675, 0.142, 0.007, 0.075, 0.85, 0.97, 0.567, 0.048, 0.121, 0.281, 0.65, 0.455, 0.936, 0.055, 0.709, 0.7, 0.384, 0.99};


	{
		rfr::util::weighted_running_statistics<double> stat1, stat2, stat3, stat4;
		
		double factor = 1.2345;
		double offset = 6.7890;
		
		for (auto i=0u; i<N; ++i){
			stat1.push(values[i], weights[i]);
			stat2.push(factor*values[i], weights[i]);
			stat3.push(values[i]+offset, weights[i]);
			stat4.push(factor*values[i]+offset, weights[i]);
		}
		
		BOOST_REQUIRE(stat2.numerically_equal(stat1*factor, 1e-4));
		BOOST_REQUIRE(stat3.numerically_equal(stat1+offset, 1e-4));
		BOOST_REQUIRE(stat4.numerically_equal(stat1*factor+offset, 1e-4));
	}

	{
		rfr::util::weighted_running_statistics<double> stat1, stat2;
		
		double factor = 1.2345;
		
		for (auto i=0u; i<N; ++i){
			stat1.push(values[i], weights[i]);
			stat2.push(values[i], factor*weights[i]);
		}
		
		// means and variance are not affected by rescaling the weights
		BOOST_REQUIRE_CLOSE(stat1.mean(), stat2.mean(), 1e-6);
		BOOST_REQUIRE_CLOSE(stat1.variance_population(), stat2.variance_population(), 1e-6);
		// check if multiplying the weights works
		auto stat3 = stat1.multiply_weights_by(factor);
		BOOST_REQUIRE(stat2.numerically_equal(stat3, 1e-4));
	}
	
}




BOOST_AUTO_TEST_CASE(test_subspace_cardinality){
	
	std::vector<std::vector<double> > subspace;
	std::vector<unsigned int> types;
	
	
	subspace.push_back(std::vector<double> ({-1,1}));
	types.emplace_back(0);
	
	BOOST_REQUIRE_EQUAL(2, rfr::util::subspace_cardinality(subspace, types) );
	
	subspace.push_back(std::vector<double> ({0,1,2,3,4,5}));
	types.emplace_back(6);
	
	BOOST_REQUIRE_EQUAL(12, rfr::util::subspace_cardinality(subspace, types) );
	
	subspace.push_back(std::vector<double> ({0,1,2,4,5}));
	types.emplace_back(6);
	
	BOOST_REQUIRE_EQUAL(60, rfr::util::subspace_cardinality(subspace, types) );

}
	

BOOST_AUTO_TEST_CASE(test_boolean_vector_helper){
	
	std::vector<double> features(8,NAN);

	auto indices = rfr::util::get_non_NAN_indices(features);

	BOOST_REQUIRE_EQUAL(0, indices.size());

	features[2] = 2;
		
	indices = rfr::util::get_non_NAN_indices(features);
	
	BOOST_REQUIRE_EQUAL(1, indices.size());
	BOOST_REQUIRE_EQUAL(2, indices[0]);
	

	features[4] = 4;
		
	indices = rfr::util::get_non_NAN_indices(features);
	
	BOOST_REQUIRE_EQUAL(2, indices.size());
	BOOST_REQUIRE_EQUAL(2, indices[0]);
	BOOST_REQUIRE_EQUAL(4, indices[1]);




	std::vector<bool> bit_vector (8, false);
	BOOST_REQUIRE_EQUAL(false, rfr::util::any_true(bit_vector, indices));

	bit_vector[3] = true;
	BOOST_REQUIRE_EQUAL(false, rfr::util::any_true(bit_vector, indices));


	bit_vector[2] = true;
	BOOST_REQUIRE_EQUAL(true, rfr::util::any_true(bit_vector, indices));

	std::vector<bool> another_bit_vector(6,false);
	rfr::util::disjunction(bit_vector, another_bit_vector);
	
	BOOST_REQUIRE_EQUAL(bit_vector.size(), another_bit_vector.size());
	BOOST_REQUIRE(bit_vector == another_bit_vector);
	
}




