HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
polynomial.hpp
1// Copyright Take Vos 2022.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "../utility/utility.hpp"
8#include "../container/container.hpp"
9#include "../macros.hpp"
10#include <numbers>
11#include <array>
12
13hi_export_module(hikogui.numeric.polynomial);
14
15hi_export namespace hi::inline v1 {
16
29template<typename T>
30hi_force_inline constexpr lean_vector<T> solvePolynomial(T const& a, T const& b) noexcept
31{
32 if (a != 0) {
33 return {static_cast<T>(-(b / a))};
34 } else if (b == 0) {
35 // Any value of x is correct.
36 return {T{0}};
37 } else {
38 // None of the values for x is correct.
39 return {};
40 }
41}
42
56template<typename T>
57hi_force_inline constexpr lean_vector<T> solvePolynomial(T const& a, T const& b, T const& c) noexcept
58{
59 if (a == 0) {
60 return solvePolynomial(b, c);
61 } else {
62 auto const D = b * b - T{4} * a * c;
63 if (D < 0) {
64 return {};
65 } else if (D == 0) {
66 return {static_cast<T>(-b / (T{2} * a))};
67 } else {
68 auto const Dsqrt = sqrt(D);
69 return {static_cast<T>((-b - Dsqrt) / (T{2} * a)), static_cast<T>((-b + Dsqrt) / (T{2} * a))};
70 }
71 }
72}
73
76template<typename T>
77hi_force_inline lean_vector<T> solveDepressedCubicTrig(T const& p, T const& q) noexcept
78{
79 constexpr T oneThird = T{1} / T{3};
80 constexpr T pi2_3 = (T{2} / T{3}) * std::numbers::pi_v<T>;
81 constexpr T pi4_3 = (T{4} / T{3}) * std::numbers::pi_v<T>;
82
83 auto const U = oneThird * acos(((T{3} * q) / (T{2} * p)) * sqrt(T{-3} / p));
84 auto const V = T{2} * sqrt(-oneThird * p);
85
86 auto const t0 = V * cos(U);
87 auto const t1 = V * cos(U - pi2_3);
88 auto const t2 = V * cos(U - pi4_3);
89 return {static_cast<T>(t0), static_cast<T>(t1), static_cast<T>(t2)};
90}
91
92template<typename T>
93hi_force_inline lean_vector<T> solveDepressedCubicCardano(T const& p, T const& q, T const& D) noexcept
94{
95 auto const sqrtD = sqrt(D);
96 auto const minusHalfQ = T{-0.5} * q;
97 auto const v = cbrt(minusHalfQ + sqrtD);
98 auto const w = cbrt(minusHalfQ - sqrtD);
99 return {static_cast<T>(v + w)};
100}
101
118template<typename T>
119hi_force_inline lean_vector<T> solveDepressedCubic(T const& p, T const& q) noexcept
120{
121 constexpr T oneForth = T{1} / T{4};
122 constexpr T oneTwentySeventh = T{1} / T{27};
123
124 if (p == 0.0 && q == 0.0) {
125 return {T{0}};
126
127 } else {
128 auto const D = oneForth * q * q + oneTwentySeventh * p * p * p;
129
130 if (D < 0 && p != 0.0) {
131 // Has three real roots.
132 return solveDepressedCubicTrig(p, q);
133
134 } else if (D == 0 && p != 0.0) {
135 // Has two real roots, or maybe one root
136 auto const t0 = (T{3} * q) / p;
137 auto const t1 = (T{-3} * q) / (T{2} * p);
138 return {static_cast<T>(t0), static_cast<T>(t1), static_cast<T>(t1)};
139
140 } else {
141 // Has one real root.
142 return solveDepressedCubicCardano(p, q, D);
143 }
144 }
145}
146
155template<typename T>
156hi_force_inline constexpr lean_vector<T> solvePolynomial(T const& a, T const& b, T const& c, T const& d) noexcept
157{
158 if (a == 0) {
159 return solvePolynomial(b, c, d);
160
161 } else {
162 auto const p = (T{3} * a * c - b * b) / (T{3} * a * a);
163 auto const q = (T{2} * b * b * b - T{9} * a * b * c + T{27} * a * a * d) /
164 (T{27} * a * a * a);
165
166 auto const b_3a = b / (T{3} * a);
167
168 auto r = solveDepressedCubic(p, q);
169 for (auto &x: r) {
170 x -= b_3a;
171 }
172
173 return r;
174 }
175}
176
177} // namespace hi::inline v1
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
hi_force_inline constexpr lean_vector< T > solvePolynomial(T const &a, T const &b) noexcept
Definition polynomial.hpp:30
hi_force_inline lean_vector< T > solveDepressedCubicTrig(T const &p, T const &q) noexcept
Definition polynomial.hpp:77
hi_force_inline lean_vector< T > solveDepressedCubic(T const &p, T const &q) noexcept
Definition polynomial.hpp:119
T cbrt(T... args)