OGS
CubicRoots.h
Go to the documentation of this file.
1
10#pragma once
11
12#include <algorithm>
13#include <limits>
14#include <range/v3/algorithm/min.hpp>
15#include <range/v3/algorithm/sort.hpp>
16#include <range/v3/range/conversion.hpp>
17#include <range/v3/view/filter.hpp>
18#include <vector>
19
20#include "BaseLib/Error.h"
21#include "cubic_roots.hpp"
22namespace MathLib
23{
24
26{
27public:
28 CubicSolver(const double a, const double b, const double c, const double d)
29 : a_(a), b_(b), c_(c), d_(d)
30 {
31 if (std::abs(a_) < 1e-9)
32 {
33 OGS_FATAL("'a' must be non-zero for a cubic equation.");
34 }
35 }
36
37 std::vector<double> solve()
38 {
39 std::array<double, 3> const roots =
40 boost::math::tools::cubic_roots<double>(a_, b_, c_, d_);
41
42 std::vector<double> adjusted_roots;
43 adjusted_roots.reserve(3);
44
45 double last_valid = std::numeric_limits<double>::quiet_NaN();
46
47 for (auto root : roots)
48 {
49 if (std::isnan(root))
50 {
51 if (!std::isnan(last_valid))
52 {
53 adjusted_roots.push_back(last_valid);
54 }
55 // If we get NaN before any valid root, we just skip it
56 }
57 else
58 {
59 adjusted_roots.push_back(root);
60 last_valid = root;
61 }
62 }
63
64 ranges::sort(adjusted_roots);
65 return adjusted_roots;
66 }
67 // Method that returns the smallest positive real root
69 {
70 std::vector<double> const roots = solve();
71
72 auto positive_roots =
73 roots | ranges::views::filter([](double root) { return root > 0; });
74
75 // If no positive root exists, return NaN
76 if (ranges::empty(positive_roots))
77 {
78 return std::numeric_limits<double>::quiet_NaN();
79 }
80
81 return ranges::min(positive_roots);
82 }
83
84private:
85 double a_, b_, c_, d_; // Coefficients of the cubic equation
86};
87
88} // namespace MathLib
#define OGS_FATAL(...)
Definition Error.h:26
double smallestPositiveRealRoot()
Definition CubicRoots.h:68
CubicSolver(const double a, const double b, const double c, const double d)
Definition CubicRoots.h:28
std::vector< double > solve()
Definition CubicRoots.h:37