2
0
mirror of https://github.com/boostorg/math.git synced 2026-01-31 20:32:07 +00:00
Files
math/test/vector_functionals_test.cpp
2018-12-07 09:02:25 -07:00

255 lines
7.3 KiB
C++

/*
* (C) Copyright Nick Thompson 2018.
* Use, modification and distribution are subject to the
* Boost Software License, Version 1.0. (See accompanying file
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#include <vector>
#include <array>
#include <forward_list>
#include <boost/core/lightweight_test.hpp>
#include <boost/numeric/ublas/vector.hpp>
#include <boost/math/tools/vector_functionals.hpp>
#include <boost/multiprecision/cpp_bin_float.hpp>
#include <boost/multiprecision/cpp_complex.hpp>
using boost::multiprecision::cpp_bin_float_50;
using boost::multiprecision::cpp_complex_50;
template<class Real>
void test_mean()
{
Real tol = std::numeric_limits<Real>::epsilon();
std::vector<Real> v{1,2,3,4,5};
Real mu = boost::math::tools::mean(v.begin(), v.end());
BOOST_TEST(abs(mu - 3) < tol);
// Can we successfully average only part of the vector?
mu = boost::math::tools::mean(v.begin(), v.begin() + 3);
BOOST_TEST(abs(mu - 2) < tol);
// Does it work when we const qualify?
mu = boost::math::tools::mean(v.cbegin(), v.cend());
BOOST_TEST(abs(mu - 3) < tol);
// Does it work for std::array?
std::array<Real, 7> u{1,2,3,4,5,6,7};
mu = boost::math::tools::mean(u.begin(), u.end());
BOOST_TEST(abs(mu - 4) < tol);
// Does it work for a forward iterator?
std::forward_list<Real> l{1,2,3,4,5,6,7};
mu = boost::math::tools::mean(l.begin(), l.end());
BOOST_TEST(abs(mu - 4) < tol);
// Does it work with ublas vectors?
boost::numeric::ublas::vector<double> w(7);
for (size_t i = 0; i < w.size(); ++i)
{
w[i] = i+1;
}
mu = boost::math::tools::mean(w.cbegin(), w.cend());
BOOST_TEST(abs(mu - 4) < tol);
}
template<class Real>
void test_mean_and_population_variance()
{
Real tol = std::numeric_limits<Real>::epsilon();
std::vector<Real> v{1,1,1,1,1,1};
auto [mu, sigma_sq] = boost::math::tools::mean_and_population_variance(v.begin(), v.end());
BOOST_TEST(abs(mu - 1) < tol);
BOOST_TEST(abs(sigma_sq) < tol);
std::vector<Real> u{1};
auto [mu1, sigma1_sq] = boost::math::tools::mean_and_population_variance(u.begin(), u.end());
BOOST_TEST(abs(mu1 - 1) < tol);
BOOST_TEST(abs(sigma1_sq) < tol);
std::vector<Real> w{0,1,0,1,0,1,0,1};
auto [mu2, sigma2_sq] = boost::math::tools::mean_and_population_variance(w.begin(), w.end());
BOOST_TEST(abs(mu2 - 1.0/2.0) < tol);
BOOST_TEST(abs(sigma2_sq - 1.0/4.0) < tol);
}
template<class Real>
void test_lp()
{
Real tol = std::numeric_limits<Real>::epsilon();
std::vector<std::complex<Real>> v{{1,0}, {0,0}, {0,0}};
Real l3 = boost::math::tools::lp_norm(v.begin(), v.end(), 3);
BOOST_TEST(abs(l3 - 1) < tol);
std::vector<Real> u{1,0,0};
l3 = boost::math::tools::lp_norm(u.begin(), u.end(), 3);
BOOST_TEST(abs(l3 - 1) < tol);
}
template<class Real>
void test_total_variation()
{
Real tol = std::numeric_limits<Real>::epsilon();
std::vector<Real> v{1,1};
Real tv = boost::math::tools::total_variation(v.begin(), v.end());
BOOST_TEST(tv >= 0 && abs(tv) < tol);
v[1] = 2;
tv = boost::math::tools::total_variation(v.begin(), v.end());
BOOST_TEST(abs(tv - 1) < tol);
v.resize(50);
for (size_t i = 0; i < v.size(); ++i) {
v[i] = i;
}
tv = boost::math::tools::total_variation(v.begin(), v.end());
BOOST_TEST(abs(tv - (v.size() -1)) < tol);
for (size_t i = 0; i < v.size(); ++i) {
v[i] = i*i;
}
tv = boost::math::tools::total_variation(v.begin(), v.end());
BOOST_TEST(abs(tv - (v.size() -1)*(v.size()-1)) < tol);
}
template<class Real>
void test_sup_norm()
{
Real tol = std::numeric_limits<Real>::epsilon();
std::vector<Real> v{-2,1,0};
Real s = boost::math::tools::sup_norm(v.begin(), v.end());
BOOST_TEST(abs(s - 2) < tol);
std::vector<std::complex<Real>> w{{0,-8}, {1,1}, {3,2}};
s = boost::math::tools::sup_norm(w.begin(), w.end());
BOOST_TEST(abs(s-8) < tol);
}
template<class Real>
void test_gini_coefficient()
{
Real tol = std::numeric_limits<Real>::epsilon();
std::vector<Real> v{1,0,0};
Real gini = boost::math::tools::gini_coefficient(v.begin(), v.end());
BOOST_TEST(abs(gini - 1) < tol);
v[0] = 1;
v[1] = 1;
v[2] = 1;
gini = boost::math::tools::gini_coefficient(v.begin(), v.end());
BOOST_TEST(abs(gini) < tol);
v[0] = 0;
v[1] = 0;
v[2] = 0;
gini = boost::math::tools::gini_coefficient(v.begin(), v.end());
BOOST_TEST(abs(gini) < tol);
}
template<class Real>
void test_hoyer_sparsity()
{
using std::sqrt;
Real tol = 5*std::numeric_limits<Real>::epsilon();
std::vector<Real> v{1,0,0};
Real hs = boost::math::tools::hoyer_sparsity(v.begin(), v.end());
BOOST_TEST(abs(hs - 1) < tol);
// Does it work with constant iterators?
hs = boost::math::tools::hoyer_sparsity(v.cbegin(), v.cend());
BOOST_TEST(abs(hs - 1) < tol);
v[0] = 1;
v[1] = 1;
v[2] = 1;
hs = boost::math::tools::hoyer_sparsity(v.cbegin(), v.cend());
BOOST_TEST(abs(hs) < tol);
}
template<class Real>
void test_absolute_gini_coefficient()
{
Real tol = std::numeric_limits<Real>::epsilon();
std::vector<Real> v{-1,0,0};
Real gini = boost::math::tools::absolute_gini_coefficient(v.begin(), v.end());
BOOST_TEST(abs(gini - 1) < tol);
v[0] = 1;
v[1] = -1;
v[2] = 1;
gini = boost::math::tools::absolute_gini_coefficient(v.begin(), v.end());
BOOST_TEST(abs(gini) < tol);
std::vector<std::complex<Real>> w(128);
std::complex<Real> i{0,1};
for(size_t k = 0; k < w.size(); ++k)
{
w[k] = exp(i*static_cast<Real>(k)/static_cast<Real>(w.size()));
}
gini = boost::math::tools::absolute_gini_coefficient(w.begin(), w.end());
BOOST_TEST(abs(gini) < tol);
// The Gini index is invariant under "cloning": If w = v \oplus v, then G(w) = G(v).
}
template<class Real>
void test_l0_norm()
{
std::vector<Real> v{0,0,1};
size_t count = boost::math::tools::l0_norm(v.begin(), v.end());
BOOST_TEST_EQ(count, 1);
// Compiles with cbegin()/cend()?
count = boost::math::tools::l0_norm(v.cbegin(), v.cend());
BOOST_TEST_EQ(count, 1);
}
int main()
{
test_mean<float>();
test_mean<double>();
test_mean<long double>();
test_mean<cpp_bin_float_50>();
test_mean_and_population_variance<float>();
test_mean_and_population_variance<double>();
test_mean_and_population_variance<long double>();
test_mean_and_population_variance<cpp_bin_float_50>();
test_lp<float>();
test_lp<double>();
test_lp<long double>();
test_total_variation<float>();
test_total_variation<double>();
test_total_variation<long double>();
test_total_variation<cpp_bin_float_50>();
test_sup_norm<float>();
test_sup_norm<double>();
test_sup_norm<long double>();
test_gini_coefficient<float>();
test_gini_coefficient<double>();
test_gini_coefficient<long double>();
test_absolute_gini_coefficient<float>();
test_absolute_gini_coefficient<double>();
test_absolute_gini_coefficient<long double>();
test_hoyer_sparsity<float>();
test_hoyer_sparsity<double>();
test_hoyer_sparsity<long double>();
test_l0_norm<float>();
test_l0_norm<double>();
test_l0_norm<long double>();
return boost::report_errors();
}