Blender V4.3
poly.h
Go to the documentation of this file.
1// Copyright (c) 2007, 2008 libmv authors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to
5// deal in the Software without restriction, including without limitation the
6// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7// sell copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19// IN THE SOFTWARE.
20
21#ifndef LIBMV_NUMERIC_POLY_H_
22#define LIBMV_NUMERIC_POLY_H_
23
24#include <stdio.h>
25#include <algorithm>
26#include <cmath>
27
28namespace libmv {
29
30// Solve the cubic polynomial
31//
32// x^3 + a*x^2 + b*x + c = 0
33//
34// The number of roots (from zero to three) is returned. If the number of roots
35// is less than three, then higher numbered x's are not changed. For example,
36// if there are 2 roots, only x0 and x1 are set.
37//
38// The GSL cubic solver was used as a reference for this routine.
39template <typename Real>
40int SolveCubicPolynomial(Real a, Real b, Real c, Real* x0, Real* x1, Real* x2) {
41 Real q = a * a - 3 * b;
42 Real r = 2 * a * a * a - 9 * a * b + 27 * c;
43
44 Real Q = q / 9;
45 Real R = r / 54;
46
47 Real Q3 = Q * Q * Q;
48 Real R2 = R * R;
49
50 Real CR2 = 729 * r * r;
51 Real CQ3 = 2916 * q * q * q;
52
53 if (R == 0 && Q == 0) {
54 // Triple root in one place.
55 *x0 = *x1 = *x2 = -a / 3;
56 return 3;
57
58 } else if (CR2 == CQ3) {
59 // This test is actually R2 == Q3, written in a form suitable for exact
60 // computation with integers.
61 //
62 // Due to finite precision some double roots may be missed, and considered
63 // to be a pair of complex roots z = x +/- epsilon i close to the real
64 // axis.
65 Real sqrtQ = sqrt(Q);
66 if (R > 0) {
67 *x0 = -2 * sqrtQ - a / 3;
68 *x1 = sqrtQ - a / 3;
69 *x2 = sqrtQ - a / 3;
70 } else {
71 *x0 = -sqrtQ - a / 3;
72 *x1 = -sqrtQ - a / 3;
73 *x2 = 2 * sqrtQ - a / 3;
74 }
75 return 3;
76
77 } else if (CR2 < CQ3) {
78 // This case is equivalent to R2 < Q3.
79 Real sqrtQ = sqrt(Q);
80 Real sqrtQ3 = sqrtQ * sqrtQ * sqrtQ;
81 Real theta = acos(R / sqrtQ3);
82 Real norm = -2 * sqrtQ;
83 *x0 = norm * cos(theta / 3) - a / 3;
84 *x1 = norm * cos((theta + 2.0 * M_PI) / 3) - a / 3;
85 *x2 = norm * cos((theta - 2.0 * M_PI) / 3) - a / 3;
86
87 // Put the roots in ascending order.
88 if (*x0 > *x1) {
89 std::swap(*x0, *x1);
90 }
91 if (*x1 > *x2) {
92 std::swap(*x1, *x2);
93 if (*x0 > *x1) {
94 std::swap(*x0, *x1);
95 }
96 }
97 return 3;
98 }
99 Real sgnR = (R >= 0 ? 1 : -1);
100 Real A = -sgnR * pow(fabs(R) + sqrt(R2 - Q3), 1.0 / 3.0);
101 Real B = Q / A;
102 *x0 = A + B - a / 3;
103 return 1;
104}
105
106// The coefficients are in ascending powers, i.e. coeffs[N]*x^N.
107template <typename Real>
108int SolveCubicPolynomial(const Real* coeffs, Real* solutions) {
109 if (coeffs[0] == 0.0) {
110 // TODO(keir): This is a quadratic not a cubic. Implement a quadratic
111 // solver!
112 return 0;
113 }
114 Real a = coeffs[2] / coeffs[3];
115 Real b = coeffs[1] / coeffs[3];
116 Real c = coeffs[0] / coeffs[3];
118 a, b, c, solutions + 0, solutions + 1, solutions + 2);
119}
120} // namespace libmv
121#endif // LIBMV_NUMERIC_POLY_H_
sqrt(x)+1/max(0
#define M_PI
#define A
SIMD_FORCE_INLINE btScalar norm() const
Return the norm (length) of the vector.
Definition btVector3.h:263
local_group_size(16, 16) .push_constant(Type b
pow(value.r - subtrahend, 2.0)") .do_static_compilation(true)
ccl_device_inline float2 fabs(const float2 a)
ccl_device_inline float3 cos(float3 v)
#define B
#define R
int SolveCubicPolynomial(Real a, Real b, Real c, Real *x0, Real *x1, Real *x2)
Definition poly.h:40