This repository has been archived on 2020-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
Files
Indoor/math/boxkde/BoxSizes.h
2018-07-31 15:41:25 +02:00

85 lines
2.5 KiB
C++

#pragma once
template<typename T>
struct BoxSizes
{
static_assert(std::is_floating_point<T>::value, "This class only works with floats.");
T sigma, sigmaActual;
T wIdeal, mIdeal;
unsigned n, m, wl, wu;
BoxSizes(T sigma, unsigned n)
: sigma(sigma), n(n)
{
assertMsg(sigma >= 0.8, "Sigma values below about 0.8 cannot be represented");
wIdeal = sqrt(12 * sigma*sigma / n + 1); // Ideal averaging filter width
// wl is first odd valued integer less than wIdeal
wl = (unsigned)floor(wIdeal);
if (wl % 2 == 0)
wl = wl - 1;
// wu is the next odd value > wl
wu = wl + 2;
// Compute m.Refer to the tech note for derivation of this formula
mIdeal = (12 * sigma*sigma - n*wl*wl - 4 * n*wl - 3 * n) / (-4 * wl - 4);
m = (unsigned)round(mIdeal);
assertMsg(!(m > n || m < 0), "calculation of m has failed");
// Compute actual sigma that will be achieved
sigmaActual = sqrt((m*wl*wl + (n - m)*wu*wu - n) / (T)12.0);
}
};
template<typename T>
struct ExBoxSizes
{
static_assert(std::is_floating_point<T>::value, "This class only works with floats.");
T sigma, sigma_actual;
unsigned n, r;
T alpha, c, c1, c2;
T r_f;
// Special case for h == 1
ExBoxSizes(T sigma, unsigned n)
: sigma(sigma), n(n)
{
T var = sigma*sigma;
r_f = 0.5*sqrt((12 * var) / n + 1) - T(0.5);
r = (unsigned)std::floor(r_f);
alpha = (2 * r + 1) * ( (r*r + r - 3*var/n) / (6 * (var/n - (r+1)*(r+1))) );
c1 = alpha / (2*alpha + 2*r + 1);
c2 = (1 - alpha) / (2 * alpha + 2 * r + 1);
c = c1 + c2;
}
ExBoxSizes(T sigma, unsigned d, T h)
: sigma(sigma), n(d)
{
T v = sigma*sigma;
r_f = sqrt((12 * v) / n + 1)/(2*h) - T(0.5); // (7)
r = (unsigned)std::floor(std::max(T(0), r_f));
alpha = (2 * r + 1) * (((r*r + r) - (v*3*h)/(d*h*h*h)) / (6 * ( v/(d*h*h) - (r+1)*(r+1)) )); // (8) (14)
c1 = alpha / (h*(2 * r + 2 * alpha + 1)); // (8) (13)
c2 = (1 - alpha) / (h*(2 * r + 2 * alpha + 1)); // (8) (13)
c = c1 + c2;
T lambda = h*(2*r + 1 + 2*alpha); // (8)
T variance_actual = (d*h*h*h) / (3 * lambda) * (2*r*r*r + 3*r*r + r + 6*alpha*(r+1)*(r+1)); // (14)
sigma_actual = sqrt(variance_actual);
}
};