PIPS
determinant.c
Go to the documentation of this file.
1 /*
2 
3  $Id: determinant.c 1669 2019-06-26 17:24:57Z coelho $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of Linear/C3 Library.
8 
9  Linear/C3 Library is free software: you can redistribute it and/or modify it
10  under the terms of the GNU Lesser General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  any later version.
13 
14  Linear/C3 Library is distributed in the hope that it will be useful, but WITHOUT ANY
15  WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  FITNESS FOR A PARTICULAR PURPOSE.
17 
18  See the GNU Lesser General Public License for more details.
19 
20  You should have received a copy of the GNU Lesser General Public License
21  along with Linear/C3 Library. If not, see <http://www.gnu.org/licenses/>.
22 
23 */
24 
25  /* package matrix */
26 
27 #ifdef HAVE_CONFIG_H
28  #include "config.h"
29 #endif
30 
31 #include <stdlib.h>
32 #include <stdio.h>
33 
34 #include "linear_assert.h"
35 
36 #include "boolean.h"
37 #include "arithmetique.h"
38 
39 #include "matrix.h"
40 
41 /* int matrix_determinant(Pmatrix a, int * result):
42  * calculate determinant of an (nxn) rational matrix a
43  *
44  * The result consists of two integers, a numerator result[1]
45  * and a denominator result[0].
46  *
47  * Algorithm: integer matrix triangularisation by Hermite normal form
48  * (because the routine is available)
49  *
50  * Complexity: O(n**3) -- up to gcd computations...
51  *
52  * Authors: Francois Irigoin, September 1989, Yi-qing Yang, January 1990
53  */
54 void matrix_determinant(a, result)
55 Pmatrix a; /* input */
56 Value result[]; /* output */
57 {
58 
59  Value determinant_gcd;
60  Value determinant_p;
61  Value determinant_q;
62  int n = MATRIX_NB_LINES(a);
63  Value denominator = MATRIX_DENOMINATOR(a);
64  int i;
65  /* cette routine est FAUSSE car la factorisation de Hermite peut
66  s'appuyer sur des matrice unimodulaires de determinant 1 ou -1.
67  Il faudrait donc ecrire un code de calcul de determinant de
68  matrice unimodulaire...
69 
70  Ou tout reprendre avec une triangularisation rapide et n'utilisant
71  que des matrice de determinant +1. Voir mon code des US.
72  Cette triangularisation donnera en derivation une routine
73  d'inversion rapide pour matrice unimodulaire */
74 
75  assert(n > 0 && denominator != 0);
76 
77  switch(n) {
78 
79  case 1:
80  result[1] = MATRIX_ELEM(a,1,1);
81  result[0] = denominator;
82  break;
83 
84  case 2:
85  {
86  Value v1 = value_mult(MATRIX_ELEM(a,1,1),MATRIX_ELEM(a,2,2)),
87  v2 = value_mult(MATRIX_ELEM(a,1,2),MATRIX_ELEM(a,2,1));
88 
89  result[1] = value_minus(v1,v2);
90  result[0] = value_mult(denominator,denominator);
91  break;
92  }
93  default: {
94  Pmatrix p = matrix_new(n,n);
95  Pmatrix h = matrix_new(n,n);
96  Pmatrix q = matrix_new(n,n);
97 
98  /* matrix_hermite expects an integer matrix */
100  matrix_hermite(a,p,h,q,&determinant_p,&determinant_q);
101  MATRIX_DENOMINATOR(a) = denominator;
102 
103  /* product of diagonal elements */
104  result[1] = MATRIX_ELEM(h,1,1);
105  result[0] = denominator;
106  for(i=2; i <= n && result[1]!=0; i++) {
107  value_product(result[1],MATRIX_ELEM(h,i,i));
108  value_product(result[0],denominator);
109  determinant_gcd = pgcd_slow(result[0],result[1]);
110  if(value_notone_p(determinant_gcd)) {
111  value_division(result[0],determinant_gcd);
112  value_division(result[1],determinant_gcd);
113  }
114  }
115 
116  /* product of determinants of three matrixs P, H, Q */
117  value_product(result[1],determinant_p);
118  value_product(result[1],determinant_q);
119 
120  /* free useless matrices */
121  matrix_free(p);
122  matrix_free(h);
123  matrix_free(q);
124  }
125  }
126  /* reduce result */
127  determinant_gcd = pgcd_slow(result[0],result[1]);
128  if(value_notone_p(determinant_gcd)) {
129  value_division(result[0],determinant_gcd);
130  value_division(result[1],determinant_gcd);
131  }
132 }
133 
134 /* void matrix_sub_determinant(Pmatrix a,int i, int j, int result[])
135  * calculate sub determinant of a matrix
136  *
137  * The sub determinant indicated by (i,j) is the one obtained
138  * by deleting row i and column j from matrix of dimension n.
139  * The result passed back consists of two integers, a numerator
140  * result[1] and a denominator result[0].
141  *
142  * Precondition: n >= i > 0 && n >= j > 0
143  *
144  * Algorithm: put 0 in row i and in column j, and 1 in a[i,j], and then
145  * call matrix_determinant, restore a
146  *
147  * Complexity: O(n**3)
148  */
149 void matrix_sub_determinant(a,i,j,result)
150 Pmatrix a; /* input matrix */
151 int i,j; /* coords of sub determinant */
152 Value result[]; /* output */
153 {
154  int n = MATRIX_NB_LINES(a);
155  int r;
156  int c;
157  Pmatrix save_row = matrix_new(1,n);
158  Pmatrix save_column = matrix_new(1,n);
159 
160  /* save column j */
161  for(r=1; r <= n; r++) {
162  MATRIX_ELEM(save_column,1,r) = MATRIX_ELEM(a,r,j);
163  MATRIX_ELEM(a,r,j) = 0;
164  }
165  /* save row i, but for the (i,j) elements */
166  for(c=1; c <= n; c++) {
167  MATRIX_ELEM(save_row,1,c) = MATRIX_ELEM(a,i,c);
168  MATRIX_ELEM(a,i,c) = VALUE_ZERO;
169  }
170  MATRIX_ELEM(a,i,j) = VALUE_ONE;
171 
172  matrix_determinant(a,result);
173 
174  /* restore row i */
175  for(c=1; c <= n; c++) {
176  MATRIX_ELEM(a,i,c) = MATRIX_ELEM(save_row,1,c);
177  }
178  /* restore column j, with proper (i,j) element */
179  for(r=1; r <= n; r++) {
180  MATRIX_ELEM(a,r,j) = MATRIX_ELEM(save_column,1,r);
181  }
182 
183  matrix_free(save_row);
184  matrix_free(save_column);
185 }
186 
#define VALUE_ZERO
#define value_minus(v1, v2)
#define value_notone_p(val)
int Value
#define value_division(ref, val)
#define value_product(v, w)
#define VALUE_ONE
#define value_mult(v, w)
whether the default is protected or not this define makes no sense any more...
Value pgcd_slow(Value, Value)
pgcd.c
Definition: pgcd.c:44
#define MATRIX_NB_LINES(matrix)
Definition: matrix-local.h:87
#define MATRIX_DENOMINATOR(matrix)
int MATRIX_DENONIMATOR(matrix): acces au denominateur global d'une matrice matrix
Definition: matrix-local.h:86
#define matrix_free(m)
Allocation et desallocation d'une matrice.
Definition: matrix-local.h:73
#define MATRIX_ELEM(matrix, i, j)
Macros d'acces aux elements d'une matrice.
Definition: matrix-local.h:80
Pmatrix matrix_new(int m, int n)
package matrix
Definition: alloc.c:41
void matrix_sub_determinant(Pmatrix a, int i, int j, result)
void matrix_sub_determinant(Pmatrix a,int i, int j, int result[]) calculate sub determinant of a matr...
Definition: determinant.c:149
void matrix_determinant(Pmatrix a, result)
package matrix
Definition: determinant.c:54
void matrix_hermite(Pmatrix MAT, Pmatrix P, Pmatrix H, Pmatrix Q, Value *det_p, Value *det_q)
package matrix
Definition: hermite.c:78
#define assert(ex)
Definition: newgen_assert.h:41
package matrice
Definition: matrix-local.h:63