Graphviz  2.29.20120524.0446
lib/pathplan/solvers.c
Go to the documentation of this file.
00001 /* $Id$ $Revision$ */
00002 /* vim:set shiftwidth=4 ts=8: */
00003 
00004 /*************************************************************************
00005  * Copyright (c) 2011 AT&T Intellectual Property 
00006  * All rights reserved. This program and the accompanying materials
00007  * are made available under the terms of the Eclipse Public License v1.0
00008  * which accompanies this distribution, and is available at
00009  * http://www.eclipse.org/legal/epl-v10.html
00010  *
00011  * Contributors: See CVS logs. Details at http://www.graphviz.org/
00012  *************************************************************************/
00013 
00014 
00015 #ifdef HAVE_CONFIG_H
00016 #include "config.h"
00017 #endif
00018 #include <math.h>
00019 #include "solvers.h"
00020 
00021 #ifdef DMALLOC
00022 #include "dmalloc.h"
00023 #endif
00024 
00025 #ifndef HAVE_CBRT
00026 #define cbrt(x) ((x < 0) ? (-1*pow(-x, 1.0/3.0)) : pow (x, 1.0/3.0))
00027 #endif
00028 #ifndef M_PI
00029 #define M_PI 3.14159265358979323846
00030 #endif
00031 
00032 #define EPS 1E-7
00033 #define AEQ0(x) (((x) < EPS) && ((x) > -EPS))
00034 
00035 int solve3(double *coeff, double *roots)
00036 {
00037     double a, b, c, d;
00038     int rootn, i;
00039     double p, q, disc, b_over_3a, c_over_a, d_over_a;
00040     double r, theta, temp, alpha, beta;
00041 
00042     a = coeff[3], b = coeff[2], c = coeff[1], d = coeff[0];
00043     if (AEQ0(a))
00044         return solve2(coeff, roots);
00045     b_over_3a = b / (3 * a);
00046     c_over_a = c / a;
00047     d_over_a = d / a;
00048 
00049     p = b_over_3a * b_over_3a;
00050     q = 2 * b_over_3a * p - b_over_3a * c_over_a + d_over_a;
00051     p = c_over_a / 3 - p;
00052     disc = q * q + 4 * p * p * p;
00053 
00054     if (disc < 0) {
00055         r = .5 * sqrt(-disc + q * q);
00056         theta = atan2(sqrt(-disc), -q);
00057         temp = 2 * cbrt(r);
00058         roots[0] = temp * cos(theta / 3);
00059         roots[1] = temp * cos((theta + M_PI + M_PI) / 3);
00060         roots[2] = temp * cos((theta - M_PI - M_PI) / 3);
00061         rootn = 3;
00062     } else {
00063         alpha = .5 * (sqrt(disc) - q);
00064         beta = -q - alpha;
00065         roots[0] = cbrt(alpha) + cbrt(beta);
00066         if (disc > 0)
00067             rootn = 1;
00068         else
00069             roots[1] = roots[2] = -.5 * roots[0], rootn = 3;
00070     }
00071 
00072     for (i = 0; i < rootn; i++)
00073         roots[i] -= b_over_3a;
00074 
00075     return rootn;
00076 }
00077 
00078 int solve2(double *coeff, double *roots)
00079 {
00080     double a, b, c;
00081     double disc, b_over_2a, c_over_a;
00082 
00083     a = coeff[2], b = coeff[1], c = coeff[0];
00084     if (AEQ0(a))
00085         return solve1(coeff, roots);
00086     b_over_2a = b / (2 * a);
00087     c_over_a = c / a;
00088 
00089     disc = b_over_2a * b_over_2a - c_over_a;
00090     if (disc < 0)
00091         return 0;
00092     else if (disc == 0) {
00093         roots[0] = -b_over_2a;
00094         return 1;
00095     } else {
00096         roots[0] = -b_over_2a + sqrt(disc);
00097         roots[1] = -2 * b_over_2a - roots[0];
00098         return 2;
00099     }
00100 }
00101 
00102 int solve1(double *coeff, double *roots)
00103 {
00104     double a, b;
00105 
00106     a = coeff[1], b = coeff[0];
00107     if (AEQ0(a)) {
00108         if (AEQ0(b))
00109             return 4;
00110         else
00111             return 0;
00112     }
00113     roots[0] = -b / a;
00114     return 1;
00115 }