PIPS
sc_triang_elim_redond.c
Go to the documentation of this file.
1 /*
2 
3  $Id: sc_triang_elim_redond.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,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or 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 sc
26  */
27 
28 #ifdef HAVE_CONFIG_H
29  #include "config.h"
30 #endif
31 
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 
36 #include "linear_assert.h"
37 #include "boolean.h"
38 #include "arithmetique.h"
39 #include "vecteur.h"
40 #include "contrainte.h"
41 #include "sc.h"
42 
43 #include "sc-private.h"
44 
45 typedef struct {
46  Pbase rbase; // reverse loop base
47  Pbase others; // other variables
48  bool inner_first; // inner or outer loop first
49  bool complex_first; // complex or simplest first
50 } sort_ctx_t;
51 
52 static void set_sort_context(
54  Pbase base,
55  Pbase sort_base,
56  bool inner_first,
57  bool complex_first)
58 {
59  Pbase btmp = BASE_NULLE;
60  assert(context != NULL);
61 
62  // the base is reversed! inner indexes first!!
63  context->rbase = base_normalize(base_reversal(sort_base));
64  btmp = base_difference(base, sort_base);
65  context->others = base_normalize(btmp);
66  context->inner_first = inner_first;
67  context->complex_first = complex_first;
68 }
69 
71 {
72  assert(context != NULL);
73  base_rm(context->rbase), context->rbase = BASE_NULLE;
74  base_rm(context->others), context->others = BASE_NULLE;
75 }
76 
77 #define ADD_COST (1)
78 #define MUL_COST (1)
79 #define AFF_COST (1)
81 {
82  int cost = AFF_COST;
83  Pbase b;
84  Value val;
85 
86  // constant
88  cost += ADD_COST;
89 
90  // other variables
91  for (b=context->others; b!=(Pvecteur)NULL; b=b->succ)
92  {
93  val = vect_coeff(var_of(b), v);
94  val = value_abs(val);
95 
96  if (value_notzero_p(val))
97  cost+=value_one_p(val)? ADD_COST: (MUL_COST+ADD_COST);
98  }
99 
100  return cost;
101 }
102 
103 /* for qsort, returns "is simpler than"
104  *
105  * - : v1 < v2
106  * 0 : v1==v2
107  * + : v1 > v2
108  *
109  * with the following criterion
110  *
111  * 1/ ranks
112  * 2/ coef of comparable ranks, +-1 or simpler...
113  * 3/
114  *
115  * rational:
116  * - loop sizes are assumed to be infinite
117  * - invariant code motion
118  * - induction variables recognized
119  */
120 #define DB_RESULT(e) \
121  { \
122  int result = (e); \
123  fprintf(stderr, "[compare_the_constraints]\n"); \
124  vect_debug(v1); vect_debug(v2); \
125  fprintf(stderr, "%s\n", result==0 ? "=" : (result>0 ? ">" : "<")); \
126  return(result); \
127  }
128 
129 #define RESULT(e) { return (e); }
130 
131 #define RETURN_HARDER(b) RESULT(context->complex_first ? (b) : -(b))
132 #define RETURN_ORDER(b) RESULT(context->inner_first ? (b) : -(b))
133 
134 #define same_sign_p(v,w) \
135  ((value_neg_p(v) && value_neg_p(w)) || (value_pos_p(v) && value_pos_p(w)))
136 
137 /* compare two constraints with a loop complexity cost in mind?
138  * not exactly, some of the choices attempt to avoid large coefs?
139  *
140  * returns -1: c1<c2, 0: c1==c2, +1: c1>c2
141  */
143  const Pcontrainte * pc1,
144  const Pcontrainte * pc2,
146 {
147  Pvecteur v1 = (*pc1)->vecteur, v2 = (*pc2)->vecteur;
148  bool null_1, null_2;
149  int i, irank = 0, cost_1, cost_2;
150  Value val_1 = VALUE_ZERO, val_2 = VALUE_ZERO,
151  val = VALUE_ZERO, val_p = VALUE_ZERO;
152  Pbase b, high = NULL;
153 
154  // for each inner first indexes, the first constraint with a null coeff
155  // while the other one is not is the simplest
156  for (i=1, b=context->rbase; !BASE_NULLE_P(b); i++, b=b->succ)
157  {
158  val_1 = vect_coeff(var_of(b), v1);
159  null_1 = value_zero_p(val_1);
160  val_2 = vect_coeff(var_of(b), v2);
161  null_2 = value_zero_p(val_2);
162 
163  // first loop index with something
164  // BUG too early
165  if (irank == 0 && !same_sign_p(val_1, val_2))
166  // BUG: condition is always false?
167  RETURN_ORDER(value_neg_p(val_1) && value_neg_p(val_2) ?
168  value_compare(val_2, val_1):
169  value_compare(val_1 ,val_2));
170 
171  // *one* coef is zero and the other *not*, we can conclude
172  if (null_1 ^ null_2)
173  {
174  if (irank == 0) // ???
175  { RETURN_ORDER(value_compare(null_1, null_2)); }
176  else
177  { RETURN_HARDER(value_compare(null_1, null_2)); }
178  }
179 
180  // keep track of first inner loop with non zero values?
181  if (irank == 0 && (!null_1 || !null_2))
182  val=val_1, val_p=val_2, irank=i, high=b;
183  }
184 
185  // BUG?
186  // why conclude now on these values, and not on the cost below first?
187  if (value_ne(val_p, val))
188  RETURN_HARDER(value_neg_p(val_1) && value_neg_p(val_2) ?
189  value_compare(val_2, val_1):
190  value_compare(val_1, val_2));
191 
192  // constant operations
193  cost_1 = cost_of_constant_operations(v1, context);
194  cost_2 = cost_of_constant_operations(v2, context);
195 
196  if (cost_1 != cost_2) RETURN_HARDER(cost_2-cost_1);
197 
198  // the depth & cost are equal, we need another criterion base on values
199  // compare the coefficients for the base, starting from the first after
200  // the first non null.
201  for (b=high==NULL ? NULL : high->succ; !BASE_NULLE_P(b); b=b->succ)
202  {
203  val_1 = vect_coeff(var_of(b), v1);
204  val_2 = vect_coeff(var_of(b), v2);
205 
206  if (value_ne(val_1, val_2))
207  RETURN_HARDER(value_neg_p(val_1) && value_neg_p(val_2)?
208  value_compare(val_1, val_2):
209  value_compare(val_2, val_1));
210  }
211 
212  // all equals, do it for the for the parameters
213  for (b=context->others; !BASE_NULLE_P(b); b=b->succ)
214  {
215  val_1 = vect_coeff(var_of(b), v1);
216  val_2 = vect_coeff(var_of(b), v2);
217 
218  if (value_ne(val_1, val_2))
219  RETURN_HARDER(value_compare(val_2,val_1));
220  }
221 
222  // at last the constant
223  val_1 = vect_coeff(TCST, v1);
224  val_2 = vect_coeff(TCST, v2);
225 
226  // the sign is needed so that equalities are normalized...
227  // here we have val==val_p
229  value_compare(val_2, val_1):
230  value_compare(val_1, val_2));
231 }
232 
233 /*
234 static int compare_the_constraints_debug(Pcontrainte *pc1, Pcontrainte *pc2)
235 {
236  int b1, b2;
237  b1 = compare_the_constraints(pc1, pc2),
238  b2 = compare_the_constraints(pc2, pc1);
239  assert((b1+b2)==0);
240  return b1;
241 }
242 */
243 
244 /* returns the highest rank pvector of v in b, of rank *prank
245  */
247 {
248  Pbase pb;
249  Pvecteur pv, result=(Pvecteur) NULL;
250  Variable var;
251  int rank;
252 
253  for (*prank=-1, rank=1, pb=b;
254  !BASE_NULLE_P(pb);
255  pb=pb->succ, rank++)
256  {
257  var = var_of(pb);
258 
259  for (pv=v; pv!=NULL; pv=pv->succ)
260  if (var_of(pv)==var)
261  {
262  result=pv;
263  *prank=rank;
264  continue;
265  }
266  }
267 
268  return result;
269 }
270 
271 /* sorts the constraints according to the compare function,
272  * and set the number of constraints for each index of the sort base
273  */
274 
276  Pcontrainte c,
277  Pbase sort_base,
278  constraint_cmp_func_t compare,
279  void * context,
280  two_int_infop info)
281 {
282  Pcontrainte pc, *tc;
283  Pvecteur phrank;
284  int i, rank,
285  nb_of_sort_vars = vect_size(sort_base),
286  nb_of_constraints = nb_elems_list(c);
287 
288  if (nb_of_constraints<=1) return c;
289 
290  tc = (Pcontrainte*) malloc(sizeof(Pcontrainte)*nb_of_constraints);
291 
292  for (i=0; i<=nb_of_sort_vars; i++)
293  info[i][0]=0, info[i][1]=0;
294 
295  /* the constraints are put in the table
296  * and info is set.
297  */
298  for (i=0, pc=c; pc!=NULL; i++, pc=pc->succ)
299  {
300  tc[i] = pc;
301  if (!BASE_NULLE_P(sort_base))
302  {
303  phrank = highest_rank_pvector(pc->vecteur, sort_base, &rank);
304  info[rank==-1?0:rank][rank==-1?0:value_pos_p(val_of(phrank))]++;
305  }
306  }
307 
308  qsort_r(tc, nb_of_constraints, sizeof(Pcontrainte),
309  (int(*)(const void *,const void *, void *)) compare,
310  (void *) context);
311 
312  /* the list of constraints is generated again
313  */
314  for (i=0; i<nb_of_constraints-1; i++)
315  {
316  tc[i]->succ = tc[i+1];
317  }
318  tc[nb_of_constraints-1]->succ=NULL;
319  c = tc[0];
320 
321  /* clean!
322  */
323  free(tc);
324  return c;
325 }
326 
328  Pcontrainte c,
329  Pbase sort_base,
330  constraint_cmp_func_t compare,
331  void * context)
332 {
333  int n = vect_size(sort_base)+1;
334  two_int_infop info;
335 
336  info = (two_int_infop) malloc(sizeof(two_int_info)*n);
337 
338  c = constraints_sort_info(c, sort_base, compare, context, info);
339 
340  free(info);
341  return c;
342 }
343 
345  Pcontrainte c,
346  Pbase base,
347  Pbase sort_base,
348  bool inner_first,
349  bool complex_first)
350 {
352  set_sort_context(&context, base, sort_base, inner_first, complex_first);
354  (c, sort_base, (constraint_cmp_func_t) compare_the_constraints, &context);
356  return c;
357 }
358 
360 {
361  // equalities???
362  ps->inegalites =
363  contrainte_sort(ps->inegalites, ps->base, base_index, true, true);
364  return ps;
365 }
366 
367 /* sort contrainte c, base b,
368  * relatively to sort_base, as defined by the switches.
369  *
370  * inner_first: innermost first
371  * complex_first: the more complex the likely to be put earlier
372  */
373 
374 /* Psysteme sc_triang_elim_redond(Psysteme ps, Pbase base_index):
375  * elimination des contraintes lineaires redondantes dans le systeme ps
376  * par test de faisabilite de contrainte inversee; cette fonction est
377  * utilisee pour calculer des bornes de boucles, c'est pourquoi il peut
378  * etre necessaire de garder des contraintes redondantes afin d'avoit
379  * toujours au moins une borne inferieure et une borne superieure
380  * pour chaque indice.
381  *
382  * resultat retourne par la fonction :
383  *
384  * Psysteme : Le systeme initial est modifie. Il est egal a NULL si
385  * le systeme initial est non faisable.
386  *
387  * Les parametres de la fonction :
388  *
389  * Psysteme ps : systeme lineaire
390  *
391  * Attention: pour chaque indice dans base_index, il doit rester au moins deux
392  * contraintes correspondantes (une positive et une negative).
393  * C'est la seule difference avec la fonction sc_elim_redond().
394  *
395  * contrainte_reverse() is used. Rational points may be added
396  * by this procedure.
397  *
398  * Yi-Qing YANG
399  *
400  * Modifications:
401  * - add a normalization step for inequalities; if they are not normalized,
402  * i.e. if the GCD of the variable coefficients is not 1, the constant
403  * term of the inverted constraint should be carefully updated using
404  * the GCD?!? (Francois Irigoin, 30 October 1991)
405  * - the variables are sorted in order to get a deterministic result
406  * (FC 26 Sept 94)
407  * - the feasible overflow function is called, and only if the constraint
408  * is not the last one (performance bug of the previous version)
409  * (FC 27 Sept 94)
410  * - a warning is displayed if many inequalities are to be dealt with,
411  * instead of returning the system as is.
412  * (FC 28 Sept 94)
413  * - sc_normalize inserted, in place of many loop that were
414  * doing nearly the same. (FC 29/09/94)
415  */
416 /* extern char *entity_local_name(); */
417 
419 {
420  Pcontrainte ineq, ineq1;
421  int level, n = vect_size(base_index)+1;
422  two_int_infop info;
424 
425  ps = sc_normalize(ps);
426 
427  if (ps==NULL)
428  return NULL;
429 
430  if (ps->nb_ineq > NB_INEQ_MAX1)
431  fprintf(stderr,
432  "[sc_triang_elim_redund] warning, %d inequalities\n",
433  ps->nb_ineq);
434 
436  {
437  sc_rm(ps), ps=NULL;
438  return NULL;
439  }
440 
441  info = malloc(sizeof(int)*2*n);
442 
443  set_sort_context(&context, ps->base, base_index, true, true);
444  ps->inegalites =
445  constraints_sort_info(ps->inegalites, base_index,
446  (constraint_cmp_func_t) compare_the_constraints,
447  &context, info);
449 
450  for (ineq = ps->inegalites; ineq != NULL; ineq = ineq1)
451  {
452  ineq1 = ineq->succ;
453  level = level_contrainte(ineq, base_index);
454 
455  /* only the variables that have more than one
456  * constraints on a given size and that deal with
457  * the variables of base_index are tested.
458  *
459  * an old comment suggested that keeping contraints on variables
460  * out of base_index would help find redundancy on the base_index
461  * contraints, but this should not be true anymore, since the
462  * variables are sorted... just help to deal with larger systems...
463  *
464  * FC 28/09/94
465  */
466  if (level!=0 && info[abs(level)][level<0?0:1]>1)
467  {
468  /* inversion du sens de l'inegalite par multiplication
469  * par -1 du coefficient de chaque variable
470  */
471  contrainte_reverse(ineq);
472 
473  /* test de sc_faisabilite avec la nouvelle inegalite
474  */
476  /* restore the initial constraint */
477  contrainte_reverse(ineq);
478  else
479  {
480  eq_set_vect_nul(ineq);
481  info[abs(level)][level<0?0:1]--;
482  }
483  }
484  }
486  ps = sc_kill_db_eg(ps);
487 
488  free(info);
489  return ps;
490 }
491 
492 /* void move_n_first_constraints(source, target, n)
493  * Pcontrainte *source, *target;
494  * int n;
495  *
496  * moves the n first constraints from source to target, in order.
497  */
498 void move_n_first_constraints(Pcontrainte *source, Pcontrainte *target, int n)
499 {
500  Pcontrainte tmp, nth;
501 
502  if (n==0) return; /* nothing to be done */
503 
504  /* nth points to the nth constraint.
505  */
506  for (nth=*source; n>1; n--, nth=nth->succ);
507 
508  tmp = *target, *target = *source, *source = nth->succ, nth->succ = tmp;
509 }
510 
511 /* void sc_triang_elim_redund_n_first(s, n)
512  * Psysteme s;
513  * int n;
514  *
515  * tries a triangular redundancy elimination on the n first constraints,
516  * which *must all* deal with the same side of the same index.
517  * if n is 0, nothing is done, but nothing is reported.
518  *
519  * contrainte_reverse() is used and rational points may be added
520  */
522 {
523  int tested, removed;
524  Pcontrainte ineq;
525 
526  if (n<=1) return; /* nothing to be done */
527 
528  for (ineq=sc_inegalites(s), tested=0, removed=0;
529  removed<n-1 && tested<n;
530  tested++, ineq=ineq->succ)
531  {
532  contrainte_reverse(ineq);
533 
535  contrainte_reverse(ineq); /* restore */
536  else
537  eq_set_vect_nul(ineq), removed++; /* remove */
538  }
539 }
540 
542  Psysteme s,
543  Pbase indexes) /* outer to inner */
544 {
545  Pcontrainte old;
546  int level, side, n_other_constraints, n = vect_size(indexes)+1;
547  two_int_infop info;
549 
550  s = sc_normalize(s);
551  if (s==NULL || sc_nbre_inegalites(s)==0) return s;
552 
553  info = (two_int_infop) malloc(sizeof(int)*2*n);
554 
555  /* sort outer first and complex first
556  */
557  set_sort_context(&context, s->base, indexes, false, true);
558  s->inegalites =
559  constraints_sort_info(s->inegalites, indexes,
560  (constraint_cmp_func_t) compare_the_constraints,
561  &context, info);
563 
564  /* remove the redundancy on others
565  * then triangular clean of what remains.
566  */
567 
568  n_other_constraints = info[0][0]+info[0][1];
569  old = sc_inegalites(s), sc_inegalites(s) = NULL, sc_nbre_inegalites(s) = 0;
570 
571  move_n_first_constraints(&old, &s->inegalites, n_other_constraints);
572  sc_nbre_inegalites(s) = n_other_constraints;
573  s = sc_elim_redund(s);
574 
575  /* what if s is empty or null ???
576  */
577 
578  /* build the non redundant triangular system for each level and side.
579  */
580  for (level=1; level<n; level++)
581  {
582  for (side=0; side<=1; side++)
583  if (info[level][side])
584  {
585  move_n_first_constraints(&old, &sc_inegalites(s), info[level][side]);
586  sc_nbre_inegalites(s)+=info[level][side];
588  }
589  }
590 
591  assert(old==NULL);
592 
593  /* clean!
594  */
596  s = sc_kill_db_eg(s);
597  free(info);
598 
599  return s;
600 }
601 
603 {
604  ps->inegalites =
605  contrainte_sort(ps->inegalites, ps->base, base_index, false, false);
606  return ps;
607 }
608 
609 /* That is all
610  */
#define value_pos_p(val)
#define VALUE_ZERO
#define value_notzero_p(val)
#define value_one_p(val)
#define value_ne(v1, v2)
#define value_zero_p(val)
#define value_compare(v1, v2)
int Value
#define value_abs(val)
#define value_neg_p(val)
Pbase base_difference(Pbase b1, Pbase b2)
Pbase base_difference(Pbase b1, Pbase b2): allocate b; b = b1 - b2 – with the set meaning return b;.
Definition: base.c:621
Pbase base_normalize(Pbase b)
Definition: base.c:594
Pbase base_reversal(Pbase b_in)
Pbase base_reversal(Pbase b_in): produces a basis b_out, having the same basis vectors as b_in,...
Definition: base.c:221
bdt base
Current expression.
Definition: bdt_read_paf.c:100
void eq_set_vect_nul(Pcontrainte)
void_eq_set_vect_nul(Pcontrainte c): transformation d'une contrainte en une contrainte triviale 0 == ...
Definition: unaires.c:84
int nb_elems_list(Pcontrainte)
int nb_elems_list(Pcontrainte list): nombre de contraintes se trouvant dans une liste de contraintes
Definition: listes.c:129
int level_contrainte(Pcontrainte, Pbase)
int level_contrainte(Pcontrainte pc, Pbase base_index) compute the level (rank) of the constraint pc ...
Definition: unaires.c:292
void contrainte_reverse(Pcontrainte)
void contrainte_reverse(Pcontrainte eq): changement de signe d'une contrainte, i.e.
Definition: unaires.c:67
void * malloc(YYSIZE_T)
void free(void *)
int vect_size(Pvecteur v)
package vecteur - reductions
Definition: reductions.c:47
static entity rank
#define assert(ex)
Definition: newgen_assert.h:41
char * info(char *about)
Definition: pypips.c:278
static int tc
Internal variables
Definition: reindexing.c:107
void sc_rm(Psysteme ps)
void sc_rm(Psysteme ps): liberation de l'espace memoire occupe par le systeme de contraintes ps;
Definition: sc_alloc.c:277
Psysteme sc_kill_db_eg(Psysteme ps)
Psysteme sc_kill_db_eg(Psysteme ps): elimination des egalites et des inegalites identiques ou inutile...
Definition: sc_elim_eq.c:133
Psysteme sc_elim_redund(Psysteme ps)
Psysteme sc_elim_redund(Psysteme ps): elimination des contraintes lineaires redondantes dans le syste...
void sc_elim_empty_constraints(Psysteme ps, bool process_equalities)
void sc_elim_empty_constraints(Psysteme ps, bool process_equalities): elimination des "fausses" contr...
#define level
bool sc_integer_feasibility_ofl_ctrl(Psysteme sc, int ofl_ctrl, bool ofl_res)
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
Psysteme sc_normalize(Psysteme ps)
Psysteme sc_normalize(Psysteme ps): normalisation d'un systeme d'equation et d'inequations lineaires ...
Psysteme sc_sort_constraints(Psysteme ps, Pbase base_index)
static void set_sort_context(sort_ctx_t *context, Pbase base, Pbase sort_base, bool inner_first, bool complex_first)
void sc_triang_elim_redund_n_first(Psysteme s, int n)
void sc_triang_elim_redund_n_first(s, n) Psysteme s; int n;
Pvecteur highest_rank_pvector(Pvecteur v, Pbase b, int *prank)
returns the highest rank pvector of v in b, of rank *prank
#define same_sign_p(v, w)
#define RETURN_HARDER(b)
Pcontrainte contrainte_sort(Pcontrainte c, Pbase base, Pbase sort_base, bool inner_first, bool complex_first)
Psysteme sc_build_triang_elim_redund(Psysteme s, Pbase indexes)
outer to inner
#define RETURN_ORDER(b)
static int compare_the_constraints(const Pcontrainte *pc1, const Pcontrainte *pc2, sort_ctx_t *context)
compare two constraints with a loop complexity cost in mind? not exactly, some of the choices attempt...
Pcontrainte constraints_sort_with_compare(Pcontrainte c, Pbase sort_base, constraint_cmp_func_t compare, void *context)
static int cost_of_constant_operations(Pvecteur v, sort_ctx_t *context)
Psysteme sc_sort_constraints_simplest_first(Psysteme ps, Pbase base_index)
static void clear_sort_context(sort_ctx_t *context)
#define AFF_COST
#define MUL_COST
Psysteme sc_triang_elim_redund(Psysteme ps, Pbase base_index)
sort contrainte c, base b, relatively to sort_base, as defined by the switches.
static Pcontrainte constraints_sort_info(Pcontrainte c, Pbase sort_base, constraint_cmp_func_t compare, void *context, two_int_infop info)
sorts the constraints according to the compare function, and set the number of constraints for each i...
#define ADD_COST
void move_n_first_constraints(Pcontrainte *source, Pcontrainte *target, int n)
void move_n_first_constraints(source, target, n) Pcontrainte *source, *target; int n;
Pvecteur vecteur
struct Scontrainte * succ
Pcontrainte inegalites
Definition: sc-local.h:71
Pbase base
Definition: sc-local.h:75
int nb_ineq
Definition: sc-local.h:73
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
Definition: delay.c:253
#define abs(v)
Definition: syntax-local.h:48
#define TCST
VARIABLE REPRESENTANT LE TERME CONSTANT.
#define val_of(varval)
struct Svecteur * Pvecteur
#define base_rm(b)
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 BASE_NULLE
MACROS SUR LES BASES.
#define OFL_CTRL
I do thing that overflows are managed in a very poor manner.
#define BASE_NULLE_P(b)
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