|
Graphviz
2.29.20120524.0446
|
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 }
1.7.5