PIPS
sc_simplex_feasibility_fixprec.c
Go to the documentation of this file.
1 /*
2 
3  $Id: sc_simplex_feasibility_fixprec.c 1669 2019-06-26 17:24:57Z coelho $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of Linear/C3 Library.
8 
9  Linear/C3 Library is free software: you can redistribute it and/or modify it
10  under the terms of the GNU Lesser General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  any later version.
13 
14  Linear/C3 Library is distributed in the hope that it will be useful, but WITHOUT ANY
15  WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  FITNESS FOR A PARTICULAR PURPOSE.
17 
18  See the GNU Lesser General Public License for more details.
19 
20  You should have received a copy of the GNU Lesser General Public License
21  along with Linear/C3 Library. If not, see <http://www.gnu.org/licenses/>.
22 
23 */
24 
25 /* test du simplex :
26  * Si on compile grace a` "make simp" dans le repertoire
27  * /projects/C3/Linear/Development/polyedre/Tests
28  * alors on peut tester l'execution dans le meme directory
29  * en faisant : make test_simp
30  */
31 
32 #ifdef HAVE_CONFIG_H
33  #include "config.h"
34 #endif
35 
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <stdint.h>
39 #include <string.h>
40 #include <limits.h>
41 
42 #include "boolean.h"
43 #include "arithmetique.h"
44 #include "linear_assert.h"
45 #include "vecteur.h"
46 #include "contrainte.h"
47 #include "sc.h"
48 
49 /* To replace #define NB_EQ and #define NB_INEQ - BC, 2/4/96 -
50  * NB_EQ and NB_INEQ are initialized at the beginning of the main subroutine.
51  * they represent the number of non-NULL constraints in sc. This is useful
52  * to allocate the minimum amount of memory necessary. */
53 static int NB_EQ = 0;
54 static int NB_INEQ = 0;
55 
56 
57 /************************************************************* DEBUG MACROS */
58 /* debug macros may be trigered with -DDEBUG{,1,2}
59  */
60 #ifndef DEBUG
61 #define DEBUG(code) { }
62 #else
63 #undef DEBUG
64 #define DEBUG(code) { code }
65 #endif
66 
67 #ifndef DEBUG1
68 #define DEBUG1(code) { }
69 #else
70 #undef DEBUG1
71 #define DEBUG1(code) { code }
72 #endif
73 
74 #ifndef DEBUG2
75 #define DEBUG2(code) { }
76 #else
77 #undef DEBUG2
78 #define DEBUG2(code) { code }
79 #endif
80 
81 #ifndef DEBUG3
82 #define DEBUG3(code) { }
83 #else
84 #undef DEBUG3
85 #define DEBUG3(code) { code }
86 #endif
87 
88 #ifdef CONTROLING
89 
90 #include <signal.h>
91 #define CONTROLING_TIMEOUT_SIMPLEX
92 
93 static void
94 control_catch_alarm_Simplex (int sig)
95 {
96  alarm(0); /*clear the alarm */
97 }
98 
99 #endif
100 
101 /*************************************************************** CONSTANTS */
102 
103 /* Hmmm. To be compatible with some weird old 16-bit constants... RK */
104 enum {
107  MAX_VAR = 1971, /* nombre max de variables */
108  /* seuil au dela duquel on se mefie d'un overflow
109  */
110 #if defined(LINEAR_VALUE_IS_LONGLONG)
111  MAXVAL = 576,
112 #else
113  MAXVAL = 24
114 #endif
115 };
116 
117 
118 #define DIMENSION sc->dimension
119 #define NUMERO hashtable[h].numero
120 #define SOLUBLE(N) soluble=N;goto FINSIMPLEX ;
121 #define CREVARVISIBLE variables[compteur-3]=compteur-2;
122 #define CREVARCACHEE { variablescachees[nbvariables]=nbvariables + MAX_VAR ; \
123  if (nbvariables ++ >= MAX_VAR) abort(); }
124 
125 /* for tracing macros after expansion:
126  */
127 #define tag(x) /* printf(x); */
128 
129 /*************************************************** MACROS FOR FRACTIONS */
130 /* maybe most of them should be functions?
131  */
132 
133 /* G computes j=gcd(a,b) assuming b>0 and better with a>b.
134  * there can be no artihmetic errors.
135  */
136 #define G(j,a,b) \
137 {tag("G") \
138  j=b; \
139  if (value_gt(b,VALUE_ONE)) \
140  { \
141  Value i=a, k; \
142  while(value_notzero_p(k=value_mod(i,j))) \
143  i=j, j=k; \
144  } \
145  if (value_neg_p(j)) \
146  value_oppose(j); \
147 }
148 
149 #define GCD(j,a,b) \
150 {tag("GCD") \
151  if (value_gt(a,b)) \
152  { G(j,a,b); } \
153  else \
154  { G(j,b,a); } \
155 }
156 /*************************************************** Replacement of macro GCD to GCD_ZERO_CTRL: DN.
157 Explication:
158 - Negative numbers (e.g: lines 238-239, variables x.num, x.den, see older version) may be given to
159 macro GCD(j,a,b). This macro calls G(j,a,b), which assumes b > 0 and better with a>b (means a>b>0).
160 (note that G(j,a,b) works well with 0 < a < b)
161 - If a < 0 then G(j,a,b) still works fine, but GCD(j,a,b) will be wrong:
162  if b > 0, a < 0, then we alwayls have GCD(a,b) = abs(a).
163  moreover, when b < 0, if we put G(a,b) = b => This is confusing!
164 Proposition:
165 - macro GCDZZN(j,a,b): ZxZ)->N+:
166  GCDZZN(a,b) = GCD(value_absolute(a),value_absolute(b)).
167 - Remark, is that the Greatest Commom Divisor of a and b where a = 0 or b = 0 makes no sense.
168  So we should test if a = 0 or b = 0 by macro GCD_ZERO_CTRL(j,a,b) before send it to GCDNNZ(j,a,b).
169  Then we can assume a != 0 and b != 0. If a = 0 or b = 0 then GCD_ZERO_CTRL(a,b) = 1.
170 ****************************************************/
171 
172 #define GCDZZN(j,a,b) \
173 {tag("GCDZZN") \
174  Value i,k; \
175  i = (value_absolute(a)), k = (value_absolute(b)); \
176  while(value_notzero_p(j=value_mod(i,k))) \
177  i=k, k=j; \
178  j = k; \
179 }
180 
181 #define GCD_ZERO_CTRL(j,a,b) \
182 {tag("GCD_ZERO_CTRL") \
183  if ((value_notzero_p(a)) && (value_notzero_p(b))) \
184  { GCDZZN(j,a,b);} \
185  else \
186  {fprintf(stderr,"********************************************************************Error : GCD of number zero !"); \
187  j = (VALUE_ONE);} \
188 }
189 
190 
191 /* SIMPL normalizes rational a/b (b<>0):
192  * divides by gcd(a,b) and returns with b>0
193  * note that there should be no arithmetic exceptions within this macro:
194  * (well, only uminus may have trouble for VALUE_MIN...)
195  * ??? a==0 ? then a = a/b = 0 and b = b/b = 1.
196  */
197 #define SIMPL(a,b) \
198 { \
199  if (value_notone_p(b) && value_notone_p(a) && \
200  value_notmone_p(b) && value_notmone_p(a)) \
201  { \
202  register Value i=a, j=b, k; \
203  while (value_notzero_p(k=value_mod(i,j))) \
204  i=j, j=k; \
205  value_division(a,j), value_division(b,j); \
206  } \
207  if (value_neg_p(b)) \
208  value_oppose(a), value_oppose(b); \
209 }
210 
211 /* SIMPLIFIE normalizes fraction f
212  */
213 #define SIMPLIFIE(f) \
214 {tag("SIMPLIFIE") \
215  if (value_zero_p(f.den)) \
216  { MET_ZERO(f);} \
217  else { \
218  if (value_zero_p(f.num)) \
219  f.den = VALUE_ONE; \
220  else \
221  SIMPL(f.num,f.den); } \
222 }
223 
224 #define AFF(x,y) {x.num=y.num; x.den=y.den;} /* x=y should be ok:-) */
225 #define AFF_PX(x,y) {x->num=y.num; x->den=y.den;}
226 #define INV(x,y) {x.num=y.den; x.den=y.num;} /* x=1/y */
227 /* ??? value_zero_p(y.num)?
228 Then x.num != VALUE_ZERO and x.den = VALUE_ZERO, it's not good at all.(assuming y.den != VALUE_ZERO)
229 This means : test if y = 0 then x = 0 else x = 1/y
230 Change in line 286 : DN.*/
231 
232 #define INV_ZERO_CTRL(x,y) {if (value_zero_p(y.num)) {fprintf(stderr,"ERROR : inverse of fraction zero !"); x.num = VALUE_ZERO; x.den = VALUE_ONE;} else {INV(x,y)}}
233 
234 
235 #define METINFINI(f) {f.num=VALUE_MAX; f.den=VALUE_ONE;}
236 #define MET_ZERO(f) {f.num=VALUE_ZERO; f.den=VALUE_ONE;}
237 #define MET_UN(f) {f.num=VALUE_ONE; f.den=VALUE_ONE;}
238 
239 #define EGAL1(x) (value_eq(x.num,x.den))
240 #define EGAL0(x) (value_zero_p(x.num))
241 #define NUL(x) (value_zero_p(x.num))
242 
243 #define NEGATIF(x) \
244  ((value_neg_p(x.num) && value_pos_p(x.den)) || \
245  (value_pos_p(x.num) && value_neg_p(x.den)))
246 
247 #define POSITIF(x) \
248  ((value_pos_p(x.num) && value_pos_p(x.den)) || \
249  (value_neg_p(x.num) && value_neg_p(x.den)))
250 
251 #define SUP1(x) \
252  ((value_pos_p(x.num) && value_pos_p(x.den) && value_gt(x.num,x.den)) || \
253  (value_neg_p(x.num) && value_neg_p(x.den) && value_gt(x.den,x.num)))
254 
255 #define EGAL_MACRO(x,y,mult) \
256  ((value_zero_p(x.num) && value_zero_p(y.num)) || \
257  (value_notzero_p(x.den) && value_notzero_p(y.den) && \
258  value_eq(mult(x.num,y.den),mult(x.den,y.num))))
259 
260 /*#define INF_MACRO(x,y,mult) (value_lt(mult(x.num,y.den),mult(x.den,y.num)))
261  DN: c'est pas assez pour la comparaison entre deux fractions, qu'est-ce qui se passe
262  s'il y a seulement un denominateur negatif??? Ca donnera un resultat faux.
263  a/b < c/d <=> if b*d > 0 then a*d < b*c else a*d < b*c
264 */
265 
266 #define INF_MACRO(x,y,mult) ((value_pos_p(mult(x.den,y.den)) && value_lt(mult(x.num,y.den),mult(x.den,y.num))) || (value_neg_p(mult(x.den,y.den)) && value_gt(mult(x.num,y.den),mult(x.den,y.num))))
267 
268 /* computes x = simplify(y/z)
269  */
270 
271 /*#define DIV_MACRO(x,y,z,mult) \
272 {tag("DIV_MACRO") \
273  if (value_zero_p(y.num)) \
274  { \
275  MET_ZERO(x); \
276  } \
277  else \
278  { \
279  x.num=mult(y.num,z.den); \
280  x.den=mult(y.den,z.num); \
281  SIMPLIFIE(x); \
282  } \
283 }
284 */
285 
286 /* DN: This macro DIV_MACRO doesn't test if z = 0,
287 then x = y/z means x.num = y.num*z.den and x.den = 0.
288 We better add the test : if z = 0 then x.num = 0 and x.den = 1
289 We try to avoid the denominator equal to 0.
290 */
291 
292 #define DIV_MACRO(x,y,z,mult) \
293 {tag("DIV_MACRO") \
294  if (value_zero_p(y.num)) \
295  { \
296  MET_ZERO(x); \
297  } \
298  else \
299  { \
300  if (value_zero_p(z.num)) \
301  { \
302  fprintf(stderr,"ATTENTION : divided by zero number!"); \
303  MET_ZERO(x); \
304  } \
305  else \
306 { \
307  x.num=mult(y.num,z.den); \
308  x.den=mult(y.den,z.num); \
309  SIMPLIFIE(x); \
310 } \
311  } \
312 }
313 
314 
315 /* computes x = simplify(y*z)
316  */
317 #define MUL_MACRO(x,y,z,mult) \
318 {tag("MUL_MACRO") \
319  if(value_zero_p(y.num) || value_zero_p(z.num)) \
320  MET_ZERO(x) \
321  else \
322  { \
323  x.num=mult(y.num,z.num); \
324  x.den=mult(y.den,z.den); \
325  SIMPLIFIE(x); \
326  } \
327 }
328 
329 /* computes X = simplify(A-B)
330  */
331 #define SUB_MACRO(X,A,B,mult) \
332 { tag("SUB_MACRO") \
333  if (value_zero_p(A.num)) \
334  X.num = value_uminus(B.num), \
335  X.den = B.den; \
336  else if (value_zero_p(B.num)) \
337  { AFF(X, A); } \
338  else if (value_eq(A.den,B.den)) \
339  { \
340  X.num = value_minus(A.num,B.num); \
341  X.den = A.den; \
342  if (value_notone_p(A.den)) \
343  { SIMPLIFIE(X);} \
344  } \
345  else /* must compute the stuff: */ \
346  { \
347  Value ad=A.den, bd=B.den, gd, v; \
348  GCD_ZERO_CTRL(gd,ad,bd); \
349  if (value_notone_p(gd)) value_division(ad,gd), value_division(bd,gd); \
350  X.num = mult(A.num,bd); \
351  v = mult(B.num,ad); \
352  value_substract(X.num,v); \
353  v = mult(ad,bd); \
354  X.den = mult(v,gd); \
355  SIMPLIFIE(X); \
356  } \
357 }
358 
359 /* computes X = A - B*C/D, trying to avoid arithmetic exceptions...
360  */
361 #define FULL_PIVOT_MACRO_SIOUX(X,A,B,C,D,mult) \
362 { \
363  frac u,v,w; tag("FULL_PIVOT_SIOUX") \
364  AFF(u,B); AFF(v,C); INV_ZERO_CTRL(w,D); /* u*v*w == B*C/D */ \
365  SIMPL(u.num,v.den); SIMPL(u.num,w.den); \
366  SIMPL(v.num,u.den); SIMPL(v.num,w.den); \
367  SIMPL(w.num,u.den); SIMPL(w.num,v.den); \
368  u.num = mult(u.num,v.num); /* u*=v */ \
369  u.den = mult(u.den,v.den); \
370  u.num = mult(u.num,w.num); /* u*=w */ \
371  u.den = mult(u.den,w.den); \
372  SUB_MACRO(X,A,u,mult); \
373 }
374 
375 /* computes X = A - B*C/D, but does not try to avoid arithmetic exceptions
376  */
377 #define FULL_PIVOT_MACRO_DIRECT(X,A,B,C,D,mult) \
378 { \
379  Value v; tag("FULL_PIVOT_DIRECT") \
380  X.num = mult(A.num,B.den); \
381  X.num = mult(X.num,C.den); \
382  X.num = mult(X.num,D.num); \
383  v = mult(A.den,B.num); \
384  v = mult(v,C.num); \
385  v = mult(v,D.den); \
386  value_substract(X.num,v); \
387  X.den = mult(A.den,B.den); \
388  X.den = mult(X.den,C.den); \
389  X.den = mult(X.den,D.num); \
390  SIMPLIFIE(X); \
391 }
392 
393 #define direct_p(v) (value_lt(v,MAXVAL))
394 
395 /* computes X = A - B*C/D, with a switch to use SIOUX or DIRECT
396  * thae rationale for the actual condition is quite fuzzy.
397  */
398 #define FULL_PIVOT_MACRO(X,A,B,C,D,mult) \
399 { tag("FULL_PIVOT") \
400  if (direct_p(A.den) && direct_p(B.den) && \
401  direct_p(C.den) && direct_p(value_abs(D.num))) \
402  { \
403  FULL_PIVOT_MACRO_DIRECT(X,A,B,C,D,mult); \
404  } \
405  else \
406  { \
407  FULL_PIVOT_MACRO_SIOUX(X,A,B,C,D,mult); \
408  } \
409 }
410 
411 /* idem if A==0
412  */
413 #define PARTIAL_PIVOT_MACRO_SIOUX(X,B,C,D,mult) \
414 { tag("PARTIAL_PIVOT_SIOUX") \
415  frac u; \
416  MUL_MACRO(u,B,C,mult); /* u=simplify(b*c) */ \
417  DIV_MACRO(X,u,D,mult); /* x=simplify(u/d) */ \
418  value_oppose(X.num); /* x=-x */ \
419 }
420 
421 #define PARTIAL_PIVOT_MACRO_DIRECT(X,B,C,D,mult) \
422 { tag("PARTIAL_PIVOT_DIRECT") \
423  X.num = mult(B.num,C.num); \
424  X.num = mult(X.num,D.den); \
425  value_oppose(X.num); \
426  X.den = mult(B.den,C.den); \
427  X.den = mult(X.den,D.num); \
428  SIMPLIFIE(X); \
429 }
430 
431 #define PARTIAL_PIVOT_MACRO(X,B,C,D,mult) \
432 { \
433  if (direct_p(B.den) && direct_p(C.den) && direct_p(D.num)) \
434  { \
435  PARTIAL_PIVOT_MACRO_DIRECT(X,B,C,D,mult); \
436  } \
437  else \
438  { \
439  PARTIAL_PIVOT_MACRO_SIOUX(X,B,C,D,mult); \
440  } \
441 }
442 
443 /* Pivot : x = a - b c / d
444  * mult is used for multiplying values.
445  * the macro has changed a lot, for indentation and so... FC.
446  * DN: Why don't we test d.num = 0 ? (meanwhile, we do test d.den = 0)
447  */
448 
449 #define PIVOT_MACRO(X,A,B,C,D,mult) \
450 { if (value_zero_p(D.num)) fprintf(stderr,"division of zero!!!"); \
451  DEBUG3(fprintf(stdout, "pivot on: "); \
452  printfrac(A); printfrac(B); printfrac(C); printfrac(D)); \
453  if (value_zero_p(A.num))/* a==0? */ \
454  { \
455  if (value_zero_p(B.num) || value_zero_p(C.num) || value_zero_p(D.den)) \
456  { MET_ZERO(X);} \
457  else /* b*c/d != 0, calculons! */ \
458  { PARTIAL_PIVOT_MACRO(X,B,C,D,mult);} \
459  } \
460  else /* a!=0 */ \
461  if (value_zero_p(B.num) || value_zero_p(C.num) || value_zero_p(D.den)) \
462  { AFF(X,A);} \
463  else /* b*c/d != 0, calculons! */ \
464  if (value_one_p(D.num) && value_one_p(A.den) && \
465  value_one_p(B.den) && value_one_p(C.den)) \
466  { /* no den to compute */ \
467  Value v = mult(B.num,C.num); \
468  v = mult(v,D.den); \
469  X.num=value_minus(A.num,v); \
470  X.den=VALUE_ONE; \
471  } \
472  else /* well, we must compute the full formula! */ \
473  { FULL_PIVOT_MACRO(X,A,B,C,D,mult);} \
474  DEBUG3(fprintf(stdout, " = "); printfrac(X); fprintf(stdout, "\n")); \
475 }
476 
477 /* multiplies two Values of no arithmetic overflow, or throw exception.
478  * this version is local to the simplex.
479  * note that under some defined macros value_mult can expand to
480  * value_protected_mult, which would be ok.
481  */
482 #undef value_protected_mult
483 #define value_protected_mult(v,w) \
484  value_protected_multiply(v,w,THROW(simplex_arithmetic_error))
485 
486 /* Version with and without arithmetic exceptions...
487  */
488 #define MULT(RES,A,B) RES=value_mult(A,B)
489 #define MULTOFL(RES,A,B) RES=value_protected_mult(A,B)
490 
491 #define DIV(x,y,z) DIV_MACRO(x,y,z,value_mult)
492 #define DIVOFL(x,y,z) DIV_MACRO(x,y,z,value_protected_mult)
493 
494 #define MUL(x,y,z) MUL_MACRO(x,y,z,value_mult)
495 #define MULOFL(x,y,z) MUL_MACRO(x,y,z,value_protected_mult)
496 
497 #define SUB(X,A,B) SUB_MACRO(X,A,B,value_mult)
498 #define SUBOFL(X,A,B) SUB_MACRO(X,A,B,value_protected_mult)
499 
500 #define PIVOT(X,A,B,C,D) PIVOT_MACRO(X,A,B,C,D,value_mult)
501 #define PIVOTOFL(X,A,B,C,D) PIVOT_MACRO(X,A,B,C,D,value_protected_mult)
502 
503 #define EGAL(x,y) EGAL_MACRO(x,y,value_mult)
504 #define EGALOFL(x,y) EGAL_MACRO(x,y,value_protected_mult)
505 
506 #define INF(x,y) INF_MACRO(x,y,value_mult)
507 #define INFOFL(x,y) INF_MACRO(x,y,value_protected_mult)
508 static frac frac0={(Value)0,(Value)1,0} ;
509 
510 /* this is already too much...
511  */
512 
513 typedef struct
514 {
516  int numero;
517  int hash ;
520 } hashtable_t;
521 
522 
523 void frac_init(frac *f, int n)
524 {
525  int i;
526  for (i=0;i<n;i++) {
527  f[i].num = (Value)0;
528  f[i].den = (Value)1;
529  f[i].numero = 0;
530  }
531 }
532 
533 void frac_simpl(Value *a,Value *b)
534 {
535  if (value_notone_p(*b) && value_notone_p(*a) &&
536  value_notmone_p(*b) && value_notmone_p(*a))
537  {
538  register long long int lli = ABS(VALUE_TO_LONG(*a)), llj= ABS(VALUE_TO_LONG(*b)),k;
539  if (lli<llj) {
540  long long int tmp = lli;
541  lli=llj;llj=tmp;}
542 
543  while ((k=lli%llj) !=0)
544  lli=llj, llj=k;
545  value_division(*a,llj), value_division(*b,llj);
546  }
547  if (value_neg_p(*b))
548  value_oppose(*a), value_oppose(*b);
549 }
550 
551 /* simplifie normalizes fraction f
552  */
554 {
555  tag("frac_simplifie")
556  if (value_zero_p(f->den))
557  {
558  MET_ZERO((*f));}
559  else {
560  if (value_zero_p(f->num))
561  f->den = VALUE_ONE;
562  else
563  frac_simpl(&(f->num),&(f->den));
564  }
565 }
566 
567 void frac_div(frac *x,frac y,frac z, bool ofl_ctrl)
568 {tag("FRAC_DIV")
569  if (value_zero_p(y.num))
570  {
571  MET_ZERO((*x));
572  }
573  else
574  {
575  if (value_zero_p(z.num))
576  {
577  fprintf(stderr,"ATTENTION : divided by zero number!");
578  MET_ZERO((*x));
579  }
580  else
581  {
582  if (ofl_ctrl == FWD_OFL_CTRL) {
583  x->num=value_protected_mult(y.num,z.den);
584  x->den=value_protected_mult(y.den,z.num);
585  }
586  else {
587  x->num=value_mult(y.num,z.den);
588  x->den=value_mult(y.den,z.num);
589  }
590  frac_simplifie(x);
591  }
592  }
593 }
594 
595 
596 /* computes x = simplify(y*z)
597  */
598 void frac_mul(frac *x,frac y,frac z, bool ofl_ctrl)
599 {tag("FRAC_MUL")
600  if(value_zero_p(y.num) || value_zero_p(z.num))
601  MET_ZERO((*x))
602  else
603  {
604  if (ofl_ctrl == FWD_OFL_CTRL) {
605  x->num=value_protected_mult(y.num,z.num);
606  x->den=value_protected_mult(y.den,z.den);
607  }
608  else {
609  x->num=value_mult(y.num,z.num);
610  x->den=value_mult(y.den,z.den);
611  }
612  frac_simplifie(x);
613  }
614 }
615 void frac_sub(frac *X,frac A,frac B, bool ofl_ctrl)
616 { tag("FRAC_SUB")
617  if (value_zero_p(A.num))
618  X->num = value_uminus(B.num),
619  X->den = B.den;
620  else if (value_zero_p(B.num))
621  { AFF_PX(X, A); }
622  else if (value_eq(A.den,B.den))
623  {
624  X->num = value_minus(A.num,B.num);
625  X->den = A.den;
626  if (value_notone_p(A.den))
627  { frac_simplifie(X);}
628  }
629  else /* must compute the stuff: */
630  {
631  Value ad=A.den, bd=B.den, gd, v;
632  GCD_ZERO_CTRL(gd,ad,bd);
633  if (value_notone_p(gd)) value_division(ad,gd), value_division(bd,gd);
634  if (ofl_ctrl == FWD_OFL_CTRL) {
635  X->num = value_protected_mult(A.num,bd);
636  v = value_protected_mult(B.num,ad);
637  value_substract(X->num,v);
638  v =value_protected_mult(ad,bd);
639  X->den = value_protected_mult(v,gd);
640  }
641  else {
642  X->num = value_mult(A.num,bd);
643  v = value_mult(B.num,ad);
644  value_substract(X->num,v);
645  v =value_mult(ad,bd);
646  X->den = value_mult(v,gd);
647  }
648  frac_simplifie(X);
649  }
650 }
651 
652 void full_pivot_sioux(frac *X,frac A,frac B,frac C,frac D,bool ofl_ctrl)
653 {
654  frac u,v,w;
655  tag("FULL_PIVOT_SIOUX")
656  AFF(u,B); AFF(v,C); INV_ZERO_CTRL(w,D); /* u*v*w == B*C/D */
657  frac_simpl(&(u.num),&(v.den));
658  frac_simpl(&(u.num),&(w.den));
659  frac_simpl(&(v.num),&(u.den));
660  frac_simpl(&(v.num),&(w.den));
661  frac_simpl(&(w.num),&(u.den));
662  frac_simpl(&(w.num),&(v.den));
663  if (ofl_ctrl == FWD_OFL_CTRL) {
664  u.num = value_protected_mult(u.num,v.num); /* u*=v */
665  u.den = value_protected_mult(u.den,v.den);
666  u.num =value_protected_mult(u.num,w.num); /* u*=w */
668  }
669  else {
670  u.num = value_mult(u.num,v.num); /* u*=v */
671  u.den = value_mult(u.den,v.den);
672  u.num =value_mult(u.num,w.num); /* u*=w */
673  u.den =value_mult(u.den,w.den);
674  }
675  frac_sub(X,A,u,ofl_ctrl);
676 
677 }
678 
679 /* computes X = A - B*C/D, but does not try to avoid arithmetic exceptions
680  */
681 void full_pivot_direct(frac *X,frac A,frac B,frac C,frac D,bool ofl_ctrl)
682 {
683  Value v; tag("FULL_PIVOT_DIRECT")
684  if (ofl_ctrl == FWD_OFL_CTRL) {
685  X->num = value_protected_mult(A.num,B.den);
686  X->num = value_protected_mult(X->num,C.den);
687  X->num = value_protected_mult(X->num,D.num);
688  v = value_protected_mult(A.den,B.num);
689  v = value_protected_mult(v,C.num);
690  v = value_protected_mult(v,D.den);
691  value_substract(X->num,v);
692  X->den = value_protected_mult(A.den,B.den);
693  X->den = value_protected_mult(X->den,C.den);
694  X->den = value_protected_mult(X->den,D.num);
695  }
696  else {
697  X->num = value_mult(A.num,B.den);
698  X->num = value_mult(X->num,C.den);
699  X->num = value_mult(X->num,D.num);
700  v = value_mult(A.den,B.num);
701  v = value_mult(v,C.num);
702  v = value_mult(v,D.den);
703  value_substract(X->num,v);
704  X->den = value_mult(A.den,B.den);
705  X->den = value_mult(X->den,C.den);
706  X->den = value_mult(X->den,D.num);
707  }
708  frac_simplifie(X);
709 }
710 void full_pivot(frac *X,frac A,frac B,frac C,frac D,bool ofl_ctrl)
711 { tag("FULL_PIVOT")
712 
713  if (direct_p(A.den) && direct_p(B.den) &&
714  direct_p(C.den) && direct_p(value_abs(D.num)))
715  {
716  full_pivot_direct(X,A,B,C,D,ofl_ctrl);
717  }
718  else
719  {
720  full_pivot_sioux(X,A,B,C,D,ofl_ctrl);
721  }
722 }
723 
724 /* idem if A==0
725  */
726 void partial_pivot_sioux(frac *X,frac B,frac C,frac D,bool ofl_ctrl)
727 {
728  tag("PARTIAL_PIVOT_SIOUX")
729  frac u = {(Value)0,(Value)1,0};
730 
731  frac_mul(&u,B,C,ofl_ctrl); /* u=simplify(b*c) */
732  frac_div(X,u,D,ofl_ctrl); /* x=simplify(u/d) */
733  value_oppose(X->num); /* x=-x */
734 }
735 
736 void partial_pivot_direct(frac *X,frac B,frac C,frac D,bool ofl_ctrl)
737 { tag("PARTIAL_PIVOT_DIRECT")
738  if (ofl_ctrl == FWD_OFL_CTRL) {
739  X->num = value_protected_mult(B.num,C.num);
740  X->num = value_protected_mult(X->num,D.den);
741  value_oppose(X->num);
742  X->den =value_protected_mult(B.den,C.den);
743  X->den = value_protected_mult(X->den,D.num);
744  }
745  else {
746  X->num = value_mult(B.num,C.num);
747  X->num = value_mult(X->num,D.den);
748  value_oppose(X->num);
749  X->den =value_mult(B.den,C.den);
750  X->den = value_mult(X->den,D.num);
751  }
752  frac_simplifie(X);
753 }
754 
755 void partial_pivot(frac *X,frac B,frac C,frac D,bool ofl_ctrl)
756 {
757 
758  if (direct_p(B.den) && direct_p(C.den) && direct_p(D.num))
759  {
760  partial_pivot_direct(X,B,C,D,ofl_ctrl);
761  }
762  else
763  {
764  partial_pivot_sioux(X,B,C,D,ofl_ctrl);
765  }
766 }
767 
768 
769 
770 void pivot(frac *X,frac A,frac B,frac C,frac D,bool ofl_ctrl)
771 {
772  if (value_zero_p(D.num))
773  fprintf(stderr,"division of zero!!!");
774  DEBUG3(fprintf(stdout, "pivot on: ");
775  printfrac(A);
776  printfrac(B);
777  printfrac(C);
778  printfrac(D));
779  if (value_zero_p(A.num))/* a==0? */
780  {
781  if (value_zero_p(B.num) || value_zero_p(C.num) || value_zero_p(D.den))
782  { MET_ZERO((*X)); }
783  else /* b*c/d != 0, calculons! */
784  { partial_pivot(X,B,C,D,ofl_ctrl);}
785  }
786  else /* a!=0 */
787  if (value_zero_p(B.num) || value_zero_p(C.num) || value_zero_p(D.den))
788  { AFF_PX(X,A);}
789  else /* b*c/d != 0, calculons! */
790  if (value_one_p(D.num) && value_one_p(A.den) &&
791  value_one_p(B.den) && value_one_p(C.den))
792  { /* no den to compute */
793  Value v;
794  if (ofl_ctrl == FWD_OFL_CTRL) {
795  v= value_protected_mult(B.num,C.num);
796  v = value_protected_mult(v,D.den);
797  }
798  else {
799  v= value_mult(B.num,C.num);
800  v = value_mult(v,D.den);
801  }
802  X->num=value_minus(A.num,v);
803  X->den=VALUE_ONE;
804  }
805  else /* well, we must compute the full formula! */
806  { full_pivot(X,A,B,C,D,ofl_ctrl);}
807  DEBUG3(fprintf(stdout, " = ");
808  printfrac(X); fprintf(stdout, "\n"));
809 }
810 
811 /* For debugging: */
812 static void __attribute__ ((unused))
813 dump_hashtable(hashtable_t hashtable[]) {
814  int i;
815  for(i=0;i<MAX_VAR;i++)
816  if(VARIABLE_DEFINED_P(hashtable[i].nom))
817  printf("%s %d ", (char *) hashtable[i].nom, hashtable[i].numero),
818  print_Value(hashtable[i].val),
819  printf("\n");
820 }
821 
822 /* Le nombre de variables visibles est : compteur-2
823  * La i-eme variable visible a le numero : variables[i+1]=i
824  * (0 <= i < compteur-2)
825  * Le nombre de variables cachees est : nbvarables
826  * La i-eme variable cachee a le numero : variablescachees[i+1]=MAX_VAR+i-1
827  * (0 <= i < nbvariables)
828  */
829 /* utilise'es par dump_tableau ; a rendre local */
831 
832 static void printfrac(frac x) {
833  printf(" "); print_Value(x.num);
834  printf("/"); print_Value(x.den);
835 }
836 
837 /* For debugging: */
838 static void __attribute__ ((unused))
839 dump_tableau(char *msg, tableau *t, int colonnes) {
840  int i,j, k, w;
841  int max=0;
842  for(i=0;i<colonnes;i++)
843  if(t[i].colonne[t[i].taille-1].numero>max)
844  max=t[i].colonne[t[i].taille-1].numero ;
845  printf("\nTableau (%s): %d colonnes %d lignes\n",msg,colonnes,max) ;
846  printf("%d Variables visibles :",colonnes-2) ;
847  for(i=0;i<colonnes-2;i++) printf(" %d",variables[i]) ;
848  printf("\n%d Variables cachees :",nbvariables);
849  for(i=0;i<nbvariables;i++) printf(" %d",variablescachees[i]) ;
850  printf("\n") ;
851  for(j=0;j<=max;j++) {
852  printf("\nLigne %d ",j) ;
853  for(i=0;i<colonnes;i++) {
854  w=1 ;
855  for(k=0;k<t[i].taille;k++)
856  if(t[i].colonne[k].numero==j)
857  printfrac(t[i].colonne[k]) , w=0 ;
858  if(w!=0)printfrac(frac0) ;
859  }
860  }
861  printf("\n\n");
862 } /* dump_tableau */
863 
864 
865 /* calcule le hashcode d'un pointeur
866  sous forme d'un nombre compris entre 0 et MAX_VAR */
867 static int hash(Variable s)
868 { long l ;
869  l=(long)s % MAX_VAR ;
870  return l ;
871 }
872 
873 /* fonction de calcul de la faisabilite' d'un systeme
874  * d'equations et d'inequations
875  * Auteur : Robert Mahl, Date : janvier 1994
876  *
877  * Retourne :
878  * 1 si le systeme est soluble (faisable) en rationnels,
879  * 0 s'il n'y a pas de solution.
880  *
881  * overflow control :
882  * ofl_ctrl == NO_OFL_CTRL => no overflow control
883  * ofl_ctrl == FWD_OFL_CTRL
884  * => overflow control is made THROW(overflow_error,5)
885  * BC, 13/12/94
886  */
887 bool
889  Psysteme sc,
890  int ofl_ctrl)
891 {
892  Pcontrainte pc, pc_tmp ;
893  Pvecteur pv ;
894  /* All the folowing automatic variables are used when coming back from
895  * longjmp (i.e. in a CATCH block) so they need to be declared volatile as
896  * specified by the documentation*/
897  intptr_t volatile premier_hash = PTR_NIL; /* tete de liste des noms de variables */
898  /* Necessaire de declarer "hashtable" static
899  * pour initialiser tout automatiquement a` 0.
900  * Necessaire de chainer les enregistrements
901  * pour reinitialiser a 0
902  * en sortie de la procedure.
903  */
904  static hashtable_t volatile hashtable[MAX_VAR];
905  Pbase volatile saved_base;
906  int volatile saved_dimension;
907  // tableau * volatile eg = NULL; /* tableau des egalite's */
908  tableau * volatile t = NULL; /* tableau des inegalite's */
909  frac * volatile nlle_colonne = NULL;
910  /* les colonnes 0 et 1 sont reservees au terme const: */
911  int compteur = 2 ;
912  intptr_t i, j, k, h, trouve, ligne, i0, i1, jj, ii ;
913  Value poidsM, valeur, tmpval;
914  intptr_t w ;
915  int soluble; /* valeur retournee par feasible */
916  frac* colo;
917  frac objectif[2] ; /* objectif de max pour simplex :
918  somme des (b2,c2) termes constants "inferieurs" */
919  frac rapport1, rapport2, min1, min2, piv, cc ;
920 
921 
922  DEBUG(static int simplex_sc_counter = 0;)
923  /* count number of calls of this function (at the beginning) */
924 
925  soluble=1;/* int soluble = 1;*/
926 
927  rapport1 =frac0, rapport2 =frac0, min1 =frac0, min2 =frac0, piv=frac0, cc =frac0 ;
928  objectif[0] = frac0, objectif[1] = frac0;
929  i=-1, j=-1, k=-1, h=-1, trouve=-1, ligne=-1, i0=-1, i1=-1, jj=-1, ii=-1;
930  poidsM =-1, valeur=-1, tmpval=-1,w=-1;/*DN.*/
931 
932  /* recompute the base so as to only allocate necessary columns
933  * some bases are quite large although all variables do not appear in
934  * actual contraints. The base is used to store all variants in
935  * preconditions for instance.
936  */
937 
938  saved_base = sc_base(sc);
939  saved_dimension = sc_dimension(sc);
940  sc_base(sc) = BASE_NULLE;
941 
942  sc_creer_base(sc);
943 
944 
945  /* Allocation a priori du tableau des egalites.
946  * "eg" : tableau a "nb_eq" lignes et "dimension"+2 colonnes.
947  */
948  if (ofl_ctrl!=FWD_OFL_CTRL)
949  fprintf(stderr, "[sc_simplexe_feasibility_ofl_ctrl] "
950  "should not (yet) be called with control %d...\n", ofl_ctrl);
951 
952  /* DEBUG(fprintf(stdout, "\n\n IN sc_simplexe_feasibility_ofl_ctrl:\n");
953  sc_fprint(stdout, sc, default_variable_to_string);)*/
954 
955  DEBUG(simplex_sc_counter ++;
956  fprintf(stderr,"BEGIN SIMPLEX : %d th\n",simplex_sc_counter);
957  sc_default_dump(sc);/*sc_default_dump_to_file(); print to file */
958  );
959 
960  /* the input Psysteme must be consistent; this is not the best way to
961  * do this; array bound checks should be added instead in proper places;
962  * no time to do it properly for the moment. BC.
963  */
964  linear_assert("sc is weakly consistent", sc_weak_consistent_p(sc));
965 
966  /* Do not allocate place for NULL constraints */
967  NB_EQ = 0;
968  NB_INEQ = 0;
969  for(pc_tmp = sc->egalites; pc_tmp!= NULL; pc_tmp=pc_tmp->succ)
970  {
971  if (pc_tmp->vecteur != NULL)
972  NB_EQ++;
973  }
974  for(pc_tmp = sc->inegalites; pc_tmp!= NULL; pc_tmp=pc_tmp->succ)
975  {
976  if (pc_tmp->vecteur != NULL)
977  NB_INEQ++;
978  }
979 
981  {
982  /* ifscdebug(2) {
983  fprintf(stderr,"[sc_simplexe_feasibility_ofl_ctrl] arithmetic error\n");
984  }
985  */
986  DEBUG(fprintf(stderr, "arithmetic error or timeout in simplex\n"););
987 
988  for(i = premier_hash ; i != PTR_NIL; i = hashtable[i].succ) {
989  hashtable[i].nom = VARIABLE_UNDEFINED ;
990  hashtable[i].numero = 0 ;
991  hashtable[i].hash = 0 ;
992  hashtable[i].val = (Value)0 ;
993  }
994 
995  for(i=0;i<(3 + NB_INEQ + NB_EQ + DIMENSION); i++)
996  free(t[i].colonne);
997  free(t);
998  free(nlle_colonne);
999 
1000  /* restore initial base */
1001  base_rm(sc_base(sc));
1002  sc_base(sc) = saved_base;
1003  sc_dimension(sc) = saved_dimension;
1004 
1005 #ifdef CONTROLING
1006  alarm(0); /*clear the alarm*/
1007 #endif
1008 
1009  if (ofl_ctrl == FWD_OFL_CTRL) {
1010  RETHROW(); /*rethrow whatever the exception is*/
1011  }
1012  /*THROW(user_exception_error);*/
1013  /* need CATCH(user_exception_error) before calling sc_simplexe_feasibility)*/
1014  ifscdebug(5) {fprintf(stderr,"DNDNDN WARNING: Exception not treated, return feasible!");}
1015  return true; /* if don't catch exception, then default is feasible */
1016 
1017  /*if (ofl_ctrl == FWD_OFL_CTRL) */
1018  /*THROW(overflow_error);*/
1019 
1020  /*return true; default is feasible */
1021  }/* of CATCH(simplex_arithmetic_error)*/
1022 
1023  /*begin of TRY*/
1024 
1025 #ifdef CONTROLING
1026  /*start the alarm*/
1027  if (CONTROLING_TIMEOUT_SIMPLEX) {
1028  signal(SIGALRM, controling_catch_alarm_Simplex);
1029  alarm(CONTROLING_TIMEOUT_SIMPLEX);
1030  } /*else nothing*/
1031 #endif
1032 
1033 
1034 
1035  /* Allocation a priori du tableau du simplex "t" par
1036  * colonnes. Soit
1037  * "dimension" le nombre de variables, la taille maximum
1038  * du tableau est de (1 + nb_ineq) lignes
1039  * et de (2 + dimension + nb_ineq + nb_eq) colonnes
1040  * On y ajoute en fait le double du nombre d'egalite's.
1041  * Ce tableau sera rempli de la facon suivante :
1042  * - ligne 0 : critere d'optimisation
1043  * - lignes 1 a nb_ineq : les inequations
1044  * - colonne 0 : le terme constant (composante de poids 1)
1045  * - colonne 1 : le terme constant (composante de poids M)
1046  * - colonnes 2 et suivantes : les elements initiaux
1047  * et les termes d'ecart
1048  * Le tableau a une derniere colonne temporaire pour
1049  * pivoter un vecteur unitaire.
1050  * */
1051 
1052  t = (tableau*)malloc((3 + NB_INEQ + NB_EQ + DIMENSION)*sizeof(tableau));
1053  for(i=0;i<(3 + NB_INEQ + NB_EQ + DIMENSION); i++) {
1054  t[i].colonne= (frac*) malloc((4 + 2*NB_EQ + NB_INEQ)*sizeof(frac)) ;
1055  frac_init(t[i].colonne,4 + 2*NB_EQ + NB_INEQ);
1056  t[i].existe = 0 ;
1057  t[i].taille = 1 ;
1058  t[i].colonne[0].numero = 0 ;
1059  t[i].colonne[0].num = VALUE_ZERO ;
1060  t[i].colonne[0].den = VALUE_ONE ;
1061  }
1062  nbvariables= 0 ;
1063  /* Initialisation de l'objectif */
1064 
1065  for(i=0;i<=1;i++)
1066  objectif[i].num=VALUE_ZERO, objectif[i].den=VALUE_ONE;
1067 
1068  DEBUG2(dump_hashtable(hashtable);)
1069 
1070  /* Entree des inegalites dans la table */
1071 
1072  for(pc=sc->inegalites, ligne=1; pc!=0; pc=pc->succ, ligne++)
1073  {
1074  pv=pc->vecteur;
1075  if (pv!=NULL) /* skip if empty */
1076  {
1077  valeur = VALUE_ZERO ;
1078  poidsM = VALUE_ZERO ;
1079  for(; pv !=0 ; pv=pv->succ)
1080  if(vect_coeff(pv->var,sc_base(sc)))
1081  value_addto(poidsM,pv->val) ;
1082  else
1083  valeur = value_uminus(pv->val) ; /* val terme const */
1084 
1085  for(pv=pc->vecteur ; pv !=0 ; pv=pv->succ) {
1086  if(value_notzero_p(vect_coeff(pv->var,sc_base(sc)))) {
1087  h = hash((Variable) pv->var) ; trouve=0 ;
1088  while (VARIABLE_DEFINED_P(hashtable[h].nom)) {
1089  if (hashtable[h].nom==pv->var) {
1090  trouve=1 ;
1091  break ;
1092  }
1093  else { h = (h+1) % MAX_VAR ; }
1094  }
1095  if(!trouve) {
1096  hashtable[h].succ=premier_hash ;
1097  premier_hash = h ;
1098  hashtable[h].val = VALUE_NAN ;
1099  hashtable[h].numero=compteur++ ;
1100  hashtable[h].nom=pv->var ;
1101  CREVARVISIBLE ;
1102  }
1103  linear_assert("current NUMERO in bound",
1104  (NUMERO) < (3 + NB_INEQ + NB_EQ + DIMENSION));
1105  if (value_neg_p(poidsM) ||
1106  (value_zero_p(poidsM) && value_neg_p(valeur)))
1107  {value_addto(t[NUMERO].colonne[0].num,pv->val),
1108  t[NUMERO].colonne[0].den = VALUE_ONE ;}
1109  t[NUMERO].existe = 1 ;
1110  t[NUMERO].colonne[t[NUMERO].taille].numero=ligne ;
1111  if(value_neg_p(poidsM) ||
1112  (value_zero_p(poidsM) && value_neg_p(valeur)))
1113  tmpval = value_uminus(pv->val) ;
1114  else tmpval = pv->val ;
1115  t[NUMERO].colonne[t[NUMERO].taille].num = tmpval ;
1117  t[NUMERO].taille++ ;
1118  }
1119  }
1120 
1121  /* Creation de variable d'ecart ? */
1122  if(value_neg_p(poidsM) ||
1123  (value_zero_p(poidsM) && value_neg_p(valeur))) {
1124  DEBUG1(dump_tableau("cre var ec", t, compteur);)
1125  i=compteur++ ;
1126  CREVARVISIBLE ;
1127  t[i].existe = 1 ; t[i].taille = 2 ;
1128  t[i].colonne[0].num = VALUE_ONE ;
1129  t[i].colonne[0].den = VALUE_ONE ;
1130  DEBUG1(printf("ligne ecart = %ld, colonne %ld\n",ligne,i);)
1131  t[i].colonne[1].numero = ligne ;
1132  t[i].colonne[1].num = VALUE_MONE ;
1133  t[i].colonne[1].den = VALUE_ONE ;
1134  value_oppose(poidsM);
1136  value_addto(objectif[0].num,valeur) ;
1137  value_addto(objectif[1].num,poidsM) ;
1138  }
1139 
1140  /* Mise a jour des colonnes 0 et 1 */
1141  t[0].colonne[t[0].taille].numero = ligne ;
1142  t[0].colonne[t[0].taille].den = VALUE_ONE ;
1143  t[0].colonne[t[0].taille].num = valeur ;
1144  t[0].existe = 1 ;
1145  t[0].taille++ ;
1146  /* Element de poids M en 1ere colonne */
1147  t[1].colonne[t[1].taille].numero = ligne ;
1148  t[1].colonne[t[1].taille].num = poidsM ;
1149  t[1].colonne[t[1].taille].den = VALUE_ONE ;
1150  t[1].existe = 1 ;
1151  t[1].taille++ ;
1152  /* Creation d'une colonne cachee */
1153  CREVARCACHEE ;
1154  DEBUG1(dump_tableau("cre col cach", t, compteur);)
1155  }
1156  else
1157  ligne--;
1158  }
1159 
1160  DEBUG1(dump_hashtable(hashtable);)
1161  DEBUG1(dump_tableau("avant sol prov", t, compteur);)
1162 
1163  /* NON IMPLEMENTE' */
1164 
1165  /* Elimination de Gauss-Jordan dans le tableau "eg"
1166  * Chaque variable a` eliminer est marquee
1167  * eg[ ].existe = 2
1168  * Si le processus d'elimination ne revele pas
1169  * d'impossibilite', il est suivi du processus
1170  * d'elimination dans les inegalites.
1171  */
1172  /* FIN DE NON IMPLEMENTE' */
1173 
1174  /* SOLUTION PROVISOIRE
1175  * Pour chaque egalite on introduit
1176  * 2 inequations complementaires
1177  */
1178 
1179  for(pc=sc->egalites ; pc!=0; pc=pc->succ, ligne++)
1180  {
1181  /* Added by bc: do nothing for nul equalities */
1182  if (pc->vecteur == NULL) continue;
1183 
1184  valeur = VALUE_ZERO ;
1185  poidsM = VALUE_ZERO ;
1186  for(pv=pc->vecteur ; pv !=0 ; pv=pv->succ)
1187  if(vect_coeff(pv->var,sc_base(sc)))
1188  value_addto(poidsM,pv->val) ;
1189  else valeur = value_uminus(pv->val); /* val terme const */
1190  for(pv=pc->vecteur ; pv !=0 ; pv=pv->succ) {
1191  if(vect_coeff(pv->var,sc_base(sc))) {
1192  h = hash((Variable) pv->var) ; trouve=0 ;
1193  while (VARIABLE_DEFINED_P(hashtable[h].nom)) {
1194  if (hashtable[h].nom==pv->var) {
1195  trouve=1 ;
1196  break ;
1197  }
1198  else { h = (h+1) % MAX_VAR ; }
1199  }
1200  if(!trouve) {
1201  hashtable[h].succ=premier_hash ;
1202  premier_hash = h ;
1203  hashtable[h].val = VALUE_NAN ;
1204  hashtable[h].numero=compteur++ ;
1205  CREVARVISIBLE ;
1206  hashtable[h].nom=pv->var ;
1207  }
1208  linear_assert("current NUMERO in bound",
1209  (NUMERO) < (3 + NB_INEQ + NB_EQ + DIMENSION));
1210  if(value_neg_p(poidsM) ||
1211  (value_zero_p(poidsM) && value_neg_p(valeur)))
1212  {value_addto(t[NUMERO].colonne[0].num,pv->val),
1213  t[NUMERO].colonne[0].den = VALUE_ONE ;}
1214  t[NUMERO].existe = 1 ;
1215  t[NUMERO].colonne[t[NUMERO].taille].numero=ligne ;
1216  if(value_neg_p(poidsM) ||
1217  (value_zero_p(poidsM) && value_neg_p(valeur)))
1218  tmpval = value_uminus(pv->val);
1219  else tmpval = pv->val ;
1220  t[NUMERO].colonne[t[NUMERO].taille].num = tmpval ;
1222  t[NUMERO].taille++ ;
1223  }
1224  }
1225  /* Creation de variable d'ecart ? */
1226  if(value_neg_p(poidsM) ||
1227  (value_zero_p(poidsM) && value_neg_p(valeur))) {
1228  i=compteur++ ;
1229  CREVARVISIBLE ;
1230  t[i].existe = 1 ; t[i].taille = 2 ;
1231  t[i].colonne[0].num = VALUE_ONE ;
1232  t[i].colonne[0].den = VALUE_ONE ;
1233  t[i].colonne[1].numero = ligne ;
1234  t[i].colonne[1].num = VALUE_MONE ;
1235  t[i].colonne[1].den = VALUE_ONE ;
1236  value_oppose(poidsM),
1238  value_addto(objectif[0].num,valeur) ;
1239  value_addto(objectif[1].num,poidsM) ;
1240  }
1241  /* Mise a jour des colonnes 0 et 1 */
1242  t[0].colonne[t[0].taille].numero = ligne ;
1243  t[0].colonne[t[0].taille].num = valeur ;
1244  t[0].colonne[t[0].taille].den = VALUE_ONE ;
1245  t[0].existe = 1 ;
1246  t[0].taille++ ;
1247  /* Element de poids M en 1ere colonne */
1248  t[1].colonne[t[1].taille].numero = ligne ;
1249  t[1].colonne[t[1].taille].num = poidsM ;
1250  t[1].colonne[t[1].taille].den = VALUE_ONE ;
1251  t[1].existe = 1 ;
1252  t[1].taille++ ;
1253  /* Creation d'une colonne cachee */
1254  CREVARCACHEE ;
1255  DEBUG1(dump_tableau("cre col cach 2", t, compteur);)
1256  }
1257 
1258  for(pc=sc->egalites ; pc!=0; pc=pc->succ, ligne++)
1259  {
1260  /* Added by bc: do nothing for nul equalities */
1261  if (pc->vecteur == NULL) continue;
1262 
1263  valeur = VALUE_ZERO ;
1264  poidsM = VALUE_ZERO ;
1265  for(pv=pc->vecteur ; pv !=0 ; pv=pv->succ)
1266  if(vect_coeff(pv->var,sc_base(sc)))
1267  value_substract(poidsM, pv->val) ;
1268  else
1269  valeur = pv->val ; /* val terme const */
1270 
1271  for(pv=pc->vecteur ; pv !=0 ; pv=pv->succ) {
1272  if (vect_coeff(pv->var,sc_base(sc))) {
1273  h = hash((Variable) pv->var) ; trouve=0 ;
1274  while (VARIABLE_DEFINED_P(hashtable[h].nom)) {
1275  if (hashtable[h].nom==pv->var) {
1276  trouve=1 ;
1277  break ;
1278  }
1279  else { h = (h+1) % MAX_VAR ; }
1280  }
1281  if(!trouve) {
1282  hashtable[h].succ=premier_hash ;
1283  premier_hash = h ;
1284  hashtable[h].val = VALUE_NAN ;
1285  hashtable[h].numero=compteur++ ;
1286  hashtable[h].nom=pv->var ;
1287  CREVARVISIBLE ;
1288  }
1289  assert((NUMERO) < (3 + NB_INEQ + NB_EQ + DIMENSION));
1290  if(value_neg_p(poidsM) ||
1291  (value_zero_p(poidsM) && value_neg_p(valeur)))
1292  {value_substract(t[NUMERO].colonne[0].num,pv->val),
1293  t[NUMERO].colonne[0].den = VALUE_ONE ;}
1294  t[NUMERO].existe = 1 ;
1295  t[NUMERO].colonne[t[NUMERO].taille].numero=ligne ;
1296  if(value_neg_p(poidsM) ||
1297  (value_zero_p(poidsM) && value_neg_p(valeur)))
1298  tmpval = pv->val ;
1299  else tmpval = value_uminus(pv->val) ;
1300  t[NUMERO].colonne[t[NUMERO].taille].num = tmpval ;
1302  t[NUMERO].taille++ ;
1303  }
1304  }
1305  /* Creation de variable d'ecart ? */
1306  if(value_neg_p(poidsM) ||
1307  (value_zero_p(poidsM) && value_neg_p(valeur))) {
1308  i=compteur++ ;
1309  CREVARVISIBLE ;
1310  t[i].existe = 1 ; t[i].taille = 2 ;
1311  t[i].colonne[0].num = VALUE_ONE ;
1312  t[i].colonne[0].den = VALUE_ONE ;
1313  t[i].colonne[1].numero = ligne ;
1314  t[i].colonne[1].num = VALUE_MONE ;
1315  t[i].colonne[1].den = VALUE_ONE ;
1316  value_oppose(poidsM),
1318  value_addto(objectif[0].num,valeur) ;
1319  value_addto(objectif[1].num,poidsM) ;
1320  }
1321  /* Mise a jour des colonnes 0 et 1 */
1322  t[0].colonne[t[0].taille].numero = ligne ;
1323  t[0].colonne[t[0].taille].num = valeur ;
1324  t[0].colonne[t[0].taille].den = VALUE_ONE ;
1325  t[0].existe = 1 ;
1326  t[0].taille++ ;
1327  /* Element de poids M en 1ere colonne */
1328  t[1].colonne[t[1].taille].numero = ligne ;
1329  t[1].colonne[t[1].taille].num = poidsM ;
1330  t[1].colonne[t[1].taille].den = VALUE_ONE ;
1331  t[1].existe = 1 ;
1332  t[1].taille++ ;
1333  /* Creation d'une colonne cachee */
1334  CREVARCACHEE ;
1335  DEBUG1(dump_tableau("cre col cach 3", t, compteur);)
1336  }
1337 
1338  /* FIN DE SOLUTION PROVISOIRE */
1339 
1340  /* Algorithme du simplexe - methode primale simple.
1341  * L'objectif est d'etudier la faisabilite' d'un systeme
1342  * de contraintes sans trouver l'optimum.
1343  * Les contraintes ont la forme : a x <= b
1344  * et d x = e
1345  * La methode de resolution procede comme suit :
1346  *
1347  * 1) Creer un tableau
1348  * a b
1349  * d e
1350  * Eliminer autant de variables que posible par
1351  * Gauss-Jordan
1352  *
1353  * 2) Travailler sur les inegalites seulement.
1354  * Poser x = x' - M 1
1355  * ou` 1 est le vecteur de chiffres 1.
1356  * Les inequations prennent alors la forme :
1357  * a1 x <= b1 + M c1
1358  * a2 x >= b2 + M c2
1359  * avec c1 et c2 positifs
1360  * On introduit les variables d'ecart y (autant que
1361  * d'inequations du 2eme type) et on cherche
1362  * max{1(a2 x - y) | x,y >= 0 ; a1 x <= b1 + M c1 ;
1363  * a2 x - y <= b2 + M c2}
1364  * On cree donc le tableau :
1365  * 0 0 1 a2 1 0 0
1366  * b1 c1 a1 0 I 0
1367  * b2 c2 a2 -I 0 I
1368  *
1369  * On applique ensuite l'algorithme du simplex en
1370  * se souvenant que c1 et c2 sont a multiplier par un
1371  * infiniment grand.
1372  * Si l'optimum est egal a (1 b2 , 1 c2), il y a une
1373  * solution.
1374  *
1375  * Structures de donnees : on travaille sur des tableaux
1376  * de fractions rationnelles.
1377  */
1378  nlle_colonne=(frac *) malloc((4 + 2*NB_EQ + NB_INEQ+1)*sizeof(frac)) ;
1379  frac_init(nlle_colonne,4 + 2*NB_EQ + NB_INEQ);
1380  while(1) {
1381 
1382  /* Recherche d'un nombre negatif 1ere ligne
1383  */
1384  for(j=2, jj= -1 ;j<compteur;j++)
1385  if(t[j].existe && NEGATIF(t[j].colonne[0]))
1386  {
1387  jj=j ; break ;
1388  }
1389 
1390  /* Terminaison */
1391  if(jj == -1) {
1392  bool cond;
1393  DEBUG1({
1394  printf ("solution :\n") ;
1395  dump_tableau("sol", t, compteur) ;
1396  printf("objectif : "); printfrac(objectif[0]) ;
1397  printfrac(objectif[1]) ; printf("\n") ;
1398  });
1399 
1400  if (ofl_ctrl == FWD_OFL_CTRL)
1401  cond = EGALOFL(objectif[0],t[0].colonne[0]) &&
1402  EGALOFL(objectif[1],t[1].colonne[0]);
1403  else
1404  cond = EGAL(objectif[0],t[0].colonne[0]) &&
1405  EGAL(objectif[1],t[1].colonne[0]);
1406 
1407  if(cond)
1408  {
1409  DEBUG1(printf("Systeme soluble (faisable) en rationnels\n");)
1410  SOLUBLE(1)
1411  }
1412  else
1413  {
1414  DEBUG1(printf("Systeme insoluble (infaisable)\n");)
1415  SOLUBLE(0)
1416  }
1417  DEBUG1(printf("fin\n");)
1418  }
1419 
1420  DEBUG1(printf("1 : jj= %ld\n",jj);
1421  dump_tableau("avant ch pivot", t, compteur);)
1422 
1423  DEBUG1(min1.num = 32700; min1.den=1; min2=min1;)
1424 
1425  /* Recherche de la ligne de pivot
1426  * si ii==-1, pas encore trouve, min{1,2} non valides...
1427  */
1428  for(i=1, i0=1, i1=1, ii=-1 ; i<t[jj].taille ; )
1429  {
1430  bool cond;
1431 
1432  DEBUG1(fprintf(stdout, "itering i{,0,1} = %ld %ld %ld\n",
1433  i, i0, i1);)
1434 
1435  if(((i0<t[0].taille && t[jj].colonne[i].numero <=
1436  t[0].colonne[i0].numero) || i0>=t[0].taille)
1437  && ((i1<t[1].taille && t[jj].colonne[i].numero <=
1438  t[1].colonne[i1].numero) || i1>=t[1].taille)) {
1439  if( POSITIF(t[jj].colonne[i])) {
1440  /* computing rapport{1,2}
1441  */
1442  frac f1 =
1443  (i0<t[0].taille &&
1444  t[jj].colonne[i].numero==t[0].colonne[i0].numero)?
1445  t[0].colonne[i0]:frac0;
1446  frac f2 = t[jj].colonne[i];
1447  frac f3 =
1448  (i1<t[1].taille &&
1449  t[jj].colonne[i].numero==t[1].colonne[i1].numero)?
1450  t[1].colonne[i1]:frac0;
1451 
1452  frac_div(&rapport1,f1,f2,ofl_ctrl);
1453  frac_div(&rapport2,f3,f2,ofl_ctrl);
1454 
1455 
1456  DEBUG1(fprintf(stdout, "rapports:");
1457  printfrac(rapport1);
1458  printfrac(min1);
1459  printfrac(rapport2);
1460  printfrac(min2);
1461  fprintf(stdout, "\nand cond: ");)
1462 
1463  if (ii==-1)
1464  cond = true; /* first assignment is forced */
1465  else
1466  if (ofl_ctrl == FWD_OFL_CTRL)
1467  cond = INFOFL(rapport2,min2) ||
1468  (EGALOFL(rapport2,min2) &&
1469  INFOFL(rapport1,min1));
1470  else
1471  cond = INF(rapport2,min2) ||
1472  (EGAL(rapport2,min2) &&
1473  INF(rapport1,min1));
1474 
1475  DEBUG1(fprintf(stdout, "%d\n", cond);)
1476 
1477  if (cond) {
1478  AFF(min1,rapport1) ;
1479  AFF(min2,rapport2) ;
1480  AFF(piv,t[jj].colonne[i]) ;
1481  frac_simplifie(&piv);
1482  ii=t[jj].colonne[i].numero ;
1483  }
1484  } /* POSITIF(t[jj].colonne[i])) */
1485  i++ ;
1486  }
1487  else {
1488  if(i0<t[0].taille && /* it may skip over */
1489  t[jj].colonne[i].numero> t[0].colonne[i0].numero) i0++ ;
1490  if(i1<t[1].taille &&
1491  t[jj].colonne[i].numero > t[1].colonne[i1].numero) i1++ ;
1492  }
1493 
1494  DEBUG1(printf("i=%ld i0=%ld i1=%ld %d %d %d\n",
1495  i,i0,i1,
1496  i<t[jj].taille? t[jj].colonne[i].numero: -1,
1497  i0<t[0].taille? t[0].colonne[i0].numero: -1,
1498  i1<t[1].taille? t[1].colonne[i1].numero: -1);)
1499  }
1500 
1501  /* Cas d'impossibilite' */
1502  if(ii==-1) {
1503  DEBUG1(dump_tableau("sol infinie", t, compteur);
1504  fprintf(stderr,"Solution infinie\n");)
1505  SOLUBLE(1)
1506  }
1507 
1508  /* Modification des numeros des variables */
1509 
1510  j = variables[jj-2];
1511  k = variablescachees[ii-1];
1512  variables[jj-2] = k;
1513  variablescachees[ii-1] = j;
1514 
1515  DEBUG2({
1516  printf("Visibles :");
1517  for(j=0;j<compteur-2;j++)
1518  printf(" %d",variables[j]);
1519  printf("\nCachees :");
1520  for(j=0;j<nbvariables;j++)
1521  printf(" %d",variablescachees[j]);
1522  printf("\n");
1523  });
1524 
1525  /* Pivot autour de la ligne ii / colonne jj
1526  * Dans ce qui suit, j = colonne courante,
1527  * k = numero element dans la nouvelle colonne
1528  * qui remplacera la colonne j,
1529  * cc = element (colonne j, ligne ii)
1530  */
1531  DEBUG(printf("Pivoter %ld %ld\n",ii,jj);)
1532 
1533  /* Remplir la derniere colonne temporaire de t
1534  * qui contient un 1 en position ligne ii
1535  */
1536  t[compteur].taille = 2 ;
1537  t[compteur].colonne[0].numero = 0 ;
1538  t[compteur].colonne[0].num = VALUE_ZERO ;
1539  t[compteur].colonne[0].den = VALUE_ONE ;
1540  t[compteur].colonne[1].numero = ii;
1541  t[compteur].colonne[1].num = VALUE_ONE ;
1542  t[compteur].colonne[1].den = VALUE_ONE ;
1543  t[compteur].existe = 1 ;
1544 
1545  for(j=0 ; j<=compteur ; j=(j==(jj-1))?(j+2):(j+1)) {
1546  if(t[j].existe)
1547  {
1548  k=0 ;
1549  cc.num= VALUE_ZERO ;
1550  cc.den= VALUE_ONE ;
1551  for(i=1;i<t[j].taille;i++)
1552  if(t[j].colonne[i].numero==ii)
1553  { AFF(cc,t[j].colonne[i]); break ; }
1554  else if(t[j].colonne[i].numero>ii)
1555  {cc.num= VALUE_ZERO ; cc.den=VALUE_ONE ; break ; }
1556  for(i=0,i1=0;i<t[j].taille || i1<t[jj].taille ;) {
1557 
1558  DEBUG2(printf("k=%ld, j=%ld, i=%ld i1=%ld\n",k,j,i,i1);
1559  printf("fractions: ");
1560  printfrac(t[j].colonne[i]) ;
1561  printfrac(t[jj].colonne[i1]) ;
1562  if (value_zero_p(t[jj].colonne[i1].den))
1563  printf("ATTENTION fraction 0/0 ");/*DN*/
1564  printfrac(cc);
1565  printfrac(piv);)
1566 
1567  if(i<t[j].taille &&
1568  i1<t[jj].taille &&
1569  t[j].colonne[i].numero == t[jj].colonne[i1].numero)
1570  {
1571  if(t[j].colonne[i].numero == ii) {
1572  AFF(nlle_colonne[k],t[j].colonne[i]);
1573  } else {
1574  frac *n = &nlle_colonne[k],
1575  *a = &t[j].colonne[i],
1576  *b = &t[jj].colonne[i1];
1577  pivot(n, (*a), (*b), cc, piv,ofl_ctrl);
1578  }
1579 
1580  if(i==0||nlle_colonne[k].num!=0) {
1581  nlle_colonne[k].numero = t[j].colonne[i].numero ;
1582  k++ ;
1583  }
1584 
1585  i++ ; i1++ ;
1586  }
1587  else
1588  if(i>=t[j].taille ||
1589  (i1<t[jj].taille &&
1590  t[j].colonne[i].numero > t[jj].colonne[i1].numero))
1591  {
1592  DEBUG1(
1593  if (i<t[j].taille)
1594  {
1595  printf("t[j].colonne[i].numero > "
1596  "t[jj].colonne[i1].numero , "
1597  "k=%ld, j=%ld, i=%ld i1=%ld\n",
1598  k,j,i,i1);
1599  printf("j = %ld t[j].taille=%d , "
1600  "t[jj].taille=%d\n",
1601  j,t[j].taille,t[jj].taille);
1602  printf("t[j].colonne[i].numero=%d , "
1603  "t[jj].colonne[i1].numero=%d\n",
1604  t[j].colonne[i].numero,
1605  t[jj].colonne[i1].numero);
1606  });
1607 
1608  /* 0 en colonne j ligne t[jj].colonne[i1].numero */
1609  if(t[jj].colonne[i1].numero == ii) {
1610  AFF(nlle_colonne[k],frac0)
1611  } else {
1612  frac *n = &(nlle_colonne[k]),
1613  *b = &(t[jj].colonne[i1]);
1614  pivot(n,frac0,(*b),cc,piv,ofl_ctrl) ;
1615  }
1616 
1617  if(i==0||nlle_colonne[k].num!=0)
1618  {
1619  nlle_colonne[k].numero =
1620  t[jj].colonne[i1].numero ;
1621  k++ ;
1622  }
1623  if(i1<t[jj].taille) i1++ ; else i++ ;
1624  }
1625  else if(i1>=t[jj].taille ||
1626  t[j].colonne[i].numero <
1627  t[jj].colonne[i1].numero)
1628  {
1629  /* 0 en col jj, ligne t[j].colonne[i].numero */
1630  DEBUG2(printf("t[j].colonne[i].numero < "
1631  "t[jj].colonne[i1].numero , "
1632  "k=%ld, j=%ld, i=%ld i1=%ld\n",
1633  k,j,i,i1);
1634  printf("j = %ld t[j].taille=%d , "
1635  "t[jj].taille=%d\n",
1636  j,t[j].taille,t[jj].taille););
1637  AFF(nlle_colonne[k],t[j].colonne[i]) ;
1638  if(i==0||nlle_colonne[k].num!=0) {
1639  nlle_colonne[k].numero =
1640  t[j].colonne[i].numero ;
1641  k++ ;
1642  }
1643  if(i<t[j].taille) i++ ; else i1++ ;
1644  }
1645  else
1646  DEBUG2(printf(" ??? ");)
1647 
1648  DEBUG2(printf(" -> ");
1649  printfrac(nlle_colonne[k-1]);
1650  printf(" [ligne numero %d]\n",
1651  nlle_colonne[k-1].numero);)
1652 
1653  }
1654  if(j==compteur) w = jj ; else w = j ;
1655  colo = t[w].colonne ;
1656  t[w].colonne=nlle_colonne ;
1657  nlle_colonne = colo ;
1658  t[w].taille=k ;
1659  DEBUG1(printf("w = %ld t[w].taille=%d \n",w,t[w].taille);
1660  dump_tableau("last", t, compteur););
1661  }
1662  }
1663  }
1664 
1665  /* Restauration des entrees vides de la table hashee */
1666  FINSIMPLEX :
1667  DEBUG1(dump_tableau("fin simplexe", t, compteur);)
1668  DEBUG(fprintf(stderr, "soluble = %d\n", soluble);)
1669 
1670  DEBUG(fprintf(stderr,"END SIMPLEX: %d th\n",simplex_sc_counter);)
1671 
1672  for(i = premier_hash ; i != PTR_NIL; i = hashtable[i].succ){
1673  hashtable[i].nom = VARIABLE_UNDEFINED;
1674  hashtable[i].numero = 0 ;
1675  hashtable[i].hash = 0 ;
1676  hashtable[i].val = (Value)0 ;
1677  }
1678 
1679 
1680  for(i=0;i<(3 + NB_INEQ + NB_EQ + DIMENSION); i++)
1681  free(t[i].colonne);
1682  free(t);
1683  free(nlle_colonne);
1684 
1685 #ifdef CONTROLING
1686  alarm(0); /*clear the alarm*/
1687 #endif
1689 
1690  /* restore initial base */
1691  vect_rm(sc_base(sc));
1692  sc_base(sc) = saved_base;
1693  sc_dimension(sc) = saved_dimension;
1694 
1695  return soluble;
1696 } /* main */
1697 
1698 /* (that is all, folks!:-)
1699  */
#define CATCH(what)
@ overflow_error
@ simplex_arithmetic_error
@ timeout_error
#define UNCATCH(what)
#define RETHROW()
#define VALUE_ZERO
#define value_minus(v1, v2)
#define value_oppose(ref)
#define value_notzero_p(val)
#define value_uminus(val)
unary operators on values
#define value_notone_p(val)
#define value_one_p(val)
#define VALUE_MONE
#define value_zero_p(val)
int Value
#define ABS(x)
was: #define value_mult(v,w) value_direct_multiply(v,w) #define value_product(v,w) value_direct_produ...
#define value_notmone_p(val)
#define value_addto(ref, val)
#define value_eq(v1, v2)
bool operators on values
#define value_division(ref, val)
#define VALUE_ONE
#define value_abs(val)
#define VALUE_TO_LONG(val)
#define value_substract(ref, val)
#define value_mult(v, w)
whether the default is protected or not this define makes no sense any more...
#define VALUE_NAN
#define value_neg_p(val)
struct col tableau
void print_Value(Value)
io.c
Definition: io.c:37
static int num
Definition: bourdoncle.c:137
#define max(a, b)
void * malloc(YYSIZE_T)
void free(void *)
#define B(A)
Definition: iabrev.h:61
#define D(A)
Definition: iabrev.h:56
#define linear_assert(msg, ex)
Definition: linear_assert.h:51
#define assert(ex)
Definition: newgen_assert.h:41
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
int f2(int off1, int off2, int w, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:1
#define X
Definition: r1.c:42
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
void sc_creer_base(Psysteme ps)
void sc_creer_base(Psysteme ps): initialisation des parametres dimension et base d'un systeme lineair...
Definition: sc_alloc.c:129
void sc_default_dump(Psysteme sc)
void sc_default_dump(Psysteme sc): dump to stderr
Definition: sc_io.c:170
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
int printf()
#define DEBUG3(code)
void partial_pivot_direct(frac *X, frac B, frac C, frac D, bool ofl_ctrl)
#define GCD_ZERO_CTRL(j, a, b)
static int variablescachees[MAX_VAR]
void frac_simpl(Value *a, Value *b)
#define EGALOFL(x, y)
void full_pivot(frac *X, frac A, frac B, frac C, frac D, bool ofl_ctrl)
#define DEBUG2(code)
#define AFF(x, y)
void pivot(frac *X, frac A, frac B, frac C, frac D, bool ofl_ctrl)
#define INV_ZERO_CTRL(x, y)
??? value_zero_p(y.num)? Then x.num != VALUE_ZERO and x.den = VALUE_ZERO, it's not good at all.
void frac_div(frac *x, frac y, frac z, bool ofl_ctrl)
void partial_pivot(frac *X, frac B, frac C, frac D, bool ofl_ctrl)
@ MAXVAL
nombre max de variables
#define INFOFL(x, y)
static void __attribute__((unused))
For debugging:
static int NB_EQ
test du simplex : Si on compile grace a` "make simp" dans le repertoire /projects/C3/Linear/Developme...
#define DEBUG(code)
debug macros may be trigered with -DDEBUG{,1,2}
void frac_mul(frac *x, frac y, frac z, bool ofl_ctrl)
computes x = simplify(y*z)
bool sc_simplex_feasibility_ofl_ctrl_fixprec(Psysteme sc, int ofl_ctrl)
fonction de calcul de la faisabilite' d'un systeme d'equations et d'inequations Auteur : Robert Mahl,...
#define MET_ZERO(f)
#define POSITIF(x)
static frac frac0
void full_pivot_direct(frac *X, frac A, frac B, frac C, frac D, bool ofl_ctrl)
computes X = A - B*C/D, but does not try to avoid arithmetic exceptions
#define tag(x)
for tracing macros after expansion:
#define value_protected_mult(v, w)
multiplies two Values of no arithmetic overflow, or throw exception.
#define direct_p(v)
void partial_pivot_sioux(frac *X, frac B, frac C, frac D, bool ofl_ctrl)
idem if A==0
static int variables[MAX_VAR]
#define CREVARVISIBLE
#define EGAL(x, y)
void frac_sub(frac *X, frac A, frac B, bool ofl_ctrl)
#define NEGATIF(x)
static int nbvariables
Le nombre de variables visibles est : compteur-2 La i-eme variable visible a le numero : variables[i+...
#define INF(x, y)
void full_pivot_sioux(frac *X, frac A, frac B, frac C, frac D, bool ofl_ctrl)
#define CREVARCACHEE
void frac_init(frac *f, int n)
static int hash(Variable s)
dump_tableau
static void printfrac(frac x)
#define DEBUG1(code)
#define AFF_PX(x, y)
static int NB_INEQ
#define SOLUBLE(N)
void frac_simplifie(frac *f)
simplifie normalizes fraction f
static char * x
Definition: split_file.c:159
#define INTPTR_MIN
7.18.2.4.
Definition: stdint.in.h:471
#define INTPTR_MAX
Definition: stdint.in.h:472
#define intptr_t
Definition: stdint.in.h:294
Definition: pip__tab.h:25
Pvecteur vecteur
struct Scontrainte * succ
Pcontrainte inegalites
Definition: sc-local.h:71
Pcontrainte egalites
Definition: sc-local.h:70
le type des coefficients dans les vecteurs: Value est defini dans le package arithmetique
Definition: vecteur-local.h:89
Value val
Definition: vecteur-local.h:91
Variable var
Definition: vecteur-local.h:90
struct Svecteur * succ
Definition: vecteur-local.h:92
frac * colonne
this is already too much...
Entier valeur(Tableau *tp, int i, int j, Entier D)
Definition: traiter.c:178
#define VARIABLE_DEFINED_P(v)
Definition: vecteur-local.h:66
#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 FWD_OFL_CTRL
#define VARIABLE_UNDEFINED
Definition: vecteur-local.h:64
#define BASE_NULLE
MACROS SUR LES BASES.
void vect_rm(Pvecteur v)
void vect_rm(Pvecteur v): desallocation des couples de v;
Definition: alloc.c:78
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