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 matrice */
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 "matrice.h"
40 
41 /* int matrice_determinant(matrice a, int n, 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 matrice_determinant(a,n,result)
55 matrice a; /* input */
56 int n; /* input */
57 Value result[]; /* output */
58 {
59  Value determinant_gcd;
60  Value determinant_p;
61  Value determinant_q;
62 
63  Value denominator = 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] = ACCESS(a,n,1,1);
81  result[0] = denominator;
82  break;
83 
84  case 2:
85  {
86  register Value v1, v2, a1, a2;
87  a1 = ACCESS(a,n,1,1);
88  a2 = ACCESS(a,n,2,2);
89  v1 = value_mult(a1,a2);
90  a1 = ACCESS(a,n,1,2);
91  a2 = ACCESS(a,n,2,1);
92  v2 = value_mult(a1,a2);
93 
94  result[1] = value_minus(v1,v2);
95  result[0] = value_mult(denominator,denominator);
96 
97  break;
98  }
99  default: {
100  matrice p = matrice_new(n,n);
101  matrice h = matrice_new(n,n);
102  matrice q = matrice_new(n,n);
103 
104  /* matrice_hermite expects an integer matrix */
105  DENOMINATOR(a) = VALUE_ONE;
106  matrice_hermite(a,n,n,p,h,q,&determinant_p,&determinant_q);
107  DENOMINATOR(a) = denominator;
108 
109  /* product of diagonal elements */
110  result[1] = ACCESS(h,n,1,1);
111  result[0] = denominator;
112  for(i=2; i <= n && result[1]!=0; i++) {
113  register Value a = ACCESS(h,n,i,i);
114  value_product(result[1], a);
115  value_product(result[0], denominator);
116  determinant_gcd = pgcd_slow(result[0],result[1]);
117  if(value_notone_p(determinant_gcd)) {
118  value_division(result[0],determinant_gcd);
119  value_division(result[1],determinant_gcd);
120  }
121  }
122 
123  /* product of determinants of three matrixs P, H, Q */
124  value_product(result[1],determinant_p);
125  value_product(result[1],determinant_q);
126 
127  /* free useless matrices */
128  matrice_free(p);
129  matrice_free(h);
130  matrice_free(q);
131  }
132  }
133  /* reduce result */
134  determinant_gcd = pgcd_slow(result[0],result[1]);\
135  if(value_notone_p(determinant_gcd)) {
136  value_division(result[0],determinant_gcd);
137  value_division(result[1],determinant_gcd);
138  }
139 }
140 
141 /* void matrice_sous_determinant(matrice a, int n,int i, int j, int result[])
142  * calculate sub determinant of a matrix
143  *
144  * The sub determinant indicated by (i,j) is the one obtained
145  * by deleting row i and column j from matrix of dimension n.
146  * The result passed back consists of two integers, a numerator
147  * result[1] and a denominator result[0].
148  *
149  * Precondition: n >= i > 0 && n >= j > 0
150  *
151  * Algorithm: put 0 in row i and in column j, and 1 in a[i,j], and then
152  * call matrice_determinant, restore a
153  *
154  * Complexity: O(n**3)
155  */
156 void matrice_sous_determinant(a,n,i,j,result)
157 matrice a; /* input matrix */
158 int n; /* dimension of matrix */
159 int i,j; /* coords of sub determinant */
160 Value result[]; /* output */
161 {
162  int r;
163  int c;
164  matrice save_row = matrice_new(1,n);
165  matrice save_column = matrice_new(1,n);
166 
167  /* save column j */
168  for(r=1; r <= n; r++) {
169  ACCESS(save_column,1,1,r) = ACCESS(a,n,r,j);
170  ACCESS(a,n,r,j) = 0;
171  }
172  /* save row i, but for the (i,j) elements */
173  for(c=1; c <= n; c++) {
174  ACCESS(save_row,1,1,c) = ACCESS(a,n,i,c);
175  ACCESS(a,n,i,c) = 0;
176  }
177  ACCESS(a,n,i,j) = VALUE_ONE;
178 
179  matrice_determinant(a,n,result);
180 
181  /* restore row i */
182  for(c=1; c <= n; c++) {
183  ACCESS(a,n,i,c) = ACCESS(save_row,1,1,c);
184  }
185  /* restore column j, with proper (i,j) element */
186  for(r=1; r <= n; r++) {
187  ACCESS(a,n,r,j) = ACCESS(save_column,1,1,r);
188  }
189 
190  matrice_free(save_row);
191  matrice_free(save_column);
192 }
193 
#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 DENOMINATOR(matrix)
int DENOMINATEUR(matrix): acces au denominateur global d'une matrice matrix La combinaison *(&()) est...
Definition: matrice-local.h:93
#define matrice_free(m)
Definition: matrice-local.h:78
#define ACCESS(matrix, column, i, j)
Macros d'acces aux elements d'une matrice.
Definition: matrice-local.h:86
#define matrice_new(n, m)
Allocation et desallocation d'une matrice.
Definition: matrice-local.h:77
Value * matrice
package matrice
Definition: matrice-local.h:71
void matrice_determinant(matrice a, int n, result)
package matrice
Definition: determinant.c:54
void matrice_sous_determinant(matrice a, int n, int i, int j, result)
void matrice_sous_determinant(matrice a, int n,int i, int j, int result[]) calculate sub determinant ...
Definition: determinant.c:156
void matrice_hermite(Value *MAT, int n, int m, Value *P, Value *H, Value *Q, Value *det_p, Value *det_q)
package matrice
Definition: hermite.c:78
#define assert(ex)
Definition: newgen_assert.h:41