Skip to content

Commit

Permalink
Refactor equations
Browse files Browse the repository at this point in the history
  • Loading branch information
R. Kaleta committed Sep 8, 2023
1 parent 4150854 commit a09aa64
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 41 deletions.
31 changes: 20 additions & 11 deletions include/algolib/maths/equation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ namespace algolib::maths
class equation
{
public:
equation(const std::array<double, N> & coefficients, double free)
: coefficients{coefficients}, free{free}
equation(const std::array<double, N> & coefficients, double free_term)
: coefficients{coefficients}, free_term_{free_term}
{
}

Expand Down Expand Up @@ -132,6 +132,14 @@ namespace algolib::maths
return this->coefficients.at(i);
}

/*!
* \return free term of this equation
*/
double free_term()
{
return this->free_term_;
}

/*!
* \brief Checks whether given values solve the equation.
* \param solution values to be checked
Expand All @@ -150,8 +158,9 @@ namespace algolib::maths
friend std::ostream & operator<< <N>(std::ostream & os, const equation<N> & eq);
// clang-format on

private:
std::array<double, N> coefficients;
double free;
double free_term_;
};

template <size_t N>
Expand All @@ -160,7 +169,7 @@ namespace algolib::maths
for(size_t i = 0; i < N; ++i)
this->coefficients[i] += equation[i];

this->free += equation.free;
this->free_term_ += equation.free_term_;
return *this;
}

Expand All @@ -170,7 +179,7 @@ namespace algolib::maths
for(size_t i = 0; i < N; ++i)
this->coefficients[i] -= equation[i];

this->free -= equation.free;
this->free_term_ -= equation.free_term_;
return *this;
}

Expand All @@ -183,7 +192,7 @@ namespace algolib::maths
for(size_t i = 0; i < N; ++i)
this->coefficients[i] *= constant;

this->free *= constant;
this->free_term_ *= constant;
return *this;
}

Expand All @@ -196,7 +205,7 @@ namespace algolib::maths
for(size_t i = 0; i < N; ++i)
this->coefficients[i] /= constant;

this->free /= constant;
this->free_term_ /= constant;
return *this;
}

Expand All @@ -208,7 +217,7 @@ namespace algolib::maths
for(size_t i = 0; i < N; ++i)
result += solution[i] * this->coefficients[i];

return result == this->free;
return result == this->free_term_;
}

#pragma endregion
Expand All @@ -225,7 +234,7 @@ namespace algolib::maths
for(size_t i = 0; i < N; ++i)
eq.coefficients[i] = -eq.coefficients[i];

eq.free = -eq.free;
eq.free_term_ = -eq.free_term_;
return eq;
}

Expand Down Expand Up @@ -275,7 +284,7 @@ namespace algolib::maths
os << eq.coefficients[i] << " x_" << i;
}

os << " = " << eq.free;
os << " = " << eq.free_term_;
return os;
}
}
Expand All @@ -291,7 +300,7 @@ namespace std
result_type operator()(const argument_type & eq)
{
result_type c_hash = std::hash<std::array<double, N>>()(eq.coefficients);
result_type f_hash = std::hash<double>()(eq.free);
result_type f_hash = std::hash<double>()(eq.free_term_);

return c_hash ^ (f_hash + 0x9e3779b9 + (c_hash << 6) + (c_hash >> 2));
}
Expand Down
50 changes: 32 additions & 18 deletions include/algolib/maths/equation_system.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,39 @@ namespace algolib::maths
* \param i index of equation
* \return equation object
*/
equation<N> & operator[](size_t i);
equation<N> & operator[](size_t i)
{
return this->equations[i];
}

/*!
* \param i index of equation
* \return equation object
*/
const equation<N> & operator[](size_t i) const
{
return this->equations[i];
}

/*!
* \param i index of equation
* \return equation object
* \throw std::out_of_range if index is out of range
*/
equation<N> & at(size_t i)
{
return this->equations.at(i);
}

/*!
* \param i index of equation
* \return equation object
* \throw std::out_of_range if index is out of range
*/
const equation<N> & operator[](size_t i) const;
const equation<N> & at(size_t i) const
{
return this->equations.at(i);
}

