7 #include <isl/polynomial.h>
9 #include <barvinok/polylib.h>
10 #include <barvinok/isl.h>
11 #include <barvinok/options.h>
12 #include <barvinok/util.h>
15 #define ALLOCN(type,n) (type*)malloc((n) * sizeof(type))
17 /* RANGE : normal range for evaluations (-RANGE -> RANGE) */
20 /* SRANGE : small range for evaluations */
23 /* if dimension >= BIDDIM, use SRANGE */
26 /* VSRANGE : very small range for evaluations */
29 /* if dimension >= VBIDDIM, use VSRANGE */
32 static int set_m(void *opt
, long val
)
34 struct verify_options
*options
= (struct verify_options
*)opt
;
40 static int set_M(void *opt
, long val
)
42 struct verify_options
*options
= (struct verify_options
*)opt
;
48 static int set_r(void *opt
, long val
)
50 struct verify_options
*options
= (struct verify_options
*)opt
;
58 ISL_ARGS_START(struct verify_options
, verify_options_args
)
59 ISL_ARG_CHILD(struct verify_options
, barvinok
, NULL
, &barvinok_options_args
,
61 ISL_ARG_BOOL(struct verify_options
, verify
, 'T', "verify", 0, NULL
)
62 ISL_ARG_BOOL(struct verify_options
, exact
, 'E', "exact", 0, NULL
)
63 ISL_ARG_BOOL(struct verify_options
, print_all
, 'A', "print-all", 0, NULL
)
64 ISL_ARG_BOOL(struct verify_options
, continue_on_error
, 'C',
65 "continue-on-error", 0, NULL
)
66 ISL_ARG_USER_LONG(struct verify_options
, m
, 'm', "min", set_m
, INT_MAX
, NULL
)
67 ISL_ARG_USER_LONG(struct verify_options
, M
, 'M', "max", set_M
, INT_MIN
, NULL
)
68 ISL_ARG_USER_LONG(struct verify_options
, r
, 'r', "range", set_r
, -1, NULL
)
71 void verify_options_set_range(struct verify_options
*options
, int dim
)
77 else if (dim
>= BIGDIM
)
81 /* If the user didn't set m or M, then we try to adjust the window
82 * to the context in check_poly_context_scan.
84 if (options
->m
== INT_MAX
&& options
->M
== INT_MIN
)
86 if (options
->M
== INT_MIN
)
88 if (options
->m
== INT_MAX
)
91 if (options
->verify
&& options
->m
> options
->M
) {
92 fprintf(stderr
,"Nothing to do: min > max !\n");
97 /* Set the range of values for verification based on
98 * the total dimensionality of "pwqp", if not already set by the user.
100 isl_stat
verify_options_set_range_pwqp(struct verify_options
*options
,
101 __isl_keep isl_pw_qpolynomial
*pwqp
)
103 isl_size total
= isl_pw_qpolynomial_dim(pwqp
, isl_dim_all
);
105 return isl_stat_error
;
106 verify_options_set_range(options
, total
);
110 static Polyhedron
*project_on(Polyhedron
*P
, int i
)
112 unsigned dim
= P
->Dimension
;
117 return Polyhedron_Copy(P
);
119 T
= Matrix_Alloc(2, dim
+1);
120 value_set_si(T
->p
[0][i
], 1);
121 value_set_si(T
->p
[1][dim
], 1);
122 I
= Polyhedron_Image(P
, T
, P
->NbConstraints
);
127 static void set_bounds(Polyhedron
*C
, Value
**rows
, int i
, unsigned nparam
,
128 const struct verify_options
*options
)
135 value_set_si(min
, options
->m
);
136 value_set_si(max
, options
->M
);
138 if (options
->r
> 0) {
139 Polyhedron
*I
= project_on(C
, i
);
140 line_minmax(I
, &min
, &max
);
141 if (value_cmp_si(min
, options
->M
) >= 0)
142 value_add_int(max
, min
, options
->r
);
143 else if (value_cmp_si(max
, options
->m
) <= 0)
144 value_sub_int(min
, max
, options
->r
);
146 value_set_si(min
, options
->m
);
147 value_set_si(max
, options
->M
);
151 value_set_si(rows
[0][0], 1);
152 value_set_si(rows
[0][1+i
], 1);
153 value_oppose(rows
[0][1+nparam
], min
);
154 value_set_si(rows
[1][0], 1);
155 value_set_si(rows
[1][1+i
], -1);
156 value_assign(rows
[1][1+nparam
], max
);
162 Polyhedron
*check_poly_context_scan(Polyhedron
*P
, Polyhedron
**C
,
164 const struct verify_options
*options
)
168 Polyhedron
*CC
, *CC2
, *CS
, *U
;
169 unsigned MaxRays
= options
->barvinok
->MaxRays
;
177 CC
= Polyhedron_Project(P
, nparam
);
179 CC2
= DomainIntersection(*C
, CC
, MaxRays
);
185 /* Intersect context with range */
186 MM
= Matrix_Alloc(2*nparam
, nparam
+2);
187 for (i
= 0; i
< nparam
; ++i
)
188 set_bounds(CC
, &MM
->p
[2*i
], i
, nparam
, options
);
189 CC2
= AddConstraints(MM
->p
[0], 2*nparam
, CC
, options
->barvinok
->MaxRays
);
193 U
= Universe_Polyhedron(0);
194 CS
= Polyhedron_Scan(CC
, U
, MaxRays
& POL_NO_DUAL
? 0 : MaxRays
);
201 void check_poly_init(Polyhedron
*C
, struct verify_options
*options
)
205 if (options
->print_all
)
207 if (C
->Dimension
<= 0)
210 d
= options
->M
- options
->m
;
212 options
->st
= 1+d
/80;
215 for (i
= options
->m
; i
<= options
->M
; i
+= options
->st
)
221 static void print_rational(FILE *out
, Value n
, Value d
)
223 value_print(out
, VALUE_FMT
, n
);
224 if (value_notone_p(d
)) {
226 value_print(out
, VALUE_FMT
, d
);
230 void check_poly_print(int ok
, int nparam
, Value
*z
,
231 Value want_n
, Value want_d
,
232 Value got_n
, Value got_d
,
233 const char *op
, const char *check
,
235 const struct verify_options
*options
)
239 if (options
->print_all
) {
241 value_print(stdout
, VALUE_FMT
, z
[0]);
242 for (k
= 1; k
< nparam
; ++k
) {
244 value_print(stdout
, VALUE_FMT
, z
[k
]);
247 print_rational(stdout
, got_n
, got_d
);
248 printf(", %s = ", check
);
249 print_rational(stdout
, want_n
, want_d
);
256 fprintf(stderr
, "Error !\n");
257 fprintf(stderr
, "%s(", op
);
258 value_print(stderr
, VALUE_FMT
, z
[0]);
259 for (k
= 1; k
< nparam
; ++k
) {
260 fprintf(stderr
,", ");
261 value_print(stderr
, VALUE_FMT
, z
[k
]);
263 fprintf(stderr
, ") should be ");
264 print_rational(stderr
, want_n
, want_d
);
265 fprintf(stderr
, ", while %s gives ", long_op
);
266 print_rational(stderr
, got_n
, got_d
);
267 fprintf(stderr
, ".\n");
268 } else if (options
->print_all
)
272 /****************************************************/
273 /* function check_poly : */
274 /* scans the parameter space from Min to Max (all */
275 /* directions). Computes the number of points in */
276 /* the polytope using both methods, and compare them*/
277 /* returns 1 on success */
278 /****************************************************/
280 int check_poly(Polyhedron
*CS
, const struct check_poly_data
*data
,
281 int nparam
, int pos
, Value
*z
,
282 const struct verify_options
*options
)
285 if (!data
->check(data
, nparam
, z
, options
) && !options
->continue_on_error
)
292 ok
= !(lower_upper_bounds(1+pos
, CS
, z
-1, &LB
, &UB
));
294 for (; value_le(LB
, UB
); value_increment(LB
, LB
)) {
295 if (!options
->print_all
) {
296 int k
= VALUE_TO_INT(LB
);
297 if (!pos
&& !(k
% options
->st
)) {
303 value_assign(z
[pos
], LB
);
304 if (!check_poly(CS
->next
, data
, nparam
, pos
+1, z
, options
)) {
310 value_set_si(z
[pos
], 0);
317 void check_EP_set_scan(struct check_EP_data
*data
, Polyhedron
*C
,
320 const evalue
*EP
= data
->EP
;
324 for (i
= 0; i
< EP
->x
.p
->size
/2; ++i
) {
325 Polyhedron
*A
= EVALUE_DOMAIN(EP
->x
.p
->arr
[2*i
]);
326 for (; A
; A
= A
->next
)
331 data
->S
= ALLOCN(Polyhedron
*, n_S
);
333 for (i
= 0; i
< EP
->x
.p
->size
/2; ++i
) {
334 Polyhedron
*A
= EVALUE_DOMAIN(EP
->x
.p
->arr
[2*i
]);
335 for (; A
; A
= A
->next
) {
336 Polyhedron
*next
= A
->next
;
338 data
->S
[n_S
++] = Polyhedron_Scan(A
, C
,
339 MaxRays
& POL_NO_DUAL
? 0 : MaxRays
);
345 void check_EP_clear_scan(struct check_EP_data
*data
)
349 for (i
= 0; i
< data
->n_S
; ++i
)
350 Domain_Free(data
->S
[i
]);
354 static int check_EP_on_poly(Polyhedron
*P
,
355 struct check_EP_data
*data
,
356 unsigned nvar
, unsigned nparam
,
357 struct verify_options
*options
)
360 unsigned MaxRays
= options
->barvinok
->MaxRays
;
363 CS
= check_poly_context_scan(NULL
, &P
, P
->Dimension
, options
);
365 check_poly_init(P
, options
);
367 if (!(CS
&& emptyQ2(CS
))) {
368 check_EP_set_scan(data
, P
, MaxRays
);
369 ok
= check_poly(CS
, &data
->cp
, nparam
, 0, data
->cp
.z
+1+nvar
, options
);
370 check_EP_clear_scan(data
);
373 if (!options
->print_all
)
385 * Project on final dim dimensions
387 Polyhedron
*DomainProject(Polyhedron
*D
, unsigned dim
, unsigned MaxRays
)
392 R
= Polyhedron_Project(D
, dim
);
393 for (P
= D
->next
; P
; P
= P
->next
) {
394 Polyhedron
*R2
= Polyhedron_Project(P
, dim
);
395 Polyhedron
*R3
= DomainUnion(R
, R2
, MaxRays
);
403 static Polyhedron
*evalue_parameter_domain(const evalue
*e
, unsigned nparam
,
407 Polyhedron
*U
= NULL
;
409 if (EVALUE_IS_ZERO(*e
))
410 return Universe_Polyhedron(0);
412 assert(value_zero_p(e
->d
));
413 assert(e
->x
.p
->type
== partition
);
414 assert(e
->x
.p
->size
>= 2);
416 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
417 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
418 Polyhedron
*P
= DomainProject(D
, nparam
, MaxRays
);
423 U
= DomainUnion(U
, P
, MaxRays
);
431 int check_EP(struct check_EP_data
*data
, unsigned nvar
, unsigned nparam
,
432 struct verify_options
*options
)
438 p
= Vector_Alloc(nvar
+nparam
+2);
439 value_set_si(p
->p
[nvar
+nparam
+1], 1);
443 D
= evalue_parameter_domain(data
->EP
, nparam
, options
->barvinok
->MaxRays
);
445 for (P
= D
; P
; P
= P
->next
) {
446 ok
= check_EP_on_poly(P
, data
, nvar
, nparam
, options
);
447 if (!ok
&& !options
->continue_on_error
)
457 __isl_give isl_set
*verify_context_set_bounds(__isl_take isl_set
*set
,
458 const struct verify_options
*options
)
465 nparam
= isl_set_dim(set
, isl_dim_param
);
467 if (options
->r
> 0) {
468 pt
= isl_set_sample_point(isl_set_copy(set
));
469 pt2
= isl_point_copy(pt
);
471 for (i
= 0; i
< nparam
; ++i
) {
472 pt
= isl_point_add_ui(pt
, isl_dim_param
, i
, options
->r
);
473 pt2
= isl_point_sub_ui(pt2
, isl_dim_param
, i
, options
->r
);
479 ctx
= isl_set_get_ctx(set
);
480 pt
= isl_point_zero(isl_set_get_space(set
));
481 v
= isl_val_int_from_si(ctx
, options
->m
);
482 for (i
= 0; i
< nparam
; ++i
)
483 pt
= isl_point_set_coordinate_val(pt
, isl_dim_param
, i
,
487 pt2
= isl_point_zero(isl_set_get_space(set
));
488 v
= isl_val_int_from_si(ctx
, options
->M
);
489 for (i
= 0; i
< nparam
; ++i
)
490 pt2
= isl_point_set_coordinate_val(pt2
, isl_dim_param
,
495 box
= isl_set_box_from_points(pt
, pt2
);
497 return isl_set_intersect(set
, box
);
500 int verify_point_data_init(struct verify_point_data
*vpd
,
501 __isl_keep isl_set
*context
)
506 context
= isl_set_copy(context
);
507 context
= isl_set_from_params(context
);
508 context
= isl_set_move_dims(context
, isl_dim_set
, 0, isl_dim_param
, 0,
509 isl_set_dim(context
, isl_dim_param
));
510 v
= isl_pw_qpolynomial_max(isl_set_card(context
));
511 vpd
->n
= isl_val_cmp_si(v
, 200) < 0 ? isl_val_get_num_si(v
) : 200;
514 if (!vpd
->options
->print_all
) {
515 vpd
->s
= vpd
->n
< 80 ? 1 : 1 + vpd
->n
/80;
516 for (i
= 0; i
< vpd
->n
; i
+= vpd
->s
)
522 vpd
->error
= !v
? -1 : 0;
527 void verify_point_data_fini(struct verify_point_data
*vpd
)
529 if (!vpd
->options
->print_all
)
533 fprintf(stderr
, "Check failed !\n");