PIPS
reductions.c
Go to the documentation of this file.
1 /*
2 
3  $Id: reductions.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 vecteur - reductions */
26 
27 /*LINTLIBRARY*/
28 
29 #ifdef HAVE_CONFIG_H
30  #include "config.h"
31 #endif
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <limits.h>
35 
36 #include "boolean.h"
37 #include "linear_assert.h"
38 #include "arithmetique.h"
39 #include "vecteur.h"
40 
41 /* int vect_size(Pvecteur v): calcul du nombre de composantes non nulles
42  * d'un vecteur
43  *
44  * sum abs(sgn(v[i]))
45  * i
46  */
47 int vect_size(v)
48 Pvecteur v;
49 {
50  int nb_elem = 0;
51 
52  for (; v != NULL; v=v->succ)
53  nb_elem++;
54 
55  return (nb_elem);
56 }
57 
58 /* int vect_dimension(Pvecteur v): calcul du nombre de composantes non nulles
59  * et non constantes d'un vecteur
60  *
61  * sum abs(sgn(v[i]))
62  * i
63  */
65 Pvecteur v;
66 {
67  Pvecteur el;
68  int nb_elem = 0;
69 
70  for (el=v; el != NULL; el=el->succ)
71  if(!term_cst(el))
72  nb_elem++;
73 
74  return (nb_elem);
75 }
76 
77 /* Value vect_prod_scal(v1,v2): produit scalaire de v1 et de v2
78  *
79  * sum v1[i] * v2[i]
80  * i
81  */
83 Pvecteur v1, v2;
84 {
85  Value result = VALUE_ZERO;
86 
87  if(v2==NULL) return result;
88 
89  for(; v1!=NULL; v1 = v1->succ)
90  {
91  Value tmp = vect_coeff(var_of(v1),v2);
92  value_product(tmp, val_of(v1));
93  value_addto(result, tmp);
94  }
95 
96  return result;
97 }
98 
99 /* Value vect_pgcd(Pvecteur v):
100  * calcul du pgcd de tous les coefficients non nul d'un vecteur v
101  *
102  * return PGCD v[i]
103  * i
104  * v[i]!=0
105  *
106  * Renvoie 1 pour le vecteur nul (ca devrait etre +infinity)
107  */
109 Pvecteur v;
110 {
111  Value d = (v!=NULL ? value_abs(val_of(v)) : VALUE_ONE);
112 
113  if (v!=NULL) {
114  for (v=v->succ; v!=NULL && value_notone_p(d); v=v->succ)
115  d = pgcd(d, value_abs(val_of(v)));
116  }
117  return d;
118 }
119 
120 /* Value vect_pgcd_except(Pvecteur v, Variable var):
121  * calcul du pgcd de tous les coefficients non nul d'un vecteur v,
122  * sauf le coefficient correspondant a la variable var
123  *
124  * return PGCD v[i]
125  * i!=var
126  * v[i]!=0
127  *
128  * Renvoie 1 pour le vecteur nul (ca devrait etre +infinity)
129  */
131 Pvecteur v;
132 Variable var;
133 {
134  Value d;
135 
136  /* skip var's coeff if it comes first */
137  if ((v!= NULL) && (var_of(v) == var))
138  v = v->succ;
139 
140 
141  if(v==NULL)
142  d = VALUE_ONE;
143  else {
144  d = value_abs(val_of(v));
145  for (v=v->succ; v!=NULL && value_notone_p(d); v=v->succ)
146  if (var_of(v) != var)
147  d = pgcd(d,value_abs(val_of(v)));
148  }
149 
150  return d;
151 }
152 
153 /* Value vect_max0(Pvecteur v): recherche du coefficient maximum
154  * d'un vecteur v; ce coefficient est toujours au moins egal a 0
155  * car on ne dispose pas d'une base pour verifier que TOUS les
156  * coefficients sont negatifs
157  *
158  * max(0,max v[i])
159  * i
160  *
161  * Note: on evite le probleme du vecteur de dimension 0 dont le max
162  * vaut moins l'infini
163  */
165 Pvecteur v;
166 {
167  Value max = VALUE_ZERO;
168 
169  for(; v!= NULL; v= v->succ)
170  max = value_max(val_of(v),max);
171 
172  return max;
173 }
174 
175 /* Value vect_min0(Pvecteur v): recherche du coefficient minimum
176  * d'un vecteur v; ce coefficient est toujours au moins egal a 0
177  * car on ne dispose pas d'une base pour verifier que TOUS les
178  * coefficients sont negatifs
179  *
180  * min(0,min v[i])
181  * i
182  *
183  * Note: on evite le probleme du vecteur de dimension 0 dont le min
184  * vaut moins l'infini
185  */
187 Pvecteur v;
188 {
189  Value min = VALUE_ZERO;
190 
191  for(; v!= NULL; v= v->succ)
192  min = value_min(val_of(v),min);
193 
194  return min;
195 }
196 
197 /* Value vect_min(Pvecteur v): recherche du coefficient non nul minimum
198  * d'un vecteur v; aborte sur le vecteur 0 puisqu'il faudrait renvoyer
199  * plus l'infini.
200  *
201  * min v[i]
202  * i
203  * v[i]!=0
204  *
205  * Note: changement de semantique puisque 0 etait renvoye auparavant
206  * pour le vecteur 0
207  */
209 Pvecteur v;
210 {
211  if(v!=NULL) {
212  Value min = val_of(v);
213  for (v=v->succ; v!= NULL; v= v->succ)
214  min = value_min(val_of(v),min);
215 
216  return min;
217  }
218  else {
219  vect_error("vect_min","ill. null vector as argument\n");
220  return VALUE_NAN; /* just to avoid a gcc warning */
221  }
222 }
223 
224 /* Value vect_max(Pvecteur v): recherche du coefficient non nul maximum
225  * d'un vecteur v; aborte sur le vecteur 0 puisqu'il faudrait renvoyer
226  * plus l'infini.
227  *
228  * max v[i]
229  * i
230  * v[i]!=0
231  *
232  * Note: changement de semantique puisque 0 etait renvoye auparavant
233  * pour le vecteur 0
234  *
235  * Modifications:
236  * - max = (val_of(v) < max) ? val_of(v) : max; I changed to:
237  * - max = (val_of(v) > max) ? val_of(v) : max;
238  * L.Zhou Apr. 4, 91
239  */
241 Pvecteur v;
242 {
243  if(v!=NULL) {
244  Value max = val_of(v);
245  for (v=v->succ; v!= NULL; v= v->succ)
246  max = value_max(val_of(v), max);
247  return max;
248  }
249  else {
250  vect_error("vect_max","ill. null vector as argument\n");
251  return VALUE_NAN;
252  }
253 }
254 
255 /* Value vect_sum(Pvecteur v): somme des coefficients d'un vecteur
256  * (i.e. produit scalaire avec le vecteur 1)
257  *
258  * sum v[i]
259  * i
260  */
262 {
263  Value sum = VALUE_ZERO;
264 
265  for (; v!=NULL; v=v->succ)
266  value_addto(sum, val_of(v));
267 
268  return sum;
269 }
270 
271 /* bool vect_equal(Pvecteur v1, Pvecteur v2): test a egalite de
272  * deux vecteurs
273  *
274  * -> ->
275  * return v1 == v2 ;
276  *
277  */
278 bool vect_equal(v1,v2)
279 Pvecteur v1,v2;
280 {
281  /* Note: le test n'est pas optimal puisque v2 est parcouru et compare
282  * a v1 meme si ces coefficients ont ete deja ete compare lors du
283  * parcours de v1; mais cela evite le "marquage" des coefficients vus;
284  *
285  * shorter version, FC 28/09/94
286  */
287  Pvecteur v;
288  register bool
289  result = true;
290 
291  if (!v1 || !v2)
292  return(!v1 && !v2);
293 
294  /* v1 must be preserved for the second loop: use v
295  */
296  for (v=v1;
297  v && result;
298  v=v->succ)
299  result = value_eq(val_of(v),vect_coeff(var_of(v),v2));
300 
301  /* now v2 may be lost: use v2
302  */
303  for (;
304  v2 && result;
305  v2=v2->succ)
306  result = value_eq(val_of(v2),vect_coeff(var_of(v2),v1));
307 
308  return result;
309 }
310 
311 /* bool vect_equal_except(Pvecteur v1, Pvecteur v2, Variable var):
312  * test a egalite des projections selon la coordonnees var de deux vecteurs
313  * ->
314  * Soit e un vecteur de base quelconque:
315  * -> -> -> ->
316  * return <v1 . e> == <v2 . e>;
317  * e!=var
318  */
319 bool vect_equal_except(v1,v2,var)
320 Pvecteur v1,v2;
321 Variable var;
322 {
323  Pvecteur pv;
324  /*
325  * Note: le test n'est pas optimal puisque v2 est parcouru et compare
326  * a v1 meme si ces coefficients ont ete deja ete compare lors du
327  * parcours de v1; mais cela evite le "marquage" des coefficients vus;
328  */
329  bool result;
330 
331  if(v1==NULL && v2==NULL)
332  result = true;
333  else if(v1==NULL)
334  result = v2->succ==NULL && var_of(v2)==var;
335  else if(v2 == NULL)
336  result = v1->succ==NULL && var_of(v1)==var;
337  else {
338  result = true;
339 
340  for (pv = v1; pv != NULL && result == true; pv = pv->succ)
341  if (var_of(pv) != var)
342  result = value_eq(val_of(pv),vect_coeff(var_of(pv), v2));
343 
344  for (pv = v2; pv != NULL && result == true; pv = pv->succ)
345  if (var_of(pv) != var)
346  result = value_eq(val_of(pv),vect_coeff(var_of(pv), v1));
347 
348  }
349 
350  return result;
351 }
352 
353 /* bool vect_oppos(Pvecteur v1, Pvecteur v2): test de l'opposition de
354  * deux vecteurs
355  *
356  * -> -> ->
357  * return v1 + v2 == 0 ;
358  *
359  */
360 bool vect_oppos(v1,v2)
361 Pvecteur v1,v2;
362 {
363  /*
364  * Note: le test n'est pas optimal puisque v2 est parcouru et compare
365  * a v1 meme si ces coefficients ont ete deja ete compare lors du
366  * parcours de v1; mais cela evite le "marquage" des coefficients vus;
367  */
368  bool result;
369  Pvecteur pv;
370 
371  if(v1==NULL && v2==NULL)
372  result = true;
373  else if(v1==NULL || v2 == NULL)
374  result = false;
375  else {
376  result = true;
377 
378  for (pv = v1; pv != NULL && result == true; pv = pv->succ)
379  result = value_eq(val_of(pv),
380  value_uminus(vect_coeff(var_of(pv), v2)));
381 
382  for (pv = v2; pv != NULL && result == true; pv = pv->succ)
383  result = value_eq(val_of(pv),
384  value_uminus(vect_coeff(var_of(pv), v1)));
385 
386  }
387 
388  return result;
389 }
390 
391 /* bool vect_opposite_except(Pvecteur v1, Pvecteur v2, Variable var):
392  * test a egalite des projections selon la coordonnees var de deux vecteurs
393  * ->
394  * Soit e un vecteur de base quelconque:
395  * -> -> -> ->
396  * return <v1 . e> == - <v2 . e>;
397  * e!=var
398  */
399 bool vect_opposite_except(v1,v2,var)
400 Pvecteur v1,v2;
401 Variable var;
402 {
403  Pvecteur pv;
404  /*
405  * Note: le test n'est pas optimal puisque v2 est parcouru et compare
406  * a v1 meme si ces coefficients ont ete deja ete compare lors du
407  * parcours de v1; mais cela evite le "marquage" des coefficients vus;
408  */
409  bool result;
410 
411  if(v1==NULL && v2==NULL)
412  result = true;
413  else if(v1==NULL)
414  result = v2->succ==NULL && var_of(v2)==var;
415  else if(v2 == NULL)
416  result = v1->succ==NULL && var_of(v1)==var;
417  else {
418  result = true;
419 
420  for (pv = v1; pv != NULL && result == true; pv = pv->succ)
421  if (var_of(pv) != var)
422  result = value_eq(val_of(pv),
423  value_uminus(vect_coeff(var_of(pv), v2)));
424 
425  for (pv = v2; pv != NULL && result == true; pv = pv->succ)
426  if (var_of(pv) != var)
427  result = value_eq(val_of(pv),
428  value_uminus(vect_coeff(var_of(pv), v1)));
429 
430  }
431 
432  return result;
433 }
434 
435 /* int vect_proport(Pvecteur v1, Pvecteur v2): test de la colinearite
436  * de deux vecteurs et de leur direction.
437  *
438  * return
439  * 1 si les deux vecteurs sont colineaires et dans la
440  * meme direction c2 v1 == c1 v1, c1*c2 > 0
441  * c'est le cas si v1 ou v2 vaut le vecteur nul
442  * -1 si les deux vecteurs sont colineaires et dans des
443  * directions opposees c2 v1 == c1 v1, c1*c2 < 0
444  * 0 s'ils ne sont pas colineaires
445  *
446  * -> -> ->
447  * Note: aborte pour v1 == v2 == 0 parce qu'il est impossible de decider entre
448  * le retour de 1 et de -1
449  *
450  * Modifications:
451  * - introduction des variables temporaires t1 et t2 pour ne pas effectuer
452  * le test de proprotionalite uniquement sur la fin des vecteurs v1 et v2;
453  * Francois Irigoin, 26 mars 1991
454  */
456 {
457  int prop = 1;
458 
459  if (v1==NULL && v2==NULL)
460  vect_error("vect_proport","ill. NULL v1 and v2 args\n");
461 
462  if (v1!=NULL && v2!=NULL) {
463  Value c1, c2;
464  Pvecteur t1;
465  Pvecteur t2;
466 
467  c1 = val_of(v1);
468  c2 = vect_coeff(var_of(v1),v2);
469  prop = 1;
470 
471  for (t1 = v1->succ; (t1!=NULL) && (prop); t1=t1->succ)
472  {
473  Value tmp1 = vect_coeff(var_of(t1),v2), tmp2;
474 
475  value_product(tmp1,c1);
476  tmp2 = value_mult(c2,val_of(t1));
477  prop = value_eq(tmp1,tmp2);
478  }
479 
480  for (t2 = v2; (t2!=NULL) && (prop != 0);t2=t2->succ)
481  {
482  Value tmp1 = vect_coeff(var_of(t2),v1), tmp2;
483 
484  value_product(tmp1,c2);
485  tmp2 = value_mult(c1,val_of(t2));
486  prop = value_eq(tmp1,tmp2);
487  }
488 
489  if(prop!=0) {
490  if (value_pos_p(value_mult(c1,c2)))
491  prop = 1;
492  else
493  prop = -1;
494  }
495  }
496 
497  return prop;
498 }
499 
500 /* bool vect_colin_base(Pvecteur vec, Variable var): renvoie true si
501  * --> -->
502  * vec = k var
503  *
504  * false sinon
505  *
506  * Attention: le vecteur nul est colineaire a tous les vecteurs de base
507  */
508 bool vect_colin_base(vec,var)
509 Pvecteur vec;
510 Variable var;
511 {
512  return(vec==NULL || (vec->succ==NULL && var_of(vec)==var));
513 }
514 
515 /* bool vect_check(Pvecteur v): renvoie true si le vecteur v est
516  * coherent avec les specifications du package; aucun des coefficients
517  * effectivement conserves en memoire ne doit etre nul (la cellule aurait
518  * du etre liberee) et aucune dimension (i.e. variable) ne peut apparaitre
519  * deux fois.
520  *
521  * Ces conditions ne sont pas verifiees par Corinne dans ses routines
522  * du package "sommet".
523  *
524  * new version to test linear_hashtable. better for large vectors,
525  * but much worse for small ones I guess. FC.
526  *
527  * Especially for the NULL vector. FI.
528  */
530 {
531  Pvecteur v = cv;
532  register bool
533  consistent = true,
534  tcst_seen = false;
536 
537  for(; v!=NULL && consistent; v=v->succ)
538  {
539  consistent = value_notzero_p(val_of(v));
540  if (var_of(v))
541  {
543  consistent = false;
544  linear_hashtable_put(seen, var_of(v), (void*) 1);
545  }
546  else {
547  if (tcst_seen) consistent = false;
548  tcst_seen = true;
549  }
550  }
551 
553  return consistent;
554 }
555 
556 /* To ease retrieval of vect_check() */
557 bool vect_consistent_p(Pvecteur v) { return vect_check(v);}
558 
559 
560 /* @return whether one coef in v is greater than abs(val), but CST
561  * @param v vecteur being scanned
562  * @param val maximum absolute value allowed, or 0 to ignore
563  */
565 {
566  linear_assert("positive value", value_posz_p(val));
567  if (value_zero_p(val)) return false;
568  for (; v!=NULL; v=v->succ)
569  if (var_of(v) &&
570  (value_lt(val_of(v), value_uminus(val)) || value_gt(val_of(v), val)))
571  return true;
572  return false;
573 }
static hash_table seen
static function to store whether a module has been seen during the recursive generation of the daVinc...
Definition: graph.c:85
#define value_pos_p(val)
#define VALUE_ZERO
#define value_gt(v1, v2)
#define pgcd(a, b)
Pour la recherche de performance, selection d'une implementation particuliere des fonctions.
#define value_min(v1, v2)
#define value_notzero_p(val)
#define value_uminus(val)
unary operators on values
#define value_notone_p(val)
#define value_zero_p(val)
int Value
#define value_max(v1, v2)
#define value_addto(ref, val)
#define value_eq(v1, v2)
bool operators on values
#define value_product(v, w)
#define VALUE_ONE
#define value_abs(val)
#define value_mult(v, w)
whether the default is protected or not this define makes no sense any more...
#define value_lt(v1, v2)
#define VALUE_NAN
#define value_posz_p(val)
#define min(a, b)
#define max(a, b)
bool linear_hashtable_isin(linear_hashtable_pt h, void *k)
Definition: hashpointer.c:273
void linear_hashtable_put(linear_hashtable_pt h, void *k, void *v)
Definition: hashpointer.c:263
linear_hashtable_pt linear_hashtable_make(void)
constructor.
Definition: hashpointer.c:165
void linear_hashtable_free(linear_hashtable_pt h)
destructor
Definition: hashpointer.c:189
bool vect_consistent_p(Pvecteur v)
To ease retrieval of vect_check()
Definition: reductions.c:557
bool vect_opposite_except(Pvecteur v1, Pvecteur v2, Variable var)
bool vect_opposite_except(Pvecteur v1, Pvecteur v2, Variable var): test a egalite des projections sel...
Definition: reductions.c:399
Value vect_sum(Pvecteur v)
Value vect_sum(Pvecteur v): somme des coefficients d'un vecteur (i.e.
Definition: reductions.c:261
Value vect_pgcd_all(Pvecteur v)
Value vect_pgcd(Pvecteur v): calcul du pgcd de tous les coefficients non nul d'un vecteur v.
Definition: reductions.c:108
Value vect_prod_scal(Pvecteur v1, Pvecteur v2)
Value vect_prod_scal(v1,v2): produit scalaire de v1 et de v2.
Definition: reductions.c:82
Value vect_min0(Pvecteur v)
Value vect_min0(Pvecteur v): recherche du coefficient minimum d'un vecteur v; ce coefficient est touj...
Definition: reductions.c:186
int vect_proport(Pvecteur v1, Pvecteur v2)
int vect_proport(Pvecteur v1, Pvecteur v2): test de la colinearite de deux vecteurs et de leur direct...
Definition: reductions.c:455
int vect_dimension(Pvecteur v)
int vect_dimension(Pvecteur v): calcul du nombre de composantes non nulles et non constantes d'un vec...
Definition: reductions.c:64
bool vect_colin_base(Pvecteur vec, Variable var)
bool vect_colin_base(Pvecteur vec, Variable var): renvoie true si --> --> vec = k var
Definition: reductions.c:508
bool vect_equal(Pvecteur v1, Pvecteur v2)
bool vect_equal(Pvecteur v1, Pvecteur v2): test a egalite de deux vecteurs
Definition: reductions.c:278
bool vect_oppos(Pvecteur v1, Pvecteur v2)
bool vect_oppos(Pvecteur v1, Pvecteur v2): test de l'opposition de deux vecteurs
Definition: reductions.c:360
Value vect_pgcd_except(Pvecteur v, Variable var)
Value vect_pgcd_except(Pvecteur v, Variable var): calcul du pgcd de tous les coefficients non nul d'u...
Definition: reductions.c:130
bool vect_larger_coef_p(Pvecteur v, Value val)
Definition: reductions.c:564
bool vect_equal_except(Pvecteur v1, Pvecteur v2, Variable var)
bool vect_equal_except(Pvecteur v1, Pvecteur v2, Variable var): test a egalite des projections selon ...
Definition: reductions.c:319
Value vect_max(Pvecteur v)
Value vect_max(Pvecteur v): recherche du coefficient non nul maximum d'un vecteur v; aborte sur le ve...
Definition: reductions.c:240
bool vect_check(Pvecteur cv)
bool vect_check(Pvecteur v): renvoie true si le vecteur v est coherent avec les specifications du pac...
Definition: reductions.c:529
Value vect_max0(Pvecteur v)
Value vect_max0(Pvecteur v): recherche du coefficient maximum d'un vecteur v; ce coefficient est touj...
Definition: reductions.c:164
int vect_size(Pvecteur v)
package vecteur - reductions
Definition: reductions.c:47
Value vect_min(Pvecteur v)
Value vect_min(Pvecteur v): recherche du coefficient non nul minimum d'un vecteur v; aborte sur le ve...
Definition: reductions.c:208
#define linear_assert(msg, ex)
Definition: linear_assert.h:51
t_real sum(int n1, int n2, int n3, t_real u[n1][n2][n3])
Definition: stencil.c:57
le type des coefficients dans les vecteurs: Value est defini dans le package arithmetique
Definition: vecteur-local.h:89
struct Svecteur * succ
Definition: vecteur-local.h:92
hidden structure to store the hashtable.
Definition: hashpointer.c:66
#define val_of(varval)
void * Variable
arithmetique is a requirement for vecteur, but I do not want to inforce it in all pips files....
Definition: vecteur-local.h:60
#define var_of(varval)
#define term_cst(varval)
void vect_error(char *name, char *fmt,...)
package vecteur
Definition: error.c:50
Value vect_coeff(Variable var, Pvecteur vect)
Variable vect_coeff(Variable var, Pvecteur vect): coefficient de coordonnee var du vecteur vect —> So...
Definition: unaires.c:228