CPolySolver.h
Go to the documentation of this file.
1 //==============================================================================
2 /*
3  Software License Agreement (BSD License)
4  Copyright (c) 2003-2016, CHAI3D.
5  (www.chai3d.org)
6 
7  All rights reserved.
8 
9  Redistribution and use in source and binary forms, with or without
10  modification, are permitted provided that the following conditions
11  are met:
12 
13  * Redistributions of source code must retain the above copyright
14  notice, this list of conditions and the following disclaimer.
15 
16  * Redistributions in binary form must reproduce the above
17  copyright notice, this list of conditions and the following
18  disclaimer in the documentation and/or other materials provided
19  with the distribution.
20 
21  * Neither the name of CHAI3D nor the names of its contributors may
22  be used to endorse or promote products derived from this software
23  without specific prior written permission.
24 
25  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
28  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
29  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
30  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
31  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  POSSIBILITY OF SUCH DAMAGE.
37 
38  \author <http://www.chai3d.org>
39  \author Francois Conti
40  \version 3.2.0 $Rev: 2015 $
41 */
42 //==============================================================================
43 
44 //------------------------------------------------------------------------------
45 #ifndef CPolySolverH
46 #define CPolySolverH
47 //------------------------------------------------------------------------------
48 #include "math/CMaths.h"
49 //------------------------------------------------------------------------------
50 
51 //------------------------------------------------------------------------------
52 namespace chai3d {
53 //------------------------------------------------------------------------------
54 
55 //==============================================================================
63 //==============================================================================
64 
65 //------------------------------------------------------------------------------
69 //------------------------------------------------------------------------------
70 
72 
73 //==============================================================================
90 //==============================================================================
91 inline int cSolveLinear(double a_coefficient[2], double a_solution[1])
92 {
93  if (cZero(a_coefficient[1]))
94  {
95  return (0);
96  }
97 
98  a_solution[0] = - a_coefficient[0] / a_coefficient[1];
99 
100  return (1);
101 }
102 
103 
104 //==============================================================================
120 //==============================================================================
121 inline int cSolveQuadric(double a_coefficient[3], double a_solution[2])
122 {
123  double p, q, D;
124 
125  // make sure we have a d2 equation
126  if (cZero(a_coefficient[2]))
127  {
128  return (cSolveLinear(a_coefficient, a_solution));
129  }
130 
131  // normal for: x^2 + px + q
132  p = a_coefficient[1] / (2.0 * a_coefficient[2]);
133  q = a_coefficient[0] / a_coefficient[2];
134  D = p * p - q;
135 
136  if (cZero(D))
137  {
138  // one double root
139  a_solution[0] = a_solution[1] = -p;
140  return (1);
141  }
142 
143  if (D < 0.0)
144  {
145  // no real root
146  return (0);
147  }
148  else
149  {
150  // two real roots
151  double sqrt_D = sqrt(D);
152  a_solution[0] = sqrt_D - p;
153  a_solution[1] = -sqrt_D - p;
154  return (2);
155  }
156 }
157 
158 
159 //==============================================================================
175 //==============================================================================
176 inline int cSolveCubic(double a_coefficient[4], double a_solution[3])
177 {
178  int i, num;
179  double sub,
180  A, B, C,
181  sq_A, p, q,
182  cb_p, D;
183 
184  // normalize the equation:x ^ 3 + Ax ^ 2 + Bx + C = 0
185  A = a_coefficient[2] / a_coefficient[3];
186  B = a_coefficient[1] / a_coefficient[3];
187  C = a_coefficient[0] / a_coefficient[3];
188 
189  // substitute x = y - A / 3 to eliminate the quadric term: x^3 + px + q = 0
190  sq_A = A * A;
191  p = 1.0/3.0 * (-1.0/3.0 * sq_A + B);
192  q = 1.0/2.0 * (2.0/27.0 * A *sq_A - 1.0/3.0 * A * B + C);
193 
194  // use Cardano's formula
195  cb_p = p * p * p;
196  D = q * q + cb_p;
197 
198  if (cZero(D))
199  {
200  if (cZero(q))
201  {
202  // one triple solution
203  a_solution[0] = 0.0;
204  num = 1;
205  }
206  else
207  {
208  // one single and one double solution
209  double u = cCbrt(-q);
210  a_solution[0] = 2.0 * u;
211  a_solution[1] = - u;
212  num = 2;
213  }
214  }
215  else
216  {
217  if (D < 0.0)
218  {
219  // casus irreductibilis: three real solutions
220  double phi = 1.0/3.0 * acos(-q / sqrt(-cb_p));
221  double t = 2.0 * sqrt(-p);
222  a_solution[0] = t * cos(phi);
223  a_solution[1] = -t * cos(phi + M_PI / 3.0);
224  a_solution[2] = -t * cos(phi - M_PI / 3.0);
225  num = 3;
226  }
227  else
228  {
229  // one real solution
230  double sqrt_D = sqrt(D);
231  double u = cCbrt(sqrt_D + fabs(q));
232  if (q > 0.0)
233  {
234  a_solution[0] = - u + p / u ;
235  }
236  else
237  {
238  a_solution[0] = u - p / u;
239  }
240  num = 1;
241  }
242  }
243 
244  // resubstitute
245  sub = 1.0 / 3.0 * A;
246  for (i = 0; i < num; i++)
247  {
248  a_solution[i] -= sub;
249  }
250 
251  return (num);
252 }
253 
254 
255 //==============================================================================
271 //==============================================================================
272 inline int cSolveQuartic(double a_coefficient[5], double a_solution[4])
273 {
274  double coeffs[4],
275  z, u, v, sub,
276  A, B, C, D,
277  sq_A, p, q, r;
278  int i, num;
279 
280  // normalize the equation:x ^ 4 + Ax ^ 3 + Bx ^ 2 + Cx + D = 0
281  A = a_coefficient[3] / a_coefficient[4];
282  B = a_coefficient[2] / a_coefficient[4];
283  C = a_coefficient[1] / a_coefficient[4];
284  D = a_coefficient[0] / a_coefficient[4];
285 
286  // subsitute x = y - A / 4 to eliminate the cubic term: x^4 + px^2 + qx + r = 0
287  sq_A = A * A;
288  p = -3.0 / 8.0 * sq_A + B;
289  q = 1.0 / 8.0 * sq_A * A - 1.0 / 2.0 * A * B + C;
290  r = -3.0 / 256.0 * sq_A * sq_A + 1.0 / 16.0 * sq_A * B - 1.0 / 4.0 * A * C + D;
291 
292  if (cZero(r))
293  {
294  // no absolute term:y(y ^ 3 + py + q) = 0
295  coeffs[0] = q;
296  coeffs[1] = p;
297  coeffs[2] = 0.0;
298  coeffs[3] = 1.0;
299 
300  num = cSolveCubic(coeffs, a_solution);
301  a_solution[num++] = 0;
302  }
303  else
304  {
305  // solve the resolvent cubic...
306  coeffs[0] = 1.0 / 2.0 * r * p - 1.0 / 8.0 * q * q;
307  coeffs[1] = -r;
308  coeffs[2] = -1.0 / 2.0 * p;
309  coeffs[3] = 1.0;
310  (void) cSolveCubic(coeffs, a_solution);
311 
312  // ...and take the one real solution...
313  z = a_solution[0];
314 
315  // ...to build two quadratic equations
316  u = z * z - r;
317  v = 2.0 * z - p;
318 
319  if (cZero(u))
320  {
321  u = 0.0;
322  }
323  else if (u > 0.0)
324  {
325  u = sqrt(u);
326  }
327  else
328  {
329  return (0);
330  }
331 
332  if (cZero(v))
333  {
334  v = 0;
335  }
336  else if (v > 0.0)
337  {
338  v = sqrt(v);
339  }
340  else
341  {
342  return (0);
343  }
344 
345  coeffs[0] = z - u;
346  coeffs[1] = q < 0 ? -v : v;
347  coeffs[2] = 1.0;
348 
349  num = cSolveQuadric(coeffs, a_solution);
350 
351  coeffs[0] = z + u;
352  coeffs[1] = q < 0 ? v : -v;
353  coeffs[2] = 1.0;
354 
355  num += cSolveQuadric(coeffs, a_solution + num);
356  }
357 
358  // resubstitute
359  sub = 1.0 / 4 * A;
360  for (i = 0; i < num; i++)
361  {
362  a_solution[i] -= sub;
363  }
364 
365  return (num);
366 }
367 
369 
370 //------------------------------------------------------------------------------
371 } // namespace chai3d
372 //------------------------------------------------------------------------------
373 
374 //------------------------------------------------------------------------------
375 #endif // CPolySolverH
376 //------------------------------------------------------------------------------
377 
378 
Implements general math utility functions.
int cSolveQuartic(double a_coefficient[5], double a_solution[4])
This function computes the solution of a quartic equation.
Definition: CPolySolver.h:272
int cSolveQuadric(double a_coefficient[3], double a_solution[2])
This function computes the solution of a quadric equation.
Definition: CPolySolver.h:121
double cCbrt(const double &a_value)
This function computes the cubic root of a scalar.
Definition: CMaths.h:493
int cSolveLinear(double a_coefficient[2], double a_solution[1])
This function computes the solution of a linear equation.
Definition: CPolySolver.h:91
Definition: CAudioBuffer.cpp:56
bool cZero(const double &a_value)
This function checks if a value is equal to or almost near zero.
Definition: CMaths.h:153
int cSolveCubic(double a_coefficient[4], double a_solution[3])
This function computes the solution of a cubic equation.
Definition: CPolySolver.h:176