2 #include <barvinok/barvinok.h>
3 #include <barvinok/util.h>
7 static Matrix
*extract_matrix(Polyhedron
*P
, unsigned dim
)
13 for (int i
= 0; i
< P
->NbConstraints
; ++i
)
14 if (value_notzero_p(P
->Constraint
[i
][1+dim
]) ||
15 value_notzero_p(P
->Constraint
[i
][1+dim
+1]))
18 A
= Matrix_Alloc(2, n_col
+2);
20 for (int i
= 0; i
< P
->NbConstraints
; ++i
) {
21 if (value_zero_p(P
->Constraint
[i
][1+dim
]) &&
22 value_zero_p(P
->Constraint
[i
][1+dim
+1]))
24 value_assign(A
->p
[0][n_col
], P
->Constraint
[i
][1+dim
]);
25 value_assign(A
->p
[1][n_col
], P
->Constraint
[i
][1+dim
+1]);
28 value_set_si(A
->p
[0][n_col
], 1);
29 value_set_si(A
->p
[1][n_col
+1], 1);
34 static int lex_sign(Value
*v
, int len
)
38 first
= First_Non_Zero(v
, len
);
39 return first
== -1 ? 0 : value_sign(v
[first
]);
42 static void set_pos(int pos
[4], int actual
, int wanted
)
47 pos
[actual
] = pos
[wanted
];
51 static Matrix
*normalize_matrix(Matrix
*A
, int pos
[4], int *n
)
54 Value tmp
, tmp2
, factor
;
61 T
= Matrix_Alloc(2, 2);
62 Extended_Euclid(A
->p
[0][pos
[0]], A
->p
[1][pos
[0]],
63 &T
->p
[0][0], &T
->p
[0][1], &tmp
);
64 value_division(T
->p
[1][0], A
->p
[1][pos
[0]], tmp
);
65 value_division(T
->p
[1][1], A
->p
[0][pos
[0]], tmp
);
66 value_oppose(T
->p
[0][0], T
->p
[0][0]);
67 value_oppose(T
->p
[0][1], T
->p
[0][1]);
68 value_oppose(T
->p
[1][0], T
->p
[1][0]);
70 B
= Matrix_Alloc(2, A
->NbColumns
);
71 Matrix_Product(T
, A
, B
);
74 /* Make zero in first position negative */
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
);
80 /* First determine whether the matrix is of sign pattern I or II
84 assert(value_neg_p(B
->p
[1][pos
[1]]));
85 assert(value_pos_p(B
->p
[1][pos
[2]]));
87 value_set_si(factor
, 0);
88 for (int i
= 1; i
<= 2; ++i
) {
89 value_pdivision(tmp
, B
->p
[0][pos
[i
]], B
->p
[1][pos
[i
]]);
90 value_increment(tmp
, tmp
);
91 if (value_gt(tmp
, factor
))
92 value_assign(factor
, tmp
);
94 value_oppose(factor
, factor
);
96 Vector_Combine(B
->p
[0], B
->p
[1], B
->p
[0],
97 tmp
, factor
, B
->NbColumns
);
98 Vector_Exchange(B
->p
[0], B
->p
[1], B
->NbColumns
);
99 /* problems with three constraints are considered
100 * to be of sign pattern II
105 for (i
= 1; i
<= 3; ++i
)
106 if (value_zero_p(B
->p
[1][pos
[i
]]))
109 /* put zero in position 3 */
112 /* put positive one in position 1 */
113 for (i
= 1; i
<= 3; ++i
)
114 if (value_pos_p(B
->p
[1][pos
[i
]]))
118 value_set_si(factor
, 0);
119 for (int i
= 1; i
<= 2; ++i
) {
120 value_pdivision(tmp
, B
->p
[0][pos
[i
]], B
->p
[1][pos
[i
]]);
121 value_increment(tmp
, tmp
);
122 if (value_gt(tmp
, factor
))
123 value_assign(factor
, tmp
);
125 value_oppose(factor
, factor
);
126 value_set_si(tmp
, 1);
127 Vector_Combine(B
->p
[0], B
->p
[1], B
->p
[0], tmp
, factor
, B
->NbColumns
);
129 assert(value_notzero_p(B
->p
[0][pos
[3]]));
130 type
= value_pos_p(B
->p
[0][pos
[3]]) ? 1 : 2;
133 int sign
= lex_sign(B
->p
[1], B
->NbColumns
);
135 for (int i
= 1; i
<= 3; ++i
)
136 if (value_neg_p(B
->p
[1][pos
[i
]]))
138 assert(neg
== 1 || neg
== 2);
141 /* put negative one in position 1 */
142 for (i
= 1; i
<= 3; ++i
)
143 if (value_neg_p(B
->p
[1][pos
[i
]]))
147 value_set_si(factor
, 0);
148 for (int i
= 1; i
<= 3; ++i
) {
149 value_pdivision(tmp
, B
->p
[0][pos
[i
]], B
->p
[1][pos
[i
]]);
150 value_increment(tmp
, tmp
);
151 if (value_gt(tmp
, factor
))
152 value_assign(factor
, tmp
);
154 value_oppose(factor
, factor
);
155 value_set_si(tmp
, 1);
156 Vector_Combine(B
->p
[0], B
->p
[1], B
->p
[0],
157 tmp
, factor
, B
->NbColumns
);
158 Vector_Exchange(B
->p
[0], B
->p
[1], B
->NbColumns
);
162 /* put positive one in position 1 */
163 for (i
= 1; i
<= 3; ++i
)
164 if (value_pos_p(B
->p
[1][pos
[i
]]))
168 value_set_si(factor
, 0);
169 for (int i
= 1; i
<= 3; ++i
) {
170 value_pdivision(tmp
, B
->p
[0][pos
[i
]], B
->p
[1][pos
[i
]]);
171 value_increment(tmp
, tmp
);
172 if (value_gt(tmp
, factor
))
173 value_assign(factor
, tmp
);
175 value_oppose(factor
, factor
);
176 value_set_si(tmp
, 1);
177 Vector_Combine(B
->p
[0], B
->p
[1], B
->p
[0],
178 tmp
, factor
, B
->NbColumns
);
188 value_oppose(tmp
, B
->p
[0][pos
[1]]);
189 value_pdivision(factor
, tmp
, B
->p
[1][pos
[1]]);
190 value_oppose(tmp
, B
->p
[1][pos
[2]]);
191 value_pdivision(tmp
, tmp
, B
->p
[0][pos
[2]]);
192 if (value_zero_p(factor
) && value_zero_p(tmp
))
194 assert(value_zero_p(factor
) || value_zero_p(tmp
));
195 if (value_pos_p(factor
)) {
196 value_set_si(tmp
, 1);
197 Vector_Combine(B
->p
[0], B
->p
[1], B
->p
[0], tmp
, factor
, B
->NbColumns
);
198 if (value_zero_p(B
->p
[0][pos
[1]])) {
199 /* We will deal with this later */
200 assert(lex_sign(B
->p
[0], B
->NbColumns
) < 0);
203 value_set_si(factor
, 1);
204 Vector_Combine(B
->p
[0], B
->p
[1], B
->p
[1], tmp
, factor
, B
->NbColumns
);
205 if (value_zero_p(B
->p
[1][pos
[2]])) {
206 /* We will deal with this later */
207 assert(lex_sign(B
->p
[1], B
->NbColumns
) < 0);
214 bool progress
= true;
217 for (int i
= 0; i
<= 1; ++i
) {
218 value_set_si(factor
, -1);
219 for (int j
= 1; j
<= 3; ++j
) {
220 if (value_zero_p(B
->p
[1-i
][pos
[j
]]))
222 value_oppose(tmp
, B
->p
[i
][pos
[j
]]);
223 value_pdivision(tmp
, tmp
, B
->p
[1-i
][pos
[j
]]);
224 if (value_neg_p(factor
) || value_lt(tmp
, factor
))
225 value_assign(factor
, tmp
);
227 if (value_pos_p(factor
)) {
228 value_set_si(tmp
, 1);
229 Vector_Combine(B
->p
[i
], B
->p
[1-i
], B
->p
[i
], tmp
, factor
,
231 sign
= lex_sign(B
->p
[i
], B
->NbColumns
);
232 for (int j
= 1; j
<= 3; ++j
) {
233 if (value_notzero_p(B
->p
[i
][pos
[j
]]))
235 /* a zero is interpreted to be of sign sign */
236 if ((sign
> 0 && value_pos_p(B
->p
[1-i
][pos
[j
]])) ||
237 (sign
< 0 && value_neg_p(B
->p
[1-i
][pos
[j
]]))) {
238 /* the zero is of the wrong sign => back-off one */
239 value_set_si(tmp2
, -1);
240 Vector_Combine(B
->p
[i
], B
->p
[1-i
], B
->p
[i
], tmp
, tmp2
,
242 value_decrement(factor
, factor
);
245 /* We may have backed-off, so we need to check again. */
246 if (value_pos_p(factor
))
252 for (int i
= 0; i
< B
->NbColumns
; ++i
) {
253 value_addto(tmp
, B
->p
[0][i
], B
->p
[1][i
]);
254 if (value_zero_p(tmp
))
256 sign
= value_neg_p(tmp
) ? -1 : 1;
260 for (int i
= 1; i
<= 3; ++i
) {
261 value_addto(tmp
, B
->p
[0][pos
[i
]], B
->p
[1][pos
[i
]]);
262 if (value_neg_p(tmp
) || (sign
< 0 && value_zero_p(tmp
)))
269 /* cases 4 and 5 in Theorem 11.1 */
270 value_set_si(tmp
, 1);
271 Vector_Combine(B
->p
[0], B
->p
[1], B
->p
[1], tmp
, tmp
, B
->NbColumns
);
273 /* put positive pair in position 3 */
274 for (i
= 1; i
<= 3; ++i
)
275 if (value_pos_p(B
->p
[0][pos
[i
]]) && value_pos_p(B
->p
[1][pos
[i
]]))
282 /* cases 1 and 2 in Theorem 11.1 */
283 value_set_si(tmp
, 1);
284 Vector_Combine(B
->p
[0], B
->p
[1], B
->p
[0], tmp
, tmp
, B
->NbColumns
);
286 /* put positive one in position 2 */
287 for (i
= 1; i
<= 3; ++i
)
288 if (value_pos_p(B
->p
[0][pos
[i
]]))
293 /* fourth constraint is redundant with respect to neighborhoods */
297 /* We will deal with these later */
310 Value last
; // last multiple of offset in link
312 Matrix
*M
; // rows: elements different from (0,0)
316 M
= Matrix_Alloc(d
, 2);
319 simplex(int d
, int mask
, Value last
) {
320 M
= Matrix_Alloc(d
, 2);
321 offset
= Vector_Alloc(2);
322 value_init(this->last
);
323 value_assign(this->last
, last
);
326 void transform(Matrix
*T
);
328 Polyhedron
*shrunk_polyhedron(Polyhedron
*P
, int dim
, Matrix
*A
,
330 void print(FILE *out
);
333 void simplex::print(FILE *out
)
336 Matrix_Print(out
, P_VALUE_FMT
, M
);
338 fprintf(out
, "%d %d\n", M
->NbRows
, M
->NbColumns
);
339 for (int j
= 0; j
< M
->NbRows
; ++j
) {
340 for (int k
= 0; k
< M
->NbColumns
; ++k
)
341 value_print(out
, P_VALUE_FMT
, M
->p
[j
][k
]);
342 if (mask
& (1 << j
)) {
343 fprintf(out
, " + k * ");
344 for (int k
= 0; k
< M
->NbColumns
; ++k
)
345 value_print(out
, P_VALUE_FMT
, offset
->p
[k
]);
349 fprintf(out
, "\t0 <= k <= ");
350 value_print(out
, P_VALUE_FMT
, last
);
355 static bool lex_smaller(Value
*v1
, Value
*v2
, int n
)
357 for (int i
= 0; i
< n
; ++i
)
358 if (value_lt(v1
[i
], v2
[i
]))
360 else if (value_gt(v1
[i
], v2
[i
]))
365 void simplex::transform(Matrix
*T
)
368 M
= Matrix_Alloc(M2
->NbRows
, M2
->NbColumns
);
369 Matrix_Product(M2
, T
, M
);
373 Vector
*offset2
= offset
;
374 offset
= Vector_Alloc(offset2
->Size
);
375 Vector_Matrix_Product(offset2
->p
, T
, offset
->p
);
376 Vector_Free(offset2
);
380 void simplex::normalize()
383 for (int i
= 1; i
< M
->NbRows
; ++i
)
384 if (lex_smaller(M
->p
[i
], M
->p
[lexmin
], 2))
386 if (lex_sign(M
->p
[lexmin
], 2) < 0) {
389 value_set_si(tmp
, -1);
390 Vector_Scale(M
->p
[lexmin
], M
->p
[lexmin
], tmp
, 2);
391 value_set_si(tmp
, 1);
392 for (int i
= 0; i
< M
->NbRows
; ++i
) {
395 Vector_Combine(M
->p
[lexmin
], M
->p
[i
], M
->p
[i
], tmp
, tmp
, 2);
397 if (offset
&& (mask
& (1 << lexmin
))) {
398 value_set_si(tmp
, -1);
399 Vector_Scale(offset
->p
, offset
->p
, tmp
, 2);
400 mask
^= (1 << M
->NbRows
) - 1 - (1 << lexmin
);
406 static Matrix
*InsertColumn(Matrix
*M
, int pos
)
411 R
= Matrix_Alloc(M
->NbRows
, M
->NbColumns
+1);
412 for (i
= 0; i
< M
->NbRows
; ++i
) {
413 Vector_Copy(M
->p
[i
], R
->p
[i
], pos
);
414 Vector_Copy(M
->p
[i
]+pos
, R
->p
[i
]+pos
+1, M
->NbColumns
-pos
);
419 Polyhedron
*simplex::shrunk_polyhedron(Polyhedron
*P
, int dim
, Matrix
*A
,
422 Matrix
*Constraints
, *b
;
423 Vector
*b_offset
= NULL
;
425 Value min
, min_var
, tmp
;
431 b
= Matrix_Alloc(M
->NbRows
, A
->NbColumns
);
432 Matrix_Product(M
, A
, b
);
435 b_offset
= Vector_Alloc(A
->NbColumns
);
436 Vector_Matrix_Product(offset
->p
, A
, b_offset
->p
);
440 Constraints
= Polyhedron2Constraints(P
);
442 Constraints
= Matrix_Alloc(P
->NbConstraints
+2, P
->Dimension
+2+1);
443 for (int i
= 0; i
< P
->NbConstraints
; ++i
) {
444 Vector_Copy(P
->Constraint
[i
], Constraints
->p
[i
], 1+dim
+2);
445 Vector_Copy(P
->Constraint
[i
]+1+dim
+2, Constraints
->p
[i
]+1+dim
+2+1,
446 (P
->Dimension
+2)-(1+dim
+2));
448 value_set_si(Constraints
->p
[P
->NbConstraints
][0], 1);
449 value_set_si(Constraints
->p
[P
->NbConstraints
][1+dim
+2], 1);
450 value_set_si(Constraints
->p
[P
->NbConstraints
+1][0], 1);
451 value_set_si(Constraints
->p
[P
->NbConstraints
+1][1+dim
+2], -1);
452 value_assign(Constraints
->p
[P
->NbConstraints
+1][Constraints
->NbColumns
-1],
455 constant
= Constraints
->NbColumns
- 1;
457 for (int i
= 0, j
= 0; i
< P
->NbConstraints
; ++i
) {
458 if (value_zero_p(Constraints
->p
[i
][1+dim
]) &&
459 value_zero_p(Constraints
->p
[i
][1+dim
+1]))
461 value_set_si(min
, 0);
462 for (int k
= 0; k
< b
->NbRows
; ++k
) {
463 if (offset
&& (mask
& (1 << k
)))
465 if (value_lt(b
->p
[k
][j
], min
))
466 value_assign(min
, b
->p
[k
][j
]);
468 value_set_si(min_var
, 0);
470 if (value_neg_p(b_offset
->p
[j
])) {
471 value_oppose(min_var
, b_offset
->p
[j
]);
472 value_multiply(min_var
, min_var
, last
);
473 value_increment(min_var
, min_var
);
475 for (int k
= 0; k
< b
->NbRows
; ++k
) {
476 if (!(mask
& (1 << k
)))
478 if (value_lt(b
->p
[k
][j
], min_var
))
479 value_assign(min_var
, b
->p
[k
][j
]);
482 if (!offset
|| value_pos_p(b_offset
->p
[j
])) {
483 if (value_le(min
, min_var
))
484 value_addto(Constraints
->p
[i
][constant
],
485 Constraints
->p
[i
][constant
], min
);
487 value_assign(tmp
, min_var
);
488 value_addmul(tmp
, last
, b_offset
->p
[j
]);
489 if (value_le(tmp
, min
)) {
490 value_addto(Constraints
->p
[i
][constant
],
491 Constraints
->p
[i
][constant
], min_var
);
492 value_addto(Constraints
->p
[i
][1+dim
+2],
493 Constraints
->p
[i
][1+dim
+2], b_offset
->p
[j
]);
495 int lastrow
= Constraints
->NbRows
;
496 int cols
= Constraints
->NbColumns
;
497 Matrix
*C
= Constraints
;
498 Constraints
= AddANullRow(Constraints
);
500 Vector_Copy(Constraints
->p
[i
], Constraints
->p
[lastrow
], cols
);
501 value_addto(Constraints
->p
[i
][constant
],
502 Constraints
->p
[i
][constant
], min_var
);
503 value_addto(Constraints
->p
[i
][1+dim
+2],
504 Constraints
->p
[i
][1+dim
+2], b_offset
->p
[j
]);
505 value_addto(Constraints
->p
[lastrow
][constant
],
506 Constraints
->p
[lastrow
][constant
], min
);
510 if (value_le(min_var
, min
)) {
511 value_addto(Constraints
->p
[i
][constant
],
512 Constraints
->p
[i
][constant
], min_var
);
513 value_addto(Constraints
->p
[i
][1+dim
+2],
514 Constraints
->p
[i
][1+dim
+2], b_offset
->p
[j
]);
516 value_assign(tmp
, min_var
);
517 value_addmul(tmp
, last
, b_offset
->p
[j
]);
518 if (value_le(min
, tmp
)) {
519 value_addto(Constraints
->p
[i
][constant
],
520 Constraints
->p
[i
][constant
], min
);
522 int lastrow
= Constraints
->NbRows
;
523 int cols
= Constraints
->NbColumns
;
524 Matrix
*C
= Constraints
;
525 Constraints
= AddANullRow(Constraints
);
527 Vector_Copy(Constraints
->p
[i
], Constraints
->p
[lastrow
], cols
);
528 value_addto(Constraints
->p
[i
][constant
],
529 Constraints
->p
[i
][constant
], min_var
);
530 value_addto(Constraints
->p
[i
][1+dim
+2],
531 Constraints
->p
[i
][1+dim
+2], b_offset
->p
[j
]);
532 value_addto(Constraints
->p
[lastrow
][constant
],
533 Constraints
->p
[lastrow
][constant
], min
);
539 Q
= Constraints2Polyhedron(Constraints
, MaxRays
);
542 Vector_Free(b_offset
);
544 Matrix_Free(Constraints
);
547 value_clear(min_var
);
552 struct scarf_complex
{
553 vector
<simplex
> simplices
;
554 void add(Matrix
*B
, int pos
[4], int n
);
555 void add(Matrix
*T
, simplex s
);
556 void print(FILE *out
);
558 for (int i
= 0; i
< simplices
.size(); ++i
) {
559 Matrix_Free(simplices
[i
].M
);
560 if (simplices
[i
].offset
) {
561 Vector_Free(simplices
[i
].offset
);
562 value_clear(simplices
[i
].last
);
568 void scarf_complex::add(Matrix
*T
, simplex s
)
572 if (s
.offset
&& lex_sign(s
.offset
->p
, 2) < 0) {
577 /* compute the smallest multiple (factor) of the offset that
578 * makes on of the vertices lexico-negative.
581 for (int i
= 0; i
< s
.M
->NbRows
; ++i
) {
582 if (!(s
.mask
& (1 << i
)))
584 if (lexmin
== -1 || lex_smaller(s
.M
->p
[i
], s
.M
->p
[lexmin
], 2))
587 if (value_zero_p(s
.offset
->p
[0])) {
588 if (value_pos_p(s
.M
->p
[lexmin
][0]))
589 value_increment(factor
, s
.last
);
591 value_oppose(factor
, s
.M
->p
[lexmin
][1]);
592 mpz_cdiv_q(factor
, factor
, s
.offset
->p
[1]);
595 value_oppose(factor
, s
.M
->p
[lexmin
][0]);
596 mpz_cdiv_q(factor
, factor
, s
.offset
->p
[0]);
597 if (mpz_divisible_p(s
.M
->p
[lexmin
][0], s
.offset
->p
[0])) {
598 value_assign(tmp
, s
.M
->p
[lexmin
][1]);
599 value_addmul(tmp
, factor
, s
.offset
->p
[1]);
600 if (value_pos_p(tmp
))
601 value_increment(factor
, factor
);
604 if (value_le(factor
, s
.last
)) {
605 simplex
part(s
.M
->NbRows
, s
.mask
, s
.last
);
606 Vector_Copy(s
.offset
->p
, part
.offset
->p
, 2);
607 value_set_si(tmp
, 1);
608 for (int i
= 0; i
< s
.M
->NbRows
; ++i
) {
609 if (s
.mask
& (1 << i
))
610 Vector_Combine(s
.M
->p
[i
], s
.offset
->p
, part
.M
->p
[i
],
613 Vector_Copy(s
.M
->p
[i
], part
.M
->p
[i
], 2);
615 value_subtract(part
.last
, part
.last
, factor
);
616 value_decrement(s
.last
, factor
);
618 simplices
.push_back(part
);
623 simplices
.push_back(s
);
626 void scarf_complex::add(Matrix
*B
, int pos
[4], int n
)
630 T
= Matrix_Alloc(2, 2);
631 Vector_Copy(B
->p
[0]+B
->NbColumns
-2, T
->p
[0], 2);
632 Vector_Copy(B
->p
[1]+B
->NbColumns
-2, T
->p
[1], 2);
634 if (n
== 3 || value_neg_p(B
->p
[0][pos
[3]])) {
635 assert(n
== 3 || value_neg_p(B
->p
[1][pos
[3]]));
638 value_set_si(s1
.M
->p
[0][0], 0);
639 value_set_si(s1
.M
->p
[0][1], 1);
643 value_set_si(s2
.M
->p
[0][0], 1);
644 value_set_si(s2
.M
->p
[0][1], 1);
648 value_set_si(s3
.M
->p
[0][0], 1);
649 value_set_si(s3
.M
->p
[0][1], 0);
653 value_set_si(s4
.M
->p
[0][0], 0);
654 value_set_si(s4
.M
->p
[0][1], 1);
655 value_set_si(s4
.M
->p
[1][0], 1);
656 value_set_si(s4
.M
->p
[1][1], 1);
660 value_set_si(s5
.M
->p
[0][0], 1);
661 value_set_si(s5
.M
->p
[0][1], 0);
662 value_set_si(s5
.M
->p
[1][0], 1);
663 value_set_si(s5
.M
->p
[1][1], 1);
669 bool progress
= true;
670 Value tmp
, tmp2
, factor
;
677 assert(value_pos_p(B
->p
[0][pos
[3]]));
678 assert(value_pos_p(B
->p
[1][pos
[3]]));
680 h
= Matrix_Alloc(3, 2);
681 value_set_si(h
->p
[0][0], 1);
682 value_set_si(h
->p
[0][1], 0);
683 value_set_si(h
->p
[1][0], 0);
684 value_set_si(h
->p
[1][1], 1);
685 value_set_si(h
->p
[2][0], 1);
686 value_set_si(h
->p
[2][1], 1);
688 offset
= Vector_Alloc(2);
692 for (int i
= 0; i
<= 1; ++i
) {
693 value_set_si(factor
, -1);
694 for (int j
= 1; j
<= 2; ++j
) {
695 if (value_zero_p(B
->p
[1-i
][pos
[j
]]))
697 value_oppose(tmp
, B
->p
[i
][pos
[j
]]);
698 value_pdivision(tmp
, tmp
, B
->p
[1-i
][pos
[j
]]);
699 if (value_neg_p(factor
) || value_lt(tmp
, factor
))
700 value_assign(factor
, tmp
);
702 if (value_pos_p(factor
)) {
703 value_set_si(tmp
, 1);
704 Vector_Combine(B
->p
[i
], B
->p
[1-i
], B
->p
[i
], tmp
, factor
,
706 sign
= lex_sign(B
->p
[i
], B
->NbColumns
);
707 for (int j
= 1; j
<= 2; ++j
) {
708 if (value_notzero_p(B
->p
[i
][pos
[j
]]))
710 /* a zero is interpreted to be of sign sign */
711 if ((sign
> 0 && value_pos_p(B
->p
[1-i
][pos
[j
]])) ||
712 (sign
< 0 && value_neg_p(B
->p
[1-i
][pos
[j
]]))) {
713 /* the zero is of the wrong sign => back-off one */
714 value_set_si(tmp2
, -1);
715 Vector_Combine(B
->p
[i
], B
->p
[1-i
], B
->p
[i
], tmp
, tmp2
,
717 value_decrement(factor
, factor
);
720 /* We may have backed-off, so we need to check again. */
721 if (value_pos_p(factor
)) {
723 value_set_si(tmp
, 1);
724 value_set_si(tmp2
, -1);
726 Vector_Combine(h
->p
[2], h
->p
[i
], offset
->p
, tmp
, tmp2
, 2);
729 /* the initial simplices not in any link */
731 Vector_Copy(h
->p
[0], l1
.M
->p
[0], 2);
735 Vector_Copy(h
->p
[1], l2
.M
->p
[0], 2);
739 Vector_Combine(h
->p
[0], h
->p
[1], l3
.M
->p
[0],
744 Vector_Copy(h
->p
[0], t1
.M
->p
[0], 2);
745 Vector_Copy(h
->p
[1], t1
.M
->p
[1], 2);
749 Vector_Combine(h
->p
[0], h
->p
[1], t2
.M
->p
[0],
751 Vector_Combine(h
->p
[2], h
->p
[1], t2
.M
->p
[1],
756 Vector_Combine(h
->p
[i
], offset
->p
, h
->p
[i
],
758 Vector_Combine(h
->p
[2], offset
->p
, h
->p
[2],
760 value_decrement(factor
, factor
);
763 simplex
q(3, 0x4 | (1 << i
), factor
);
764 Vector_Copy(h
->p
[0], q
.M
->p
[0], 2);
765 Vector_Copy(h
->p
[1], q
.M
->p
[1], 2);
766 Vector_Copy(h
->p
[2], q
.M
->p
[2], 2);
767 Vector_Copy(offset
->p
, q
.offset
->p
, 2);
770 simplex
t1(2, 0x3, factor
);
771 Vector_Copy(h
->p
[i
], t1
.M
->p
[0], 2);
772 Vector_Copy(h
->p
[2], t1
.M
->p
[1], 2);
773 Vector_Copy(offset
->p
, t1
.offset
->p
, 2);
776 simplex
t2(2, 0x2, factor
);
777 Vector_Copy(h
->p
[1-i
], t2
.M
->p
[0], 2);
778 Vector_Copy(h
->p
[2], t2
.M
->p
[1], 2);
779 Vector_Copy(offset
->p
, t2
.offset
->p
, 2);
782 simplex
l(1, 0x1, factor
);
783 Vector_Copy(h
->p
[2], l
.M
->p
[0], 2);
784 Vector_Copy(offset
->p
, l
.offset
->p
, 2);
788 Vector_Combine(h
->p
[i
], offset
->p
, h
->p
[i
], tmp
, factor
, 2);
789 Vector_Combine(h
->p
[2], offset
->p
, h
->p
[2], tmp
, factor
, 2);
797 /* the initial simplices not in any link */
799 Vector_Copy(h
->p
[0], l1
.M
->p
[0], 2);
803 Vector_Copy(h
->p
[1], l2
.M
->p
[0], 2);
807 Vector_Combine(h
->p
[0], h
->p
[1], l3
.M
->p
[0],
812 Vector_Copy(h
->p
[0], t1
.M
->p
[0], 2);
813 Vector_Copy(h
->p
[1], t1
.M
->p
[1], 2);
817 Vector_Combine(h
->p
[0], h
->p
[1], t2
.M
->p
[0],
819 Vector_Combine(h
->p
[2], h
->p
[1], t2
.M
->p
[1],
824 /* the simplices in a link, here of length 1 */
826 Vector_Copy(h
->p
[0], q
.M
->p
[0], 2);
827 Vector_Copy(h
->p
[1], q
.M
->p
[1], 2);
828 Vector_Copy(h
->p
[2], q
.M
->p
[2], 2);
832 Vector_Copy(h
->p
[0], t1
.M
->p
[0], 2);
833 Vector_Copy(h
->p
[2], t1
.M
->p
[1], 2);
837 Vector_Copy(h
->p
[1], t2
.M
->p
[0], 2);
838 Vector_Copy(h
->p
[2], t2
.M
->p
[1], 2);
842 Vector_Copy(h
->p
[2], l
.M
->p
[0], 2);
858 void scarf_complex::print(FILE *out
)
860 for (int i
= 0; i
< simplices
.size(); ++i
)
861 simplices
[i
].print(out
);
864 struct scarf_collector
{
865 virtual void add(Polyhedron
*P
, int sign
, Polyhedron
*C
,
866 barvinok_options
*options
) = 0;
869 static void scarf(Polyhedron
*P
, unsigned exist
, unsigned nparam
,
870 barvinok_options
*options
, scarf_collector
& col
)
873 int dim
= P
->Dimension
- exist
- nparam
;
880 A
= extract_matrix(P
, dim
);
882 n
= A
->NbColumns
- 2;
883 assert(n
>= 3 && n
<= 4);
886 for (int i
= 0; i
< n
; ++i
) {
888 for (j
= 0; j
< l
; ++j
)
889 if (value_eq(A
->p
[0][pos
[j
]], A
->p
[0][i
]) &&
890 value_eq(A
->p
[1][pos
[j
]], A
->p
[1][i
]))
897 assert(l
>= 3 && l
<= 4);
898 B
= normalize_matrix(A
, pos
, &l
);
901 scarf
.add(B
, pos
, l
);
903 U
= Universe_Polyhedron(nparam
);
904 col
.add(P
, 0, U
, options
);
905 for (int i
= 0; i
< scarf
.simplices
.size(); ++i
) {
907 int sign
= (scarf
.simplices
[i
].M
->NbRows
% 2) ? -1 : 1;
908 Q
= scarf
.simplices
[i
].shrunk_polyhedron(P
, dim
, A
, options
->MaxRays
);
909 col
.add(Q
, sign
, U
, options
);
919 struct scarf_collector_gf
: public scarf_collector
{
923 scarf_collector_gf() {
926 virtual void add(Polyhedron
*P
, int sign
, Polyhedron
*C
,
927 barvinok_options
*options
);
930 void scarf_collector_gf::add(Polyhedron
*P
, int sign
, Polyhedron
*C
,
931 barvinok_options
*options
)
934 gf
= barvinok_series_with_options(P
, C
, options
);
938 gf2
= barvinok_series_with_options(P
, C
, options
);
944 gen_fun
*barvinok_enumerate_scarf_series(Polyhedron
*P
,
945 unsigned exist
, unsigned nparam
, barvinok_options
*options
)
947 scarf_collector_gf scgf
;
948 scarf(P
, exist
, nparam
, options
, scgf
);
952 struct scarf_collector_ev
: public scarf_collector
{
956 scarf_collector_ev() {
958 evalue_set_si(&mone
, -1, 1);
960 ~scarf_collector_ev() {
961 free_evalue_refs(&mone
);
963 virtual void add(Polyhedron
*P
, int sign
, Polyhedron
*C
,
964 barvinok_options
*options
);
967 void scarf_collector_ev::add(Polyhedron
*P
, int sign
, Polyhedron
*C
,
968 barvinok_options
*options
)
971 EP
= barvinok_enumerate_with_options(P
, C
, options
);
974 E2
= barvinok_enumerate_with_options(P
, C
, options
);
978 free_evalue_refs(E2
);
983 evalue
*barvinok_enumerate_scarf(Polyhedron
*P
,
984 unsigned exist
, unsigned nparam
, barvinok_options
*options
)
986 scarf_collector_ev scev
;
987 scarf(P
, exist
, nparam
, options
, scev
);