1
/* ZM - Z's Mathematics Toolbox
2
* Copyright (C) 1998 Tomomichi Sugihara (Zhidao)
4
* zm_le_minv - linear equation: determinant and inverse matrix.
9
static zMat _zMulInvMat(zMat m1, zMat m2, zMat m, zIndex idx, zVec s);
10
static void _zBalancingMatDST(zMat m1, zMat m2, zVec s);
13
* - determinant of matrix (destructive).
15
double zMatDetDST(zMat m, zIndex idx)
17
register int i, j, k, p, q;
20
zIndexOrder( idx, 0 );
21
for( i=0; i<zMatRowSizeNC(m); i++ ){
22
p = zIndexElem( idx, i );
23
if( p != zPivoting( m, idx, i, i ) ){
25
p = zIndexElem( idx, i );
27
if( zIsTiny( ( det *= zMatElem( m, p, i ) ) ) ) return 0;
28
for( j=i+1; j<zMatRowSizeNC(m); j++ ){
29
q = zIndexElem( idx, j );
30
for( k=i+1; k<zMatRowSizeNC(m); k++ )
32
zMatElem(m,p,k) / zMatElem(m,p,i) * zMatElem(m,q,i);
39
* - determinant of matrix.
41
double zMatDet(zMat m)
48
if( !zMatIsSqr( m ) ){
49
ZRUNERROR( ZM_ERR_NONSQR_MAT );
54
idx = zIndexCreate( n );
56
det = zMatDetDST( mcp, idx );
66
zMat zMatAdj(zMat m, zMat adj)
68
register int i, j, k, l, u, v;
72
if( !zMatIsSqr(m) || !zMatIsSqr(adj) ){
73
ZRUNERROR( ZM_ERR_NONSQR_MAT );
76
if( !zMatSizeIsEqual(m,adj) ){
77
ZRUNERROR( ZM_ERR_SIZMIS_MAT );
80
smat = zMatAllocSqr( zMatRowSizeNC(m)-1 );
81
idx = zIndexCreate( zMatRowSizeNC(smat) );
87
for( i=0; i<zMatRowSizeNC(m); i++ ){
88
for( j=0; j<zMatColSizeNC(m); j++ ){
89
for( k=u=0; k<zMatRowSizeNC(m); k++ ){
90
if( k == i ) continue;
91
for( l=v=0; l<zMatColSizeNC(m); l++ ){
92
if( l == j ) continue;
93
zMatSetElem( smat, u, v, zMatElem(m,k,l) );
98
zMatSetElem( adj, j, i,
99
(i+j)%2 ? -zMatDetDST( smat, idx ) : zMatDetDST( smat, idx ) );
110
* - directly make a matrix row-balanced and column-balanced.
112
void _zBalancingMatDST(zMat m1, zMat m2, zVec s)
115
double *mp1, *mp2, tmp;
117
/* column balancing */
119
for( i=0; i<zMatColSizeNC(m1); i++ ){
120
zVecSetElem( s, i, fabs( zMatElem(m1,0,i) ) );
121
for( j=1; j<zMatRowSizeNC(m1); j++ ){
122
tmp = fabs( zMatElem(m1,j,i) );
123
if( tmp > zVecElem(s,i) ) zVecSetElem( s, i, tmp );
125
if( zVecElem(s,i) == 0 ) continue;
126
/* inverse column-balancing factor */
127
zVecSetElem( s, i, 1.0 / zVecElem(s,i) );
128
for( j=0; j<zMatRowSizeNC(m1); j++ )
129
zMatElem(m1,j,i) *= zVecElem(s,i);
132
for( mp1=zMatBuf(m1), mp2=zMatBuf(m2), i=0; i<zMatRowSizeNC(m1); mp1+=zMatColSizeNC(m1), mp2+=zMatColSizeNC(m2), i++ ){
133
if( ( tmp = zDataAbsMax( mp1, zMatColSizeNC(m1), NULL ) ) == 0 )
135
zRawVecDivDRC( mp1, tmp, zMatColSizeNC(m1) );
136
zRawVecDivDRC( mp2, tmp, zMatColSizeNC(m2) );
142
* - inner operation of zMulInvMatMat and zMulMatInvMat.
144
zMat _zMulInvMat(zMat m1, zMat m2, zMat m, zIndex idx, zVec s)
146
register int i, j, k;
151
n = zMatRowSizeNC( m );
152
_zBalancingMatDST( m1, m2, s );
153
/* forward elimination */
154
for( i=0; i<n; i++ ){
155
p = zPivoting( m1, idx, i, i );
156
if( ( head = zMatElem(m1,p,i) ) == 0 ){
157
ZRUNERROR( ZM_ERR_LE_SINGULAR );
161
zMatSetElem( m1, p, i, 1 );
162
for( j=i+1; j<n; j++ )
163
zMatElem(m1,p,j) *= head;
164
for( j=0; j<zMatColSizeNC(m2); j++ )
165
zMatElem(m2,p,j) *= head;
166
for( j=i+1; j<n; j++ ){
167
q = zIndexElem( idx, j );
168
if( !zIsTiny( head = zMatElem(m1,q,i) ) ){
169
for( k=i+1; k<n; k++ )
170
zMatElem(m1,q,k) -= zMatElem(m1,p,k) * head;
171
for( k=0; k<zMatColSizeNC(m2); k++ )
172
zMatElem(m2,q,k) -= zMatElem(m2,p,k) * head;
174
zMatSetElem( m1, q, i, 0 );
177
/* backward elimination */
178
for( i=n-1; i>=0; i-- ){
179
p = zIndexElem( idx, i );
180
for( j=0; j<zMatColSizeNC(m2); j++ ){
181
x = zMatElem( m2, p, j );
182
for( k=n-1; k>i; k-- )
183
x -= zMatElem(m1,p,k)*zMatElem(m,k,j);
184
zMatSetElem( m, i, j, x );
189
zRawVecMulDRC( &zMatElem(m,i,0), zVecElem(s,i), zMatColSizeNC(m) );
194
* - multiplication of inverse matrix and matrix.
196
zMat zMulInvMatMat(zMat m1, zMat m2, zMat m)
203
if( !zMatIsSqr(m1) ){
204
ZRUNERROR( ZM_ERR_NONSQR_MAT );
207
if( zMatColSize(m1)!=zMatRowSize(m2) || !zMatSizeIsEqual(m2,m) ){
208
ZRUNERROR( ZM_ERR_SIZMIS_MAT );
211
mcp1 = zMatClone( m1 );
212
mcp2 = zMatClone( m2 );
213
idx = zIndexCreate( zMatRowSizeNC(m1) );
214
s = zVecAlloc( zMatRowSizeNC(m1) );
215
if( !mcp1 || !mcp2 || !idx || !s ||
216
!_zMulInvMat( mcp1, mcp2, m, idx, s ) ) m = NULL;
226
* - multiplication of matrix and inverse matrix.
228
zMat zMulMatInvMat(zMat m1, zMat m2, zMat m)
231
zMat mcp1, mcp2, mcp;
235
if( !zMatIsSqr(m2) ){
236
ZRUNERROR( ZM_ERR_NONSQR_MAT );
239
if( zMatRowSize(m1)!=zMatColSize(m2) || !zMatSizeIsEqual(m1,m) ){
240
ZRUNERROR( ZM_ERR_SIZMIS_MAT );
243
mcp1 = zMatAlloc( zMatColSizeNC(m1), zMatRowSizeNC(m1) );
244
mcp2 = zMatAlloc( zMatColSizeNC(m2), zMatRowSizeNC(m2) );
245
mcp = zMatAlloc( zMatColSizeNC(m), zMatRowSizeNC(m) );
246
idx = zIndexCreate( zMatRowSizeNC(m2) );
247
s = zVecAlloc( zMatRowSizeNC(m2) );
248
if( !mcp1 || !mcp2 || !mcp || !idx || !s ) goto TERMINATE;
251
if( _zMulInvMat( mcp2, mcp1, mcp, idx, s ) )
268
zMat zMatInv(zMat m, zMat im)
271
return zMulInvMatMat( m, im, im );
275
* - inverse matrix by Hotelling's method.
277
zMat zMatInvHotelling(zMat m, zMat im, double tol, int iter)
280
zMat im2, tmp, mc, mn;
282
if( !zMatIsSqr( m ) ){
283
ZRUNERROR( ZM_ERR_NONSQR_MAT );
286
if( !zMatSizeIsEqual( m, im ) ){
287
ZRUNERROR( ZM_ERR_SIZMIS_MAT );
290
im2 = zMatAllocSqr( zMatRowSizeNC(m) );
291
tmp = zMatAllocSqr( zMatRowSizeNC(m) );
299
zMatDivDRC( im, zMatSqrNorm(m) );
301
for( mc=im, mn=im2, i=0; i<iter; i++ ){
303
zMulMatMatNC( m, mc, mn );
304
zMulMatMatNC( mc, mn, tmp );
305
zMatMul( mc, 2, mn );
306
zMatSubNCDRC( mn, tmp );
308
zMulMatMatNC( m, mn, tmp );
309
for( j=0; j<zMatRowSizeNC(tmp); j++ )
310
zMatElem(tmp,j,j) -= 1.0;
311
if( zMatIsTol( tmp, tol ) ){
312
if( mc != im ) zMatCopy( mc, im );
315
/* swap working memory */
316
zSwap( zMat, mc, mn );