Page MenuHomec4science

test_units.cc
No OneTemporary

File Metadata

Created
Tue, Jul 2, 10:38

test_units.cc

/**
* file test_units.cc
*
* @author Till Junge <till.junge@epfl.ch>
*
* @date 02 May 2017
*
* @brief Test the compile-time unit enforcement
*
* @section LICENCE
*
* Copyright (C) 2017 Till Junge
*
* µSpectre is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3, or (at
* your option) any later version.
*
* µSpectre is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Emacs; see the file COPYING. If not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <boost/test/unit_test.hpp>
#include <Eigen/Dense>
#include <chrono>
#include "common/units.hh"
namespace muSpectre{
BOOST_AUTO_TEST_SUITE(units)
BOOST_AUTO_TEST_CASE (unit_test) {
auto length = 20._m;
auto mass = 15._kg;
BOOST_CHECK_EQUAL(length*mass,mass*length);
BOOST_CHECK_NE(length, 2*length);
BOOST_CHECK_EQUAL(1._kg*1._m/1._s/1._s, 1._N);
BOOST_CHECK_EQUAL(1._N*1._m, 1_J);
BOOST_CHECK_EQUAL(1_N/1._m/1._m, 1._Pa);
}
BOOST_AUTO_TEST_CASE (mixed_assigment) {
auto l1 = 0_m;
Quantity<int, units::m> l2(5);
l1 = l2;
BOOST_CHECK_EQUAL(l1, 5_m);
}
BOOST_AUTO_TEST_CASE(eigen_basic_compatibility) {
Eigen::Matrix<Quantity<Real,units::nodim>, 2, 2> mat;
mat = mat.Random();
Eigen::Matrix<Quantity<Real,units::nodim>, 2, 2> mat2;
mat2 = mat;
BOOST_CHECK_EQUAL(mat2, mat);
BOOST_CHECK_NE(mat2, mat*mat);
BOOST_CHECK_EQUAL(mat+mat, mat*2);
BOOST_CHECK_EQUAL(mat+mat, 2*mat);
BOOST_CHECK_EQUAL((mat+mat)/2, mat);
}
BOOST_AUTO_TEST_CASE(eigen_compatibility) {
Eigen::Matrix<Quantity<Real,units::m>, 2, 2> mat;
mat = mat.Random();
Eigen::Matrix<Quantity<Real,units::m>, 2, 2> mat2;
mat2 = mat;
Eigen::Matrix<Quantity<Real,units::si_area>, 2, 2> mat3;
mat3 = mat3.Random();
Eigen::Matrix<Quantity<Real,units::N>, 2, 2> mat4;
mat4 = mat4.Random();
Eigen::Matrix<Quantity<Real,units::kg>, 2, 2> mat5;
mat5 = mat5.Random();
Eigen::Matrix<Quantity<Real,units::si_acceleration>, 2, 2> mat6;
mat6 = mat6.Random();
BOOST_CHECK_EQUAL(mat2, mat);
BOOST_CHECK_NE(mat3, mat*mat);
BOOST_CHECK_EQUAL(mat+mat, mat*2);
BOOST_CHECK_EQUAL(mat+mat, 2*mat);
BOOST_CHECK_EQUAL((mat+mat)/2, mat);
BOOST_CHECK_NE(mat4, mat5*mat6);
}
BOOST_AUTO_TEST_CASE(eigen_dynamic) {
const auto dyn = Eigen::Dynamic;
Eigen::Matrix<Quantity<Real,units::nodim>, dyn, dyn> mat(2, 2);
mat = mat.Random(2, 2);
Eigen::Matrix<Quantity<Real,units::nodim>, dyn, dyn> mat2(2, 2);
mat2 = mat;
Eigen::Matrix<Quantity<Real,units::nodim>, dyn, dyn> mat3(2, 2);
mat3 = mat3.Random(2, 2);
Eigen::Matrix<Quantity<Real,units::nodim>, dyn, dyn> mat4(2, 2);
mat4 = mat4.Random(2, 2);
Eigen::Matrix<Quantity<Real,units::nodim>, dyn, dyn> mat5(2, 2);
mat5 = mat5.Random(2, 2);
Eigen::Matrix<Quantity<Real,units::nodim>, dyn, dyn> mat6(2, 2);
mat6 = mat6.Random(2, 2);
BOOST_CHECK_EQUAL(mat2, mat);
BOOST_CHECK_EQUAL(mat+mat, mat*2);
BOOST_CHECK_EQUAL(mat+mat, 2*mat);
BOOST_CHECK_EQUAL((mat+mat)/2, mat);
BOOST_CHECK_NE(mat3, mat*mat);
BOOST_CHECK_NE(mat4, mat5*mat6);
}
BOOST_AUTO_TEST_CASE(eigen_compatibility_dynamic) {
Quantity<Eigen::Matrix<Real, Eigen::Dynamic, Eigen::Dynamic>, units::m> mat(2, 2);
mat.val = mat.val.Random(2, 2);
Quantity<Eigen::Matrix<Real, Eigen::Dynamic, Eigen::Dynamic>, units::m> mat2(2, 2);
mat2.val = mat.val;
Quantity<Eigen::Matrix<Real, Eigen::Dynamic, Eigen::Dynamic>, units::si_area> mat3(2, 2);
mat3.val = mat3.val.Random(2, 2);
Quantity<Eigen::Matrix<Real, Eigen::Dynamic, Eigen::Dynamic>, units::N> mat4(2, 2);
mat4.val = mat4.val.Random(2, 2);
Quantity<Eigen::Matrix<Real, Eigen::Dynamic, Eigen::Dynamic>, units::kg> mat5(2, 2);
mat5.val = mat5.val.Random(2, 2);
Quantity<Eigen::Matrix<Real, Eigen::Dynamic, Eigen::Dynamic>, units::si_acceleration> mat6(2, 2);
mat6.val = mat6.val.Random(2, 2);
BOOST_CHECK_EQUAL(mat2, mat);
BOOST_CHECK_EQUAL(mat+mat, mat*2);
BOOST_CHECK_EQUAL(mat+mat, 2*mat);
BOOST_CHECK_EQUAL((mat+mat)/2, mat);
BOOST_CHECK_NE(mat3, mat*mat);
BOOST_CHECK_NE(mat4, mat5*mat6);
}
BOOST_AUTO_TEST_CASE(eigen_speed) {
const size_t size{20};
using rtype = Eigen::MatrixXd;
using utype = Quantity<Eigen::MatrixXd, units::m>;
rtype rmat(size, size);
utype umat(size, size);
Real r_duration = 0, u_duration = 0;
rtype r_result(size, size);
Quantity<Eigen::MatrixXd, units::si_area> u_result(size, size);
const size_t nb_rep = 50;
std::chrono::time_point<std::chrono::high_resolution_clock> start;
std::chrono::duration<Real> duration;
for (Uint rep = 0; rep < nb_rep; ++rep) {
umat.val = umat.val.Random(size, size);
rmat = rmat.Random(size, size);
start = std::chrono::high_resolution_clock::now();
u_result = umat * umat;
duration = std::chrono::high_resolution_clock::now() - start;
u_duration += duration.count();
start = std::chrono::high_resolution_clock::now();
r_result = rmat * rmat;
duration = std::chrono::high_resolution_clock::now() - start;
r_duration += duration.count();
}
for (Uint rep = 0; rep < nb_rep; ++rep) {
}
// just to sound the alarms in case the units make the execution time explode
// (should not have *any* runtime cost)
BOOST_CHECK_LT(u_duration, r_duration*1.5);
}
BOOST_AUTO_TEST_SUITE_END()
} // muSpectre

Event Timeline