Graphviz  2.29.20120524.0446
lib/neatogen/solve.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 /* solves the system ab=c using gauss reduction */
00016 #include <math.h>
00017 #include <stdlib.h>
00018 #include <stdio.h>
00019 #include "render.h"
00020 #define asub(i,j) a[(i)*n + (j)]
00021 
00022 
00023 void solve(double *a, double *b, double *c, int n)
00024 {                               /*a[n][n],b[n],c[n] */
00025     double *asave, *csave;
00026     double amax, dum, pivot;
00027     register int i, ii, j;
00028     register int k, m, mp;
00029     register int istar, ip;
00030     register int nm, nsq, t;
00031 
00032     istar = 0;                  /* quiet warnings */
00033     nsq = n * n;
00034     asave = N_GNEW(nsq, double);
00035     csave = N_GNEW(n, double);
00036 
00037     for (i = 0; i < n; i++)
00038         csave[i] = c[i];
00039     for (i = 0; i < nsq; i++)
00040         asave[i] = a[i];
00041     /* eliminate ith unknown */
00042     nm = n - 1;
00043     for (i = 0; i < nm; i++) {
00044         /* find largest pivot */
00045         amax = 0.;
00046         for (ii = i; ii < n; ii++) {
00047             dum = fabs(asub(ii, i));
00048             if (dum < amax)
00049                 continue;
00050             istar = ii;
00051             amax = dum;
00052         }
00053         /* return if pivot is too small */
00054         if (amax < 1.e-10)
00055             goto bad;
00056         /* switch rows */
00057         for (j = i; j < n; j++) {
00058             t = istar * n + j;
00059             dum = a[t];
00060             a[t] = a[i * n + j];
00061             a[i * n + j] = dum;
00062         }
00063         dum = c[istar];
00064         c[istar] = c[i];
00065         c[i] = dum;
00066         /*pivot */
00067         ip = i + 1;
00068         for (ii = ip; ii < n; ii++) {
00069             pivot = a[ii * n + i] / a[i * n + i];
00070             c[ii] = c[ii] - pivot * c[i];
00071             for (j = 0; j < n; j++)
00072                 a[ii * n + j] = a[ii * n + j] - pivot * a[i * n + j];
00073         }
00074     }
00075     /* return if last pivot is too small */
00076     if (fabs(a[n * n - 1]) < 1.e-10)
00077         goto bad;
00078     b[n - 1] = c[n - 1] / a[n * n - 1];
00079     /* back substitute */
00080     for (k = 0; k < nm; k++) {
00081         m = n - k - 2;
00082         b[m] = c[m];
00083         mp = m + 1;
00084         for (j = mp; j < n; j++)
00085             b[m] = b[m] - a[m * n + j] * b[j];
00086         b[m] = b[m] / a[m * n + m];
00087     }
00088     /* restore original a,c */
00089     for (i = 0; i < n; i++)
00090         c[i] = csave[i];
00091     for (i = 0; i < nsq; i++)
00092         a[i] = asave[i];
00093     free(asave);
00094     free(csave);
00095     return;
00096   bad:
00097     printf("ill-conditioned\n");
00098     free(asave);
00099     free(csave);
00100     return;
00101 }