Fix overflow issue in epee:misc_utils::rolling_median_t and median(), with unit test
This commit is contained in:
parent
5d850dde99
commit
85efc88c1e
|
@ -106,6 +106,14 @@ namespace misc_utils
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T get_mid(const T &a, const T &b)
|
||||||
|
{
|
||||||
|
//returns the average of two numbers; overflow safe and works with at least all integral and floating point types
|
||||||
|
//(a+b)/2 = (a/2) + (b/2) + ((a - 2*(a/2)) + (b - 2*(b/2)))/2
|
||||||
|
return (a/2) + (b/2) + ((a - 2*(a/2)) + (b - 2*(b/2)))/2;
|
||||||
|
}
|
||||||
|
|
||||||
template<class type_vec_type>
|
template<class type_vec_type>
|
||||||
type_vec_type median(std::vector<type_vec_type> &v)
|
type_vec_type median(std::vector<type_vec_type> &v)
|
||||||
{
|
{
|
||||||
|
@ -122,7 +130,7 @@ namespace misc_utils
|
||||||
return v[n];
|
return v[n];
|
||||||
}else
|
}else
|
||||||
{//2, 4, 6...
|
{//2, 4, 6...
|
||||||
return (v[n-1] + v[n])/2;
|
return get_mid<type_vec_type>(v[n-1],v[n]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "misc_language.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
@ -226,7 +228,7 @@ public:
|
||||||
Item v = data[heap[0]];
|
Item v = data[heap[0]];
|
||||||
if (minCt < maxCt)
|
if (minCt < maxCt)
|
||||||
{
|
{
|
||||||
v = (v + data[heap[-1]]) / 2;
|
v = get_mid<Item>(v, data[heap[-1]]);
|
||||||
}
|
}
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,6 +170,17 @@ TEST(rolling_median, history_blind)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(rolling_median, overflow)
|
||||||
|
{
|
||||||
|
epee::misc_utils::rolling_median_t<uint64_t> m(2);
|
||||||
|
|
||||||
|
uint64_t over_half = static_cast<uint64_t>(3) << static_cast<uint64_t>(62);
|
||||||
|
m.insert(over_half);
|
||||||
|
m.insert(over_half);
|
||||||
|
ASSERT_EQ((over_half + over_half) < over_half, true);
|
||||||
|
ASSERT_EQ(over_half, m.median());
|
||||||
|
}
|
||||||
|
|
||||||
TEST(rolling_median, size)
|
TEST(rolling_median, size)
|
||||||
{
|
{
|
||||||
epee::misc_utils::rolling_median_t<uint64_t> m(10);
|
epee::misc_utils::rolling_median_t<uint64_t> m(10);
|
||||||
|
|
Loading…
Reference in New Issue