Page MenuHomec4science

tests_gtest.cc
No OneTemporary

File Metadata

Created
Thu, Apr 25, 17:07

tests_gtest.cc

/**
* @file
*
* @author Lucas Frérot <lucas.frerot@epfl.ch>
*
* @section LICENSE
*
* Copyright (©) 2018-2021 EPFL (Ecole Polytechnique Fédérale de
* Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des
* Solides)
*
* Expolit is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Expolit 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 Lesser General Public License for
* more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Expolit. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <expolit/expolit>
#include <complex>
#include <gtest/gtest.h>
using namespace expolit;
using Real = double;
static constexpr Polynomial<Int, 1> Zi({0, 1});
static constexpr Polynomial<std::complex<Real>, 1> Zc({0, 1});
static constexpr Polynomial<Real, 1> Zr({0, 1});
using lin = std::remove_cv_t<decltype(Zr)>;
template <typename CT, UInt order>
constexpr void compare(const Polynomial<CT, order>& p1,
const Polynomial<CT, order>& p2) {
for (UInt i = 0; i < p1.terms; ++i)
ASSERT_NEAR(std::abs(p1.coeffs[i] - p2.coeffs[i]), 0, 1e-14)
<< "Polynomials are not equal (i = " << i << ")";
}
template <typename T, UInt order>
constexpr void compare(const Polynomial<Int, order>& p1,
const Polynomial<Int, order>& p2) {
for (UInt i = 0; i < p1.terms; ++i)
ASSERT_EQ(p1.coeffs[i], p2.coeffs[i])
<< "Polynomials are not equal (i = " << i << ")";
}
TEST(Polynomial, initialization) {
constexpr auto p = 1 + 2 * pow<2>(Zi) + pow<3>(Zi);
constexpr Int z = 3;
constexpr Int sol = 1 + 2 * z * z + z * z * z;
constexpr Int res = p(z);
static_assert(sol == res, "Bad coefficients");
// This guy cannot be consexpr because std::complex is stupid
auto p2 = 1. + Zc * Zc;
std::complex<Real> z2(0, 1);
ASSERT_NEAR(std::abs(p2(z2)), 0, 1e-14) << "Bad coefficents (complex)";
}
TEST(Polynomial, sum) {
constexpr auto p = 1 + 2 * pow<2>(Zi) + pow<3>(Zi);
constexpr auto p2 = Zi + 2 * Zi * Zi;
constexpr auto res = 1 + Zi + 4 * Zi * Zi + Zi * Zi * Zi;
compare(p + p2, res);
}
TEST(Polynomial, product) {
constexpr auto p = 1 + 2 * pow<2>(Zi) + pow<3>(Zi);
constexpr auto p2 = Zi + 2 * pow<2>(Zi);
constexpr auto res =
Zi + 2 * pow<2>(Zi) + 2 * pow<3>(Zi) + 5 * pow<4>(Zi) + 2 * pow<5>(Zi);
compare(p * p2, res);
}
TEST(Polynomial, derivative) {
constexpr auto p = 1 + 2 * pow<2>(Zi) + pow<3>(Zi);
constexpr auto res = 4 * Zi + 3 * Zi * Zi;
compare(differentiate(p), res);
}
TEST(Polynomial, integration) {
constexpr auto p = 1. + 2. * pow<2>(Zr) + pow<3>(Zr);
constexpr auto res = Zr + 2 / 3. * pow<3>(Zr) + 1 / 4. * pow<4>(Zr);
compare(integrate(p), res);
}
TEST(Exponential, evaluation) {
constexpr auto e = exp(2. * Zr);
constexpr Real z = 3.4;
const Real res = e(z); // cannot be constexpr because of exponential
ASSERT_NEAR(std::exp(2 * z), res, 1e-14) << "Exponential evaluation fail";
}
TEST(Exponential, derivative) {
constexpr auto e = exp(2. * Zr);
constexpr auto diff = differentiate(e);
constexpr auto res = Constant<Real>({2}) * e;
compare(res.operands.first, diff.operands.first);
compare(e.expression, diff.operands.second.expression);
}
TEST(Exponential, integration) {
constexpr auto e = exp(2. * Zr);
constexpr auto integ = integrate(e);
constexpr auto res = Constant<Real>({1 / 2.}) * e;
compare(res.operands.first, integ.operands.first);
compare(e.expression, integ.operands.second.expression);
}
TEST(Integration, parts) {
constexpr auto e = exp(2. * Zr);
constexpr auto expr = e * (2. * Zr);
constexpr auto res = Zr * e - Constant<Real>({1 / 2.}) * e;
constexpr auto integ = integrate(expr);
compare(integ.operands.first.operands.first,
res.operands.first.operands.first);
compare(integ.operands.second.operands.first,
res.operands.second.operands.first);
}
TEST(Integration, definite_integral) {
constexpr auto p = Zr;
constexpr std::pair<Real, Real> bounds(0, 1);
constexpr auto res = definite_integral(bounds, p);
ASSERT_NEAR(0.5, res, 1e-14) << "Definite integral fail";
constexpr auto pi = 2 * Zi;
static_assert(definite_integral(std::make_pair(0, 1), pi) == 1,
"Definite integral fail");
}
using Q = Litteral<struct Q_>;
TEST(Litteral, substitution) {
constexpr Q q;
constexpr auto p = q * Zi;
constexpr auto c = Constant<Int>({2});
constexpr auto p_sub = substitute<Q::tag>(c, p);
compare(2 * Zi, p_sub);
constexpr auto expo = exp(q * Zr);
constexpr auto x_sub = substitute<Q::tag>(c, expo);
compare(2. * Zr, x_sub.expression);
}
TEST(Litteral, differentiation) {
constexpr Q q;
constexpr auto c = Constant<Real>({2});
constexpr auto expo = exp(q * Zr);
constexpr auto dexpo = differentiate(expo);
constexpr auto res = substitute<Q::tag>(c, dexpo);
compare(c, res.operands.first);
compare(2. * Zr, res.operands.second.expression);
}
TEST(Litteral, integration) {
constexpr Q q;
constexpr auto c = Constant<Real>({2});
constexpr auto res = substitute<Q::tag>(c, integrate(2 * Zr * exp(q * Zr)));
constexpr auto sol =
Zr * exp(2. * Zr) - Constant<Real>({1 / 2.}) * exp(2. * Zr);
compare(sol.operands.first.operands.first,
res.operands.first.operands.first);
compare(sol.operands.second.operands.first,
res.operands.second.operands.first);
}

Event Timeline