|
GRASS Programmer's Manual
6.5.svn(2012)-r51648
|
00001 /* minv.c CCMATH mathematics library source code. 00002 * 00003 * Copyright (C) 2000 Daniel A. Atkinson All rights reserved. 00004 * This code may be redistributed under the terms of the GNU library 00005 * public license (LGPL). ( See the lgpl.license file for details.) 00006 * ------------------------------------------------------------------------ 00007 */ 00008 #include <stdlib.h> 00009 #include "ccmath.h" 00010 int minv(double *a, int n) 00011 { 00012 int lc, *le; 00013 00014 double s, t, tq = 0., zr = 1.e-15; 00015 00016 double *pa, *pd, *ps, *p, *q, *q0; 00017 00018 int i, j, k, m; 00019 00020 le = (int *)malloc(n * sizeof(int)); 00021 q0 = (double *)malloc(n * sizeof(double)); 00022 for (j = 0, pa = pd = a; j < n; ++j, ++pa, pd += n + 1) { 00023 if (j > 0) { 00024 for (i = 0, q = q0, p = pa; i < n; ++i, p += n) 00025 *q++ = *p; 00026 for (i = 1; i < n; ++i) { 00027 lc = i < j ? i : j; 00028 for (k = 0, p = pa + i * n - j, q = q0, t = 0.; k < lc; ++k) 00029 t += *p++ * *q++; 00030 q0[i] -= t; 00031 } 00032 for (i = 0, q = q0, p = pa; i < n; ++i, p += n) 00033 *p = *q++; 00034 } 00035 s = fabs(*pd); 00036 lc = j; 00037 for (k = j + 1, ps = pd; k < n; ++k) { 00038 if ((t = fabs(*(ps += n))) > s) { 00039 s = t; 00040 lc = k; 00041 } 00042 } 00043 tq = tq > s ? tq : s; 00044 if (s < zr * tq) { 00045 free(le - j); 00046 free(q0); 00047 return -1; 00048 } 00049 *le++ = lc; 00050 if (lc != j) { 00051 for (k = 0, p = a + n * j, q = a + n * lc; k < n; ++k) { 00052 t = *p; 00053 *p++ = *q; 00054 *q++ = t; 00055 } 00056 } 00057 for (k = j + 1, ps = pd, t = 1. / *pd; k < n; ++k) 00058 *(ps += n) *= t; 00059 *pd = t; 00060 } 00061 for (j = 1, pd = ps = a; j < n; ++j) { 00062 for (k = 0, pd += n + 1, q = ++ps; k < j; ++k, q += n) 00063 *q *= *pd; 00064 } 00065 for (j = 1, pa = a; j < n; ++j) { 00066 ++pa; 00067 for (i = 0, q = q0, p = pa; i < j; ++i, p += n) 00068 *q++ = *p; 00069 for (k = 0; k < j; ++k) { 00070 t = 0.; 00071 for (i = k, p = pa + k * n + k - j, q = q0 + k; i < j; ++i) 00072 t -= *p++ * *q++; 00073 q0[k] = t; 00074 } 00075 for (i = 0, q = q0, p = pa; i < j; ++i, p += n) 00076 *p = *q++; 00077 } 00078 for (j = n - 2, pd = pa = a + n * n - 1; j >= 0; --j) { 00079 --pa; 00080 pd -= n + 1; 00081 for (i = 0, m = n - j - 1, q = q0, p = pd + n; i < m; ++i, p += n) 00082 *q++ = *p; 00083 for (k = n - 1, ps = pa; k > j; --k, ps -= n) { 00084 t = -(*ps); 00085 for (i = j + 1, p = ps, q = q0; i < k; ++i) 00086 t -= *++p * *q++; 00087 q0[--m] = t; 00088 } 00089 for (i = 0, m = n - j - 1, q = q0, p = pd + n; i < m; ++i, p += n) 00090 *p = *q++; 00091 } 00092 for (k = 0, pa = a; k < n - 1; ++k, ++pa) { 00093 for (i = 0, q = q0, p = pa; i < n; ++i, p += n) 00094 *q++ = *p; 00095 for (j = 0, ps = a; j < n; ++j, ps += n) { 00096 if (j > k) { 00097 t = 0.; 00098 p = ps + j; 00099 i = j; 00100 } 00101 else { 00102 t = q0[j]; 00103 p = ps + k + 1; 00104 i = k + 1; 00105 } 00106 for (; i < n;) 00107 t += *p++ * q0[i++]; 00108 q0[j] = t; 00109 } 00110 for (i = 0, q = q0, p = pa; i < n; ++i, p += n) 00111 *p = *q++; 00112 } 00113 for (j = n - 2, le--; j >= 0; --j) { 00114 for (k = 0, p = a + j, q = a + *(--le); k < n; ++k, p += n, q += n) { 00115 t = *p; 00116 *p = *q; 00117 *q = t; 00118 } 00119 } 00120 free(le); 00121 free(q0); 00122 return 0; 00123 }