/*!
* \brief Computes the solution of the equation system.
Expand Down Expand Up @@ -87,36 +113,24 @@ namespace algolib::maths
std::array<equation<N>, N> equations;
};

template <size_t N>
equation<N> & equation_system<N>::operator[](size_t i)
{
return this->equations.at(i);
}

template <size_t N>
const equation<N> & equation_system<N>::operator[](size_t i) const
{
return this->equations.at(i);
}

template <size_t N>
std::array<double, N> equation_system<N>::solve()
{
gaussian_reduce();

if(this->equations[N - 1][N - 1] == 0 && this->equations[N - 1].free == 0)
if(this->equations[N - 1][N - 1] == 0 && this->equations[N - 1].free_term() == 0)
throw infinite_solutions_error("Equation system has an infinite number of solutions");

if(this->equations[N - 1][N - 1] == 0 && this->equations[N - 1].free != 0)
if(this->equations[N - 1][N - 1] == 0 && this->equations[N - 1].free_term() != 0)
throw no_solution_error("Equation system has no solution");

std::array<double, N> solution;

solution.back() = this->equations[N - 1].free / this->equations[N - 1][N - 1];
solution.back() = this->equations[N - 1].free_term() / this->equations[N - 1][N - 1];

for(int i = N - 2; i >= 0; --i)
{
double value = this->equations[i].free;
double value = this->equations[i].free_term();

for(int j = N - 1; j > i; --j)
value -= this->equations[i][j] * solution[j];
Expand Down
35 changes: 23 additions & 12 deletions test/maths/equation_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,17 @@

namespace alma = algolib::maths;

template <size_t N>
std::array<double, N> coefficients(alma::equation<N> eq)
{
std::array<double, N> result;

for(size_t i = 0; i < N; ++i)
result[i] = eq[i];

return result;
}

class EquationTest : public ::testing::Test
{
protected:
Expand All @@ -26,44 +37,44 @@ TEST_F(EquationTest, operatorUnaryPlus_ThenCopied)
// when
alma::equation<4> result = +test_object;
// then
EXPECT_EQ((std::array<double, 4>{2, 3, 0, -2.5}), result.coefficients);
EXPECT_EQ(15, result.free);
EXPECT_EQ((std::array<double, 4>{2, 3, 0, -2.5}), coefficients(result));
EXPECT_EQ(15, result.free_term());
}

TEST_F(EquationTest, operatorUnaryMinus_ThenNegated)
{
// when
alma::equation<4> result = -test_object;
// then
EXPECT_EQ((std::array<double, 4>{-2, -3, 0, 2.5}), result.coefficients);
EXPECT_EQ(-15, result.free);
EXPECT_EQ((std::array<double, 4>{-2, -3, 0, 2.5}), coefficients(result));
EXPECT_EQ(-15, result.free_term());
}

TEST_F(EquationTest, operatorPlus_ThenAddingEquations)
{
// when
alma::equation<4> result = test_object + alma::equation<4>({1, -1, 4, 10}, 5);
// then
EXPECT_EQ((std::array<double, 4>{3, 2, 4, 7.5}), result.coefficients);
EXPECT_EQ(20, result.free);
EXPECT_EQ((std::array<double, 4>{3, 2, 4, 7.5}), coefficients(result));
EXPECT_EQ(20, result.free_term());
}

TEST_F(EquationTest, operatorMinus_ThenSubtractingEquations)
{
// when
alma::equation<4> result = test_object - alma::equation<4>({1, -1, 4, 10}, 5);
// then
EXPECT_EQ((std::array<double, 4>{1, 4, -4, -12.5}), result.coefficients);
EXPECT_EQ(10, result.free);
EXPECT_EQ((std::array<double, 4>{1, 4, -4, -12.5}), coefficients(result));
EXPECT_EQ(10, result.free_term());
}

TEST_F(EquationTest, operatorAsterisk_WhenConstantIsNonZero_ThenMultiplyingEquations)
{
// when
alma::equation<4> result = test_object * 2;
// then
EXPECT_EQ((std::array<double, 4>{4, 6, 0, -5}), result.coefficients);
EXPECT_EQ(30, result.free);
EXPECT_EQ((std::array<double, 4>{4, 6, 0, -5}), coefficients(result));
EXPECT_EQ(30, result.free_term());
}

TEST_F(EquationTest, operatorAsterisk_WhenConstantIsZero_ThenDomainError)
Expand All @@ -79,8 +90,8 @@ TEST_F(EquationTest, operatorSlash_WhenConstantIsNonZero_ThenDividingEquations)
// when
alma::equation<4> result = test_object / -2;
// then
EXPECT_EQ((std::array<double, 4>{-1, -1.5, 0, 1.25}), result.coefficients);
EXPECT_EQ(-7.5, result.free);
EXPECT_EQ((std::array<double, 4>{-1, -1.5, 0, 1.25}), coefficients(result));
EXPECT_EQ(-7.5, result.free_term());
}

TEST_F(EquationTest, operatorSlash_WhenConstantIsZero_ThenDomainError)
Expand Down

0 comments on commit a09aa64

Please sign in to comment.