3 #include <barvinok/options.h>
4 #include <barvinok/util.h>
7 /* RANGE : normal range for evalutations (-RANGE -> RANGE) */
10 /* SRANGE : small range for evalutations */
13 /* if dimension >= BIDDIM, use SRANGE */
16 /* VSRANGE : very small range for evalutations */
19 /* if dimension >= VBIDDIM, use VSRANGE */
22 static struct argp_option argp_options
[] = {
23 { "verify", 'T', 0, 0 },
24 { "exact", 'E', 0, 0 },
25 { "print-all", 'A', 0, 0 },
26 { "continue-on-error", 'C', 0, 0 },
27 { "min", 'm', "int", 0 },
28 { "max", 'M', "int", 0 },
29 { "range", 'r', "int", 0 },
33 static error_t
parse_opt(int key
, char *arg
, struct argp_state
*state
)
35 struct verify_options
*options
= state
->input
;
41 options
->print_all
= 0;
42 options
->continue_on_error
= 0;
56 options
->print_all
= 1;
59 options
->continue_on_error
= 1;
62 options
->m
= atoi(arg
);
66 options
->M
= atoi(arg
);
70 options
->r
= atoi(arg
);
71 options
->M
= atoi(arg
);
72 options
->m
= -options
->M
;
76 return ARGP_ERR_UNKNOWN
;
81 void verify_options_set_range(struct verify_options
*options
, int dim
)
87 else if (dim
>= BIGDIM
)
91 /* If the user didn't set m or M, then we try to adjust the window
92 * to the context in check_poly_context_scan.
94 if (options
->m
== INT_MAX
&& options
->M
== INT_MIN
)
96 if (options
->M
== INT_MIN
)
98 if (options
->m
== INT_MAX
)
101 if (options
->verify
&& options
->m
> options
->M
) {
102 fprintf(stderr
,"Nothing to do: min > max !\n");
107 struct argp verify_argp
= {
108 argp_options
, parse_opt
, 0, 0
111 static Polyhedron
*project_on(Polyhedron
*P
, int i
)
113 unsigned dim
= P
->Dimension
;
118 return Polyhedron_Copy(P
);
120 T
= Matrix_Alloc(2, dim
+1);
121 value_set_si(T
->p
[0][i
], 1);
122 value_set_si(T
->p
[1][dim
], 1);
123 I
= Polyhedron_Image(P
, T
, P
->NbConstraints
);
128 static void set_bounds(Polyhedron
*C
, Value
**rows
, int i
, unsigned nparam
,
129 const struct verify_options
*options
)
136 value_set_si(min
, options
->m
);
137 value_set_si(max
, options
->M
);
139 if (options
->r
> 0) {
140 Polyhedron
*I
= project_on(C
, i
);
141 line_minmax(I
, &min
, &max
);
142 if (value_cmp_si(min
, options
->M
) >= 0)
143 value_add_int(max
, min
, options
->r
);
144 else if (value_cmp_si(max
, options
->m
) <= 0)
145 value_sub_int(min
, max
, options
->r
);
147 value_set_si(min
, options
->m
);
148 value_set_si(max
, options
->M
);
152 value_set_si(rows
[0][0], 1);
153 value_set_si(rows
[0][1+i
], 1);
154 value_oppose(rows
[0][1+nparam
], min
);
155 value_set_si(rows
[1][0], 1);
156 value_set_si(rows
[1][1+i
], -1);
157 value_assign(rows
[1][1+nparam
], max
);
163 Polyhedron
*check_poly_context_scan(Polyhedron
*P
, Polyhedron
**C
,
165 const struct verify_options
*options
)
169 Polyhedron
*CC
, *CC2
, *CS
, *U
;
170 unsigned MaxRays
= options
->barvinok
->MaxRays
;
178 CC
= Polyhedron_Project(P
, nparam
);
180 CC2
= DomainIntersection(*C
, CC
, MaxRays
);
186 /* Intersect context with range */
187 MM
= Matrix_Alloc(2*nparam
, nparam
+2);
188 for (i
= 0; i
< nparam
; ++i
)
189 set_bounds(CC
, &MM
->p
[2*i
], i
, nparam
, options
);
190 CC2
= AddConstraints(MM
->p
[0], 2*nparam
, CC
, options
->barvinok
->MaxRays
);
194 U
= Universe_Polyhedron(0);
195 CS
= Polyhedron_Scan(CC
, U
, MaxRays
& POL_NO_DUAL
? 0 : MaxRays
);
202 void check_poly_init(Polyhedron
*C
, struct verify_options
*options
)
206 if (options
->print_all
)
208 if (C
->Dimension
<= 0)
211 d
= options
->M
- options
->m
;
213 options
->st
= 1+d
/80;
216 for (i
= options
->m
; i
<= options
->M
; i
+= options
->st
)
222 static void print_rational(FILE *out
, Value n
, Value d
)
224 value_print(out
, VALUE_FMT
, n
);
225 if (value_notone_p(d
)) {
227 value_print(out
, VALUE_FMT
, d
);
231 void check_poly_print(int ok
, int nparam
, Value
*z
,
232 Value want_n
, Value want_d
,
233 Value got_n
, Value got_d
,
234 const char *op
, const char *check
,
236 const struct verify_options
*options
)
240 if (options
->print_all
) {
242 value_print(stdout
, VALUE_FMT
, z
[0]);
243 for (k
= 1; k
< nparam
; ++k
) {
245 value_print(stdout
, VALUE_FMT
, z
[k
]);
248 print_rational(stdout
, got_n
, got_d
);
249 printf(", %s = ", check
);
250 print_rational(stdout
, want_n
, want_d
);
257 fprintf(stderr
, "Error !\n");
258 fprintf(stderr
, "%s(", op
);
259 value_print(stderr
, VALUE_FMT
, z
[0]);
260 for (k
= 1; k
< nparam
; ++k
) {
261 fprintf(stderr
,", ");
262 value_print(stderr
, VALUE_FMT
, z
[k
]);
264 fprintf(stderr
, ") should be ");
265 print_rational(stderr
, want_n
, want_d
);
266 fprintf(stderr
, ", while %s gives ", long_op
);
267 print_rational(stderr
, got_n
, got_d
);
268 fprintf(stderr
, ".\n");
269 } else if (options
->print_all
)
273 /****************************************************/
274 /* function check_poly : */
275 /* scans the parameter space from Min to Max (all */
276 /* directions). Computes the number of points in */
277 /* the polytope using both methods, and compare them*/
278 /* returns 1 on success */
279 /****************************************************/
281 int check_poly(Polyhedron
*CS
, const struct check_poly_data
*data
,
282 int nparam
, int pos
, Value
*z
,
283 const struct verify_options
*options
)
286 if (!data
->check(data
, nparam
, z
, options
) && !options
->continue_on_error
)
293 ok
= !(lower_upper_bounds(1+pos
, CS
, z
-1, &LB
, &UB
));
295 for (; value_le(LB
, UB
); value_increment(LB
, LB
)) {
296 if (!options
->print_all
) {
297 int k
= VALUE_TO_INT(LB
);
298 if (!pos
&& !(k
% options
->st
)) {
304 value_assign(z
[pos
], LB
);
305 if (!check_poly(CS
->next
, data
, nparam
, pos
+1, z
, options
)) {
311 value_set_si(z
[pos
], 0);