lu.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. /*************************************************************************
  2. * Copyright (c) 2011 AT&T Intellectual Property
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution, and is available at
  6. * https://www.eclipse.org/legal/epl-v10.html
  7. *
  8. * Contributors: Details at https://graphviz.org
  9. *************************************************************************/
  10. /*
  11. * This code was (mostly) written by Ken Turkowski, who said:
  12. *
  13. * Oh, that. I wrote it in college the first time. It's open source - I think I
  14. * posted it after seeing so many people solve equations by inverting matrices
  15. * by computing minors naïvely.
  16. * -Ken
  17. *
  18. * The views represented here are mine and are not necessarily shared by
  19. * my employer.
  20. Ken Turkowski [email protected]
  21. Immersive Media Technologist http://www.worldserver.com/turk/
  22. Apple Computer, Inc.
  23. 1 Infinite Loop, MS 302-3VR
  24. Cupertino, CA 95014
  25. */
  26. /* This module solves linear equations in several variables (Ax = b) using
  27. * LU decomposition with partial pivoting and row equilibration. Although
  28. * slightly more work than Gaussian elimination, it is faster for solving
  29. * several equations using the same coefficient matrix. It is
  30. * particularly useful for matrix inversion, by sequentially solving the
  31. * equations with the columns of the unit matrix.
  32. *
  33. * lu_decompose() decomposes the coefficient matrix into the LU matrix,
  34. * and lu_solve() solves the series of matrix equations using the
  35. * previous LU decomposition.
  36. *
  37. * Ken Turkowski (apple!turk)
  38. * written 3/2/79, revised and enhanced 8/9/83.
  39. */
  40. #include <math.h>
  41. #include <neatogen/neato.h>
  42. #include <util/alloc.h>
  43. static double *scales;
  44. static double **lu;
  45. static int *ps;
  46. /* lu_decompose() decomposes the coefficient matrix A into upper and lower
  47. * triangular matrices, the composite being the LU matrix.
  48. *
  49. * The arguments are:
  50. *
  51. * a - the (n x n) coefficient matrix
  52. * n - the order of the matrix
  53. *
  54. * 1 is returned if the decomposition was successful,
  55. * and 0 is returned if the coefficient matrix is singular.
  56. */
  57. int lu_decompose(double **a, int n)
  58. {
  59. int i, j, k;
  60. int pivotindex = 0;
  61. double pivot, biggest, mult, tempf;
  62. if (lu)
  63. free_array(lu);
  64. lu = new_array(n, n, 0.0);
  65. free(ps);
  66. ps = gv_calloc(n, sizeof(int));
  67. free(scales);
  68. scales = gv_calloc(n, sizeof(double));
  69. for (i = 0; i < n; i++) { /* For each row */
  70. /* Find the largest element in each row for row equilibration */
  71. biggest = 0.0;
  72. for (j = 0; j < n; j++)
  73. biggest = fmax(biggest, fabs(lu[i][j] = a[i][j]));
  74. if (biggest > 0.0)
  75. scales[i] = 1.0 / biggest;
  76. else {
  77. scales[i] = 0.0;
  78. return 0; /* Zero row: singular matrix */
  79. }
  80. ps[i] = i; /* Initialize pivot sequence */
  81. }
  82. for (k = 0; k < n - 1; k++) { /* For each column */
  83. /* Find the largest element in each column to pivot around */
  84. biggest = 0.0;
  85. for (i = k; i < n; i++) {
  86. if (biggest < (tempf = fabs(lu[ps[i]][k]) * scales[ps[i]])) {
  87. biggest = tempf;
  88. pivotindex = i;
  89. }
  90. }
  91. if (biggest <= 0.0)
  92. return 0; /* Zero column: singular matrix */
  93. if (pivotindex != k) { /* Update pivot sequence */
  94. j = ps[k];
  95. ps[k] = ps[pivotindex];
  96. ps[pivotindex] = j;
  97. }
  98. /* Pivot, eliminating an extra variable each time */
  99. pivot = lu[ps[k]][k];
  100. for (i = k + 1; i < n; i++) {
  101. lu[ps[i]][k] = mult = lu[ps[i]][k] / pivot;
  102. for (j = k + 1; j < n; j++)
  103. lu[ps[i]][j] -= mult * lu[ps[k]][j];
  104. }
  105. }
  106. if (lu[ps[n - 1]][n - 1] == 0.0)
  107. return 0; /* Singular matrix */
  108. return 1;
  109. }
  110. /* lu_solve() solves the linear equation (Ax = b) after the matrix A has
  111. * been decomposed with lu_decompose() into the lower and upper triangular
  112. * matrices L and U.
  113. *
  114. * The arguments are:
  115. *
  116. * x - the solution vector
  117. * b - the constant vector
  118. * n - the order of the equation
  119. */
  120. void lu_solve(double *x, double *b, int n)
  121. {
  122. int i, j;
  123. double dot;
  124. /* Vector reduction using U triangular matrix */
  125. for (i = 0; i < n; i++) {
  126. dot = 0.0;
  127. for (j = 0; j < i; j++)
  128. dot += lu[ps[i]][j] * x[j];
  129. x[i] = b[ps[i]] - dot;
  130. }
  131. /* Back substitution, in L triangular matrix */
  132. for (i = n - 1; i >= 0; i--) {
  133. dot = 0.0;
  134. for (j = i + 1; j < n; j++)
  135. dot += lu[ps[i]][j] * x[j];
  136. x[i] = (x[i] - dot) / lu[ps[i]][i];
  137. }
  138. }