2 #include <barvinok/barvinok.h>
3 #include <barvinok/util.h>
8 static Matrix
*extract_matrix(Polyhedron
*P
, unsigned dim
)
14 for (int i
= 0; i
< P
->NbConstraints
; ++i
)
15 if (value_notzero_p(P
->Constraint
[i
][1+dim
]) ||
16 value_notzero_p(P
->Constraint
[i
][1+dim
+1]))
19 A
= Matrix_Alloc(2, n_col
+2);
21 for (int i
= 0; i
< P
->NbConstraints
; ++i
) {
22 if (value_zero_p(P
->Constraint
[i
][1+dim
]) &&
23 value_zero_p(P
->Constraint
[i
][1+dim
+1]))
25 value_assign(A
->p
[0][n_col
], P
->Constraint
[i
][1+dim
]);
26 value_assign(A
->p
[1][n_col
], P
->Constraint
[i
][1+dim
+1]);
29 value_set_si(A
->p
[0][n_col
], 1);
30 value_set_si(A
->p
[1][n_col
+1], 1);
35 static int lex_sign(Value
*v
, int len
)
39 first
= First_Non_Zero(v
, len
);
40 return first
== -1 ? 0 : value_sign(v
[first
]);
43 static void set_pos(int pos
[4], int actual
, int wanted
)
48 pos
[actual
] = pos
[wanted
];
52 static Matrix
*normalize_matrix(Matrix
*A
, int pos
[4], int n
)
55 Value tmp
, tmp2
, factor
;
62 T
= Matrix_Alloc(2, 2);
63 Extended_Euclid(A
->p
[0][pos
[0]], A
->p
[1][pos
[0]],
64 &T
->p
[0][0], &T
->p
[0][1], &tmp
);
65 value_division(T
->p
[1][0], A
->p
[1][pos
[0]], tmp
);
66 value_division(T
->p
[1][1], A
->p
[0][pos
[0]], tmp
);
67 value_oppose(T
->p
[0][0], T
->p
[0][0]);
68 value_oppose(T
->p
[0][1], T
->p
[0][1]);
69 value_oppose(T
->p
[1][0], T
->p
[1][0]);
71 B
= Matrix_Alloc(2, A
->NbColumns
);
72 Matrix_Product(T
, A
, B
);
75 if (lex_sign(B
->p
[1], B
->NbColumns
) > 0) {
76 value_set_si(tmp
, -1);
77 Vector_Scale(B
->p
[1], B
->p
[1], tmp
, B
->NbColumns
);
81 assert(value_neg_p(B
->p
[1][pos
[1]]));
82 assert(value_pos_p(B
->p
[1][pos
[2]]));
84 value_set_si(factor
, 0);
85 for (int i
= 1; i
<= 2; ++i
) {
86 value_pdivision(tmp
, B
->p
[0][pos
[i
]], B
->p
[1][pos
[i
]]);
87 value_increment(tmp
, tmp
);
88 if (value_gt(tmp
, factor
))
89 value_assign(factor
, tmp
);
91 value_oppose(factor
, factor
);
93 Vector_Combine(B
->p
[0], B
->p
[1], B
->p
[0],
94 tmp
, factor
, B
->NbColumns
);
95 Vector_Exchange(B
->p
[0], B
->p
[1], B
->NbColumns
);
99 for (i
= 1; i
<= 3; ++i
)
100 if (value_zero_p(B
->p
[1][pos
[i
]]))
103 /* put zero in position 3 */
106 /* put positive one in position 1 */
107 for (i
= 1; i
<= 3; ++i
)
108 if (value_pos_p(B
->p
[1][pos
[i
]]))
112 value_set_si(factor
, 0);
113 for (int i
= 1; i
<= 2; ++i
) {
114 value_pdivision(tmp
, B
->p
[0][pos
[i
]], B
->p
[1][pos
[i
]]);
115 value_increment(tmp
, tmp
);
116 if (value_gt(tmp
, factor
))
117 value_assign(factor
, tmp
);
119 value_oppose(factor
, factor
);
120 value_set_si(tmp
, 1);
121 Vector_Combine(B
->p
[0], B
->p
[1], B
->p
[0], tmp
, factor
, B
->NbColumns
);
123 assert(value_notzero_p(B
->p
[0][pos
[3]]));
124 type
= value_pos_p(B
->p
[0][pos
[3]]) ? 1 : 2;
127 for (int i
= 1; i
<= 3; ++i
)
128 if (value_neg_p(B
->p
[1][pos
[i
]]))
130 assert(neg
== 1 || neg
== 2);
133 /* put negative one in position 1 */
134 for (i
= 1; i
<= 3; ++i
)
135 if (value_neg_p(B
->p
[1][pos
[i
]]))
139 value_set_si(factor
, 0);
140 for (int i
= 1; i
<= 3; ++i
) {
141 value_pdivision(tmp
, B
->p
[0][pos
[i
]], B
->p
[1][pos
[i
]]);
142 value_increment(tmp
, tmp
);
143 if (value_gt(tmp
, factor
))
144 value_assign(factor
, tmp
);
146 value_oppose(factor
, factor
);
147 value_set_si(tmp
, 1);
148 Vector_Combine(B
->p
[0], B
->p
[1], B
->p
[0],
149 tmp
, factor
, B
->NbColumns
);
150 Vector_Exchange(B
->p
[0], B
->p
[1], B
->NbColumns
);
154 /* put positive one in position 1 */
155 for (i
= 1; i
<= 3; ++i
)
156 if (value_pos_p(B
->p
[1][pos
[i
]]))
160 value_set_si(factor
, 0);
161 for (int i
= 1; i
<= 3; ++i
) {
162 value_pdivision(tmp
, B
->p
[0][pos
[i
]], B
->p
[1][pos
[i
]]);
163 value_increment(tmp
, tmp
);
164 if (value_gt(tmp
, factor
))
165 value_assign(factor
, tmp
);
167 value_oppose(factor
, factor
);
168 value_set_si(tmp
, 1);
169 Vector_Combine(B
->p
[0], B
->p
[1], B
->p
[0],
170 tmp
, factor
, B
->NbColumns
);
180 value_oppose(tmp
, B
->p
[0][pos
[1]]);
181 value_pdivision(factor
, tmp
, B
->p
[1][pos
[1]]);
182 value_oppose(tmp
, B
->p
[1][pos
[2]]);
183 value_pdivision(tmp
, tmp
, B
->p
[0][pos
[2]]);
184 if (value_zero_p(factor
) && value_zero_p(tmp
))
186 assert(value_zero_p(factor
) || value_zero_p(tmp
));
187 if (value_pos_p(factor
)) {
188 value_set_si(tmp
, 1);
189 Vector_Combine(B
->p
[0], B
->p
[1], B
->p
[0], tmp
, factor
, B
->NbColumns
);
190 if (value_zero_p(B
->p
[0][pos
[1]])) {
191 /* We will deal with this later */
192 assert(lex_sign(B
->p
[0], B
->NbColumns
) < 0);
195 value_set_si(factor
, 1);
196 Vector_Combine(B
->p
[0], B
->p
[1], B
->p
[1], tmp
, factor
, B
->NbColumns
);
197 if (value_zero_p(B
->p
[1][pos
[2]])) {
198 /* We will deal with this later */
199 assert(lex_sign(B
->p
[1], B
->NbColumns
) < 0);
206 bool progress
= true;
209 for (int i
= 0; i
<= 1; ++i
) {
210 value_set_si(factor
, -1);
211 for (int j
= 1; j
<= 3; ++j
) {
212 if (value_zero_p(B
->p
[1-i
][pos
[j
]]))
214 value_oppose(tmp
, B
->p
[i
][pos
[j
]]);
215 value_pdivision(tmp
, tmp
, B
->p
[1-i
][pos
[j
]]);
216 if (value_neg_p(factor
) || value_lt(tmp
, factor
))
217 value_assign(factor
, tmp
);
219 if (value_pos_p(factor
)) {
220 value_set_si(tmp
, 1);
221 Vector_Combine(B
->p
[i
], B
->p
[1-i
], B
->p
[i
], tmp
, factor
,
223 sign
= lex_sign(B
->p
[i
], B
->NbColumns
);
224 for (int j
= 1; j
<= 3; ++j
) {
225 if (value_notzero_p(B
->p
[i
][pos
[j
]]))
227 /* a zero is interpreted to be of sign sign */
228 if ((sign
> 0 && value_pos_p(B
->p
[1-i
][pos
[j
]])) ||
229 (sign
< 0 && value_neg_p(B
->p
[1-i
][pos
[j
]]))) {
230 /* the zero is of the wrong sign => back-off one */
231 value_set_si(tmp2
, -1);
232 Vector_Combine(B
->p
[i
], B
->p
[1-i
], B
->p
[i
], tmp
, tmp2
,
234 value_decrement(factor
, factor
);
237 /* We may have backed-off, so we need to check again. */
238 if (value_pos_p(factor
))
244 for (int i
= 0; i
< B
->NbColumns
; ++i
) {
245 value_addto(tmp
, B
->p
[0][i
], B
->p
[1][i
]);
246 if (value_zero_p(tmp
))
248 sign
= value_neg_p(tmp
) ? -1 : 1;
252 for (int i
= 1; i
<= 3; ++i
) {
253 value_addto(tmp
, B
->p
[0][pos
[i
]], B
->p
[1][pos
[i
]]);
254 if (value_neg_p(tmp
) || (sign
< 0 && value_zero_p(tmp
)))
261 value_set_si(tmp
, 1);
262 Vector_Combine(B
->p
[0], B
->p
[1], B
->p
[1], tmp
, tmp
, B
->NbColumns
);
264 /* put positive pair in position 3 */
265 for (i
= 1; i
<= 3; ++i
)
266 if (value_pos_p(B
->p
[0][pos
[i
]]) && value_pos_p(B
->p
[1][pos
[i
]]))
278 /* We will deal with these later */
291 Value last
; // last multiple of offset in link
293 Matrix
*M
; // rows: elements different from (0,0)
297 M
= Matrix_Alloc(d
, 2);
300 simplex(int d
, int mask
, Value last
) {
301 M
= Matrix_Alloc(d
, 2);
302 offset
= Vector_Alloc(2);
303 value_init(this->last
);
304 value_assign(this->last
, last
);
307 void transform(Matrix
*T
);
309 Polyhedron
*shrunk_polyhedron(Polyhedron
*P
, int dim
, Matrix
*A
,
311 void print(FILE *out
);
314 void simplex::print(FILE *out
)
317 Matrix_Print(out
, P_VALUE_FMT
, M
);
319 fprintf(out
, "%d %d\n", M
->NbRows
, M
->NbColumns
);
320 for (int j
= 0; j
< M
->NbRows
; ++j
) {
321 for (int k
= 0; k
< M
->NbColumns
; ++k
)
322 value_print(out
, P_VALUE_FMT
, M
->p
[j
][k
]);
323 if (mask
& (1 << j
)) {
324 fprintf(out
, " + k * ");
325 for (int k
= 0; k
< M
->NbColumns
; ++k
)
326 value_print(out
, P_VALUE_FMT
, offset
->p
[k
]);
330 fprintf(out
, "\t0 <= k <= ");
331 value_print(out
, P_VALUE_FMT
, last
);
336 static bool lex_smaller(Value
*v1
, Value
*v2
, int n
)
338 for (int i
= 0; i
< n
; ++i
)
339 if (value_lt(v1
[i
], v2
[i
]))
341 else if (value_gt(v1
[i
], v2
[i
]))
346 void simplex::transform(Matrix
*T
)
349 M
= Matrix_Alloc(M2
->NbRows
, M2
->NbColumns
);
350 Matrix_Product(M2
, T
, M
);
354 Vector
*offset2
= offset
;
355 offset
= Vector_Alloc(offset2
->Size
);
356 Vector_Matrix_Product(offset2
->p
, T
, offset
->p
);
357 Vector_Free(offset2
);
361 void simplex::normalize()
364 for (int i
= 1; i
< M
->NbRows
; ++i
)
365 if (lex_smaller(M
->p
[i
], M
->p
[lexmin
], 2))
367 if (lex_sign(M
->p
[lexmin
], 2) < 0) {
370 value_set_si(tmp
, -1);
371 Vector_Scale(M
->p
[lexmin
], M
->p
[lexmin
], tmp
, 2);
372 value_set_si(tmp
, 1);
373 for (int i
= 0; i
< M
->NbRows
; ++i
) {
376 Vector_Combine(M
->p
[lexmin
], M
->p
[i
], M
->p
[i
], tmp
, tmp
, 2);
378 if (offset
&& (mask
& (1 << lexmin
))) {
379 value_set_si(tmp
, -1);
380 Vector_Scale(offset
->p
, offset
->p
, tmp
, 2);
381 mask
^= (1 << M
->NbRows
) - 1 - (1 << lexmin
);
387 static Matrix
*InsertColumn(Matrix
*M
, int pos
)
392 R
= Matrix_Alloc(M
->NbRows
, M
->NbColumns
+1);
393 for (i
= 0; i
< M
->NbRows
; ++i
) {
394 Vector_Copy(M
->p
[i
], R
->p
[i
], pos
);
395 Vector_Copy(M
->p
[i
]+pos
, R
->p
[i
]+pos
+1, M
->NbColumns
-pos
);
400 Polyhedron
*simplex::shrunk_polyhedron(Polyhedron
*P
, int dim
, Matrix
*A
,
403 Matrix
*Constraints
, *b
;
404 Vector
*b_offset
= NULL
;
406 Value min
, min_var
, tmp
;
412 b
= Matrix_Alloc(M
->NbRows
, A
->NbColumns
);
413 Matrix_Product(M
, A
, b
);
416 b_offset
= Vector_Alloc(A
->NbColumns
);
417 Vector_Matrix_Product(offset
->p
, A
, b_offset
->p
);
421 Constraints
= Polyhedron2Constraints(P
);
423 Constraints
= Matrix_Alloc(P
->NbConstraints
+2, P
->Dimension
+2+1);
424 for (int i
= 0; i
< P
->NbConstraints
; ++i
) {
425 Vector_Copy(P
->Constraint
[i
], Constraints
->p
[i
], 1+dim
+2);
426 Vector_Copy(P
->Constraint
[i
]+1+dim
+2, Constraints
->p
[i
]+1+dim
+2+1,
427 (P
->Dimension
+2)-(1+dim
+2));
429 value_set_si(Constraints
->p
[P
->NbConstraints
][0], 1);
430 value_set_si(Constraints
->p
[P
->NbConstraints
][1+dim
+2], 1);
431 value_set_si(Constraints
->p
[P
->NbConstraints
+1][0], 1);
432 value_set_si(Constraints
->p
[P
->NbConstraints
+1][1+dim
+2], -1);
433 value_assign(Constraints
->p
[P
->NbConstraints
+1][Constraints
->NbColumns
-1],
436 constant
= Constraints
->NbColumns
- 1;
438 for (int i
= 0, j
= 0; i
< P
->NbConstraints
; ++i
) {
439 if (value_zero_p(Constraints
->p
[i
][1+dim
]) &&
440 value_zero_p(Constraints
->p
[i
][1+dim
+1]))
442 value_set_si(min
, 0);
443 for (int k
= 0; k
< b
->NbRows
; ++k
) {
444 if (offset
&& (mask
& (1 << k
)))
446 if (value_lt(b
->p
[k
][j
], min
))
447 value_assign(min
, b
->p
[k
][j
]);
449 value_set_si(min_var
, 0);
451 if (value_neg_p(b_offset
->p
[j
])) {
452 value_oppose(min_var
, b_offset
->p
[j
]);
453 value_multiply(min_var
, min_var
, last
);
454 value_increment(min_var
, min_var
);
456 for (int k
= 0; k
< b
->NbRows
; ++k
) {
457 if (!(mask
& (1 << k
)))
459 if (value_lt(b
->p
[k
][j
], min_var
))
460 value_assign(min_var
, b
->p
[k
][j
]);
463 if (!offset
|| value_pos_p(b_offset
->p
[j
])) {
464 if (value_le(min
, min_var
))
465 value_addto(Constraints
->p
[i
][constant
],
466 Constraints
->p
[i
][constant
], min
);
468 value_assign(tmp
, min_var
);
469 value_addmul(tmp
, last
, b_offset
->p
[j
]);
470 if (value_le(tmp
, min
)) {
471 value_addto(Constraints
->p
[i
][constant
],
472 Constraints
->p
[i
][constant
], min_var
);
473 value_addto(Constraints
->p
[i
][1+dim
+2],
474 Constraints
->p
[i
][1+dim
+2], b_offset
->p
[j
]);
476 int lastrow
= Constraints
->NbRows
;
477 int cols
= Constraints
->NbColumns
;
478 Matrix
*C
= Constraints
;
479 Constraints
= AddANullRow(Constraints
);
481 Vector_Copy(Constraints
->p
[i
], Constraints
->p
[lastrow
], cols
);
482 value_addto(Constraints
->p
[i
][constant
],
483 Constraints
->p
[i
][constant
], min_var
);
484 value_addto(Constraints
->p
[i
][1+dim
+2],
485 Constraints
->p
[i
][1+dim
+2], b_offset
->p
[j
]);
486 value_addto(Constraints
->p
[lastrow
][constant
],
487 Constraints
->p
[lastrow
][constant
], min
);
491 if (value_le(min_var
, min
)) {
492 value_addto(Constraints
->p
[i
][constant
],
493 Constraints
->p
[i
][constant
], min_var
);
494 value_addto(Constraints
->p
[i
][1+dim
+2],
495 Constraints
->p
[i
][1+dim
+2], b_offset
->p
[j
]);
497 value_assign(tmp
, min_var
);
498 value_addmul(tmp
, last
, b_offset
->p
[j
]);
499 if (value_le(min
, tmp
)) {
500 value_addto(Constraints
->p
[i
][constant
],
501 Constraints
->p
[i
][constant
], min
);
503 int lastrow
= Constraints
->NbRows
;
504 int cols
= Constraints
->NbColumns
;
505 Matrix
*C
= Constraints
;
506 Constraints
= AddANullRow(Constraints
);
508 Vector_Copy(Constraints
->p
[i
], Constraints
->p
[lastrow
], cols
);
509 value_addto(Constraints
->p
[i
][constant
],
510 Constraints
->p
[i
][constant
], min_var
);
511 value_addto(Constraints
->p
[i
][1+dim
+2],
512 Constraints
->p
[i
][1+dim
+2], b_offset
->p
[j
]);
513 value_addto(Constraints
->p
[lastrow
][constant
],
514 Constraints
->p
[lastrow
][constant
], min
);
520 Q
= Constraints2Polyhedron(Constraints
, MaxRays
);
523 Vector_Free(b_offset
);
525 Matrix_Free(Constraints
);
528 value_clear(min_var
);
533 struct scarf_complex
{
534 vector
<simplex
> simplices
;
535 void add(Matrix
*B
, int pos
[4], int n
);
536 void add(Matrix
*T
, simplex s
);
537 void print(FILE *out
);
539 for (int i
= 0; i
< simplices
.size(); ++i
) {
540 Matrix_Free(simplices
[i
].M
);
541 if (simplices
[i
].offset
) {
542 Vector_Free(simplices
[i
].offset
);
543 value_clear(simplices
[i
].last
);
549 void scarf_complex::add(Matrix
*T
, simplex s
)
553 if (s
.offset
&& lex_sign(s
.offset
->p
, 2) < 0) {
558 /* compute the smallest multiple (factor) of the offset that
559 * makes on of the vertices lexico-negative.
562 for (int i
= 0; i
< s
.M
->NbRows
; ++i
) {
563 if (!(s
.mask
& (1 << i
)))
565 if (lexmin
== -1 || lex_smaller(s
.M
->p
[i
], s
.M
->p
[lexmin
], 2))
568 if (value_zero_p(s
.offset
->p
[0])) {
569 if (value_pos_p(s
.M
->p
[lexmin
][0]))
570 value_increment(factor
, s
.last
);
572 value_oppose(factor
, s
.M
->p
[lexmin
][1]);
573 mpz_cdiv_q(factor
, factor
, s
.offset
->p
[1]);
576 value_oppose(factor
, s
.M
->p
[lexmin
][0]);
577 mpz_cdiv_q(factor
, factor
, s
.offset
->p
[0]);
578 if (mpz_divisible_p(s
.M
->p
[lexmin
][0], s
.offset
->p
[0])) {
579 value_assign(tmp
, s
.M
->p
[lexmin
][1]);
580 value_addmul(tmp
, factor
, s
.offset
->p
[1]);
581 if (value_pos_p(tmp
))
582 value_increment(factor
, factor
);
585 if (value_le(factor
, s
.last
)) {
586 simplex
part(s
.M
->NbRows
, s
.mask
, s
.last
);
587 Vector_Copy(s
.offset
->p
, part
.offset
->p
, 2);
588 value_set_si(tmp
, 1);
589 for (int i
= 0; i
< s
.M
->NbRows
; ++i
) {
590 if (s
.mask
& (1 << i
))
591 Vector_Combine(s
.M
->p
[i
], s
.offset
->p
, part
.M
->p
[i
],
594 Vector_Copy(s
.M
->p
[i
], part
.M
->p
[i
], 2);
596 value_subtract(part
.last
, part
.last
, factor
);
597 value_decrement(s
.last
, factor
);
599 simplices
.push_back(part
);
604 simplices
.push_back(s
);
607 void scarf_complex::add(Matrix
*B
, int pos
[4], int n
)
611 T
= Matrix_Alloc(2, 2);
612 Vector_Copy(B
->p
[0]+B
->NbColumns
-2, T
->p
[0], 2);
613 Vector_Copy(B
->p
[1]+B
->NbColumns
-2, T
->p
[1], 2);
615 if (n
== 3 || value_neg_p(B
->p
[0][pos
[3]])) {
616 assert(n
== 3 || value_neg_p(B
->p
[1][pos
[3]]));
619 value_set_si(s1
.M
->p
[0][0], 0);
620 value_set_si(s1
.M
->p
[0][1], 1);
624 value_set_si(s2
.M
->p
[0][0], 1);
625 value_set_si(s2
.M
->p
[0][1], 1);
629 value_set_si(s3
.M
->p
[0][0], 1);
630 value_set_si(s3
.M
->p
[0][1], 0);
634 value_set_si(s4
.M
->p
[0][0], 0);
635 value_set_si(s4
.M
->p
[0][1], 1);
636 value_set_si(s4
.M
->p
[1][0], 1);
637 value_set_si(s4
.M
->p
[1][1], 1);
641 value_set_si(s5
.M
->p
[0][0], 1);
642 value_set_si(s5
.M
->p
[0][1], 0);
643 value_set_si(s5
.M
->p
[1][0], 1);
644 value_set_si(s5
.M
->p
[1][1], 1);
650 bool progress
= true;
651 Value tmp
, tmp2
, factor
;
658 assert(value_pos_p(B
->p
[0][pos
[3]]));
659 assert(value_pos_p(B
->p
[1][pos
[3]]));
661 h
= Matrix_Alloc(3, 2);
662 value_set_si(h
->p
[0][0], 1);
663 value_set_si(h
->p
[0][1], 0);
664 value_set_si(h
->p
[1][0], 0);
665 value_set_si(h
->p
[1][1], 1);
666 value_set_si(h
->p
[2][0], 1);
667 value_set_si(h
->p
[2][1], 1);
669 offset
= Vector_Alloc(2);
673 for (int i
= 0; i
<= 1; ++i
) {
674 value_set_si(factor
, -1);
675 for (int j
= 1; j
<= 2; ++j
) {
676 if (value_zero_p(B
->p
[1-i
][pos
[j
]]))
678 value_oppose(tmp
, B
->p
[i
][pos
[j
]]);
679 value_pdivision(tmp
, tmp
, B
->p
[1-i
][pos
[j
]]);
680 if (value_neg_p(factor
) || value_lt(tmp
, factor
))
681 value_assign(factor
, tmp
);
683 if (value_pos_p(factor
)) {
684 value_set_si(tmp
, 1);
685 Vector_Combine(B
->p
[i
], B
->p
[1-i
], B
->p
[i
], tmp
, factor
,
687 sign
= lex_sign(B
->p
[i
], B
->NbColumns
);
688 for (int j
= 1; j
<= 2; ++j
) {
689 if (value_notzero_p(B
->p
[i
][pos
[j
]]))
691 /* a zero is interpreted to be of sign sign */
692 if ((sign
> 0 && value_pos_p(B
->p
[1-i
][pos
[j
]])) ||
693 (sign
< 0 && value_neg_p(B
->p
[1-i
][pos
[j
]]))) {
694 /* the zero is of the wrong sign => back-off one */
695 value_set_si(tmp2
, -1);
696 Vector_Combine(B
->p
[i
], B
->p
[1-i
], B
->p
[i
], tmp
, tmp2
,
698 value_decrement(factor
, factor
);
701 /* We may have backed-off, so we need to check again. */
702 if (value_pos_p(factor
)) {
704 value_set_si(tmp
, 1);
705 value_set_si(tmp2
, -1);
707 Vector_Combine(h
->p
[2], h
->p
[i
], offset
->p
, tmp
, tmp2
, 2);
710 /* the initial simplices not in any link */
712 Vector_Copy(h
->p
[0], l1
.M
->p
[0], 2);
716 Vector_Copy(h
->p
[1], l2
.M
->p
[0], 2);
720 Vector_Combine(h
->p
[0], h
->p
[1], l3
.M
->p
[0],
725 Vector_Copy(h
->p
[0], t1
.M
->p
[0], 2);
726 Vector_Copy(h
->p
[1], t1
.M
->p
[1], 2);
730 Vector_Combine(h
->p
[0], h
->p
[1], t2
.M
->p
[0],
732 Vector_Combine(h
->p
[2], h
->p
[1], t2
.M
->p
[1],
737 Vector_Combine(h
->p
[i
], offset
->p
, h
->p
[i
],
739 Vector_Combine(h
->p
[2], offset
->p
, h
->p
[2],
741 value_decrement(factor
, factor
);
744 simplex
q(3, 0x4 | (1 << i
), factor
);
745 Vector_Copy(h
->p
[0], q
.M
->p
[0], 2);
746 Vector_Copy(h
->p
[1], q
.M
->p
[1], 2);
747 Vector_Copy(h
->p
[2], q
.M
->p
[2], 2);
748 Vector_Copy(offset
->p
, q
.offset
->p
, 2);
751 simplex
t1(2, 0x3, factor
);
752 Vector_Copy(h
->p
[i
], t1
.M
->p
[0], 2);
753 Vector_Copy(h
->p
[2], t1
.M
->p
[1], 2);
754 Vector_Copy(offset
->p
, t1
.offset
->p
, 2);
757 simplex
t2(2, 0x2, factor
);
758 Vector_Copy(h
->p
[1-i
], t2
.M
->p
[0], 2);
759 Vector_Copy(h
->p
[2], t2
.M
->p
[1], 2);
760 Vector_Copy(offset
->p
, t2
.offset
->p
, 2);
763 simplex
l(1, 0x1, factor
);
764 Vector_Copy(h
->p
[2], l
.M
->p
[0], 2);
765 Vector_Copy(offset
->p
, l
.offset
->p
, 2);
769 Vector_Combine(h
->p
[i
], offset
->p
, h
->p
[i
], tmp
, factor
, 2);
770 Vector_Combine(h
->p
[2], offset
->p
, h
->p
[2], tmp
, factor
, 2);
778 /* the initial simplices not in any link */
780 Vector_Copy(h
->p
[0], l1
.M
->p
[0], 2);
784 Vector_Copy(h
->p
[1], l2
.M
->p
[0], 2);
788 Vector_Combine(h
->p
[0], h
->p
[1], l3
.M
->p
[0],
793 Vector_Copy(h
->p
[0], t1
.M
->p
[0], 2);
794 Vector_Copy(h
->p
[1], t1
.M
->p
[1], 2);
798 Vector_Combine(h
->p
[0], h
->p
[1], t2
.M
->p
[0],
800 Vector_Combine(h
->p
[2], h
->p
[1], t2
.M
->p
[1],
805 /* the simplices in a link, here of length 1 */
807 Vector_Copy(h
->p
[0], q
.M
->p
[0], 2);
808 Vector_Copy(h
->p
[1], q
.M
->p
[1], 2);
809 Vector_Copy(h
->p
[2], q
.M
->p
[2], 2);
813 Vector_Copy(h
->p
[0], t1
.M
->p
[0], 2);
814 Vector_Copy(h
->p
[2], t1
.M
->p
[1], 2);
818 Vector_Copy(h
->p
[1], t2
.M
->p
[0], 2);
819 Vector_Copy(h
->p
[2], t2
.M
->p
[1], 2);
823 Vector_Copy(h
->p
[2], l
.M
->p
[0], 2);
839 void scarf_complex::print(FILE *out
)
841 for (int i
= 0; i
< simplices
.size(); ++i
)
842 simplices
[i
].print(out
);
845 struct scarf_collector
{
846 virtual void add(Polyhedron
*P
, int sign
, Polyhedron
*C
, unsigned MaxRays
) = 0;
849 static void scarf(Polyhedron
*P
, unsigned exist
, unsigned nparam
, unsigned MaxRays
,
850 scarf_collector
& col
)
853 int dim
= P
->Dimension
- exist
- nparam
;
860 A
= extract_matrix(P
, dim
);
862 n
= A
->NbColumns
- 2;
863 assert(n
>= 3 && n
<= 4);
866 for (int i
= 0; i
< n
; ++i
) {
868 for (j
= 0; j
< l
; ++j
)
869 if (value_eq(A
->p
[0][pos
[j
]], A
->p
[0][i
]) &&
870 value_eq(A
->p
[1][pos
[j
]], A
->p
[1][i
]))
877 assert(l
>= 3 && l
<= 4);
878 B
= normalize_matrix(A
, pos
, l
);
881 scarf
.add(B
, pos
, l
);
883 U
= Universe_Polyhedron(nparam
);
884 col
.add(P
, 0, U
, MaxRays
);
885 for (int i
= 0; i
< scarf
.simplices
.size(); ++i
) {
887 int sign
= (scarf
.simplices
[i
].M
->NbRows
% 2) ? -1 : 1;
888 Q
= scarf
.simplices
[i
].shrunk_polyhedron(P
, dim
, A
, MaxRays
);
889 col
.add(Q
, sign
, U
, MaxRays
);
899 struct scarf_collector_gf
: public scarf_collector
{
903 scarf_collector_gf() {
906 virtual void add(Polyhedron
*P
, int sign
, Polyhedron
*C
, unsigned MaxRays
);
909 void scarf_collector_gf::add(Polyhedron
*P
, int sign
, Polyhedron
*C
,
913 gf
= barvinok_series(P
, C
, MaxRays
);
917 gf2
= barvinok_series(P
, C
, MaxRays
);
923 gen_fun
*barvinok_enumerate_scarf_series(Polyhedron
*P
,
924 unsigned exist
, unsigned nparam
, unsigned MaxRays
)
926 scarf_collector_gf scgf
;
927 scarf(P
, exist
, nparam
, MaxRays
, scgf
);
931 struct scarf_collector_ev
: public scarf_collector
{
935 scarf_collector_ev() {
937 evalue_set_si(&mone
, -1, 1);
939 ~scarf_collector_ev() {
940 free_evalue_refs(&mone
);
942 virtual void add(Polyhedron
*P
, int sign
, Polyhedron
*C
, unsigned MaxRays
);
945 void scarf_collector_ev::add(Polyhedron
*P
, int sign
, Polyhedron
*C
,
949 EP
= barvinok_enumerate_ev(P
, C
, MaxRays
);
952 E2
= barvinok_enumerate_ev(P
, C
, MaxRays
);
956 free_evalue_refs(E2
);
961 evalue
*barvinok_enumerate_scarf(Polyhedron
*P
,
962 unsigned exist
, unsigned nparam
, unsigned MaxRays
)
964 scarf_collector_ev scev
;
965 scarf(P
, exist
, nparam
, MaxRays
, scev
);