PIPS
transformer.c
Go to the documentation of this file.
1 /*
2 
3  $Id: transformer.c 23412 2017-08-09 15:07:09Z irigoin $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of PIPS.
8 
9  PIPS is free software: you can redistribute it and/or modify it
10  under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  any later version.
13 
14  PIPS 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 General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
22 
23 */
24 #ifdef HAVE_CONFIG_H
25  #include "pips_config.h"
26 #endif
27  /* Predicate transformer package: sc complexity level
28  */
29 
30 #include <stdio.h>
31 
32 /* #include "boolean.h" */
33 /* #include "vecteur.h" */
34 /* #include "contrainte.h" */
35 /* #include "sc.h" */
36 /* #include "matrix.h" */
37 #include "linear.h"
38 #include "matrice.h" // for space_sc.h
39 #include "sparse_sc.h" // for constraints_to_matrices()
40 
41 #include "genC.h"
42 #include "linear.h"
43 #include "ri.h"
44 #include "ri-util.h"
45 #include "effects-util.h"
46 #include "prettyprint.h"
47 
48 #include "misc.h"
49 
50 #include "transformer.h"
51 
53 {
54  return sc;
55 }
56 
57 /* e and f are assumed to be values, Type independent. */
59 {
61 
62  return tf;
63 }
64 
66 {
67  transformer tf = generic_equality_to_transformer(e, f, false, true);
68 
69  return tf;
70 }
71 
73  entity f,
74  bool assignment,
75  bool unary_minus_p)
76 {
79  cons * tf_args = NIL;
80  Pcontrainte c;
81 
82  ifdebug(9) {
83  pips_debug(9, "entity e: %s, entity f: %s, %s\n",
85  assignment? "Is an assignment" : "Is not an assignment");
86  }
87 
88  if(assignment)
89  tf_args = CONS(ENTITY, e, NIL);
90 
91  vect_add_elem(&eq, (Variable) f, unary_minus_p? VALUE_ONE : VALUE_MONE);
92  c = contrainte_make(eq);
93  tf = make_transformer(tf_args,
95 
96  ifdebug(9) {
97  pips_debug(9, "end with tf=%p\n", tf);
98  dump_transformer(tf);
99  }
100 
101  return tf;
102 }
103 
104 /* e and e1 and e2 are assumed to be values. State e=e1+e2 or
105  e=e1-e2. Type independent. */
107  entity e1,
108  entity e2,
109  bool addition_p)
110 {
113  Pcontrainte c;
114 
115  ifdebug(9) {
116  pips_debug(9, "entity e: %s, entity e1: %s, entity e2: %s, %s\n",
118  entity_local_name(e1),
119  entity_local_name(e2),
120  addition_p? "Is an addition" : "Is a subtraction");
121  }
122 
124  vect_add_elem(&eq, (Variable) e2, addition_p? VALUE_MONE : VALUE_ONE);
125  c = contrainte_make(eq);
126  tf = make_transformer(NIL,
128 
129  ifdebug(9) {
130  pips_debug(9, "end with tf=%p\n", tf);
131  dump_transformer(tf);
132  }
133 
134  return tf;
135 }
136 
137 /* e and f are assumed to be values. Operator op is overloaded and the
138  result is operator and type dependent */
140  bool veracity)
141 {
146  Pvecteur ineq = VECTEUR_NUL;
149 
150  ifdebug(9) {
151  pips_debug(9, "Begin for entity e1: %s of basic %s, "
152  "entity e2: %s of basic %s and operator %s\n",
155  module_local_name(op));
156  }
157 
158  /* Beware of type coercion... Fabien conjectures that values with
159  incompatible types won't get mixed up... */
160 
161  if((ENTITY_EQUAL_P(op) && veracity)
162  || (ENTITY_NON_EQUAL_P(op) && !veracity)) {
163  /* type independent */
164  eq = vect_new((Variable) e1, VALUE_ONE);
166  }
167  else if((ENTITY_NON_EQUAL_P(op) && veracity)
168  || (ENTITY_EQUAL_P(op) && !veracity)) {
169  /* Non convex information */
170  ;
171  }
172  else if((ENTITY_LESS_OR_EQUAL_P(op) && veracity)
173  || (ENTITY_GREATER_THAN_P(op) && !veracity)) {
174  ineq = vect_new((Variable) e1, VALUE_ONE);
175  vect_add_elem(&ineq, (Variable) e2, VALUE_MONE);
176  }
177  else if((ENTITY_LESS_THAN_P(op) && veracity)
178  ||(ENTITY_GREATER_OR_EQUAL_P(op) && !veracity)) {
179  ineq = vect_new((Variable) e1, VALUE_ONE);
180  vect_add_elem(&ineq, (Variable) e2, VALUE_MONE);
181  // if we want to authorize to compare a pointer with an integer
182  //if((basic_int_p(b1) || basic_logical_p(b1) || basic_pointer_p(b1))
183  // && (basic_int_p(b2) || basic_logical_p(b2) || basic_pointer_p(b2))) {
184  // if we only want to compare a pointer with an another pointer
185  if(((basic_int_p(b1) || basic_logical_p(b1))
186  && (basic_int_p(b2) || basic_logical_p(b2)))
187  || (basic_pointer_p(b1) && basic_pointer_p(b2))) {
188  vect_add_elem(&ineq, TCST, VALUE_ONE);
189  }
190  }
191  else if((ENTITY_GREATER_OR_EQUAL_P(op) && veracity)
192  || (ENTITY_LESS_THAN_P(op) && !veracity)) {
193  ineq = vect_new((Variable) e1, VALUE_MONE);
194  vect_add_elem(&ineq, (Variable) e2, VALUE_ONE);
195  }
196  else if((ENTITY_GREATER_THAN_P(op) && veracity)
197  || (ENTITY_LESS_OR_EQUAL_P(op) && !veracity)) {
198  ineq = vect_new((Variable) e1, VALUE_MONE);
199  vect_add_elem(&ineq, (Variable) e2, VALUE_ONE);
200  // if we want to authorize to compare a pointer with an integer
201  //if((basic_int_p(b1) || basic_logical_p(b1) || basic_pointer_p(b1))
202  // && (basic_int_p(b2) || basic_logical_p(b2) || basic_pointer_p(b2))) {
203  // if we only want to compare a pointer with an another pointer
204  if(((basic_int_p(b1) || basic_logical_p(b1))
205  && (basic_int_p(b2) || basic_logical_p(b2)))
206  || (basic_pointer_p(b1) && basic_pointer_p(b2))) {
207  vect_add_elem(&ineq, TCST, VALUE_ONE);
208  }
209  }
210  else {
211  pips_internal_error("Unexpected relational operator %s", entity_name(op));
212  }
213 
215  cineq = VECTEUR_NUL_P(ineq)? CONTRAINTE_UNDEFINED : contrainte_make(ineq);
216 
217  if(ceq!=CONTRAINTE_UNDEFINED||cineq!=CONTRAINTE_UNDEFINED) {
218  tf = make_transformer(NIL,
219  make_predicate(sc_make(ceq, cineq)));
220  }
221 
222  ifdebug(9) {
223  pips_debug(9, "end with tf=%p\n", tf);
224  dump_transformer(tf);
225  }
226 
227  return tf;
228 }
229 ␌
230 /* transformer transformer_combine(transformer t1, transformer t2):
231  * compute the composition of transformers t1 and t2 (t1 then t2)
232  *
233  * t1 := t2 o t1
234  * return t1
235  *
236  * t1 is updated, but t2 is preserved
237  */
239 {
240  /* general algorithm:
241  let a1 be t1 arguments, a2 be t2 arguments,
242  let ints be the intersection of a1 and a2
243  let r1 be t1 relation and r2 be a copy of t2 relation
244  let a be a1 union a2
245  rename entities in ints in r1 (new->int) and r2 (old->int)
246  rename entities in a2-ints in r1 (new->old)
247  build a system b with r1 and r2
248  project b along ints
249  build t1 with a and b
250  */
251  volatile list a1 = transformer_arguments(t1);
252  list a2 = transformer_arguments(t2);
254 
255  /* Handling of four special cases because abstract effects are
256  likely to generate rn transformers, which lead to lots of
257  variable projections if handled as a usual transformer. Not
258  sufficient to solve Ticket 644. But sufficient to introduce lots
259  of bugs... */
260  if(transformer_is_rn_p(t1) && !ENDP(wvl) && arguments_set_equal_p(a1, wvl)) {
261  if(transformer_is_empty_p(t2)) {
262  free_transformer(t1);
263  t1 = copy_transformer(t2); // t1 is empty
264  }
265  else {
266  /* not much to do since t1 is going to destroy all information
267  in t2, except its range */
269  t1 = transformer_range_intersection(t1, r);
270  free_transformer(r);
271  }
272  }
273  else if(transformer_is_rn_p(t2) && !ENDP(wvl) && arguments_set_equal_p(a2, wvl)) {
274  if(transformer_is_empty_p(t1))
275  //t1 == t1;
276  ;
277  else {
278  /* not much to do since t2 is going to destroy all information
279  in t1, except its domain */
281  free_transformer(t1);
283  free_transformer(d);
284  }
285  }
286  /* Standard case */
287  else {
288  /* Newgen does not generate the proper castings */
289  /* Automatic variables read in a CATCH block need to be declared volatile as
290  * specified by the documentation*/
293  /* ints: list of intermediate value entities */
294  volatile list ints = NIL;
295  list ce2;
296 
297  pips_debug(8,"begin\n");
298 
299  pips_debug(8,"arg. t1=%p\n",t1);
300  ifdebug(8) (void) dump_transformer(t1);
301  /* The consistencies of transformers t1 and t2 cannot be checked with
302  respect to the current environment because t1 or t2 may be relative
303  to a callee as in user_function_call_to_transformer(). Hence a
304  debug level of 10. */
305  ifdebug(10) pips_assert("consistent t1", transformer_consistency_p(t1));
306 
307  pips_debug(8,"arg. t2=%p\n",t2);
308  ifdebug(8) (void) dump_transformer(t2);
309  ifdebug(10) pips_assert("consistent t2", transformer_consistency_p(t2));
310 
311  if(!sc_empty_p(r1)) {
312 
313  if(sc_empty_p(r2)) {
314  empty_transformer(t1);
315  }
316  else { /* both t1 and t2 are not obviously unfeasible */
317 
318  /* build new argument list and rename old and intermediate values,
319  as well as new (i.e. unmodified) variables in t1 */
320 
321  for(ce2 = a2; !ENDP(ce2); POP(ce2)) {
322  entity e2 = ENTITY(CAR(ce2));
323  if(entity_is_argument_p(e2, a1)) {
324  /* renaming of intermediate values in r1 and r2 */
326  entity e_old = entity_to_old_value(e2);
327  r1 = sc_variable_rename(r1, (Variable) e2, (Variable) e_int);
328  r2 = sc_variable_rename(r2, (Variable) e_old, (Variable) e_int);
329  ints = arguments_add_entity(ints, e_int);
330  }
331  else {
332  /* if ever e2 is used as e2#new in r1 it must now be
333  replaced by e2#old */
334  if(base_contains_variable_p(r1->base, (Variable) e2)) {
335  entity e_old = entity_to_old_value(e2);
336  r1 = sc_variable_rename(r1, (Variable) e2, (Variable) e_old);
337  }
338  /* e2 must be appended to a1 as new t1's arguments;
339  hopefully we are not iterating on a1; but
340  entity_is_argument_p() receives a longer argument each time;
341  possible improvements? */
342  a1 = gen_nconc(a1, CONS(ENTITY, e2, NIL));
343  }
344  }
345 
346  /* build global linear system: r1 is destroyed, r2 is preserved
347  */
348  r1 = sc_append(r1, r2);
349 
350  /* ??? The base returned may be empty... FC...
351  * boumbadaboum in the projection later on.
352  */
353  sc_rm(r2);
354  r2 = SC_UNDEFINED;
355  ifdebug(9) {
356  pips_debug(9, "global linear system r1 before projection\n");
357  sc_fprint(stderr, r1, (char * (*)(Variable)) dump_value_name);
358  sc_dump(r1);
359  }
360 
361  /* get rid of intermediate values, if any.
362  * ??? guard added to avoid an obscure bug, but I guess it should
363  * never get here with en nil base... FC
364  */
365  if (sc_base(r1)) {
366  VOLATILE_FOREACH(ENTITY, e_temp, ints)
367  {
368  if (sc_expensive_projection_p(r1,(Variable) e_temp)) {
369  ifdebug(9) {
370  pips_debug(9, "expensive projection on %s with\n",
371  entity_local_name(e_temp));
372  sc_fprint(stderr, r1, (char * (*)(Variable)) entity_local_name);
373  }
374  sc_elim_var(r1,(Variable) e_temp);
375  sc_base_remove_variable(r1,(Variable) e_temp);
376  ifdebug(9) {
377  pips_debug(9, "simplified tranformer\n");
378  sc_fprint(stderr, r1,(char * (*)(Variable)) entity_local_name);
379  }
380  }
381  else {
383  {
384  /* CA */
385  /*PIER: problem with e_temp that should be volatile because of
386  * the catch structure. Not easy make it volatile because of
387  * the MAP MACRO */
388  pips_user_warning("overflow error in projection of %s, "
389  "variable eliminated\n",
390  entity_name(e_temp));
391  r1 = sc_elim_var(r1, (Variable) e_temp);
392  }
393  TRY
394  {
395  sc_and_base_projection_along_variable_ofl_ctrl
396  (&r1, (Variable) e_temp, NO_OFL_CTRL);
398  }
399 
400  if (! sc_empty_p(r1)) {
401  r1 = sc_normalize2(r1);
402  if(SC_EMPTY_P(r1)) {
403  r1 = sc_empty(BASE_NULLE);
404  break;
405  }
406  }
407  }
408  }
409  }
410 
411  ifdebug(9) {
412  pips_debug(9, "global linear system r1 after projection\n");
413  sc_fprint(stderr, r1, (char * (*)(Variable)) dump_value_name);
414  sc_dump(r1);
415  }
416 
417  /* get rid of ints */
418  gen_free_list(ints);
419  ints = NIL;
420 
421  /* update t1 */
422  if(sc_empty_p(r1)) {
423  /* No old values should be left in r1's basis. */
424  MAP(ENTITY, v, {
425  entity oldv = entity_to_old_value(v);
426  if(base_contains_variable_p(sc_base(r1), (Variable) oldv))
427  sc_base_remove_variable(r1, (Variable) oldv);
428  }, a1);
429  free_arguments(a1);
431  }
432  else {
433  transformer_arguments(t1) = a1;
434  }
436  }
437  }
438  }
439 
440  pips_debug(8,"res. t1=%p\n",t1);
441  ifdebug(8) dump_transformer(t1);
442  pips_debug(8,"end\n");
443 
444  return t1;
445 }
446 
447 /* Combine each transformer of transformer list tl1 with
448  * t2. Side-effect on tl1 or new list etl. See comments for
449  * transformer_combine()
450  *
451  * FI: I'm not too sure about the best way to remove the resulting
452  * empty transformers. gen_remove() on tl1 or creation of new list...
453  */
455 {
456  list ntl = NIL;
457 
458  FOREACH(TRANSFORMER, t1, tl1) {
459  t1 = transformer_combine(t1, t2);
460  if(!transformer_empty_p(t1))
461  ntl = gen_nconc(ntl, CONS(TRANSFORMER, t1, NIL));
462  }
463 
464  gen_free_list(tl1);
465  return ntl;
466 }
467 
468 /* Combine each transformer of transformer list tl1 with the
469  * corresponding transformer in transformer list tl2.
470  *
471  * Side-effect on tl1. See comments for transformer_combine().
472  *
473  * See combine_transformer_lists() to combine each element of t1 with
474  * each element of t2.
475  */
477 {
478  list ntl2 = tl2;
479  pips_assert("The two lists have the same number of elements",
480  gen_length(tl1)==gen_length(tl2));
481  FOREACH(TRANSFORMER, t1, tl1) {
482  transformer t2 = TRANSFORMER(CAR(ntl2));
483  t1 = transformer_combine(t1, t2);
484  POP(ntl2);
485  }
486  return tl1;
487 }
488 
489 /* Transformer tf1 and tf2 are supposed to be independent but they may
490  interfere, for instance because subexpressions have non-standard
491  conformant side effects. tf12 is a newly allocated transformer with no
492  sharing with tf1 or tf2 (theoretically). */
494 {
496 
497  /* Intersection is not powerful enough to cope with side effects. But
498  side effects can be dealt with only if the operation order is known
499  when the standard is violated. We assume here a right to left evaluation. */
501  pips_debug(9, "Side effects of tf2 on tf1\n");
502  pips_user_warning("Non standard compliant code: side effect in part\n"
503  "of an expression affects variable(s) used in a later part\n");
504  tf12 = transformer_combine(tf1, tf2);
505  }
506  else if (transformer_safe_affect_transformer_p(tf2, tf1)){
507  pips_debug(9, "Side effects of tf2 on tf1\n");
508  pips_user_warning("Non standard compliant code: side effect in part\n"
509  "of an expression affect variables used in an earlier part\n");
510  tf12 = transformer_combine(tf1, tf2);
511  }
512  else {
513  pips_debug(9, "No adversary side effects\n");
517  /* No side effects at all */
518  pips_debug(9, "No side effects at all\n");
519  tf12 = transformer_safe_intersection(tf1, tf2);
520  free_transformer(tf1);
521  }
522  else {
523  pips_debug(9, "Side effects on other variables\n");
524  tf12 = transformer_combine(tf1, tf2);
525  }
526  }
527  return tf12;
528 }
529 ␌
530 /* Allocate a new transformer with constraints in t1 and t2.
531  *
532  * If t2 has no arguments, it restrains the domain of t1. This
533  * is necessary if image_only is true.
534  *
535  * If not, the two transformers are supposed to be two separate
536  * abstraction of the same transformation and an intersection
537  * of the relation graphs is performed.
538  */
540  transformer t2,
541  bool image_only)
542 {
544 
545  pips_debug(9, "Begins with t1 = %p and t2 = %p, image_only=%s\n",
546  t1, t2, bool_to_string(image_only));
547 
548 
550  t = transformer_empty();
551  }
552  else {
554  /* no need to duplicate s2, it is done in sc_append.
555  Psysteme s2 = sc_dup((Psysteme) predicate_system(transformer_relation(t2))); */
557 
558  t = transformer_identity();
559  /*
560  pips_debug(9, "begin with s1 and s2:\n");
561  sc_dump(s1);
562  sc_dump(s2);
563  */
564 
565  s1 = sc_append(s1, s2);
566 
567  /*
568  pips_debug(9, "new s1:\n");
569  sc_dump(s1);
570  */
571 
573 
574  if(image_only) {
575  /* Do not restrict the transition but the image of the relation t1
576  with constraints in t2. */
577  if(!ENDP(transformer_arguments(t2))) {
578  dump_transformer(t2);
579  pips_assert("Transformer t2 has no arguments", ENDP(transformer_arguments(t2)));
580  }
582  }
583  else {
584  /* intersect transition t1 and transition t2 */
587  }
588  }
589 
590  pips_debug(9, "Exit with t=%p, for t1 = %p and t2 = %p\n", t, t1, t2);
591 
592  return t;
593 }
594 
595 /* tf is a new transformer that receives the constraints in t1 and
596  t2. For implicit equalities carried by args, this implies that the
597  args for tf is the intersection of the args. And that the resulting
598  transformer may be empty: for instance, a variable may be untouched
599  in t1 and incremented in t2, which is impossible. */
601 {
603  return t;
604 }
605 
606 /* allocate a new transformer based on transformer t1 and
607  postcondition t2 */
609 {
611 
612  pips_debug(9, "begins with t1 = %p and t2 = %p\n", t1, t2);
613 
614  t = transformer_general_intersection(t1, t2, true);
615 
616  pips_debug(9, "ends with t = %p, t1 = %p and t2 = %p\n", t, t1, t2);
617 
618  return t;
619 }
620 
621 /* Allocate a new transformer */
623  transformer t2,
624  bool image_only)
625 {
627 
629  tf = copy_transformer(t2);
630  else if(transformer_undefined_p(t2))
631  tf = copy_transformer(t1);
632  else
633  tf = transformer_general_intersection(t1, t2, image_only);
634 
635  return tf;
636 }
637 
638 /* Allocate a new transformer */
640 {
642 
643  return tf;
644 }
645 
646 /* Allocate a new transformer */
648 {
650 
651  return tf;
652 }
653 ␌
654 /* Restrict the domain of the relation tf with pre. pre is assumed to be
655  restricted to a store predicate: its argument list must be empty.
656 
657  For a restriction on the image of tf, see transformer_image_intersection
658 
659  tf is updated by side effect although transformer_image_intersection()
660 allocates a fresh new transformer. */
662  transformer pre)
663 {
664  transformer dom = transformer_dup(pre);
666 
667  pips_assert("pre does not involve old values and has no arguments",
669 
670  pips_debug(9, "Begin with tf=%p and pre=%p\n", tf, pre);
671 
672  /* if a value in pre is modified by tf, it must be renamed as an old
673  value */
674  MAP(ENTITY, a, {
675  entity na = entity_to_new_value(a);
676  entity oa = entity_to_old_value(a);
678  pre_sc = sc_variable_rename(pre_sc, (Variable) na, (Variable) oa);
679  }, transformer_arguments(tf));
680 
681  /* transformer dom is not consistent since it references old values but
682  has no arguments */
683 
684  tf_inter = transformer_image_intersection(tf, dom);
685  tf = move_transformer(tf, tf_inter);
686  free_transformer(dom);
687 
688  return tf;
689 }
690 
691 /* If tf and pre are defined, update tf.
692  * If tf is defined and pre is undefined, return tf unchanged.
693  * If tf and pre are undefined, return tf unchanged.
694  * If tf is undefined and pre is defined, we could exploit pre or return undefined.
695  *.*/
697  transformer pre)
698 {
699  if(!transformer_undefined_p(pre)) {
700  if(transformer_undefined_p(tf)) {
702  }
703  else {
704  tf = transformer_domain_intersection(tf, pre);
705  }
706  }
707 
708  return tf;
709 }
710 ␌
711 /* Return the range of relation tf in a newly allocated transformer.
712  * Projection of all old values.
713  */
715 {
716  transformer rtf = transformer_dup(tf);
717  list args = NIL;
719  Pbase b = sc_base(sc);
720 
722  entity ov = entity_to_old_value(a);
723 
724  /* A variable may be modified but its old value does not have to
725  appear in the basis. Although the opposite is wrong. */
726  if(base_contains_variable_p(b, (Variable) ov)) {
727  args = CONS(ENTITY, ov, args);
728  }
729  }
730 
731  /* rtf = transformer_projection(rtf, args); */
733  sc_identity);
734 
735  gen_free_list(args);
736 
738  transformer_arguments(rtf) = NIL;
739 
740  return rtf;
741 }
742 
744 {
746 
747  if(!transformer_undefined_p(tf)) {
748  rtf = transformer_range(tf);
749  }
750  return rtf;
751 }
752 
753 /* Substitute each transformer in list tfl by its range */
755 {
756  // The substitution in the list cannot be performed by a FOREACH
757  MAPL(ctf, {
758  transformer tf = TRANSFORMER(CAR(ctf));
759  transformer tfr = transformer_range(tf);
760  free_transformer(tf);
761  TRANSFORMER_(CAR(ctf)) = tfr;
762  }, tfl);
763  return tfl;
764 }
765 ␌
766 /* Return the domain of relation tf in a newly allocated transformer.
767  * Projection of all new values of modified variables. Renaming of old
768  * values as new values. The transformer returned is a predicate on the
769  * input state (i.e. not really a transformer).
770  *
771  */
773 {
774  transformer dtf = transformer_dup(tf);
775  list new_args = NIL;
777  Pbase b = sc_base(sc);
778 
780  entity nv = entity_to_new_value(a);
781 
782  if(base_contains_variable_p(b, (Variable) nv)) {
783  new_args = CONS(ENTITY, nv, new_args);
784  }
785  }
786 
787  /* dtf = transformer_projection(dtf, args); */
788  /* dtf = transformer_projection_with_redundancy_elimination(dtf, new_args,
789  sc_identity); */
790  /* The resulting transformer is going to be inconsistent because old
791  values appear although the argument list is empty. */
792  dtf = transformer_projection_without_check(dtf, new_args,
793  sc_identity);
794 
795  /* Careful, sc and b have been updated by the projections */
797  b = sc_base(sc);
798 
799  FOREACH(ENTITY, a, new_args) {
800  entity ov = entity_to_old_value(a);
801  entity nv = entity_to_new_value(a);
802 
803  /* A variable may be modified but its old value does not have to
804  appear in the basis. Although the opposite is wrong. */
805  if(base_contains_variable_p(b, (Variable) ov)) {
806  dtf = transformer_value_substitute(dtf, ov, nv);
807  }
808  }
809 
810  gen_free_list(new_args);
811 
812  return dtf;
813 }
814 
816 {
818 
819  if(!transformer_undefined_p(tf)) {
820  dtf = transformer_to_domain(tf);
821  }
822  return dtf;
823 }
824 ␌
825 /* Allocate a new transformer rtf that is tf with its range restricted
826  * by the range r.
827  *
828  * As a range, r is assumed to have no arguments.
829  */
831 {
832  pips_assert("r does not involve old values and has no arguments",
835 
836  return rtf;
837 }
838 
839 /* When tf is used repeatedly in a loop, the range is part of the
840  domain from iteration 2 to the end. This improves the derivative of
841  tf when tf is involutive on a subspace. A new transformer is
842  allocated. Of course, it cannot be used without caution. note that
843  tf must be a range, i.e. no arguments, no old values in the
844  basis. */
846 {
848  transformer ntf = copy_transformer(tf);
851  Pbase b = sc_base(scr);
852  list vl = base_to_entities(b);
853 
854  // No convenient iterator on the basis, hence the temporary list of values
855  FOREACH(ENTITY, v, vl) {
856  entity ov = entity_to_old_value(v);
857 
858  r = transformer_value_substitute(r, v, ov);
859  }
860 
862  // let's hope sc_append takes care of the consistency of sc
863  sc = sc_append(sc, scr);
864 
865  gen_free_list(vl);
866 
867  return ntf;
868 }
869 ␌
870 static int varval_value_name_is_inferior_p(Pvecteur * pvarval1, Pvecteur * pvarval2)
871 {
872  int is_inferior = true;
873  const char* s1 = generic_value_name((entity) vecteur_var(*pvarval1));
874  const char* s2 = generic_value_name((entity) vecteur_var(*pvarval2));
875 
876  is_inferior = (strcmp(s1, s2) > 0 );
877 
878  return is_inferior;
879 }
880 
881 /* Eliminate (some) rational or integer redundancy.
882 
883  Remember that integer redundancy elimination may degrade results
884  because some transformer operator such as convex hull use a
885  rational interpretation of the constraints. Unfortunately, no
886  information is given here about the properties used by the
887  different functions of the C3 linear library which are used.
888 
889  Does not take into account value types. So s=="hello" and
890  s=="world" do not result into an empty transformer. But floating
891  point values are taken into account.
892 
893  Start with sc_bounded_normalization and then according to level:
894 
895  0 -> sc_safe_elim_redund(), sc_elim_redund(),
896  sc_inequations_elim_redund(), sc_rational_feasibility_ofl_ctrl()
897 
898  1 -> sc_nredund(), build_sc_nredund_2pass(),
899  build_sc_nredund_2pass_ofl_ctrl(), sc_normalize(),
900  build_sc_nredund_1pass_ofl_ctrl(), build_sc_nredund_1pass_ofl_ctrl()
901 
902  sc_normalize() is well documented (in French)
903 
904  2 -> sc_strong_normalize(), sc_normalize()
905  sc_strong_normalize_and_check_feasibility(),
906  sc_check_inequality_redundancy(),
907 
908  3 -> sc_strong_normalize2(): resolve the equations first, then deal
909  with inequalities
910 
911  4 -> sc_normalize2(): well documented; does not detect redundancy
912  in a<=b, b<=c, a<=c
913 
914  5 -> sc_strong_normalize3(), sc_strong_normalize_and_check_feasibility
915  (ps, sc_rational_feasibility);
916 
917  6 -> sc_strong_normalize4()
918  sc_strong_normalize_and_check_feasibility2(ps, sc_normalize,
919  variable_name, 2): well documented, deterministic
920 
921 
922  7 -> sc_strong_normalize5()
923  sc_strong_normalize_and_check_feasibility2(ps,
924  sc_rational_feasibility, variable_name, 2);
925 
926  8 -> sc_safe_build_sc_nredund_1pass(): not documented
927  build_sc_nredund_1pass(): do not take equations into consideration
928 
929  See timing information in the comments below.
930 
931  */
933 {
934  ifdebug(1) {
935  pips_assert("Transformer t is consistent on entrance",
937  }
938 
939  if(!transformer_is_empty_p(t)) {
940  if(float_analyzed_p()) {
943  ifdebug(1)
944  pips_assert("t is consistent after floating point simplification\n",
946  }
947 
948  /* Automatic variables read in a CATCH block need to be declared volatile as
949  * specified by the documentation*/
951 
952  if (!sc_empty_p(r)) {
953  Pbase b = base_dup(sc_base(r));
954  /* Automatic variables read in a CATCH block need to be declared volatile as
955  * specified by the documentation*/
956  Psysteme r2 = sc_dup(r);
957 
958  /* Select one tradeoff between speed and accuracy:
959  * enumerated by increasing speeds according to Beatrice
960  */
961 
963  {
964  /* CA */
965  pips_user_warning("overflow error in redundancy elimination\n");
966  sc_rm(r);
967  r = r2;
968  }
969  TRY
970  {
971  /* Let start with an easy O(n) phase, unlikely to generate an
972  overflow. It should be placed in another try-cath in order
973  to return a better r2 in case of a later overflow. */
974  /* This is not sufficient: it is more efficient to put this
975  call directly in sc_normalize(). */
977 
978  switch(level) {
979 
980  case 0:
981  /* Our best choice for accuracy, but damned slow on ocean */
982  r = sc_safe_elim_redund(r);
983  break;
984 
985  case 1:
986  /* Beatrice's best choice: does not deal with minmax2 (only)
987  * but still requires 74 minutes of real time
988  * (55 minutes of CPU time) for ocean preconditions,
989  * when applied to each precondition stored.
990  *
991  * Only 64 s for ocean, if preconditions are not normalized.
992  * But andne, callabsval, dead2, hind, negand, negand2, or,
993  * validation_dead_code are not validated any more. Redundancy
994  * could always be detected in a trivial way after propagating
995  * values from equations into inequalities.
996  */
997  sc_nredund(&r);
998  //predicate_system(transformer_relation(t)) = r;
999  break;
1000 
1001  case 2:
1002  /* Francois' own: does most of the easy stuff.
1003  * Fails on mimax2 and sum_prec, but it is somehow
1004  * more user-friendly because trivial preconditions are
1005  * not destroyed as redundant. It makes you feel safer.
1006  *
1007  * Result for full precondition normalization on ocean: 114 s
1008  * for preconditions, 4 minutes between split ocean.f and
1009  * OCEAN.prec
1010  */
1011  r = sc_strong_normalize(r);
1012  // predicate_system(transformer_relation(t)) = r;
1013  break;
1014 
1015  case 5:
1016  /* Same plus a good feasibility test
1017  */
1018  r = sc_strong_normalize3(r);
1019  break;
1020 
1021  case 3:
1022  /* Similar, but variable are actually substituted
1023  * which is sometimes painful when a complex equations
1024  * is used to replace a simple variable in a simple
1025  * inequality.
1026  */
1027  r = sc_strong_normalize2(r);
1028  break;
1029  case 6:
1030  /* Similar, but variables are substituted if they belong to
1031  * a more or less simple equation, and simpler equations
1032  * are processed first and a lexicographically minimal
1033  * variable is chosen when equivalent variables are
1034  * available.
1035  */
1036  r = sc_strong_normalize4(r,
1037  (char * (*)(Variable)) external_value_name);
1038  break;
1039 
1040  case 7:
1041  /* Same plus a good feasibility test, plus variable selection
1042  * for elimination, plus equation selection for elimination
1043  */
1044  r = sc_strong_normalize5(r,
1045  (char * (*)(Variable)) external_value_name);
1046  break;
1047 
1048  case 4:
1049  /* Too expensive according to measurements by Beatrice
1050  * Creusillet to be used anywhere but before storing
1051  * transformers or preconditions or before printing
1052  * them. Lots of calls to string operations when C is the
1053  * analyzed language because variable names used for sorting
1054  * are easy to extract due to scope information. It is not
1055  * clear from the information mailed by Beatrice if
1056  * sc_normalize2 is also too computational but it should be
1057  * as only the basis of the constraint system is sorted out
1058  * to normalize r more effectively.
1059  */
1061  r = sc_normalize2(r);
1062  break;
1063 
1064  case 8:
1065  /* Very expensive: the system is rebuilt by adding constraints
1066  * one by one
1067  */
1069  break;
1070 
1071  default:
1072  pips_internal_error("unknown level %d", level);
1073  }
1074 
1075  sc_rm(r2), r2 = NULL;
1077  } /* end of TRY */
1078 
1079  if (SC_EMPTY_P(r)) {
1080  r = sc_empty(BASE_NULLE);
1081  }
1082  else
1083  base_rm(b), b=BASE_NULLE;
1084 
1085  r->dimension = vect_size(r->base);
1086 
1087  if(sc_empty_p(r)) {
1088  //empty_transformer(t);
1092  }
1093  else
1095  }
1096  }
1097  ifdebug(8) {
1098  fprintf(stderr, "After normalization of transformer t=%p at level %d:\n",
1099  t, level);
1101  }
1102 
1103  ifdebug(1) {
1104  pips_assert("Transformer t is consistent on exit",
1106  }
1107 
1108  return t;
1109 }
1110 
1112 {
1113  if(!transformer_undefined_p(t)) {
1114  t = transformer_normalize(t, level);
1115  }
1116  return t;
1117 }
1118 
1120 {
1121  list ntl = NIL;
1122  FOREACH(TRANSFORMER, tf, tl) {
1124  ntl = CONS(TRANSFORMER, ntf, ntl);
1125  }
1126  ntl = gen_nreverse(ntl);
1127  return ntl;
1128 }
1129 ␌
1130 /* Does transformer tf use temporary values? */
1132 {
1133  int count = 0;
1134 
1135  if(number_of_temporary_values()>0) {
1137  Pbase b = BASE_NULLE;
1138 
1139  for(b = sc_base(r); !BASE_NULLE_P(b); b = vecteur_succ(b)) {
1140  entity e = (entity) vecteur_var(b);
1142  count++;
1143  }
1144  }
1145  }
1146  return count>0;
1147 }
1148 ␌
1150 {
1151  list tv = NIL;
1152 
1153  if(number_of_temporary_values()>0) {
1155  Pbase b = BASE_NULLE;
1156 
1157  for(b = sc_base(r); !BASE_NULLE_P(b); b = vecteur_succ(b)) {
1158  entity e = (entity) vecteur_var(b);
1160  tv = CONS(ENTITY, e, tv);
1161  }
1162  }
1163  /* tf = transformer_projection(tf, tv); */
1164  /* tf = transformer_projection_with_redundancy_elimination(tf, tv, sc_identity); */
1166  }
1167  else ifdebug(1) {
1169  Pbase b = BASE_NULLE;
1170 
1171  for(b = sc_base(r); !BASE_NULLE_P(b); b = vecteur_succ(b)) {
1172  entity e = (entity) vecteur_var(b);
1174  tv = CONS(ENTITY, e, tv);
1175  }
1176  }
1177  pips_assert("No temporary values exist in the system since a reset "
1178  "counter for them has been performed\n", ENDP(tv));
1179  }
1180 
1181  gen_free_list(tv);
1182 
1183  return tf;
1184 }
1185 
1186 /* t may be undefined, args may contain values unrelated to t */
1188 {
1190  if(!transformer_undefined_p(t)) {
1192  list nargs = NIL;
1193 
1194  /* keep only values of args related to the transformer t */
1195  FOREACH(ENTITY, v, args) {
1196  /* Make sure v is in the basis */
1197  if(base_contains_variable_p(sc_base(r), (Variable) v)) {
1198  nargs = arguments_add_entity(nargs, v);
1199  }
1201  /* Make sure the old value is projected too */
1202  entity ov = entity_to_old_value(v);
1203  if(base_contains_variable_p(sc_base(r), (Variable) ov)) {
1204  nargs = arguments_add_entity(nargs, ov);
1205  }
1206  }
1207  }
1208 
1209  nt = transformer_projection(t, nargs);
1210  gen_free_list(nargs);
1211  }
1212  return nt;
1213 }
1214 
1215 /* Project return values that are not linked to function f
1216  *
1217  * Almost identical to transformer_formal_parameter_projection(). A
1218  * lambda expression should be passed for the filtering.
1219  */
1221 {
1223  Pbase b = sc_base(sc);
1224  Pbase cd = BASE_UNDEFINED;
1225  list fpl = NIL;
1226 
1227  /* Dealing with an interprocedural transformer, weak consistency is
1228  not true */
1229  /* pips_assert("t is weakly consistent",
1230  transformer_weak_consistency_p(t));*/
1231  pips_assert("sc is consistent", sc_weak_consistent_p(sc));
1232  pips_assert("t is weakly consistent", transformer_weak_consistency_p(t));
1233 
1234  for(cd = b; !BASE_NULLE_P(cd); cd = vecteur_succ(cd)) {
1235  entity val = (entity) vecteur_var(cd);
1236  entity var = value_to_variable(val);
1237  storage s = entity_storage(var);
1238 
1239  if(storage_return_p(s) && storage_return(s)!=f)
1240  fpl = CONS(ENTITY, var, fpl);
1241  }
1242 
1243  ifdebug(1) {
1244  pips_debug(1, "Transformer before projection:\n");
1245  dump_transformer(t);
1246  pips_debug(1, "Projected variables:\n");
1247  print_entities(fpl);
1248  fprintf(stderr, "\n");
1249  }
1250 
1251  t = transformer_projection(t, fpl);
1252 
1253  gen_free_list(fpl);
1254 
1255  return t;
1256 }
1257 
1258 /* values in args must be in t's base */
1259 /* transformer transformer_projection(transformer t, cons * args):
1260  * projection of t along the hyperplane defined by values in args;
1261  * this generate a projection and not a cylinder based on the projection
1262  *
1263  * use the most complex/complete redundancy elimination in Linear
1264  *
1265  * args is not modified. t is modified by side effects.
1266  */
1268 {
1269  /* sc_safe_elim_redund() may increase the rational generating system */
1270  /* t = transformer_projection_with_redundancy_elimination(t, args,
1271  sc_safe_elim_redund); */
1274  return t;
1275 }
1276 
1277 /* transformer transformer_projection(transformer t);
1278  * projection of t along the hyperplane defined by values of variables in arguments;
1279  * this generate a projection and not a cylinder based on the projection
1280  *
1281  * use the most complex/complete redundancy elimination in Linear
1282  *
1283  * args is not modified. t is modified by side effects.
1284  */
1286 {
1287  list args = NIL;
1289  Pbase b = sc_base(sc);
1290 
1291  MAP(ENTITY, a, {
1292  entity ov = entity_to_old_value(a);
1293  entity nv = entity_to_new_value(a);
1294 
1295  if(base_contains_variable_p(b, (Variable) ov))
1296  args = CONS(ENTITY, ov, args);
1297  if(base_contains_variable_p(b, (Variable) nv))
1298  args = CONS(ENTITY, nv, args);
1299  }, transformer_arguments(t));
1300 
1301  t = transformer_projection(t, args);
1302  gen_free_list(args);
1303  return t;
1304 }
1305 
1307 {
1308  return ps;
1309 }
1310 
1311 /* It is not clear if this function projects values or variables. If
1312  variables were projected, all values associated to a variable should
1313  also be projected. If values are projected and the transformer argument
1314  updated using args, old values should not be left in the basis when a
1315  new value is projected and its associated variable removed from tthe
1316  argument.
1317 
1318  New values are identical to variables which makes it confusing.
1319 
1320  The implementation, and the signature, are aware of the nature of the
1321  underlying predicate. */
1323  transformer t,
1324  list args,
1325  Psysteme (*elim)(Psysteme))
1326 {
1328  (t, args, elim, true);
1329 }
1330 
1331 /* In some cases, you know the projection will result in a non-consistent
1332  transformer that will be fixed later. The input transformer is
1333  nevertheless expected weakly consistent. */
1335  transformer t,
1336  list args,
1337  Psysteme (*elim)(Psysteme))
1338 {
1340  (t, args, elim, false);
1341 }
1342 
1344  volatile transformer t,
1345  list args,
1346  Psysteme (*elim)(Psysteme),
1347  bool check_consistency_p)
1348 {
1349  /* Library Linear/sc contains several reundancy elimination functions:
1350  * sc_elim_redund()
1351  * build_sc_nredund_2pass_ofl_ctrl() --- if it had the same profile...
1352  * ...
1353  * no_elim() is provided here to obtain the fastest possible projection
1354  */
1355  volatile list new_args = NIL;
1356  /* Automatic variables read in a CATCH block need to be declared volatile as
1357  * specified by the documentation*/
1359 
1360  ifdebug(9) {
1361  pips_debug(9, "Begin for transformer %p\n", t);
1362  /* sc_fprint(stderr, r, exernal_value_name); */
1363  /* sc_fprint(stderr, r, (char * (*)(Variable)) entity_local_name); */
1365  pips_debug(9, "and entities to be projected: ");
1366  print_entities(args);
1367  }
1368 
1369  pips_assert("t is weakly consistent", transformer_weak_consistency_p(t));
1370 
1371  /* A side effect of transformer_empty_p() is to normalize the transformer.
1372  *
1373  * This is very expensive before a projection. empty_transformer_p()
1374  */
1375  if(transformer_empty_p(t)) {
1376  t = empty_transformer(t);
1377  }
1378  else if(!ENDP(args)) {
1379  volatile list cea;
1380  Pbase mb = sc_to_minimal_basis(r); // Get the variables with non-zero coefficients
1381 
1382  /* Step 1: get rid of unwanted values in the relation r and in the basis */
1383  for (cea = args ; !ENDP(cea); POP(cea)) {
1384  /* Automatic variables read in a CATCH block need to be declared
1385  * volatile as specified by the documentation*/
1386  entity volatile e = ENTITY(CAR(cea));
1387  pips_assert("base contains variable to project...",
1388  base_contains_variable_p(sc_base(r), (Variable) e));
1389 
1390  pips_debug(9, "Projection of %s\n", entity_name(e));
1391 
1392  if(base_contains_variable_p(mb, (Variable) e)) {
1393  // The variable appears with a non-zero coefficient in at least one constraint
1395  {
1396  /* FC */
1397  pips_user_warning("overflow error in projection of %s, "
1398  "variable eliminated\n",
1399  entity_name(e));
1400  r = sc_elim_var(r, (Variable) e);
1401  }
1402  TRY
1403  {
1404  /* sc_projection_along_variable_ofl_ctrl_timeout_ctrl */
1405  sc_projection_along_variable_ofl_ctrl
1406  (&r,(Variable) e, NO_OFL_CTRL);
1408  }
1409 
1410  /* could eliminate redundancy at each projection stage to avoid
1411  * explosion of the constraint number... however it is pretty
1412  * expensive to do so. But we explode with NPRIO in FPPP (Spec
1413  * CFP'95 benchmark). A heuristic could apply redundacy elimination
1414  * from time to time?
1415  *
1416  */
1417 
1418  if(true) {
1419  // if (!sc_empty_p(r)) {
1420  // Pbase b = base_dup(sc_base(r));
1421 
1422  /* Eliminate trivial redundant constraints generated by the
1423  projection */
1424  /* Probably redundant with what happens in elim() */
1425  r = sc_bounded_normalization(r);
1426 
1427  r = elim(r);
1428  /* if (SC_EMPTY_P(r)) {
1429  r = sc_empty(BASE_NULLE);
1430  sc_base_remove_variable(r,(Variable) e);
1431  }
1432  else base_rm(b);
1433  }*/
1434 
1435  }
1436  }
1437 
1439 
1440  ifdebug(9) {
1441  pips_debug(9, "System after projection of %s\n", entity_name(e));
1442  /* sc_fprint(stderr, r, exernal_value_name); */
1443  sc_fprint(stderr, r, (char * (*)(Variable)) entity_global_name);
1444  }
1445  }
1446  vect_rm(mb);
1447 
1448  /* Step 2: eliminate redundancy only/again once projections have all
1449  * been performed because redundancy elimination is
1450  * expensive and because most variables are exactly
1451  * projected because they appear in at least one equation
1452  */
1453  if (!sc_empty_p(r)) {
1454  Pbase b = base_dup(sc_base(r));
1455  r = elim(r);
1456  if (SC_EMPTY_P(r)) {
1457  /* Should we use b or not? It does make some mathematical sense
1458  but it is not compatible with the argument list which should
1459  not be empty if old values appear in the basis. And the basis
1460  should not be used, even in convex hulls if the emptiness is
1461  detected first. */
1462  r = sc_empty(BASE_NULLE);
1463  base_rm(b);
1464  }
1465  else {
1466  base_rm(b);
1467  }
1468  }
1469  else {
1470  /* get rid of a useless basis */
1471  base_rm(sc_base(r));
1472  sc_base(r) = BASE_NULLE;
1473  }
1474 
1475  r->dimension = vect_size(r->base);
1476 
1477  ifdebug(9) {
1478  pips_debug(9, "System after redundancy elimination\n");
1479  /* sc_fprint(stderr, r, exernal_value_name); */
1480  sc_fprint(stderr, r, (char * (*)(Variable)) entity_global_name);
1481  }
1482 
1483  /* Step 3: compute new_args, but beware of left over old values! */
1486  entity v = value_to_variable(e);
1487 
1488  if((entity) gen_find_eq(e, args) == (entity) chunk_undefined)
1489  {
1490  /* e must be kept if it is not in args */
1491  new_args = arguments_add_entity(new_args, e);
1492  }
1493  else {
1494  /* The variable is going to be dropped from the argument list */
1495  entity old_e = entity_undefined;
1496 
1497  if(entity_has_values_p(v)) {
1498  old_e = entity_to_old_value(v);
1499  }
1500  else {
1501  /* Must be a variable from a module which is not the current module */
1503  }
1504 
1505  if(check_consistency_p
1506  && base_contains_variable_p(sc_base(r), (Variable) old_e)) {
1507  fprintf(stderr, "Value %s should have been eliminated earlier\n",
1508  entity_name(old_e));
1510  pips_internal_error("Wrong set of projected variables");
1511  }
1512  }
1513  }
1514  }
1515 
1516  /* Step 4: update the relation and the arguments field for t */
1517 
1518  /* the relation is updated by side effect FI ?
1519  * Maybe not if SC_EMPTY(r) 1 Feb. 94 */
1521 
1522  /* replace the old arguments by the new one, except if the
1523  constraint system is not feasible */
1525  if(sc_empty_p(r)) {
1526  transformer_arguments(t) = NULL;
1527  gen_free_list(new_args);
1528  }
1529  else
1530  transformer_arguments(t) = new_args;
1531  }
1532 
1533  ifdebug(9) {
1534  pips_debug(9, "Transformer after argument list update\n");
1535  /* sc_fprint(stderr, r, exernal_value_name); */
1537  }
1538 
1539  ifdebug(1) {
1540  /* Weak, because return value may still be present for functions. */
1541  if(check_consistency_p)
1542  pips_assert("After projection and redundancy elimination,"
1543  " transformer t is consistent",
1545  }
1546  pips_debug(9, "End for t=%p\n", t);
1547 
1548  return t;
1549 }
1550 ␌
1551 /* transformer transformer_apply(transformer tf, transformer pre):
1552  * apply transformer tf on precondition pre to obtain postcondition post
1553  *
1554  * post = tf(pre) = pre o tf
1555  *
1556  * There is (should be!) no sharing between pre and tf. No sharing is
1557  * introduced between pre or tf and post. Neither pre nor tf are modified.
1558  */
1560 {
1561  transformer post;
1562  transformer copy_pre;
1563 
1564  pips_debug(8,"begin\n");
1565  pips_assert("tf is not undefined", tf!=transformer_undefined);
1566  pips_debug(8,"tf=%p\n", tf);
1567  ifdebug(8) (void) dump_transformer(tf);
1568  pips_assert("pre is not undefined", pre!=transformer_undefined);
1569  pips_debug(8,"pre=%p\n", pre);
1570  ifdebug(8) (void) dump_transformer(pre);
1571 
1572  /* post = tf o pre ; pre would be modified by transformer_combine */
1573  copy_pre = transformer_dup(pre);
1574  post = transformer_combine(copy_pre, tf);
1575 
1576  pips_assert("post is not undefined", post!=transformer_undefined);
1577  pips_debug(8,"post=%p\n", post);
1578  ifdebug(8) (void) dump_transformer(post);
1579  pips_assert("unexpected sharing",post != pre);
1580  pips_debug(8,"end\n");
1581 
1582  return post;
1583 }
1584 
1585 /* Generates a new list of postconditions, one for each transformer
1586  * in tl, unless the postcondition is empty and keep_p is FALSE.
1587  *
1588  * keep_p is used to preserve the list lengths: the output list is
1589  * exactly as long as the input list.
1590  *
1591  * If keep_p is true, the output list is not "normalized"
1592  */
1594 {
1595  list ntl = NIL;
1596  FOREACH(TRANSFORMER, tf, tl) {
1597  transformer post = transformer_apply(tf, pre);
1598 
1599  // Be careful with empty transformers that may creep out
1600 
1601  if(!transformer_empty_p(post) || keep_p)
1602  ntl = CONS(TRANSFORMER, post, ntl);
1603  }
1604  ntl = gen_nreverse(ntl);
1605  return ntl;
1606 }
1607 
1608 /* Generates a new list of postconditions, one for each transformer
1609  in tl, unless the postcondition is empty. */
1611 {
1612  return transformer_apply_generic(tl, pre, false);
1613 }
1614 
1615 /* Same as previous one, but with a more normalized name */
1617 {
1618  return transformer_apply_generic(tl, pre, false);
1619 }
1620 
1621 /* Same as previous one, but with a more normalized name */
1623 {
1624  return transformer_apply_generic(tl, pre, true);
1625 }
1626 
1628 {
1630 
1632  post = transformer_apply(tf, pre);
1633 
1634  return post;
1635 }
1636 
1637 /* returns a list of postconditions, one for each transformer in tl */
1639 {
1640  list postl = NIL;
1641  FOREACH(TRANSFORMER, tf, tl) {
1642  transformer post = transformer_safe_apply(tf, pre);
1643  postl = CONS(TRANSFORMER, post, postl);
1644  }
1645  postl = gen_nreverse(postl);
1646  return postl;
1647 }
1648 ␌
1649 /* transformer transformer_inverse_apply(transformer tf, transformer post):
1650  * apply transformer tf on precondition pre to obtain postcondition post
1651  *
1652  * pre = post(tf) = tf o post
1653  *
1654  * There is (should be!) no sharing between post and tf. No sharing is
1655  * introduced between post or tf and pre. Neither post nor tf are modified.
1656  */
1658 {
1660  transformer copy_tf = transformer_dup(tf);
1661 
1662  pips_debug(8,"begin with\n");
1663  pips_assert("tf is not undefined", tf!=transformer_undefined);
1664  pips_debug(8,"tf=%p\n", tf);
1665  ifdebug(8) (void) dump_transformer(tf);
1666  pips_assert("post is not undefined", post!=transformer_undefined);
1667  pips_debug(8,"post=%p\n", post);
1668  ifdebug(8) {
1669  (void) dump_transformer(post);
1670  pips_assert("tf is consistent", transformer_consistency_p(tf));
1671  pips_assert("post is consistent", transformer_consistency_p(post));
1672  }
1673 
1674  /* pre = post o tf ; tf would be modified by transformer_combine */
1675  pre = transformer_combine(copy_tf, post);
1676 
1677  pips_assert("pre is not undefined", pre!=transformer_undefined);
1678  pips_debug(8,"return: pre=%p\n", pre);
1679  ifdebug(8) (void) dump_transformer(pre);
1680  pips_assert("unexpected sharing",post != pre);
1681  pips_debug(8,"end\n");
1682 
1683  return pre;
1684 }
1685 
1687 {
1689 
1691  pre = transformer_inverse_apply(tf, post);
1692 
1693  return pre;
1694 }
1695 ␌
1696 /* transformer transformer_filter(transformer t, cons * args):
1697  * projection of t along the hyperplane defined by entities in args;
1698  * this generate a projection and not a cylinder based on the projection;
1699  *
1700  * if the relation associated to t is empty, t is not modified although
1701  * it should have a basis and this basis should be cleaned up. Since
1702  * no basis is carried in the current implementation of an empty system,
1703  * this cannot be performed (FI, 7/12/92).
1704  *
1705  * formal argument args is not modified. t is updated by side effect.
1706  *
1707  * Note: this function is almost equal to transformer_projection();
1708  * however, entities of args do not all have to appear in t's
1709  * relation; thus transformer_filter has a larger definition domain
1710  * than transformer_projection; on transformer_projection's domain,
1711  * both functions are equal
1712  *
1713  * transformer_projection is useful to get cores when you know all entities
1714  * in args should appear in the relation.
1715  */
1717 {
1718  cons * new_args = NIL;
1719  /* Automatic variables read in a CATCH block need to be declared volatile as
1720  * specified by the documentation*/
1722 
1723  ifdebug(9) {
1724  pips_debug(9, "Begin for transformer %p\n", t);
1725  /* sc_fprint(stderr, r, exernal_value_name); */
1726  /* sc_fprint(stderr, r, (char * (*)(Variable)) entity_local_name); */
1728  pips_debug(9, "and entities to be projected: ");
1729  dump_arguments(args);
1730  pips_assert("t is weakly consistent", transformer_weak_consistency_p(t));
1731  }
1732 
1733  if(!ENDP(args) && !SC_EMPTY_P(r)) {
1734  /* get rid of unwanted values in the relation r and in the basis */
1735  volatile list cea = list_undefined;
1736 
1737  for(cea=args; !ENDP(cea); POP(cea)) {
1738  /* Automatic variables read in a CATCH block need to be declared volatile as
1739  * specified by the documentation*/
1740  entity volatile e = ENTITY(CAR(cea));
1741  if(base_contains_variable_p(r->base, (Variable) e)) {
1742  /* r = sc_projection(r, (Variable) e); */
1743  /*
1744  sc_projection_along_variable_ofl_ctrl(&r, (Variable) e,
1745  NO_OFL_CTRL); */
1747  {
1748  /* CA */
1749  pips_user_warning("overflow error in projection of %s, "
1750  "variable eliminated\n",
1751  entity_name(e));
1752  r = sc_elim_var(r, (Variable) e);
1753  }
1754  TRY
1755  {
1756  /* sc_projection_along_variable_ofl_ctrl_timeout_ctrl */
1757  sc_projection_along_variable_ofl_ctrl
1758  (&r, (Variable) e, NO_OFL_CTRL);
1760  }
1761  /* sc_projection_along_variable_ofl_ctrl(&r, (Variable) e,
1762  OFL_CTRL);*/
1764  }
1765  r->dimension = vect_size(r->base);
1766 
1767  /* compute new_args */
1768  /* use functions on arguments instead of in-lining !
1769  MAPL(ce, { entity e = ENTITY(CAR(ce));
1770  if((entity) gen_find_eq(e, args)== (entity) chunk_undefined) {
1771  -- e must be kept if it is not in args --
1772  new_args = arguments_add_entity(new_args, e);
1773  }},
1774  transformer_arguments(t));
1775  */
1776  new_args = arguments_difference(transformer_arguments(t), args);
1777 
1778  /* update the relation and the arguments field for t */
1779 
1780  /* Is the relation updated by side effect?
1781  * Yes, in general. No if the system is non feasible
1782  */
1783 
1785 
1786  /* replace the old arguments by the new one */
1788  if(sc_empty_p(r)) {
1789  transformer_arguments(t) = NULL;
1790  gen_free_list(new_args);
1791  }
1792  else
1793  transformer_arguments(t) = new_args;
1794  }
1795 
1796  ifdebug(9) {
1797  pips_debug(9, "Transformer after argument list update\n");
1798  /* sc_fprint(stderr, r, exernal_value_name); */
1800  }
1801 
1802  ifdebug(1) {
1803  pips_assert("After filtering,"
1804  " transformer t is consistent",
1806  }
1807  pips_debug(9, "End for t=%p\n", t);
1808 
1809  return t;
1810 }
1811 
1812 /* Transformers are dealing with variables and/or variable values.
1813  *
1814  * The confusion is magnified because the new value of a variable is
1815  * often identified to the variable. Also, it is not 100% clear if the
1816  * argument list of a transformer is a list of variables or a list of
1817  * new values. In principle, it is a list of variables or
1818  * locations. To make thisn worse, both value and variable start with
1819  * a v...
1820  *
1821  * Here, it is assumed that list vl is a list of variables or locations.
1822  *
1823  * Transformer t is modified by side effect. All values linked to any
1824  * variable in ist vl are projected, when possible. It is assumed that
1825  * the projected variables are removed from the transformer argument.
1826  */
1828 {
1829  list values = NIL;
1830  FOREACH(ENTITY, var, vl) {
1831  if(entity_has_values_p(var)) {
1832  entity new_val = entity_to_new_value(var);
1833  // FI it might be necessary to guard this definition
1834  entity old_val = entity_to_old_value(var);
1835  values = CONS(ENTITY, new_val, values);
1836  if(!entity_undefined_p(old_val))
1837  values = CONS(ENTITY, old_val, values);
1838  }
1839  }
1840  t = transformer_filter(t, values);
1841  gen_free_list(values);
1842  return t;
1843 }
1844 ␌
1845 /* bool transformer_affect_linear_p(transformer tf, Pvecteur l): returns TRUE
1846  * if there is a state s such that eval(l, s) != eval(l, tf(s));
1847  * returns false if l is invariant w.r.t. tf, i.e. for all state s,
1848  * eval(l, s) == eval(l, tf(s))
1849  */
1851 {
1852  if (!transformer_undefined_p(tf)){
1853  list args = transformer_arguments(tf);
1854 
1855  MAP(ENTITY, e,
1856  {
1857  Value v = vect_coeff((Variable) e, l);
1858  if(value_notzero_p(v)) return true;
1859  },
1860  args);
1861  }
1862 
1863  return false;
1864 }
1865 
1866 /* Transformer tf1 affects transformer tf2 if values modified by tf1
1867  appear in any constraint of tf2. The two transformer do not commute and
1868  tf1 o tf2 does not equal tf2 o tf1. */
1869 
1871 {
1872  bool affect_p = false;
1873 
1874  /* No need to check anything if tf1 does not change the memory state */
1875  if(!ENDP(transformer_arguments(tf1))) {
1877  Pcontrainte ceq = sc_egalites(s2);
1878  Pcontrainte cineq = sc_inegalites(s2);
1879 
1880  for(; !CONTRAINTE_UNDEFINED_P(ceq) && !affect_p; ceq = contrainte_succ(ceq)) {
1881  Pvecteur v = contrainte_vecteur(ceq);
1882  affect_p = transformer_affect_linear_p(tf1, v);
1883  }
1884 
1885  for(; !CONTRAINTE_UNDEFINED_P(cineq) && !affect_p; cineq = contrainte_succ(cineq)) {
1886  Pvecteur v = contrainte_vecteur(cineq);
1887  affect_p = transformer_affect_linear_p(tf1, v);
1888  }
1889  }
1890 
1891  return affect_p;
1892 }
1893 
1895 {
1896  bool affect_p = false;
1897 
1899  affect_p = transformer_affect_transformer_p(tf1, tf2);
1900 
1901  return affect_p;
1902 }
1903 ␌
1904 /* Generates a transformer abstracting a totally unknown modification of
1905  * the values associated to variables in list le.
1906  */
1907 transformer args_to_transformer(list le) /* list of entities */
1908 {
1910  cons * args = transformer_arguments(tf);
1911  Pbase b = VECTEUR_NUL;
1912  Psysteme s = sc_new();
1913 
1914  MAPL(ce, {
1915  entity e = ENTITY(CAR(ce));
1916  entity new_val = entity_to_new_value(e);
1917 
1918  args = arguments_add_entity(args, new_val);
1919  b = vect_add_variable(b, (Variable) new_val);
1920  }, le);
1921 
1922  transformer_arguments(tf) = args;
1923  s->base = b;
1924  s->dimension = vect_size(b);
1926  return tf;
1927 }
1928 ␌
1929 /* transformer invariant_wrt_transformer(transformer p, transformer tf):
1930  * Assume that tf is a fix-point operator.
1931  *
1932  * Old version:
1933  * keep the invariant part of predicat p wrt tf in a VERY crude way;
1934  * old and new values related to an entity modified by tf are discarded
1935  * by projection, regardless of the way they are modified; information
1936  * that they are modified is preserved; in fact, this is *not* a projection
1937  * but a cylinder based on the projection.
1938  * inf
1939  * A real fix-point a la Halbwachs should be used p' = UNION(tf^k(p))
1940  * k=0
1941  * or simply one of PIPS loop fix-points.
1942  *
1943  * Be careful if tf is not feasible because the result is p itself which may not
1944  * be what you expect.
1945  *
1946  * p is not modified.
1947  */
1949 {
1952 
1953  if(!transformer_undefined_p(p)) {
1954  //transformer raw_inv = transformer_undefined;
1955  if(false)
1956  {
1958  }
1959  else
1960  {
1961  /* if it is expensive, maybe it should not be computed over and over...
1962  */
1964  }
1965 
1966  inv = transformer_apply(fptf, p); /* tf? fptf? */
1967  //inv = transformer_range(raw_inv);
1968 
1969  //free_transformer(raw_inv); // Newgen syntax
1970  transformer_free(fptf); /* must be freed, otherwise it is leaked. */
1971  }
1972  else {
1973  inv = transformer_undefined;
1974  }
1975  return inv;
1976 }
1977 ␌
1978 /* transformer transformer_value_substitute(transformer t,
1979  * entity e1, entity e2):
1980  * if e2 does not appear in t initially:
1981  * replaces occurences of value e1 by value e2 in transformer t's arguments
1982  * and relation fields;
1983  * else
1984  * error
1985  * fi
1986  *
1987  * "e2 must not appear in t initially": this is the general case;
1988  * the second case may occur when procedure A calls B and C and when B and C
1989  * share a global variable X which is not seen from A. A may contain
1990  * relations between B:X and C:X...
1991  * See hidden.f in Bugs or Validation...
1992  */
1994 {
1995  /* updates are performed by side effects */
1996 
1997  cons * a = transformer_arguments(t);
1999 
2000  pips_assert("e1 and e2 are defined entities",
2001  e1 != entity_undefined && e2 != entity_undefined);
2002  /*
2003  pips_assert("transformer_value_substitute",
2004  !base_contains_variable_p(s->base, (Variable) e2));
2005  */
2006 
2007  /* update only if necessary */
2008  if(base_contains_variable_p(s->base, (Variable) e1)) {
2009 
2010  if(!base_contains_variable_p(s->base, (Variable) e2)) {
2011 
2012  (void) sc_variable_rename(s,(Variable) e1, (Variable)e2);
2013 
2014  /* rename value e1 in argument a; e1 does not necessarily
2015  appear in a because it's not necessarily the new value of
2016  a modified variable */
2017  MAPL(ce, {entity e = ENTITY(CAR(ce));
2018  if( e == e1) ENTITY_(CAR(ce)) = e2;},
2019  a);
2020  }
2021  else {
2022  pips_internal_error("cannot substitute e1=%s by e2=%s: e2 already in basis",
2023  entity_name(e1), entity_name(e2));
2024  }
2025  }
2026 
2027  return t;
2028 }
2029 
2030 /* If e1 does not appear in t, it is substitutable. If e1 does appear
2031  * in t but not e2, again it is substitutable. Else, it if not.
2032  */
2034 {
2035  bool substitutable_p = true;
2037 
2038  pips_assert("e1 and e2 are defined entities",
2039  e1 != entity_undefined && e2 != entity_undefined);
2040 
2041  if(base_contains_variable_p(s->base, (Variable) e1)) {
2042  substitutable_p = !base_contains_variable_p(s->base, (Variable) e2);
2043  }
2044 
2045  return substitutable_p;
2046 }
2047 
2049  entity e1,
2050  entity e2)
2051 {
2052  if(!transformer_undefined_p(t))
2053  t = transformer_value_substitute(t, e1, e2);
2054 
2055  return t;
2056 }
2057 ␌
2058 /* If v is a not a float constraint, retun v. If v is a float
2059  constraint, merge all float constants. If the constraint is
2060  trivially satisfied, return a NULL vector. */
2062 {
2063  long double x = 0.;
2064  int occ = 0;
2065  bool is_float = true; // maybe a float constraint
2067  Pvecteur nv = VECTEUR_NUL;
2068 
2069  for(cv=v; !VECTEUR_UNDEFINED_P(cv) && is_float; cv = vecteur_succ(cv)) {
2070  entity e = (entity) vecteur_var(cv);
2071  Value val = vecteur_val(cv);
2072 
2073  if((Variable) e == TCST) {
2074  /* An integer constant cannot be mixed with floating point
2075  values */
2076  // pips_assert("x is zero", x==0.);
2077  is_float = false;
2078  }
2079  else if(entity_constant_p(e)) {
2080  if(float_constant_p(e)) {
2081  double d = float_constant_to_double(e);
2082  x += (long double)(val) * (long double) (d);
2083  occ++;
2084  if(val!=1)
2085  occ++;
2086  vect_add_elem(&nv, (Variable) e, -val);
2087  }
2088  else
2089  is_float = false;
2090  }
2091  else {
2092  type t = entity_type(e);
2093  if(float_type_p(t)) {
2094  ;
2095  }
2096  else {
2097  is_float = false;
2098  }
2099  }
2100  }
2101 
2102  if(is_float && vect_size(nv) > 0 && occ > 1 /* x!=0. */) {
2103  /* FI: do we want to represent 0. by 0? */
2104  if(x!=0.) {
2105  // FI: awfull precision loss...
2106  entity vx = float_to_entity((float) x>0?x:-x);
2107  // FI: let's try to move the constants on the right side,
2108  // i.e. the constant side, of the constraints
2109  // Might be independent of the constant sign
2110  // Avoid -(-6.) if a term is moved from one side to the other
2111  if(x>0)
2112  vect_add_elem(&nv, (Variable) vx, VALUE_ONE);
2113  else
2114  vect_add_elem(&nv, (Variable) vx, VALUE_MONE);
2115  }
2116  Pvecteur sv = vect_add(v, nv);
2117  vect_rm(v);
2118  vect_rm(nv);
2119  v = sv;
2120  }
2121 
2122  /* Check that v is a feasible constraint */
2123  if(vect_size(v)==1) {
2124  entity e = (entity) vecteur_var(v);
2125  /* The new term must be the only one since vx is a new entity
2126  whose term cannot be cancelled by vect_add() */
2127  if(e != (entity) TCST && entity_constant_p(e)) {
2128  if((!is_equation_p && x >0)
2129  || (is_equation_p && x!=0.)) {
2130  /* Unfeasible constraint */
2132  vect_rm(v);
2133  v = nv;
2134  }
2135  else {
2136  vect_rm(v);
2137  v = VECTEUR_NUL;
2138  }
2139  }
2140  }
2141 
2142  return v;
2143 }
2144 
2145 /* Simplify float constraints and possibly detect*/
2147 {
2148  Pcontrainte eq;
2149 
2150  for (eq = ps->egalites; eq != NULL; eq=eq->succ) {
2151  if (eq->vecteur) {
2153  }
2154  }
2155  for (eq = ps->inegalites; eq != NULL; eq=eq->succ) {
2156  if (eq->vecteur) {
2158  }
2159  }
2160 
2161  /* Recompute the base, most of the time useless, but you cannot
2162  guess what happened in simplify_float_constraint() */
2163  Pbase ob = sc_base(ps);
2164  Pbase nb = sc_to_minimal_basis(ps);
2165  /* Do not discard old values due to arguments... Just in case, keep
2166  too many floating point constants in the base. But add the new
2167  ones. */
2168  sc_base(ps) = base_union(ob, nb);
2169  sc_dimension(ps) = base_dimension(sc_base(ps));
2170  vect_rm(ob);
2171  vect_rm(nb);
2172 
2173  ifdebug(1) pips_assert("sc is consistent", sc_consistent_p(ps));
2174 
2175  return ps;
2176 }
2177 ␌
2178 /* Check if a transformer is empty. Take into account, if necessary,
2179  constraints with floating point and string constraints.
2180  */
2181 
2182 /* Simplify constraints build with float and string constants only */
2183 static bool constant_constraint_check(Pvecteur v, bool is_equation_p)
2184 {
2185  string s1 = string_undefined;
2186  int i1 = 0;
2187  string s2 = string_undefined;
2188  int i2 = 0;
2189  double x = 0.;
2190  bool is_string = false;
2191  bool is_float = false;
2192  bool type_undecided_p = true;
2194  bool is_checked = true;
2195  int number_of_strings = 0;
2196 
2197  for(cv=v; !VECTEUR_UNDEFINED_P(cv); cv = vecteur_succ(cv)) {
2198  entity e = (entity) vecteur_var(cv);
2199  Value val = vecteur_val(cv);
2200 
2201  pips_assert("e is a constant", (Variable) e == TCST || entity_constant_p(e));
2202 
2203  if((Variable) e!=TCST) {
2204  basic b = constant_basic(e);
2205 
2206  switch(basic_tag(b)) {
2207  case is_basic_int:
2208  case is_basic_logical:
2209  /* Logical are represented by integer values*/
2210  pips_internal_error("Unexpected integer or logical type for constant %s",
2211  entity_name(e));
2212  break;
2213  case is_basic_float:
2214  /* PIPS does not represent negative constants: call to unary_minus */
2215  if(type_undecided_p) {
2216  type_undecided_p = false;
2217  is_float = true;
2218  }
2219  else {
2220  if(is_string) {
2221  pips_internal_error("String constant mixed up with float constant %s",
2222  entity_name(e));
2223  }
2224  }
2225  x = x + ((double) val) * float_constant_to_double(e);
2226  break;
2227  case is_basic_string:
2228  if(type_undecided_p) {
2229  type_undecided_p = false;
2230  is_string = true;
2231  }
2232  else {
2233  if(is_float) {
2234  pips_internal_error("Float constant mixed up with string constant %s",
2235  entity_name(e));
2236  }
2237  }
2238  if(number_of_strings==0) {
2239  /* s1 = module_local_name(e); */
2240  s1 = entity_name(e);
2241  i1 = (int) val;
2242  }
2243  else if(number_of_strings==1) {
2244  /* s2 = module_local_name(e); */
2245  s2 = entity_name(e);
2246  i2 = (int) val;
2247  }
2248  else
2249  pips_internal_error("Too many strings in a string constraint");
2250 
2251  number_of_strings++;
2252  break;
2253  case is_basic_complex:
2254  /* PIPS does not represent complex constants: call to CMPLX */
2255  pips_internal_error("Unexpected complex type for constant %s",
2256  entity_name(e));
2257  break;
2258  case is_basic_overloaded:
2259  pips_internal_error("Unexpected overloaded type for constant %s",
2260  entity_name(e));
2261  break;
2262  default:
2263  pips_internal_error("unknown basic b=%d", basic_tag(b));
2264  }
2265  }
2266  else {
2267  if(vect_size(v)==1) {
2268  /* Unfeasible equation or trivial inequality */
2269  is_checked = (is_equation_p ? false : (val <= 0));
2270  }
2271  else {
2272  pips_internal_error("Unexpected integer constant mixed up with "
2273  "non-integer constants\n");
2274  }
2275  }
2276  }
2277 
2278  pips_assert("It can't be a float and a string simultaneously",
2279  !(is_float && is_string));
2280 
2281  if(is_string) {
2282  if(number_of_strings!=2)
2283  pips_internal_error("Illegal number of strings in string constraint");
2284  if(is_equation_p) {
2285  if(i1+i2==0)
2286  is_checked = (fortran_string_compare(s1, s2)==0);
2287  else
2288  pips_internal_error("Unexpected string coefficients i1=%d, i2=%d for equality",
2289  i1, i2);
2290  }
2291  else {
2292  if(i1>0 && i1+i2==0)
2293  is_checked = (fortran_string_compare(s1, s2) <= 0);
2294  else if(i1<0 && i1+i2==0)
2295  is_checked = (fortran_string_compare(s1, s2) >= 0);
2296  else
2297  pips_internal_error("Unexpected string coefficients i1=%d, i2=%d for inequality",
2298  i1, i2);
2299  }
2300  }
2301  else if(is_float) {
2302  if(is_equation_p)
2303  is_checked = (x==0.);
2304  else
2305  is_checked = (x<0.);
2306  }
2307  else {
2308  /* Must be a trivial integer constraint. Already processed*/
2309  ;
2310  }
2311 
2312  return is_checked;
2313 }
2314 
2315 /* If true is returned, the transformer certainly is empty. If false
2316  * is returned, the transformer still might be empty, it all depends
2317  * on the normalization procedure power. Beware of its execution time!
2318  */
2320  Psysteme (*normalize)(Psysteme,
2321  char * (*)(Variable)))
2322 {
2323  /* FI: the arguments seem to have no impact on the emptiness
2324  * (i.e. falseness) of t
2325  */
2326  predicate pred = transformer_relation(t);
2327  Psysteme ps = predicate_system(pred);
2328  bool empty_p = false;
2329  volatile bool consistent_p = true;
2330  /* Automatic variables read in a CATCH block need to be declared volatile as
2331  * specified by the documentation*/
2332  Psysteme volatile new_ps = sc_dup (ps);
2333 
2334  pips_debug(9,"Begin for t=%p\n", t);
2335 
2336  /* empty_p = !sc_faisabilite(ps); */
2337  /* empty_p = !sc_rational_feasibility_ofl_ctrl(ps, OFL_CTRL, true); */
2338 
2339  /* Normalize the transformer, use all "reasonnable" equations
2340  * to reduce the problem
2341  * size, check feasibility on the projected system
2342  */
2343  /* new_ps = normalize(new_ps, (char * (*)(Variable)) external_value_name); */
2344  /* FI: when dealing with interprocedural preconditions, the value mappings
2345  * are initialized for the caller but the convex hull, which calls this function,
2346  * must be performed in the calle value space.
2347  */
2348  new_ps = normalize(new_ps, (char * (*)(Variable)) entity_local_name);
2349 
2350  if(SC_EMPTY_P(new_ps)) {
2351  empty_p = true;
2352  }
2353  else if(sc_empty_p(new_ps)) {
2354  /* Depending on the instance of "normalize", might always be trapped
2355  by the previous test. */
2356  empty_p = true;
2357  }
2358  else {
2359  if(string_analyzed_p() || float_analyzed_p()) {
2360  /* Inconsistent equalities or inequalities between constants may be
2361  present. Project variable and temporary values and analyze resulting system. No
2362  equations should be left over unless equal constants are encoded
2363  differently. Inequations should be interpreted and checked. */
2364  volatile Pvecteur b = VECTEUR_UNDEFINED;
2367  volatile Pbase b_min = sc_to_minimal_basis(new_ps);
2368 
2369  for (b = b_min ; !VECTEUR_UNDEFINED_P(b) && !empty_p; b = vecteur_succ(b)) {
2370  /* Automatic variables read in a CATCH block need to be declared volatile as
2371  * specified by the documentation*/
2372  Variable volatile var = vecteur_var(b);
2373  entity volatile e_var = (entity) var;
2374 
2375  if(!entity_constant_p(e_var)) {
2376 
2377  pips_debug(9, "Projection of %s\n", entity_name(e_var));
2378 
2380  {
2381  /* FC */
2382  pips_user_warning("overflow error in projection of %s, "
2383  "variable eliminated\n",
2384  entity_name(e_var));
2385  new_ps = sc_elim_var(new_ps, var);
2386  }
2387  TRY
2388  {
2389  /* sc_projection_along_variable_ofl_ctrl_timeout_ctrl */
2390  sc_projection_along_variable_ofl_ctrl
2391  (&new_ps, var, NO_OFL_CTRL);
2393  }
2394 
2395  sc_base_remove_variable(new_ps, var);
2396  /* No redundancy elimination... */
2397  /* new_ps = elim(new_ps); */
2398 
2399  ifdebug(10) {
2400  pips_debug(10, "System after projection of %s\n", entity_name(e_var));
2401  /* sc_fprint(stderr, r, exernal_value_name); */
2402  sc_fprint(stderr, new_ps, (char * (*)(Variable)) value_full_name);
2403  }
2404  empty_p = sc_empty_p(new_ps);
2405  }
2406  }
2407 
2408  base_rm(b_min);
2409 
2410  /* Check remaining equalities and inequalities */
2411 
2412  ifdebug(9) {
2413  pips_debug(9, "System after all projections or emptiness detection:\n");
2414  /* sc_fprint(stderr, r, exernal_value_name); */
2415  sc_fprint(stderr, new_ps, (char * (*)(Variable)) value_full_name);
2416  }
2417 
2418  if(!empty_p) {
2419  for(eq = sc_egalites(new_ps);
2420  !CONTRAINTE_UNDEFINED_P(eq) && consistent_p;
2421  eq = contrainte_succ(eq)) {
2422  consistent_p = constant_constraint_check(contrainte_vecteur(eq), true);
2423  }
2424 
2425  for(ineq = sc_inegalites(new_ps);
2426  !CONTRAINTE_UNDEFINED_P(ineq) && consistent_p;
2427  ineq = contrainte_succ(ineq)) {
2428  consistent_p = constant_constraint_check(contrainte_vecteur(ineq), false);
2429  }
2430  empty_p = !consistent_p;
2431  }
2432  }
2433  else {
2434  empty_p = false;
2435  }
2436 
2437  sc_rm(new_ps);
2438  }
2439 
2440  pips_debug(9,"End: %sfeasible\n", empty_p? "not " : "");
2441 
2442  return empty_p;
2443 }
2444 
2445 /* If true is returned, the transformer certainly is empty.
2446  * If false is returned,
2447  * the transformer still might be empty, but it's not too likely...
2448  *
2449  * Well, k <= 2 and k >= 3 does not return empty in spite of
2450  * sc_strong_normalize()... sc_bounded_normalization() should be used
2451  * at a cost of O(n)
2452  *
2453  * See also transformer_is_empty_p() for a simple quick syntactic check
2454  */
2456 {
2458  return empty_p;
2459 }
2460 
2461 /* If true is returned, the transformer certainly is empty.
2462  * If false is returned,
2463  * the transformer still might be empty, but it's not likely at all...
2464  */
2466 {
2468  return empty_p;
2469 }
2470 ␌
2471 /* See if the equations in transformer "pre" constraint variable "v"
2472  * by v = gcd x + c, where x is a free variable.
2473  *
2474  * If "v" is free, gcd==1 and c==0
2475  *
2476  * Entity "v" is supposed to represent a value
2477  *
2478  * Returns true unless the equations in "pre" have no integer solutions.
2479 */
2481 {
2483  Pbase b = sc_base(sc);
2484  bool success = true;
2485  // Default returned values
2486  *gcd_p = 1L;
2487  *c_p = 0L;
2488 
2489  if(base_contains_variable_p(b, (Variable) v)) {
2490  int rank = rank_of_variable(b, (Variable) v); // could be used in the test
2491  int n = sc_nbre_egalites(sc);
2492  if(n>0) {
2493  int m = base_dimension(sc_base(sc));
2494  Pmatrix A, B;
2495  A = matrix_new(n, m);
2496  B = matrix_new(n, 1);
2497  constraints_to_matrices(sc_egalites(sc), sc_base(sc), A, B);
2498  // A x + B = 0 is transformed into A x = B
2499  for(int i=1;i<=n;i++) MATRIX_ELEM(B, i, 1) = -MATRIX_ELEM(B, i, 1);
2500  if(!matrices_to_1D_lattice(A, B, n, m, rank, gcd_p, c_p)) {
2501  // The transformer is in fact empty because its diophantine
2502  // equations have no solution
2503  success = false;
2504  }
2505  free(A);
2506  free(B);
2507  }
2508  }
2509  return success;
2510 }
2511 
2512 /* get unsorted list of formal integer parameters of module f by declaration
2513  filtering; these parameters may not be used by the callee's
2514  semantics analysis, but we have no way to know it because
2515  value mappings are not available.
2516 */
2518 {
2519 
2520  list formals = NIL;
2521 
2522  pips_assert("entity is a module", entity_module_p(f));
2523 
2525  {
2528  formals = CONS(ENTITY, e, formals);
2529  }
2530 
2531  return formals;
2532 }
2533 
2534 /* formal_and_actual_parameters_association(call c, transformer pre):
2535  * Add equalities between actual and formal parameters binding by call c
2536  * to pre
2537  * pre := pre U {f = expr }
2538  * i i
2539  * for all i such that formal fi is an integer scalar variable and
2540  * expression expr-i is affine
2541  */
2543 {
2544  entity f = call_function(c);
2545  list pc = call_arguments(c);
2547  cons * ce;
2548 
2549  ifdebug(6) {
2550  debug(6,"formal_and_actual_parameters_association",
2551  "begin for call to %s pre=%x\n", module_local_name(f), pre);
2552  dump_transformer(pre);
2553  }
2554 
2555  pips_assert("formal_and_actual_parameters_association",
2556  entity_module_p(f));
2557  pips_assert("formal_and_actual_parameters_association",
2558  pre != transformer_undefined);
2559 
2560  /* let's start a long, long, long MAPL, so long that MAPL is a pain */
2561  for( ce = formals; !ENDP(ce); POP(ce)) {
2562  entity e = ENTITY(CAR(ce));
2564  expression expr;
2565  normalized n;
2566 
2567  if((expr = find_ith_argument(pc, r)) == expression_undefined)
2568  user_error("formal_and_actual_parameters_association",
2569  "not enough args for formal parm. %d\n", r);
2570 
2571  n = NORMALIZE_EXPRESSION(expr);
2572  if(normalized_linear_p(n)) {
2575 
2576  vect_add_elem(&v, (Variable) e_new, -1);
2577  pre = transformer_equality_add(pre, v);
2578  }
2579  }
2580 
2581  free_arguments(formals);
2582 
2583  ifdebug(6) {
2584  debug(6,"formal_and_actual_parameters_association",
2585  "new pre=%x\n", pre);
2586  dump_transformer(pre);
2587  debug(6,"formal_and_actual_parameters_association","end for call to %s\n",
2588  module_local_name(f));
2589  }
2590 
2591  return pre;
2592 }
2593 
2594 /* Fast checks :
2595  + e1 and e2 are same expressions
2596  + e1 and e2 are equivalent because they are same common variables
2597  Slow check:
2598  If NOT(e1=e2) + prec = infeasible, we have e1=e2 is always true
2599 */
2602 {
2603  normalized n1, n2;
2604  if (same_expression_p(e1,e2)) return true;
2606  {
2607  reference ref1 = expression_reference(e1);
2608  reference ref2 = expression_reference(e2);
2609  entity en1 = reference_variable(ref1);
2610  entity en2 = reference_variable(ref2);
2611  if (same_scalar_location_p(en1, en2)) return true;
2612  }
2615  n1 = NORMALIZE_EXPRESSION(e1);
2616  n2 = NORMALIZE_EXPRESSION(e2);
2617  ifdebug(4)
2618  {
2619  fprintf(stderr, "\n First expression : ");
2620  print_expression(e1);
2621  fprintf(stderr, "\n Second expression : ");
2622  print_expression(e2);
2623  fprintf(stderr, " \n equal in the context ?");
2625  }
2627  {
2628  Pvecteur v1 = normalized_linear(n1), v2 = normalized_linear(n2);
2629  Pvecteur v_init = vect_substract(v1, v2);
2630  // Trivial test e1=N+M, e2=M+N => e1=e2.
2631  // This test may be subsumed by the above test same_expression_p()
2632  if (vect_constant_p(v_init))
2633  {
2634  // Tets if v_init == 0
2635  if (VECTEUR_NUL_P(v_init)) return true;
2636  if (value_zero_p(val_of(v_init))) return true;
2637  if (value_notzero_p(val_of(v_init))) return false;
2638  }
2639  else
2640  {
2641  Pvecteur v_one = vect_new(TCST,1);
2642  Pvecteur v_not_e = vect_add(v_init,v_one);
2643  Pvecteur v_temp = vect_multiply(v_init,-1);
2644  Pvecteur v_not_e_2 = vect_add(v_temp,v_one);
2646  if (!efficient_sc_check_inequality_feasibility(v_not_e,ps) &&
2648  {
2649  vect_rm(v_one);
2650  return true;
2651  }
2652  vect_rm(v_one);
2653  }
2654  }
2655  return false;
2656 }
2657 
2658 /* This function returns true if the actual array and the dummy array
2659  * have the same dimension number i, with respect to the current context
2660  * (precondition + association)
2661  * In case if the actual argument is an array element, we have to add
2662  * the following condition: the i-th subscript of the array element
2663  * is equal to its correspond lower bound.
2664 */
2666  entity actual_array, entity dummy_array,
2667  list l_actual_ref, size_t i, transformer context)
2668 {
2669  variable actual_var = type_variable(entity_type(actual_array));
2670  variable dummy_var = type_variable(entity_type(dummy_array));
2671  list l_actual_dims = variable_dimensions(actual_var);
2672  list l_dummy_dims = variable_dimensions(dummy_var);
2673 
2674  /* The following test is necessary in case of array reshaping */
2675  if ((i <= gen_length(l_actual_dims)) && (i < gen_length(l_dummy_dims)))
2676  {
2677  dimension dummy_dim = find_ith_dimension(l_dummy_dims,i);
2678  expression dummy_lower = dimension_lower(dummy_dim);
2679  expression dummy_upper = dimension_upper(dummy_dim);
2680  dimension actual_dim = find_ith_dimension(l_actual_dims,i);
2681  expression actual_lower = dimension_lower(actual_dim);
2682  expression actual_upper = dimension_upper(actual_dim);
2683  expression dummy_size, actual_size;
2684  if (expression_equal_integer_p(dummy_lower,1) &&
2685  expression_equal_integer_p(actual_lower,1))
2686  {
2687  dummy_size = copy_expression(dummy_upper);
2688  actual_size = copy_expression(actual_upper);
2689  }
2690  else
2691  {
2693  dummy_upper,dummy_lower);
2695  actual_upper,actual_lower);
2696  }
2697  if (expression_equal_in_context_p(actual_size, dummy_size, context))
2698  {
2699  if (l_actual_ref == NIL)
2700  // case : array name
2701  return true;
2702  else
2703  {
2704  // the actual argument is an array element name,
2705  // we have to calculate the subscript value also*/
2706  expression actual_sub = find_ith_argument(l_actual_ref,i);
2707  if (same_expression_p(actual_sub,actual_lower))
2708  return true;
2709  }
2710  }
2711  }
2712  return false;
2713 }
2714 
2715 /* Provide a list of variables that might be forward translated into a
2716  * stub when preconditions are propagated in callees
2717  *
2718  * Basically, remove nothing from the transformer base ?
2719  */
2721 {
2722  list l = NIL;
2724  Pvecteur b = sc_base(sc), cb;
2725  for(cb=b; !VECTEUR_UNDEFINED_P(cb); cb = vecteur_succ(cb)) {
2726  Variable v = vecteur_var(cb);
2728  entity e = value_to_variable((entity) v);
2729  value ev = entity_initial(e);
2730  entity te = e;
2731  if(value_reference_p(ev)) {
2732  reference r = value_reference(ev);
2733  te = reference_variable(r);
2734  }
2735  if(!gen_in_list_p(te, l))
2736  l = CONS(ENTITY, te, l);
2737  }
2738  }
2739  return l;
2740 }
2741 
2742 /* The list of location entities that appear in the basis of the
2743  * transformer predicate.
2744  */
2746 {
2747  list l = NIL;
2748  //entity m = get_current_module_entity();
2750  Pvecteur b = sc_base(sc), cb;
2751  for(cb=b; !VECTEUR_UNDEFINED_P(cb); cb = vecteur_succ(cb)) {
2752  Variable v = vecteur_var(cb);
2754  entity e = value_to_variable((entity) v);
2755  value val = entity_initial(e);
2756  //if(location_entity_p(e)) {
2757  if(value_reference_p(val)) {
2758  // The test is not needed beause of the basis property: each
2759  // dimension is unique. But value_to_variable() is a
2760  // many-to-one mapping
2761 
2762  if(!gen_in_list_p(e, l))
2763  l = CONS(ENTITY, e, l);
2764  }
2765  // FI: m should be the callee and it is the caller
2766  //else if(!array_p && stub_entity_of_module_p(e, m)) {
2767  else if(!array_p && entity_stub_sink_p(e)) {
2768  if(!gen_in_list_p(e, l))
2769  l = CONS(ENTITY, e, l);
2770  }
2771  }
2772  }
2773  return l;
2774 }
2775 
2777 {
2779 }
2780 
2781 /* The list of location entities that appear in the basis of the
2782  * transformer predicate.
2783  */
2784 // FI: I am confused with the naming
2786 {
2788 }
2789 
2790 /* The list of array entities that appear in the basis of the
2791  * transformer predicate as array element locations.
2792  */
2794 {
2795  list l = NIL;
2797  Pvecteur b = sc_base(sc), cb;
2798  for(cb=b; !VECTEUR_UNDEFINED_P(cb); cb = vecteur_succ(cb)) {
2799  Variable v = vecteur_var(cb);
2800  entity e = value_to_variable((entity) v);
2801  value val = entity_initial(e);
2802  //if(location_entity_p(e)) {
2803  if(value_reference_p(val)) {
2804  value val = entity_initial(e);
2805  reference r = value_reference(val);
2806  entity a = reference_variable(r);
2807  if(!gen_in_list_p(a, l))
2808  l = CONS(ENTITY, a, l);
2809  }
2810  }
2811  return l;
2812 }
2813 
2814 /* Build a list of values appearing in tf that are linked to a
2815  * variable in dl. These values must be projected if the variables in
2816  * dl are no longer in the scope, e.g. because they were declared in a
2817  * block.
2818  *
2819  * FI: I am not sure about what shuold be done for stubs
2820  */
2822 {
2823  list l = NIL;
2824  //entity m = get_current_module_entity();
2826  Pvecteur b = sc_base(sc), cb;
2827  for(cb=b; !VECTEUR_UNDEFINED_P(cb); cb = vecteur_succ(cb)) {
2828  Variable v = vecteur_var(cb);
2829  entity e = value_to_variable((entity) v);
2830  bool remove_p = false;
2831  if(gen_in_list_p(e, dl))
2832  remove_p = true;
2833  else {
2834  value val = entity_initial(e);
2835  if(value_reference_p(val)) {
2836  reference r = value_reference(val);
2837  e = reference_variable(r);
2838  if(gen_in_list_p(e, dl))
2839  remove_p = true;
2840  }
2841  }
2842  if(remove_p && !gen_in_list_p(v, l))
2843  l = CONS(ENTITY, v, l);
2844  }
2845  return l;
2846 }
float a2sf[2] __attribute__((aligned(16)))
USER generates a user error (i.e., non fatal) by printing the given MSG according to the FMT.
Definition: 3dnow.h:3
void free_transformer(transformer p)
Definition: ri.c:2616
transformer make_transformer(list a1, predicate a2)
Definition: ri.c:2649
predicate make_predicate(Psysteme a1)
Definition: ri.c:1820
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
bool transformer_consistent_p(transformer p)
Definition: ri.c:2622
transformer copy_transformer(transformer p)
TRANSFORMER.
Definition: ri.c:2613
static int count
Definition: SDG.c:519
struct _newgen_struct_entity_ * entity
Definition: abc_private.h:14
bool entity_stub_sink_p(entity e)
test if an entity is a stub sink for a formal parameter e.g.
cons * dup_arguments(cons *args)
Definition: arguments.c:225
void free_arguments(cons *args)
Definition: arguments.c:218
bool arguments_set_equal_p(list a1, list a2)
Set equality of lists a1 and a2.
Definition: arguments.c:181
bool entity_is_argument_p(entity e, cons *args)
Definition: arguments.c:150
cons * arguments_add_entity(cons *a, entity e)
Definition: arguments.c:85
void dump_arguments(cons *args)
entity_name is a macro, hence the code replication
Definition: arguments.c:69
cons * arguments_difference(cons *a1, cons *a2)
set difference: a1 - a2 ; similar to set intersection
Definition: arguments.c:233
list base_to_entities(Pvecteur b)
generate a Newgen list with all entities refered in vector b
Definition: arguments.c:250
list arguments_intersection(list a1, list a2)
Build a new list with all entities occuring in both a1 and a2.
Definition: arguments.c:158
#define CATCH(what)
@ overflow_error
#define UNCATCH(what)
#define TRY
#define value_notzero_p(val)
void const char const char const int
#define VALUE_MONE
#define value_zero_p(val)
int Value
#define VALUE_ONE
int rank_of_variable(Pbase base, Variable var)
this function returns the rank of the variable var in the base 0 encodes TCST, but I do not know why,...
Definition: base.c:497
bool base_contains_variable_p(Pbase b, Variable v)
bool base_contains_variable_p(Pbase b, Variable v): returns true if variable v is one of b's elements...
Definition: base.c:136
Pbase vect_add_variable(Pbase b, Variable v)
package vecteur - routines sur les bases
Definition: base.c:61
Pbase base_union(Pbase b1, Pbase b2)
Pbase base_union(Pbase b1, Pbase b2): compute a new basis containing all elements of b1 and all eleme...
Definition: base.c:428
transformer transformer_dup(transformer t_in)
transformer package - basic routines
Definition: basic.c:49
void transformer_free(transformer t)
Definition: basic.c:68
bool transformer_weak_consistency_p(transformer t)
Interprocedural transformers do not meet all conditions.
Definition: basic.c:626
bool transformer_is_rn_p(transformer t)
Check that transformer t is the canonical representation of the whole afine space defined by its basi...
Definition: basic.c:183
transformer transformer_equality_add(transformer tf, Pvecteur i)
Definition: basic.c:383
transformer empty_transformer(transformer t)
Do not allocate an empty transformer, but transform an allocated transformer into an empty_transforme...
Definition: basic.c:144
transformer transformer_identity()
Allocate an identity transformer.
Definition: basic.c:110
bool transformer_consistency_p(transformer t)
FI: I do not know if this procedure should always return or fail when an inconsistency is found.
Definition: basic.c:612
transformer transformer_empty()
Allocate an empty transformer.
Definition: basic.c:120
transformer move_transformer(transformer t1, transformer t2)
Move arguments and predicate of t2 into t1, free old arguments and predicate of t1,...
Definition: basic.c:939
bool transformer_is_empty_p(transformer t)
Check that transformer t is the canonical representation of an empty transformer.
Definition: basic.c:172
#define A(i, j)
comp_matrice.c
Definition: comp_matrice.c:63
double float_constant_to_double(entity c)
Definition: constant.c:639
entity float_to_entity(float c)
Definition: constant.c:430
bool float_constant_p(entity ent)
ent can be either a numerical or a symbolic float constant
Definition: constant.c:487
basic constant_basic(entity c)
Definition: constant.c:633
#define CONTRAINTE_UNDEFINED_P(c)
#define contrainte_succ(c)
#define contrainte_vecteur(c)
passage au champ vecteur d'une contrainte "a la Newgen"
#define CONTRAINTE_UNDEFINED
Pcontrainte contrainte_make(Pvecteur pv)
Pcontrainte contrainte_make(Pvecteur pv): allocation et initialisation d'une contrainte avec un vecte...
Definition: alloc.c:73
bool vect_constant_p(Pvecteur)
bool vect_constant_p(Pvecteur v): v contains only a constant term, may be zero
Definition: predicats.c:211
transformer transformer_derivative_fix_point(transformer)
Computation of a transitive closure using constraints on the discrete derivative.
Definition: fix_point.c:1067
#define newgen_Psysteme(p)
Definition: effects.h:47
#define chunk_undefined
obsolete
Definition: genC.h:79
void free(void *)
bool success
Definition: gpips-local.h:59
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
list gen_nreverse(list cp)
reverse a list in place
Definition: list.c:304
#define POP(l)
Modify a list pointer to point on the next element of the list.
Definition: newgen_list.h:59
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
#define VOLATILE_FOREACH(_fe_CASTER, _fe_item, _fe_list)
Definition: newgen_list.h:186
size_t gen_length(const list l)
Definition: list.c:150
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
Definition: list.c:344
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
bool gen_in_list_p(const void *vo, const list lx)
tell whether vo belongs to lx
Definition: list.c:734
#define FOREACH(_fe_CASTER, _fe_item, _fe_list)
Apply/map an instruction block on all the elements of a list.
Definition: newgen_list.h:179
void * gen_find_eq(const void *item, const list seq)
Definition: list.c:422
#define MAPL(_map_list_cp, _code, _l)
Apply some code on the addresses of all the elements of a list.
Definition: newgen_list.h:203
#define list_undefined
Undefined list definition :-)
Definition: newgen_list.h:69
#define MAP(_map_CASTER, _map_item, _map_code, _map_list)
Apply/map an instruction block on all the elements of a list (old fashioned)
Definition: newgen_list.h:226
#define B(A)
Definition: iabrev.h:61
int vect_size(Pvecteur v)
package vecteur - reductions
Definition: reductions.c:47
#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
int matrices_to_1D_lattice(Pmatrix, Pmatrix, int, int, int, Value *, Value *)
Under the assumption A x = B, A[n,m] and B[n], compute the 1-D lattice for x_i of x[m] as.
Definition: smith.c:195
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
#define pips_user_warning
Definition: misc-local.h:146
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define pips_internal_error
Definition: misc-local.h:149
#define user_error(fn,...)
Definition: misc-local.h:265
void debug(const int the_expected_debug_level, const char *calling_function_name, const char *a_message_format,...)
ARARGS0.
Definition: debug.c:189
static entity rank
string bool_to_string(bool)
Definition: string.c:243
#define string_undefined
Definition: newgen_types.h:40
#define false
Definition: newgen_types.h:80
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
transformer fprint_transformer(FILE *fd, transformer tf, get_variable_name_t value_name)
Definition: io.c:69
char * dump_value_name(entity e)
char * dump_value_name(e): used as functional argument because entity_name is a macro
Definition: io.c:128
void print_expression(expression e)
no file descriptor is passed to make is easier to use in a debugging stage.
Definition: expression.c:58
#define dump_transformer(t)
Definition: print.c:355
string basic_to_string(basic)
Definition: type.c:87
#define ENTITY_NON_EQUAL_P(e)
#define ENTITY_EQUAL_P(e)
#define MINUS_OPERATOR_NAME
#define ENTITY_LESS_THAN_P(e)
#define NORMALIZE_EXPRESSION(e)
#define binary_intrinsic_expression(name, e1, e2)
#define ENTITY_GREATER_THAN_P(e)
#define ENTITY_LESS_OR_EQUAL_P(e)
#define entity_constant_p(e)
#define ENTITY_GREATER_OR_EQUAL_P(e)
const char * entity_local_name(entity e)
entity_local_name modified so that it does not core when used in vect_fprint, since someone thought t...
Definition: entity.c:453
string entity_global_name(entity e)
Used instead of the macro to pass as formal argument.
Definition: entity.c:464
code entity_code(entity e)
Definition: entity.c:1098
const char * module_local_name(entity e)
Returns the module local user name.
Definition: entity.c:582
void print_entities(list l)
Definition: entity.c:167
bool entity_module_p(entity e)
Definition: entity.c:683
void clean_all_normalized(expression e)
Definition: expression.c:4102
int fortran_string_compare(string fs1, string fs2)
compare pips fortran string constants from the fortran point of view.
Definition: expression.c:101
expression find_ith_argument(list args, int n)
Definition: expression.c:1147
bool expression_reference_p(expression e)
Test if an expression is a reference.
Definition: expression.c:528
bool expression_equal_integer_p(expression exp, int i)
================================================================
Definition: expression.c:1977
reference expression_reference(expression e)
Short cut, meaningful only if expression_reference_p(e) holds.
Definition: expression.c:1832
bool same_expression_p(expression e1, expression e2)
this is slightly different from expression_equal_p, as it will return true for a+b vs b+a
Definition: expression.c:1426
dimension find_ith_dimension(list, int)
This function returns the ith dimension of a list of dimensions.
Definition: type.c:5621
bool same_scalar_location_p(entity, entity)
FI: transferred from semantics (should be used for effect translation as well)
Definition: variable.c:1992
bool float_type_p(type)
Definition: type.c:3263
bool entity_integer_scalar_p(entity)
for variables (like I), not constants (like 1)! use integer_constant_p() for constants
Definition: variable.c:1130
#define formal_offset(x)
Definition: ri.h:1408
@ is_basic_string
Definition: ri.h:576
@ is_basic_float
Definition: ri.h:572
@ is_basic_overloaded
Definition: ri.h:574
@ is_basic_int
Definition: ri.h:571
@ is_basic_logical
Definition: ri.h:573
@ is_basic_complex
Definition: ri.h:575
#define transformer_undefined
Definition: ri.h:2847
#define transformer_undefined_p(x)
Definition: ri.h:2848
#define storage_formal_p(x)
Definition: ri.h:2522
#define basic_int_p(x)
Definition: ri.h:614
#define value_reference(x)
Definition: ri.h:3085
#define normalized_linear_p(x)
Definition: ri.h:1779
#define call_function(x)
Definition: ri.h:709
#define reference_variable(x)
Definition: ri.h:2326
#define TRANSFORMER(x)
TRANSFORMER.
Definition: ri.h:2841
#define TRANSFORMER_(x)
Definition: ri.h:2844
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define dimension_lower(x)
Definition: ri.h:980
#define basic_tag(x)
Definition: ri.h:613
#define type_variable(x)
Definition: ri.h:2949
#define basic_pointer_p(x)
Definition: ri.h:635
#define entity_storage(x)
Definition: ri.h:2794
#define code_declarations(x)
Definition: ri.h:784
#define storage_formal(x)
Definition: ri.h:2524
#define entity_undefined_p(x)
Definition: ri.h:2762
#define entity_undefined
Definition: ri.h:2761
#define expression_undefined
Definition: ri.h:1223
#define entity_name(x)
Definition: ri.h:2790
#define transformer_relation(x)
Definition: ri.h:2873
#define ENTITY_(x)
Definition: ri.h:2758
#define transformer_arguments(x)
Definition: ri.h:2871
#define dimension_upper(x)
Definition: ri.h:982
#define value_reference_p(x)
Definition: ri.h:3083
#define variable_dimensions(x)
Definition: ri.h:3122
#define predicate_system_(x)
Definition: ri.h:2068
#define call_arguments(x)
Definition: ri.h:711
#define entity_type(x)
Definition: ri.h:2792
#define normalized_linear(x)
Definition: ri.h:1781
#define storage_return_p(x)
Definition: ri.h:2516
#define predicate_system(x)
Definition: ri.h:2069
#define storage_return(x)
Definition: ri.h:2518
#define variable_basic(x)
Definition: ri.h:3120
#define basic_logical_p(x)
Definition: ri.h:620
#define entity_initial(x)
Definition: ri.h:2796
struct Ssysteme * Psysteme
void sc_base_remove_variable(Psysteme sc, Variable v)
Definition: sc.c:239
bool sc_consistent_p(Psysteme sc)
bool sc_consistent_p(Psysteme sc): check that sc is well defined, that the numbers of equalities and ...
Definition: sc.c:282
Psysteme sc_make(Pcontrainte leg, Pcontrainte lineg)
Psysteme sc_make(Pcontrainte leg, Pcontrainte lineg): allocation et initialisation d'un systeme d'equ...
Definition: sc.c:78
Psysteme sc_variable_rename(Psysteme s, Variable v_old, Variable v_new)
Psysteme sc_variable_rename(Psysteme s, Variable v_old, Variable v_new): reecriture du systeme s remp...
Definition: sc.c:157
bool sc_weak_consistent_p(Psysteme sc)
check that sc is well defined, that the numbers of equalities and inequalities are consistent with th...
Definition: sc.c:362
Psysteme sc_empty(Pbase b)
Psysteme sc_empty(Pbase b): build a Psysteme with one unfeasible constraint to define the empty subsp...
Definition: sc_alloc.c:319
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
Pbase sc_to_minimal_basis(Psysteme ps)
creation d'une base contenant toutes les variables apparaissant avec des coefficients non-nuls dans l...
Definition: sc_alloc.c:76
Psysteme sc_new(void)
Psysteme sc_new(): alloue un systeme vide, initialise tous les champs avec des valeurs nulles,...
Definition: sc_alloc.c:55
bool sc_empty_p(Psysteme sc)
bool sc_empty_p(Psysteme sc): check if the set associated to sc is the constant sc_empty or not.
Definition: sc_alloc.c:350
Psysteme sc_dup(Psysteme ps)
Psysteme sc_dup(Psysteme ps): should becomes a link.
Definition: sc_alloc.c:176
void sc_safe_build_sc_nredund_1pass(Psysteme volatile *ps)
Psysteme sc_safe_elim_redund(Psysteme ps)
Same as above, but the basis is preserved and sc_empty is returned is the system is not feasible.
#define level
bool efficient_sc_check_inequality_feasibility(Pvecteur v, Psysteme prec)
Value b2
Definition: sc_gram.c:105
Value b1
booleen indiquant quel membre est en cours d'analyse
Definition: sc_gram.c:105
Pcontrainte eq
element du vecteur colonne du systeme donne par l'analyse
Definition: sc_gram.c:108
Psysteme sc_append(Psysteme s1, Psysteme s2)
Psysteme sc_append(Psysteme s1, Psysteme s2): calcul de l'intersection des polyedres definis par s1 e...
void sc_fprint(FILE *fp, Psysteme ps, get_variable_name_t nom_var)
void sc_fprint(FILE * f, Psysteme ps, char * (*nom_var)()): cette fonction imprime dans le fichier po...
Definition: sc_io.c:220
void sc_dump(Psysteme sc)
void sc_dump(Psysteme sc): dump to stderr
Definition: sc_io.c:142
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
Psysteme sc_normalize2(volatile Psysteme ps)
Psysteme sc_normalize2(Psysteme ps): normalisation d'un systeme d'equation et d'inequations lineaires...
Psysteme sc_strong_normalize3(Psysteme ps)
Psysteme sc_strong_normalize5(Psysteme ps, char *(*variable_name)(Variable))
Psysteme sc_strong_normalize4(Psysteme ps, char *(*variable_name)(Variable))
Psysteme sc_strong_normalize4(Psysteme ps, char * (*variable_name)(Variable))
Psysteme sc_strong_normalize2(volatile Psysteme ps)
Psysteme sc_strong_normalize2(Psysteme ps)
Psysteme sc_safe_normalize(Psysteme ps)
Psysteme sc_safe_normalize(Psysteme ps) output : ps, normalized.
Psysteme sc_bounded_normalization(Psysteme ps)
Eliminate trivially redundant integer constraint using a O(n x d^2) algorithm, where n is the number ...
Psysteme sc_strong_normalize(Psysteme ps)
Psysteme sc_strong_normalize(Psysteme ps)
Psysteme sc_elim_var(Psysteme sc, Variable v)
package sur les systemes de contraintes sc
Definition: sc_unaires.c:49
Pvecteur vect_multiply(Pvecteur v, Value x)
Pvecteur vect_multiply(Pvecteur v, Value x): multiplication du vecteur v par le scalaire x,...
Definition: scalaires.c:123
s1
Definition: set.c:247
#define ifdebug(n)
Definition: sg.c:47
void constraints_to_matrices(Pcontrainte, Pbase, Pmatrix, Pmatrix)
=======================================================================
static char * x
Definition: split_file.c:159
Definition: pip__tab.h:25
Definition: pip__tab.h:30
package matrice
Definition: matrix-local.h:63
Pvecteur vecteur
struct Scontrainte * succ
Pcontrainte inegalites
Definition: sc-local.h:71
Pcontrainte egalites
Definition: sc-local.h:70
Pbase base
Definition: sc-local.h:75
int dimension
Definition: sc-local.h:74
le type des coefficients dans les vecteurs: Value est defini dans le package arithmetique
Definition: vecteur-local.h:89
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
Definition: delay.c:253
const char * generic_value_name(entity e)
Definition: prettyprint.c:81
transformer transformer_safe_apply(transformer tf, transformer pre)
Definition: transformer.c:1627
transformer formal_and_actual_parameters_association(call c, transformer pre)
formal_and_actual_parameters_association(call c, transformer pre): Add equalities between actual and ...
Definition: transformer.c:2542
transformer transformer_image_intersection(transformer t1, transformer t2)
allocate a new transformer based on transformer t1 and postcondition t2
Definition: transformer.c:608
list one_to_one_transformers_combine(list tl1, list tl2)
Combine each transformer of transformer list tl1 with the corresponding transformer in transformer li...
Definition: transformer.c:476
list transformer_apply_generic(list tl, transformer pre, bool keep_p)
Generates a new list of postconditions, one for each transformer in tl, unless the postcondition is e...
Definition: transformer.c:1593
list transformer_to_local_values(transformer tf, list dl)
Build a list of values appearing in tf that are linked to a variable in dl.
Definition: transformer.c:2821
bool same_dimension_p(entity actual_array, entity dummy_array, list l_actual_ref, size_t i, transformer context)
This function returns true if the actual array and the dummy array have the same dimension number i,...
Definition: transformer.c:2665
transformer transformer_projection_with_redundancy_elimination(transformer t, list args, Psysteme(*elim)(Psysteme))
It is not clear if this function projects values or variables.
Definition: transformer.c:1322
static list generic_transformer_to_analyzed_locations(transformer tf, bool array_p)
The list of location entities that appear in the basis of the transformer predicate.
Definition: transformer.c:2745
transformer transformer_intersect_range_with_domain(transformer tf)
When tf is used repeatedly in a loop, the range is part of the domain from iteration 2 to the end.
Definition: transformer.c:845
static bool expression_equal_in_context_p(expression e1, expression e2, transformer context)
Fast checks :
Definition: transformer.c:2600
transformer transformer_safe_intersection(transformer t1, transformer t2)
Allocate a new transformer.
Definition: transformer.c:639
transformer transformer_safe_inverse_apply(transformer tf, transformer post)
Definition: transformer.c:1686
bool transformer_strongly_empty_p(transformer t)
If true is returned, the transformer certainly is empty.
Definition: transformer.c:2465
transformer transformer_variables_filter(transformer t, list vl)
Transformers are dealing with variables and/or variable values.
Definition: transformer.c:1827
static transformer transformer_general_intersection(transformer t1, transformer t2, bool image_only)
Allocate a new transformer with constraints in t1 and t2.
Definition: transformer.c:539
list transformers_range(list tfl)
Substitute each transformer in list tfl by its range.
Definition: transformer.c:754
static transformer transformer_safe_general_intersection(transformer t1, transformer t2, bool image_only)
Allocate a new transformer.
Definition: transformer.c:622
list transformer_apply_map(list tl, transformer pre)
Generates a new list of postconditions, one for each transformer in tl, unless the postcondition is e...
Definition: transformer.c:1610
bool transformer_affect_transformer_p(transformer tf1, transformer tf2)
Transformer tf1 affects transformer tf2 if values modified by tf1 appear in any constraint of tf2.
Definition: transformer.c:1870
transformer transformer_normalize(transformer t, int level)
Eliminate (some) rational or integer redundancy.
Definition: transformer.c:932
static int varval_value_name_is_inferior_p(Pvecteur *pvarval1, Pvecteur *pvarval2)
Definition: transformer.c:870
transformer transformer_safe_normalize(transformer t, int level)
Definition: transformer.c:1111
bool transformer_safe_affect_transformer_p(transformer tf1, transformer tf2)
Definition: transformer.c:1894
bool transformer_affect_linear_p(transformer tf, Pvecteur l)
bool transformer_affect_linear_p(transformer tf, Pvecteur l): returns TRUE if there is a state s such...
Definition: transformer.c:1850
transformer transformer_safe_domain_intersection(transformer tf, transformer pre)
If tf and pre are defined, update tf.
Definition: transformer.c:696
transformer simple_addition_to_transformer(entity e, entity e1, entity e2, bool addition_p)
e and e1 and e2 are assumed to be values.
Definition: transformer.c:106
transformer transformer_projection_with_redundancy_elimination_and_check(volatile transformer t, list args, Psysteme(*elim)(Psysteme), bool check_consistency_p)
Definition: transformer.c:1343
transformer transformer_filter(transformer t, list args)
transformer transformer_filter(transformer t, cons * args): projection of t along the hyperplane defi...
Definition: transformer.c:1716
transformer safe_transformer_projection(transformer t, list args)
t may be undefined, args may contain values unrelated to t
Definition: transformer.c:1187
bool transformer_empty_p(transformer t)
If true is returned, the transformer certainly is empty.
Definition: transformer.c:2455
transformer transformer_inverse_apply(transformer tf, transformer post)
transformer transformer_inverse_apply(transformer tf, transformer post): apply transformer tf on prec...
Definition: transformer.c:1657
static bool parametric_transformer_empty_p(transformer t, Psysteme(*normalize)(Psysteme, char *(*)(Variable)))
If true is returned, the transformer certainly is empty.
Definition: transformer.c:2319
transformer transformer_domain_intersection(transformer tf, transformer pre)
Restrict the domain of the relation tf with pre.
Definition: transformer.c:661
transformer generic_equality_to_transformer(entity e, entity f, bool assignment, bool unary_minus_p)
Definition: transformer.c:72
transformer invariant_wrt_transformer(transformer p, transformer tf)
transformer invariant_wrt_transformer(transformer p, transformer tf): Assume that tf is a fix-point o...
Definition: transformer.c:1948
list transformers_combine(list tl1, transformer t2)
Combine each transformer of transformer list tl1 with t2.
Definition: transformer.c:454
list transformers_apply(list tl, transformer pre)
Same as previous one, but with a more normalized name.
Definition: transformer.c:1616
Psysteme no_elim(Psysteme ps)
Definition: transformer.c:1306
transformer args_to_transformer(list le)
Generates a transformer abstracting a totally unknown modification of the values associated to variab...
Definition: transformer.c:1907
transformer transformer_range_intersection(transformer tf, transformer r)
Allocate a new transformer rtf that is tf with its range restricted by the range r.
Definition: transformer.c:830
transformer transformer_safe_image_intersection(transformer t1, transformer t2)
Allocate a new transformer.
Definition: transformer.c:647
transformer transformer_arguments_projection(transformer t)
transformer transformer_projection(transformer t); projection of t along the hyperplane defined by va...
Definition: transformer.c:1285
transformer relation_to_transformer(entity op, entity e1, entity e2, bool veracity)
e and f are assumed to be values.
Definition: transformer.c:139
transformer transformer_safe_combine_with_warnings(transformer tf1, transformer tf2)
Transformer tf1 and tf2 are supposed to be independent but they may interfere, for instance because s...
Definition: transformer.c:493
transformer simple_unary_minus_to_transformer(entity e, entity f)
Definition: transformer.c:65
transformer transformer_combine(volatile transformer t1, transformer t2)
transformer transformer_combine(transformer t1, transformer t2): compute the composition of transform...
Definition: transformer.c:238
transformer transformer_projection_without_check(transformer t, list args, Psysteme(*elim)(Psysteme))
In some cases, you know the projection will result in a non-consistent transformer that will be fixed...
Definition: transformer.c:1334
list transformers_safe_apply(list tl, transformer pre)
returns a list of postconditions, one for each transformer in tl
Definition: transformer.c:1638
transformer transformer_value_substitute(transformer t, entity e1, entity e2)
transformer transformer_value_substitute(transformer t, entity e1, entity e2): if e2 does not appear ...
Definition: transformer.c:1993
bool transformer_value_substitutable_p(transformer t, entity e1, entity e2)
If e1 does not appear in t, it is substitutable.
Definition: transformer.c:2033
transformer transformer_safe_value_substitute(transformer t, entity e1, entity e2)
Definition: transformer.c:2048
transformer transformer_safe_domain(transformer tf)
Definition: transformer.c:815
static bool constant_constraint_check(Pvecteur v, bool is_equation_p)
Check if a transformer is empty.
Definition: transformer.c:2183
list transformer_to_analyzed_arrays(transformer tf)
The list of array entities that appear in the basis of the transformer predicate as array element loc...
Definition: transformer.c:2793
transformer transformer_apply(transformer tf, transformer pre)
transformer transformer_apply(transformer tf, transformer pre): apply transformer tf on precondition ...
Definition: transformer.c:1559
list transformer_to_analyzed_array_locations(transformer tf)
Definition: transformer.c:2776
transformer transformer_safe_range(transformer tf)
Definition: transformer.c:743
list transformers_safe_normalize(list tl, int level)
Definition: transformer.c:1119
static list entity_to_formal_integer_parameters(entity f)
get unsorted list of formal integer parameters of module f by declaration filtering; these parameters...
Definition: transformer.c:2517
transformer transformer_to_domain(transformer tf)
Return the domain of relation tf in a newly allocated transformer.
Definition: transformer.c:772
transformer transformer_range(transformer tf)
Return the range of relation tf in a newly allocated transformer.
Definition: transformer.c:714
Pvecteur simplify_float_constraint(Pvecteur v, bool is_equation_p)
If v is a not a float constraint, retun v.
Definition: transformer.c:2061
transformer transformer_temporary_value_projection(transformer tf)
Definition: transformer.c:1149
transformer transformer_intersection(transformer t1, transformer t2)
tf is a new transformer that receives the constraints in t1 and t2.
Definition: transformer.c:600
list transformer_to_analyzed_locations(transformer tf)
The list of location entities that appear in the basis of the transformer predicate.
Definition: transformer.c:2785
Psysteme simplify_float_constraint_system(Psysteme ps)
Simplify float constraints and possibly detect.
Definition: transformer.c:2146
transformer transformer_return_value_projection(entity f, transformer t)
Project return values that are not linked to function f.
Definition: transformer.c:1220
list transformers_apply_and_keep_all(list tl, transformer pre)
Same as previous one, but with a more normalized name.
Definition: transformer.c:1622
bool transformer_with_temporary_values_p(transformer tf)
Does transformer tf use temporary values?
Definition: transformer.c:1131
transformer simple_equality_to_transformer(entity e, entity f, bool assignment)
e and f are assumed to be values, Type independent.
Definition: transformer.c:58
transformer transformer_projection(transformer t, list args)
values in args must be in t's base
Definition: transformer.c:1267
bool transformer_to_1D_lattice(entity v, transformer pre, Value *gcd_p, Value *c_p)
See if the equations in transformer "pre" constraint variable "v" by v = gcd x + c,...
Definition: transformer.c:2480
list transformer_to_potential_stub_translation(transformer tf, entity m __attribute__((unused)))
Provide a list of variables that might be forward translated into a stub when preconditions are propa...
Definition: transformer.c:2720
static Psysteme sc_identity(Psysteme sc)
Predicate transformer package: sc complexity level.
Definition: transformer.c:52
const char * external_value_name(entity)
Definition: value.c:753
int number_of_temporary_values(void)
Definition: value.c:255
entity global_new_value_to_global_old_value(entity)
Definition: value.c:716
string value_full_name(entity)
for debugging purposes
Definition: value.c:1762
bool float_analyzed_p(void)
Definition: value.c:315
entity entity_to_intermediate_value(entity)
Definition: value.c:879
entity external_entity_to_new_value(entity)
Definition: value.c:1411
bool string_analyzed_p(void)
Definition: value.c:310
entity entity_to_new_value(entity)
Definition: value.c:859
bool entity_has_values_p(entity)
This function could be made more robust by checking the storage of e.
Definition: value.c:911
bool local_temporary_value_entity_p(entity)
Definition: value.c:654
list modified_variables_with_values(void)
Return the list of all analyzed variables which are modified in the current module.
Definition: value.c:1094
entity entity_to_old_value(entity)
Definition: value.c:869
entity value_to_variable(entity)
Get the primitive variable associated to any value involved in a transformer.
Definition: value.c:1624
#define TCST
VARIABLE REPRESENTANT LE TERME CONSTANT.
#define vecteur_val(v)
#define vecteur_var(v)
#define val_of(varval)
#define VECTEUR_NUL
DEFINITION DU VECTEUR NUL.
#define NO_OFL_CTRL
#define VECTEUR_UNDEFINED
char *(* get_variable_name_t)(Variable)
Definition: vecteur-local.h:62
#define vecteur_succ(v)
#define VECTEUR_NUL_P(v)
#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 BASE_UNDEFINED
#define base_dimension(b)
#define BASE_NULLE
MACROS SUR LES BASES.
#define BASE_NULLE_P(b)
#define VECTEUR_UNDEFINED_P(v)
Pvecteur vect_dup(Pvecteur v_in)
Pvecteur vect_dup(Pvecteur v_in): duplication du vecteur v_in; allocation de et copie dans v_out;.
Definition: alloc.c:51
Pbase base_dup(Pbase b)
Pbase base_dup(Pbase b) Note: this function changes the value of the pointer.
Definition: alloc.c:268
Pvecteur vect_new(Variable var, Value coeff)
Pvecteur vect_new(Variable var,Value coeff): allocation d'un vecteur colineaire au vecteur de base va...
Definition: alloc.c:110
void vect_rm(Pvecteur v)
void vect_rm(Pvecteur v): desallocation des couples de v;
Definition: alloc.c:78
Pvecteur vect_add(Pvecteur v1, Pvecteur v2)
package vecteur - operations binaires
Definition: binaires.c:53
Pvecteur vect_substract(Pvecteur v1, Pvecteur v2)
Pvecteur vect_substract(Pvecteur v1, Pvecteur v2): allocation d'un vecteur v dont la valeur est la di...
Definition: binaires.c:75
void vect_add_elem(Pvecteur *pvect, Variable var, Value val)
void vect_add_elem(Pvecteur * pvect, Variable var, Value val): addition d'un vecteur colineaire au ve...
Definition: unaires.c:72
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
void vect_sort_in_place(Pvecteur *pv, int *compare)
void vect_sort_in_place(pv, compare) Pvecteur *pv; int (*compare)(Pvecteur *, Pvecteur *);
Definition: unaires.c:290