1 | /* |
2 | * Copyright 2013 Ecole Normale Superieure |
3 | * |
4 | * Use of this software is governed by the MIT license |
5 | * |
6 | * Written by Sven Verdoolaege, |
7 | * Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France |
8 | */ |
9 | |
10 | #include <isl_int.h> |
11 | #include <isl_ctx_private.h> |
12 | #include <isl_val_private.h> |
13 | |
14 | #undef EL_BASE |
15 | #define EL_BASE val |
16 | |
17 | #include <isl_list_templ.c> |
18 | #include <isl_list_read_templ.c> |
19 | |
20 | /* Allocate an isl_val object with indeterminate value. |
21 | */ |
22 | __isl_give isl_val *isl_val_alloc(isl_ctx *ctx) |
23 | { |
24 | isl_val *v; |
25 | |
26 | v = isl_alloc_type(ctx, struct isl_val); |
27 | if (!v) |
28 | return NULL; |
29 | |
30 | v->ctx = ctx; |
31 | isl_ctx_ref(ctx); |
32 | v->ref = 1; |
33 | isl_int_init(v->n); |
34 | isl_int_init(v->d); |
35 | |
36 | return v; |
37 | } |
38 | |
39 | /* Return a reference to an isl_val representing zero. |
40 | */ |
41 | __isl_give isl_val *isl_val_zero(isl_ctx *ctx) |
42 | { |
43 | return isl_val_int_from_si(ctx, i: 0); |
44 | } |
45 | |
46 | /* Return a reference to an isl_val representing one. |
47 | */ |
48 | __isl_give isl_val *isl_val_one(isl_ctx *ctx) |
49 | { |
50 | return isl_val_int_from_si(ctx, i: 1); |
51 | } |
52 | |
53 | /* Return a reference to an isl_val representing negative one. |
54 | */ |
55 | __isl_give isl_val *isl_val_negone(isl_ctx *ctx) |
56 | { |
57 | return isl_val_int_from_si(ctx, i: -1); |
58 | } |
59 | |
60 | /* Return a reference to an isl_val representing NaN. |
61 | */ |
62 | __isl_give isl_val *isl_val_nan(isl_ctx *ctx) |
63 | { |
64 | isl_val *v; |
65 | |
66 | v = isl_val_alloc(ctx); |
67 | if (!v) |
68 | return NULL; |
69 | |
70 | isl_int_set_si(v->n, 0); |
71 | isl_int_set_si(v->d, 0); |
72 | |
73 | return v; |
74 | } |
75 | |
76 | /* Change "v" into a NaN. |
77 | */ |
78 | __isl_give isl_val *isl_val_set_nan(__isl_take isl_val *v) |
79 | { |
80 | if (!v) |
81 | return NULL; |
82 | if (isl_val_is_nan(v)) |
83 | return v; |
84 | v = isl_val_cow(val: v); |
85 | if (!v) |
86 | return NULL; |
87 | |
88 | isl_int_set_si(v->n, 0); |
89 | isl_int_set_si(v->d, 0); |
90 | |
91 | return v; |
92 | } |
93 | |
94 | /* Return a reference to an isl_val representing +infinity. |
95 | */ |
96 | __isl_give isl_val *isl_val_infty(isl_ctx *ctx) |
97 | { |
98 | isl_val *v; |
99 | |
100 | v = isl_val_alloc(ctx); |
101 | if (!v) |
102 | return NULL; |
103 | |
104 | isl_int_set_si(v->n, 1); |
105 | isl_int_set_si(v->d, 0); |
106 | |
107 | return v; |
108 | } |
109 | |
110 | /* Return a reference to an isl_val representing -infinity. |
111 | */ |
112 | __isl_give isl_val *isl_val_neginfty(isl_ctx *ctx) |
113 | { |
114 | isl_val *v; |
115 | |
116 | v = isl_val_alloc(ctx); |
117 | if (!v) |
118 | return NULL; |
119 | |
120 | isl_int_set_si(v->n, -1); |
121 | isl_int_set_si(v->d, 0); |
122 | |
123 | return v; |
124 | } |
125 | |
126 | /* Return a reference to an isl_val representing the integer "i". |
127 | */ |
128 | __isl_give isl_val *isl_val_int_from_si(isl_ctx *ctx, long i) |
129 | { |
130 | isl_val *v; |
131 | |
132 | v = isl_val_alloc(ctx); |
133 | if (!v) |
134 | return NULL; |
135 | |
136 | isl_int_set_si(v->n, i); |
137 | isl_int_set_si(v->d, 1); |
138 | |
139 | return v; |
140 | } |
141 | |
142 | /* Change the value of "v" to be equal to the integer "i". |
143 | */ |
144 | __isl_give isl_val *isl_val_set_si(__isl_take isl_val *v, long i) |
145 | { |
146 | if (!v) |
147 | return NULL; |
148 | if (isl_val_is_int(v) && isl_int_cmp_si(v->n, i) == 0) |
149 | return v; |
150 | v = isl_val_cow(val: v); |
151 | if (!v) |
152 | return NULL; |
153 | |
154 | isl_int_set_si(v->n, i); |
155 | isl_int_set_si(v->d, 1); |
156 | |
157 | return v; |
158 | } |
159 | |
160 | /* Change the value of "v" to be equal to zero. |
161 | */ |
162 | __isl_give isl_val *isl_val_set_zero(__isl_take isl_val *v) |
163 | { |
164 | return isl_val_set_si(v, i: 0); |
165 | } |
166 | |
167 | /* Return a reference to an isl_val representing the unsigned integer "u". |
168 | */ |
169 | __isl_give isl_val *isl_val_int_from_ui(isl_ctx *ctx, unsigned long u) |
170 | { |
171 | isl_val *v; |
172 | |
173 | v = isl_val_alloc(ctx); |
174 | if (!v) |
175 | return NULL; |
176 | |
177 | isl_int_set_ui(v->n, u); |
178 | isl_int_set_si(v->d, 1); |
179 | |
180 | return v; |
181 | } |
182 | |
183 | /* Return a reference to an isl_val representing the integer "n". |
184 | */ |
185 | __isl_give isl_val *isl_val_int_from_isl_int(isl_ctx *ctx, isl_int n) |
186 | { |
187 | isl_val *v; |
188 | |
189 | v = isl_val_alloc(ctx); |
190 | if (!v) |
191 | return NULL; |
192 | |
193 | isl_int_set(v->n, n); |
194 | isl_int_set_si(v->d, 1); |
195 | |
196 | return v; |
197 | } |
198 | |
199 | /* Return a reference to an isl_val representing the rational value "n"/"d". |
200 | * Normalizing the isl_val (if needed) is left to the caller. |
201 | */ |
202 | __isl_give isl_val *isl_val_rat_from_isl_int(isl_ctx *ctx, |
203 | isl_int n, isl_int d) |
204 | { |
205 | isl_val *v; |
206 | |
207 | v = isl_val_alloc(ctx); |
208 | if (!v) |
209 | return NULL; |
210 | |
211 | isl_int_set(v->n, n); |
212 | isl_int_set(v->d, d); |
213 | |
214 | return v; |
215 | } |
216 | |
217 | /* Return a new reference to "v". |
218 | */ |
219 | __isl_give isl_val *isl_val_copy(__isl_keep isl_val *v) |
220 | { |
221 | if (!v) |
222 | return NULL; |
223 | |
224 | v->ref++; |
225 | return v; |
226 | } |
227 | |
228 | /* Return a fresh copy of "val". |
229 | */ |
230 | __isl_give isl_val *isl_val_dup(__isl_keep isl_val *val) |
231 | { |
232 | isl_val *dup; |
233 | |
234 | if (!val) |
235 | return NULL; |
236 | |
237 | dup = isl_val_alloc(ctx: isl_val_get_ctx(val)); |
238 | if (!dup) |
239 | return NULL; |
240 | |
241 | isl_int_set(dup->n, val->n); |
242 | isl_int_set(dup->d, val->d); |
243 | |
244 | return dup; |
245 | } |
246 | |
247 | /* Return an isl_val that is equal to "val" and that has only |
248 | * a single reference. |
249 | */ |
250 | __isl_give isl_val *isl_val_cow(__isl_take isl_val *val) |
251 | { |
252 | if (!val) |
253 | return NULL; |
254 | |
255 | if (val->ref == 1) |
256 | return val; |
257 | val->ref--; |
258 | return isl_val_dup(val); |
259 | } |
260 | |
261 | /* Free "v" and return NULL. |
262 | */ |
263 | __isl_null isl_val *isl_val_free(__isl_take isl_val *v) |
264 | { |
265 | if (!v) |
266 | return NULL; |
267 | |
268 | if (--v->ref > 0) |
269 | return NULL; |
270 | |
271 | isl_ctx_deref(ctx: v->ctx); |
272 | isl_int_clear(v->n); |
273 | isl_int_clear(v->d); |
274 | free(ptr: v); |
275 | return NULL; |
276 | } |
277 | |
278 | /* Extract the numerator of a rational value "v" as an integer. |
279 | * |
280 | * If "v" is not a rational value, then the result is undefined. |
281 | */ |
282 | long isl_val_get_num_si(__isl_keep isl_val *v) |
283 | { |
284 | if (!v) |
285 | return 0; |
286 | if (!isl_val_is_rat(v)) |
287 | isl_die(isl_val_get_ctx(v), isl_error_invalid, |
288 | "expecting rational value" , return 0); |
289 | if (!isl_int_fits_slong(v->n)) |
290 | isl_die(isl_val_get_ctx(v), isl_error_invalid, |
291 | "numerator too large" , return 0); |
292 | return isl_int_get_si(v->n); |
293 | } |
294 | |
295 | /* Extract the numerator of a rational value "v" as an isl_int. |
296 | * |
297 | * If "v" is not a rational value, then the result is undefined. |
298 | */ |
299 | isl_stat isl_val_get_num_isl_int(__isl_keep isl_val *v, isl_int *n) |
300 | { |
301 | if (!v) |
302 | return isl_stat_error; |
303 | if (!isl_val_is_rat(v)) |
304 | isl_die(isl_val_get_ctx(v), isl_error_invalid, |
305 | "expecting rational value" , return isl_stat_error); |
306 | isl_int_set(*n, v->n); |
307 | return isl_stat_ok; |
308 | } |
309 | |
310 | /* Extract the denominator of a rational value "v" as an integer. |
311 | * |
312 | * If "v" is not a rational value, then the result is undefined. |
313 | */ |
314 | long isl_val_get_den_si(__isl_keep isl_val *v) |
315 | { |
316 | if (!v) |
317 | return 0; |
318 | if (!isl_val_is_rat(v)) |
319 | isl_die(isl_val_get_ctx(v), isl_error_invalid, |
320 | "expecting rational value" , return 0); |
321 | if (!isl_int_fits_slong(v->d)) |
322 | isl_die(isl_val_get_ctx(v), isl_error_invalid, |
323 | "denominator too large" , return 0); |
324 | return isl_int_get_si(v->d); |
325 | } |
326 | |
327 | /* Extract the denominator of a rational value "v" as an isl_val. |
328 | * |
329 | * If "v" is not a rational value, then the result is undefined. |
330 | */ |
331 | __isl_give isl_val *isl_val_get_den_val(__isl_keep isl_val *v) |
332 | { |
333 | if (!v) |
334 | return NULL; |
335 | if (!isl_val_is_rat(v)) |
336 | isl_die(isl_val_get_ctx(v), isl_error_invalid, |
337 | "expecting rational value" , return NULL); |
338 | return isl_val_int_from_isl_int(ctx: isl_val_get_ctx(val: v), n: v->d); |
339 | } |
340 | |
341 | /* Return an approximation of "v" as a double. |
342 | */ |
343 | double isl_val_get_d(__isl_keep isl_val *v) |
344 | { |
345 | if (!v) |
346 | return 0; |
347 | if (!isl_val_is_rat(v)) |
348 | isl_die(isl_val_get_ctx(v), isl_error_invalid, |
349 | "expecting rational value" , return 0); |
350 | return isl_int_get_d(v->n) / isl_int_get_d(v->d); |
351 | } |
352 | |
353 | /* Return the isl_ctx to which "val" belongs. |
354 | */ |
355 | isl_ctx *isl_val_get_ctx(__isl_keep isl_val *val) |
356 | { |
357 | return val ? val->ctx : NULL; |
358 | } |
359 | |
360 | /* Return a hash value that digests "val". |
361 | */ |
362 | uint32_t isl_val_get_hash(__isl_keep isl_val *val) |
363 | { |
364 | uint32_t hash; |
365 | |
366 | if (!val) |
367 | return 0; |
368 | |
369 | hash = isl_hash_init(); |
370 | hash = isl_int_hash(val->n, hash); |
371 | hash = isl_int_hash(val->d, hash); |
372 | |
373 | return hash; |
374 | } |
375 | |
376 | /* Normalize "v". |
377 | * |
378 | * In particular, make sure that the denominator of a rational value |
379 | * is positive and the numerator and denominator do not have any |
380 | * common divisors. |
381 | * |
382 | * This function should not be called by an external user |
383 | * since it will only be given normalized values. |
384 | */ |
385 | __isl_give isl_val *isl_val_normalize(__isl_take isl_val *v) |
386 | { |
387 | isl_ctx *ctx; |
388 | |
389 | if (!v) |
390 | return NULL; |
391 | if (isl_val_is_int(v)) |
392 | return v; |
393 | if (!isl_val_is_rat(v)) |
394 | return v; |
395 | if (isl_int_is_neg(v->d)) { |
396 | isl_int_neg(v->d, v->d); |
397 | isl_int_neg(v->n, v->n); |
398 | } |
399 | ctx = isl_val_get_ctx(val: v); |
400 | isl_int_gcd(ctx->normalize_gcd, v->n, v->d); |
401 | if (isl_int_is_one(ctx->normalize_gcd)) |
402 | return v; |
403 | isl_int_divexact(v->n, v->n, ctx->normalize_gcd); |
404 | isl_int_divexact(v->d, v->d, ctx->normalize_gcd); |
405 | return v; |
406 | } |
407 | |
408 | /* Return the opposite of "v". |
409 | */ |
410 | __isl_give isl_val *isl_val_neg(__isl_take isl_val *v) |
411 | { |
412 | if (!v) |
413 | return NULL; |
414 | if (isl_val_is_nan(v)) |
415 | return v; |
416 | if (isl_val_is_zero(v)) |
417 | return v; |
418 | |
419 | v = isl_val_cow(val: v); |
420 | if (!v) |
421 | return NULL; |
422 | isl_int_neg(v->n, v->n); |
423 | |
424 | return v; |
425 | } |
426 | |
427 | /* Return the inverse of "v". |
428 | */ |
429 | __isl_give isl_val *isl_val_inv(__isl_take isl_val *v) |
430 | { |
431 | if (!v) |
432 | return NULL; |
433 | if (isl_val_is_nan(v)) |
434 | return v; |
435 | if (isl_val_is_zero(v)) { |
436 | isl_ctx *ctx = isl_val_get_ctx(val: v); |
437 | isl_val_free(v); |
438 | return isl_val_nan(ctx); |
439 | } |
440 | if (isl_val_is_infty(v) || isl_val_is_neginfty(v)) { |
441 | isl_ctx *ctx = isl_val_get_ctx(val: v); |
442 | isl_val_free(v); |
443 | return isl_val_zero(ctx); |
444 | } |
445 | |
446 | v = isl_val_cow(val: v); |
447 | if (!v) |
448 | return NULL; |
449 | isl_int_swap(v->n, v->d); |
450 | |
451 | return isl_val_normalize(v); |
452 | } |
453 | |
454 | /* Return the absolute value of "v". |
455 | */ |
456 | __isl_give isl_val *isl_val_abs(__isl_take isl_val *v) |
457 | { |
458 | if (!v) |
459 | return NULL; |
460 | if (isl_val_is_nan(v)) |
461 | return v; |
462 | if (isl_val_is_nonneg(v)) |
463 | return v; |
464 | return isl_val_neg(v); |
465 | } |
466 | |
467 | /* Return the "floor" (greatest integer part) of "v". |
468 | * That is, return the result of rounding towards -infinity. |
469 | */ |
470 | __isl_give isl_val *isl_val_floor(__isl_take isl_val *v) |
471 | { |
472 | if (!v) |
473 | return NULL; |
474 | if (isl_val_is_int(v)) |
475 | return v; |
476 | if (!isl_val_is_rat(v)) |
477 | return v; |
478 | |
479 | v = isl_val_cow(val: v); |
480 | if (!v) |
481 | return NULL; |
482 | isl_int_fdiv_q(v->n, v->n, v->d); |
483 | isl_int_set_si(v->d, 1); |
484 | |
485 | return v; |
486 | } |
487 | |
488 | /* Return the "ceiling" of "v". |
489 | * That is, return the result of rounding towards +infinity. |
490 | */ |
491 | __isl_give isl_val *isl_val_ceil(__isl_take isl_val *v) |
492 | { |
493 | if (!v) |
494 | return NULL; |
495 | if (isl_val_is_int(v)) |
496 | return v; |
497 | if (!isl_val_is_rat(v)) |
498 | return v; |
499 | |
500 | v = isl_val_cow(val: v); |
501 | if (!v) |
502 | return NULL; |
503 | isl_int_cdiv_q(v->n, v->n, v->d); |
504 | isl_int_set_si(v->d, 1); |
505 | |
506 | return v; |
507 | } |
508 | |
509 | /* Truncate "v". |
510 | * That is, return the result of rounding towards zero. |
511 | */ |
512 | __isl_give isl_val *isl_val_trunc(__isl_take isl_val *v) |
513 | { |
514 | if (!v) |
515 | return NULL; |
516 | if (isl_val_is_int(v)) |
517 | return v; |
518 | if (!isl_val_is_rat(v)) |
519 | return v; |
520 | |
521 | v = isl_val_cow(val: v); |
522 | if (!v) |
523 | return NULL; |
524 | isl_int_tdiv_q(v->n, v->n, v->d); |
525 | isl_int_set_si(v->d, 1); |
526 | |
527 | return v; |
528 | } |
529 | |
530 | /* Return 2^v, where v is an integer (that is not too large). |
531 | */ |
532 | __isl_give isl_val *isl_val_pow2(__isl_take isl_val *v) |
533 | { |
534 | unsigned long exp; |
535 | int neg; |
536 | |
537 | v = isl_val_cow(val: v); |
538 | if (!v) |
539 | return NULL; |
540 | if (!isl_val_is_int(v)) |
541 | isl_die(isl_val_get_ctx(v), isl_error_invalid, |
542 | "can only compute integer powers" , |
543 | return isl_val_free(v)); |
544 | neg = isl_val_is_neg(v); |
545 | if (neg) |
546 | isl_int_neg(v->n, v->n); |
547 | if (!isl_int_fits_ulong(v->n)) |
548 | isl_die(isl_val_get_ctx(v), isl_error_invalid, |
549 | "exponent too large" , return isl_val_free(v)); |
550 | exp = isl_int_get_ui(v->n); |
551 | if (neg) { |
552 | isl_int_mul_2exp(v->d, v->d, exp); |
553 | isl_int_set_si(v->n, 1); |
554 | } else { |
555 | isl_int_mul_2exp(v->n, v->d, exp); |
556 | } |
557 | |
558 | return v; |
559 | } |
560 | |
561 | /* This is an alternative name for the function above. |
562 | */ |
563 | __isl_give isl_val *isl_val_2exp(__isl_take isl_val *v) |
564 | { |
565 | return isl_val_pow2(v); |
566 | } |
567 | |
568 | /* Return the minimum of "v1" and "v2". |
569 | */ |
570 | __isl_give isl_val *isl_val_min(__isl_take isl_val *v1, __isl_take isl_val *v2) |
571 | { |
572 | if (!v1 || !v2) |
573 | goto error; |
574 | |
575 | if (isl_val_is_nan(v: v1)) { |
576 | isl_val_free(v: v2); |
577 | return v1; |
578 | } |
579 | if (isl_val_is_nan(v: v2)) { |
580 | isl_val_free(v: v1); |
581 | return v2; |
582 | } |
583 | if (isl_val_le(v1, v2)) { |
584 | isl_val_free(v: v2); |
585 | return v1; |
586 | } else { |
587 | isl_val_free(v: v1); |
588 | return v2; |
589 | } |
590 | error: |
591 | isl_val_free(v: v1); |
592 | isl_val_free(v: v2); |
593 | return NULL; |
594 | } |
595 | |
596 | /* Return the maximum of "v1" and "v2". |
597 | */ |
598 | __isl_give isl_val *isl_val_max(__isl_take isl_val *v1, __isl_take isl_val *v2) |
599 | { |
600 | if (!v1 || !v2) |
601 | goto error; |
602 | |
603 | if (isl_val_is_nan(v: v1)) { |
604 | isl_val_free(v: v2); |
605 | return v1; |
606 | } |
607 | if (isl_val_is_nan(v: v2)) { |
608 | isl_val_free(v: v1); |
609 | return v2; |
610 | } |
611 | if (isl_val_ge(v1, v2)) { |
612 | isl_val_free(v: v2); |
613 | return v1; |
614 | } else { |
615 | isl_val_free(v: v1); |
616 | return v2; |
617 | } |
618 | error: |
619 | isl_val_free(v: v1); |
620 | isl_val_free(v: v2); |
621 | return NULL; |
622 | } |
623 | |
624 | /* Return the sum of "v1" and "v2". |
625 | */ |
626 | __isl_give isl_val *isl_val_add(__isl_take isl_val *v1, __isl_take isl_val *v2) |
627 | { |
628 | if (!v1 || !v2) |
629 | goto error; |
630 | if (isl_val_is_nan(v: v1)) { |
631 | isl_val_free(v: v2); |
632 | return v1; |
633 | } |
634 | if (isl_val_is_nan(v: v2)) { |
635 | isl_val_free(v: v1); |
636 | return v2; |
637 | } |
638 | if ((isl_val_is_infty(v: v1) && isl_val_is_neginfty(v: v2)) || |
639 | (isl_val_is_neginfty(v: v1) && isl_val_is_infty(v: v2))) { |
640 | isl_val_free(v: v2); |
641 | return isl_val_set_nan(v: v1); |
642 | } |
643 | if (isl_val_is_infty(v: v1) || isl_val_is_neginfty(v: v1)) { |
644 | isl_val_free(v: v2); |
645 | return v1; |
646 | } |
647 | if (isl_val_is_infty(v: v2) || isl_val_is_neginfty(v: v2)) { |
648 | isl_val_free(v: v1); |
649 | return v2; |
650 | } |
651 | if (isl_val_is_zero(v: v1)) { |
652 | isl_val_free(v: v1); |
653 | return v2; |
654 | } |
655 | if (isl_val_is_zero(v: v2)) { |
656 | isl_val_free(v: v2); |
657 | return v1; |
658 | } |
659 | |
660 | v1 = isl_val_cow(val: v1); |
661 | if (!v1) |
662 | goto error; |
663 | if (isl_val_is_int(v: v1) && isl_val_is_int(v: v2)) |
664 | isl_int_add(v1->n, v1->n, v2->n); |
665 | else { |
666 | if (isl_int_eq(v1->d, v2->d)) |
667 | isl_int_add(v1->n, v1->n, v2->n); |
668 | else { |
669 | isl_int_mul(v1->n, v1->n, v2->d); |
670 | isl_int_addmul(v1->n, v2->n, v1->d); |
671 | isl_int_mul(v1->d, v1->d, v2->d); |
672 | } |
673 | v1 = isl_val_normalize(v: v1); |
674 | } |
675 | isl_val_free(v: v2); |
676 | return v1; |
677 | error: |
678 | isl_val_free(v: v1); |
679 | isl_val_free(v: v2); |
680 | return NULL; |
681 | } |
682 | |
683 | /* Return the sum of "v1" and "v2". |
684 | */ |
685 | __isl_give isl_val *isl_val_add_ui(__isl_take isl_val *v1, unsigned long v2) |
686 | { |
687 | if (!v1) |
688 | return NULL; |
689 | if (!isl_val_is_rat(v: v1)) |
690 | return v1; |
691 | if (v2 == 0) |
692 | return v1; |
693 | v1 = isl_val_cow(val: v1); |
694 | if (!v1) |
695 | return NULL; |
696 | |
697 | isl_int_addmul_ui(v1->n, v1->d, v2); |
698 | |
699 | return v1; |
700 | } |
701 | |
702 | /* Subtract "v2" from "v1". |
703 | */ |
704 | __isl_give isl_val *isl_val_sub(__isl_take isl_val *v1, __isl_take isl_val *v2) |
705 | { |
706 | if (!v1 || !v2) |
707 | goto error; |
708 | if (isl_val_is_nan(v: v1)) { |
709 | isl_val_free(v: v2); |
710 | return v1; |
711 | } |
712 | if (isl_val_is_nan(v: v2)) { |
713 | isl_val_free(v: v1); |
714 | return v2; |
715 | } |
716 | if ((isl_val_is_infty(v: v1) && isl_val_is_infty(v: v2)) || |
717 | (isl_val_is_neginfty(v: v1) && isl_val_is_neginfty(v: v2))) { |
718 | isl_val_free(v: v2); |
719 | return isl_val_set_nan(v: v1); |
720 | } |
721 | if (isl_val_is_infty(v: v1) || isl_val_is_neginfty(v: v1)) { |
722 | isl_val_free(v: v2); |
723 | return v1; |
724 | } |
725 | if (isl_val_is_infty(v: v2) || isl_val_is_neginfty(v: v2)) { |
726 | isl_val_free(v: v1); |
727 | return isl_val_neg(v: v2); |
728 | } |
729 | if (isl_val_is_zero(v: v2)) { |
730 | isl_val_free(v: v2); |
731 | return v1; |
732 | } |
733 | if (isl_val_is_zero(v: v1)) { |
734 | isl_val_free(v: v1); |
735 | return isl_val_neg(v: v2); |
736 | } |
737 | |
738 | v1 = isl_val_cow(val: v1); |
739 | if (!v1) |
740 | goto error; |
741 | if (isl_val_is_int(v: v1) && isl_val_is_int(v: v2)) |
742 | isl_int_sub(v1->n, v1->n, v2->n); |
743 | else { |
744 | if (isl_int_eq(v1->d, v2->d)) |
745 | isl_int_sub(v1->n, v1->n, v2->n); |
746 | else { |
747 | isl_int_mul(v1->n, v1->n, v2->d); |
748 | isl_int_submul(v1->n, v2->n, v1->d); |
749 | isl_int_mul(v1->d, v1->d, v2->d); |
750 | } |
751 | v1 = isl_val_normalize(v: v1); |
752 | } |
753 | isl_val_free(v: v2); |
754 | return v1; |
755 | error: |
756 | isl_val_free(v: v1); |
757 | isl_val_free(v: v2); |
758 | return NULL; |
759 | } |
760 | |
761 | /* Subtract "v2" from "v1". |
762 | */ |
763 | __isl_give isl_val *isl_val_sub_ui(__isl_take isl_val *v1, unsigned long v2) |
764 | { |
765 | if (!v1) |
766 | return NULL; |
767 | if (!isl_val_is_rat(v: v1)) |
768 | return v1; |
769 | if (v2 == 0) |
770 | return v1; |
771 | v1 = isl_val_cow(val: v1); |
772 | if (!v1) |
773 | return NULL; |
774 | |
775 | isl_int_submul_ui(v1->n, v1->d, v2); |
776 | |
777 | return v1; |
778 | } |
779 | |
780 | /* Return the product of "v1" and "v2". |
781 | */ |
782 | __isl_give isl_val *isl_val_mul(__isl_take isl_val *v1, __isl_take isl_val *v2) |
783 | { |
784 | if (!v1 || !v2) |
785 | goto error; |
786 | if (isl_val_is_nan(v: v1)) { |
787 | isl_val_free(v: v2); |
788 | return v1; |
789 | } |
790 | if (isl_val_is_nan(v: v2)) { |
791 | isl_val_free(v: v1); |
792 | return v2; |
793 | } |
794 | if ((!isl_val_is_rat(v: v1) && isl_val_is_zero(v: v2)) || |
795 | (isl_val_is_zero(v: v1) && !isl_val_is_rat(v: v2))) { |
796 | isl_val_free(v: v2); |
797 | return isl_val_set_nan(v: v1); |
798 | } |
799 | if (isl_val_is_zero(v: v1)) { |
800 | isl_val_free(v: v2); |
801 | return v1; |
802 | } |
803 | if (isl_val_is_zero(v: v2)) { |
804 | isl_val_free(v: v1); |
805 | return v2; |
806 | } |
807 | if (isl_val_is_infty(v: v1) || isl_val_is_neginfty(v: v1)) { |
808 | if (isl_val_is_neg(v: v2)) |
809 | v1 = isl_val_neg(v: v1); |
810 | isl_val_free(v: v2); |
811 | return v1; |
812 | } |
813 | if (isl_val_is_infty(v: v2) || isl_val_is_neginfty(v: v2)) { |
814 | if (isl_val_is_neg(v: v1)) |
815 | v2 = isl_val_neg(v: v2); |
816 | isl_val_free(v: v1); |
817 | return v2; |
818 | } |
819 | |
820 | v1 = isl_val_cow(val: v1); |
821 | if (!v1) |
822 | goto error; |
823 | if (isl_val_is_int(v: v1) && isl_val_is_int(v: v2)) |
824 | isl_int_mul(v1->n, v1->n, v2->n); |
825 | else { |
826 | isl_int_mul(v1->n, v1->n, v2->n); |
827 | isl_int_mul(v1->d, v1->d, v2->d); |
828 | v1 = isl_val_normalize(v: v1); |
829 | } |
830 | isl_val_free(v: v2); |
831 | return v1; |
832 | error: |
833 | isl_val_free(v: v1); |
834 | isl_val_free(v: v2); |
835 | return NULL; |
836 | } |
837 | |
838 | /* Return the product of "v1" and "v2". |
839 | * |
840 | * This is a private copy of isl_val_mul for use in the generic |
841 | * isl_multi_*_scale_val instantiated for isl_val. |
842 | */ |
843 | __isl_give isl_val *isl_val_scale_val(__isl_take isl_val *v1, |
844 | __isl_take isl_val *v2) |
845 | { |
846 | return isl_val_mul(v1, v2); |
847 | } |
848 | |
849 | /* Return the product of "v1" and "v2". |
850 | */ |
851 | __isl_give isl_val *isl_val_mul_ui(__isl_take isl_val *v1, unsigned long v2) |
852 | { |
853 | if (!v1) |
854 | return NULL; |
855 | if (isl_val_is_nan(v: v1)) |
856 | return v1; |
857 | if (!isl_val_is_rat(v: v1)) { |
858 | if (v2 == 0) |
859 | v1 = isl_val_set_nan(v: v1); |
860 | return v1; |
861 | } |
862 | if (v2 == 1) |
863 | return v1; |
864 | v1 = isl_val_cow(val: v1); |
865 | if (!v1) |
866 | return NULL; |
867 | |
868 | isl_int_mul_ui(v1->n, v1->n, v2); |
869 | |
870 | return isl_val_normalize(v: v1); |
871 | } |
872 | |
873 | /* Divide "v1" by "v2". |
874 | */ |
875 | __isl_give isl_val *isl_val_div(__isl_take isl_val *v1, __isl_take isl_val *v2) |
876 | { |
877 | if (!v1 || !v2) |
878 | goto error; |
879 | if (isl_val_is_nan(v: v1)) { |
880 | isl_val_free(v: v2); |
881 | return v1; |
882 | } |
883 | if (isl_val_is_nan(v: v2)) { |
884 | isl_val_free(v: v1); |
885 | return v2; |
886 | } |
887 | if (isl_val_is_zero(v: v2) || |
888 | (!isl_val_is_rat(v: v1) && !isl_val_is_rat(v: v2))) { |
889 | isl_val_free(v: v2); |
890 | return isl_val_set_nan(v: v1); |
891 | } |
892 | if (isl_val_is_zero(v: v1)) { |
893 | isl_val_free(v: v2); |
894 | return v1; |
895 | } |
896 | if (isl_val_is_infty(v: v1) || isl_val_is_neginfty(v: v1)) { |
897 | if (isl_val_is_neg(v: v2)) |
898 | v1 = isl_val_neg(v: v1); |
899 | isl_val_free(v: v2); |
900 | return v1; |
901 | } |
902 | if (isl_val_is_infty(v: v2) || isl_val_is_neginfty(v: v2)) { |
903 | isl_val_free(v: v2); |
904 | return isl_val_set_zero(v: v1); |
905 | } |
906 | |
907 | v1 = isl_val_cow(val: v1); |
908 | if (!v1) |
909 | goto error; |
910 | if (isl_val_is_int(v: v2)) { |
911 | isl_int_mul(v1->d, v1->d, v2->n); |
912 | v1 = isl_val_normalize(v: v1); |
913 | } else { |
914 | isl_int_mul(v1->d, v1->d, v2->n); |
915 | isl_int_mul(v1->n, v1->n, v2->d); |
916 | v1 = isl_val_normalize(v: v1); |
917 | } |
918 | isl_val_free(v: v2); |
919 | return v1; |
920 | error: |
921 | isl_val_free(v: v1); |
922 | isl_val_free(v: v2); |
923 | return NULL; |
924 | } |
925 | |
926 | /* Divide "v1" by "v2". |
927 | */ |
928 | __isl_give isl_val *isl_val_div_ui(__isl_take isl_val *v1, unsigned long v2) |
929 | { |
930 | if (!v1) |
931 | return NULL; |
932 | if (isl_val_is_nan(v: v1)) |
933 | return v1; |
934 | if (v2 == 0) |
935 | return isl_val_set_nan(v: v1); |
936 | if (v2 == 1) |
937 | return v1; |
938 | if (isl_val_is_zero(v: v1)) |
939 | return v1; |
940 | if (isl_val_is_infty(v: v1) || isl_val_is_neginfty(v: v1)) |
941 | return v1; |
942 | v1 = isl_val_cow(val: v1); |
943 | if (!v1) |
944 | return NULL; |
945 | |
946 | isl_int_mul_ui(v1->d, v1->d, v2); |
947 | |
948 | return isl_val_normalize(v: v1); |
949 | } |
950 | |
951 | /* Divide "v1" by "v2". |
952 | * |
953 | * This is a private copy of isl_val_div for use in the generic |
954 | * isl_multi_*_scale_down_val instantiated for isl_val. |
955 | */ |
956 | __isl_give isl_val *isl_val_scale_down_val(__isl_take isl_val *v1, |
957 | __isl_take isl_val *v2) |
958 | { |
959 | return isl_val_div(v1, v2); |
960 | } |
961 | |
962 | /* Given two integer values "v1" and "v2", check if "v1" is divisible by "v2". |
963 | */ |
964 | isl_bool isl_val_is_divisible_by(__isl_keep isl_val *v1, __isl_keep isl_val *v2) |
965 | { |
966 | if (!v1 || !v2) |
967 | return isl_bool_error; |
968 | |
969 | if (!isl_val_is_int(v: v1) || !isl_val_is_int(v: v2)) |
970 | isl_die(isl_val_get_ctx(v1), isl_error_invalid, |
971 | "expecting two integers" , return isl_bool_error); |
972 | |
973 | return isl_bool_ok(isl_int_is_divisible_by(v1->n, v2->n)); |
974 | } |
975 | |
976 | /* Given two integer values "v1" and "v2", return the residue of "v1" |
977 | * modulo "v2". |
978 | */ |
979 | __isl_give isl_val *isl_val_mod(__isl_take isl_val *v1, __isl_take isl_val *v2) |
980 | { |
981 | if (!v1 || !v2) |
982 | goto error; |
983 | if (!isl_val_is_int(v: v1) || !isl_val_is_int(v: v2)) |
984 | isl_die(isl_val_get_ctx(v1), isl_error_invalid, |
985 | "expecting two integers" , goto error); |
986 | if (isl_val_is_nonneg(v: v1) && isl_val_lt(v1, v2)) { |
987 | isl_val_free(v: v2); |
988 | return v1; |
989 | } |
990 | v1 = isl_val_cow(val: v1); |
991 | if (!v1) |
992 | goto error; |
993 | isl_int_fdiv_r(v1->n, v1->n, v2->n); |
994 | isl_val_free(v: v2); |
995 | return v1; |
996 | error: |
997 | isl_val_free(v: v1); |
998 | isl_val_free(v: v2); |
999 | return NULL; |
1000 | } |
1001 | |
1002 | /* Given two integer values "v1" and "v2", return the residue of "v1" |
1003 | * modulo "v2". |
1004 | * |
1005 | * This is a private copy of isl_val_mod for use in the generic |
1006 | * isl_multi_*_mod_multi_val instantiated for isl_val. |
1007 | */ |
1008 | __isl_give isl_val *isl_val_mod_val(__isl_take isl_val *v1, |
1009 | __isl_take isl_val *v2) |
1010 | { |
1011 | return isl_val_mod(v1, v2); |
1012 | } |
1013 | |
1014 | /* Given two integer values, return their greatest common divisor. |
1015 | */ |
1016 | __isl_give isl_val *isl_val_gcd(__isl_take isl_val *v1, __isl_take isl_val *v2) |
1017 | { |
1018 | if (!v1 || !v2) |
1019 | goto error; |
1020 | if (!isl_val_is_int(v: v1) || !isl_val_is_int(v: v2)) |
1021 | isl_die(isl_val_get_ctx(v1), isl_error_invalid, |
1022 | "expecting two integers" , goto error); |
1023 | if (isl_val_eq(v1, v2)) { |
1024 | isl_val_free(v: v2); |
1025 | return v1; |
1026 | } |
1027 | if (isl_val_is_one(v: v1)) { |
1028 | isl_val_free(v: v2); |
1029 | return v1; |
1030 | } |
1031 | if (isl_val_is_one(v: v2)) { |
1032 | isl_val_free(v: v1); |
1033 | return v2; |
1034 | } |
1035 | v1 = isl_val_cow(val: v1); |
1036 | if (!v1) |
1037 | goto error; |
1038 | isl_int_gcd(v1->n, v1->n, v2->n); |
1039 | isl_val_free(v: v2); |
1040 | return v1; |
1041 | error: |
1042 | isl_val_free(v: v1); |
1043 | isl_val_free(v: v2); |
1044 | return NULL; |
1045 | } |
1046 | |
1047 | /* Compute x, y and g such that g = gcd(a,b) and a*x+b*y = g. |
1048 | */ |
1049 | static void isl_int_gcdext(isl_int *g, isl_int *x, isl_int *y, |
1050 | isl_int a, isl_int b) |
1051 | { |
1052 | isl_int d, tmp; |
1053 | isl_int a_copy, b_copy; |
1054 | |
1055 | isl_int_init(a_copy); |
1056 | isl_int_init(b_copy); |
1057 | isl_int_init(d); |
1058 | isl_int_init(tmp); |
1059 | isl_int_set(a_copy, a); |
1060 | isl_int_set(b_copy, b); |
1061 | isl_int_abs(*g, a_copy); |
1062 | isl_int_abs(d, b_copy); |
1063 | isl_int_set_si(*x, 1); |
1064 | isl_int_set_si(*y, 0); |
1065 | while (isl_int_is_pos(d)) { |
1066 | isl_int_fdiv_q(tmp, *g, d); |
1067 | isl_int_submul(*x, tmp, *y); |
1068 | isl_int_submul(*g, tmp, d); |
1069 | isl_int_swap(*g, d); |
1070 | isl_int_swap(*x, *y); |
1071 | } |
1072 | if (isl_int_is_zero(a_copy)) |
1073 | isl_int_set_si(*x, 0); |
1074 | else if (isl_int_is_neg(a_copy)) |
1075 | isl_int_neg(*x, *x); |
1076 | if (isl_int_is_zero(b_copy)) |
1077 | isl_int_set_si(*y, 0); |
1078 | else { |
1079 | isl_int_mul(tmp, a_copy, *x); |
1080 | isl_int_sub(tmp, *g, tmp); |
1081 | isl_int_divexact(*y, tmp, b_copy); |
1082 | } |
1083 | isl_int_clear(d); |
1084 | isl_int_clear(tmp); |
1085 | isl_int_clear(a_copy); |
1086 | isl_int_clear(b_copy); |
1087 | } |
1088 | |
1089 | /* Given two integer values v1 and v2, return their greatest common divisor g, |
1090 | * as well as two integers x and y such that x * v1 + y * v2 = g. |
1091 | */ |
1092 | __isl_give isl_val *isl_val_gcdext(__isl_take isl_val *v1, |
1093 | __isl_take isl_val *v2, __isl_give isl_val **x, __isl_give isl_val **y) |
1094 | { |
1095 | isl_ctx *ctx; |
1096 | isl_val *a = NULL, *b = NULL; |
1097 | |
1098 | if (!x && !y) |
1099 | return isl_val_gcd(v1, v2); |
1100 | |
1101 | if (!v1 || !v2) |
1102 | goto error; |
1103 | |
1104 | ctx = isl_val_get_ctx(val: v1); |
1105 | if (!isl_val_is_int(v: v1) || !isl_val_is_int(v: v2)) |
1106 | isl_die(ctx, isl_error_invalid, |
1107 | "expecting two integers" , goto error); |
1108 | |
1109 | v1 = isl_val_cow(val: v1); |
1110 | a = isl_val_alloc(ctx); |
1111 | b = isl_val_alloc(ctx); |
1112 | if (!v1 || !a || !b) |
1113 | goto error; |
1114 | isl_int_gcdext(g: &v1->n, x: &a->n, y: &b->n, a: v1->n, b: v2->n); |
1115 | if (x) { |
1116 | isl_int_set_si(a->d, 1); |
1117 | *x = a; |
1118 | } else |
1119 | isl_val_free(v: a); |
1120 | if (y) { |
1121 | isl_int_set_si(b->d, 1); |
1122 | *y = b; |
1123 | } else |
1124 | isl_val_free(v: b); |
1125 | isl_val_free(v: v2); |
1126 | return v1; |
1127 | error: |
1128 | isl_val_free(v: v1); |
1129 | isl_val_free(v: v2); |
1130 | isl_val_free(v: a); |
1131 | isl_val_free(v: b); |
1132 | if (x) |
1133 | *x = NULL; |
1134 | if (y) |
1135 | *y = NULL; |
1136 | return NULL; |
1137 | } |
1138 | |
1139 | /* Does "v" represent an integer value? |
1140 | */ |
1141 | isl_bool isl_val_is_int(__isl_keep isl_val *v) |
1142 | { |
1143 | if (!v) |
1144 | return isl_bool_error; |
1145 | |
1146 | return isl_bool_ok(isl_int_is_one(v->d)); |
1147 | } |
1148 | |
1149 | /* Does "v" represent a rational value? |
1150 | */ |
1151 | isl_bool isl_val_is_rat(__isl_keep isl_val *v) |
1152 | { |
1153 | if (!v) |
1154 | return isl_bool_error; |
1155 | |
1156 | return isl_bool_ok(b: !isl_int_is_zero(v->d)); |
1157 | } |
1158 | |
1159 | /* Does "v" represent NaN? |
1160 | */ |
1161 | isl_bool isl_val_is_nan(__isl_keep isl_val *v) |
1162 | { |
1163 | if (!v) |
1164 | return isl_bool_error; |
1165 | |
1166 | return isl_bool_ok(isl_int_is_zero(v->n) && isl_int_is_zero(v->d)); |
1167 | } |
1168 | |
1169 | /* Does "v" represent +infinity? |
1170 | */ |
1171 | isl_bool isl_val_is_infty(__isl_keep isl_val *v) |
1172 | { |
1173 | if (!v) |
1174 | return isl_bool_error; |
1175 | |
1176 | return isl_bool_ok(isl_int_is_pos(v->n) && isl_int_is_zero(v->d)); |
1177 | } |
1178 | |
1179 | /* Does "v" represent -infinity? |
1180 | */ |
1181 | isl_bool isl_val_is_neginfty(__isl_keep isl_val *v) |
1182 | { |
1183 | if (!v) |
1184 | return isl_bool_error; |
1185 | |
1186 | return isl_bool_ok(isl_int_is_neg(v->n) && isl_int_is_zero(v->d)); |
1187 | } |
1188 | |
1189 | /* Does "v" represent the integer zero? |
1190 | */ |
1191 | isl_bool isl_val_is_zero(__isl_keep isl_val *v) |
1192 | { |
1193 | if (!v) |
1194 | return isl_bool_error; |
1195 | |
1196 | return isl_bool_ok(isl_int_is_zero(v->n) && !isl_int_is_zero(v->d)); |
1197 | } |
1198 | |
1199 | /* Does "v" represent the integer one? |
1200 | */ |
1201 | isl_bool isl_val_is_one(__isl_keep isl_val *v) |
1202 | { |
1203 | if (!v) |
1204 | return isl_bool_error; |
1205 | |
1206 | if (isl_val_is_nan(v)) |
1207 | return isl_bool_false; |
1208 | |
1209 | return isl_bool_ok(isl_int_eq(v->n, v->d)); |
1210 | } |
1211 | |
1212 | /* Does "v" represent the integer negative one? |
1213 | */ |
1214 | isl_bool isl_val_is_negone(__isl_keep isl_val *v) |
1215 | { |
1216 | if (!v) |
1217 | return isl_bool_error; |
1218 | |
1219 | return isl_bool_ok(isl_int_is_neg(v->n) && isl_int_abs_eq(v->n, v->d)); |
1220 | } |
1221 | |
1222 | /* Is "v" (strictly) positive? |
1223 | */ |
1224 | isl_bool isl_val_is_pos(__isl_keep isl_val *v) |
1225 | { |
1226 | if (!v) |
1227 | return isl_bool_error; |
1228 | |
1229 | return isl_bool_ok(isl_int_is_pos(v->n)); |
1230 | } |
1231 | |
1232 | /* Is "v" (strictly) negative? |
1233 | */ |
1234 | isl_bool isl_val_is_neg(__isl_keep isl_val *v) |
1235 | { |
1236 | if (!v) |
1237 | return isl_bool_error; |
1238 | |
1239 | return isl_bool_ok(isl_int_is_neg(v->n)); |
1240 | } |
1241 | |
1242 | /* Is "v" non-negative? |
1243 | */ |
1244 | isl_bool isl_val_is_nonneg(__isl_keep isl_val *v) |
1245 | { |
1246 | if (!v) |
1247 | return isl_bool_error; |
1248 | |
1249 | if (isl_val_is_nan(v)) |
1250 | return isl_bool_false; |
1251 | |
1252 | return isl_bool_ok(isl_int_is_nonneg(v->n)); |
1253 | } |
1254 | |
1255 | /* Is "v" non-positive? |
1256 | */ |
1257 | isl_bool isl_val_is_nonpos(__isl_keep isl_val *v) |
1258 | { |
1259 | if (!v) |
1260 | return isl_bool_error; |
1261 | |
1262 | if (isl_val_is_nan(v)) |
1263 | return isl_bool_false; |
1264 | |
1265 | return isl_bool_ok(isl_int_is_nonpos(v->n)); |
1266 | } |
1267 | |
1268 | /* Return the sign of "v". |
1269 | * |
1270 | * The sign of NaN is undefined. |
1271 | */ |
1272 | int isl_val_sgn(__isl_keep isl_val *v) |
1273 | { |
1274 | if (!v) |
1275 | return 0; |
1276 | if (isl_val_is_zero(v)) |
1277 | return 0; |
1278 | if (isl_val_is_pos(v)) |
1279 | return 1; |
1280 | return -1; |
1281 | } |
1282 | |
1283 | /* Is "v1" (strictly) less than "v2"? |
1284 | */ |
1285 | isl_bool isl_val_lt(__isl_keep isl_val *v1, __isl_keep isl_val *v2) |
1286 | { |
1287 | isl_int t; |
1288 | isl_bool lt; |
1289 | |
1290 | if (!v1 || !v2) |
1291 | return isl_bool_error; |
1292 | if (isl_val_is_int(v: v1) && isl_val_is_int(v: v2)) |
1293 | return isl_bool_ok(isl_int_lt(v1->n, v2->n)); |
1294 | if (isl_val_is_nan(v: v1) || isl_val_is_nan(v: v2)) |
1295 | return isl_bool_false; |
1296 | if (isl_val_eq(v1, v2)) |
1297 | return isl_bool_false; |
1298 | if (isl_val_is_infty(v: v2)) |
1299 | return isl_bool_true; |
1300 | if (isl_val_is_infty(v: v1)) |
1301 | return isl_bool_false; |
1302 | if (isl_val_is_neginfty(v: v1)) |
1303 | return isl_bool_true; |
1304 | if (isl_val_is_neginfty(v: v2)) |
1305 | return isl_bool_false; |
1306 | |
1307 | isl_int_init(t); |
1308 | isl_int_mul(t, v1->n, v2->d); |
1309 | isl_int_submul(t, v2->n, v1->d); |
1310 | lt = isl_bool_ok(isl_int_is_neg(t)); |
1311 | isl_int_clear(t); |
1312 | |
1313 | return lt; |
1314 | } |
1315 | |
1316 | /* Is "v1" (strictly) greater than "v2"? |
1317 | */ |
1318 | isl_bool isl_val_gt(__isl_keep isl_val *v1, __isl_keep isl_val *v2) |
1319 | { |
1320 | return isl_val_lt(v1: v2, v2: v1); |
1321 | } |
1322 | |
1323 | /* Is "v" (strictly) greater than "i"? |
1324 | */ |
1325 | isl_bool isl_val_gt_si(__isl_keep isl_val *v, long i) |
1326 | { |
1327 | isl_val *vi; |
1328 | isl_bool res; |
1329 | |
1330 | if (!v) |
1331 | return isl_bool_error; |
1332 | if (isl_val_is_int(v)) |
1333 | return isl_bool_ok(isl_int_cmp_si(v->n, i) > 0); |
1334 | if (isl_val_is_nan(v)) |
1335 | return isl_bool_false; |
1336 | if (isl_val_is_infty(v)) |
1337 | return isl_bool_true; |
1338 | if (isl_val_is_neginfty(v)) |
1339 | return isl_bool_false; |
1340 | |
1341 | vi = isl_val_int_from_si(ctx: isl_val_get_ctx(val: v), i); |
1342 | res = isl_bool_ok(b: isl_val_gt(v1: v, v2: vi)); |
1343 | isl_val_free(v: vi); |
1344 | |
1345 | return res; |
1346 | } |
1347 | |
1348 | /* Is "v1" less than or equal to "v2"? |
1349 | */ |
1350 | isl_bool isl_val_le(__isl_keep isl_val *v1, __isl_keep isl_val *v2) |
1351 | { |
1352 | isl_int t; |
1353 | isl_bool le; |
1354 | |
1355 | if (!v1 || !v2) |
1356 | return isl_bool_error; |
1357 | if (isl_val_is_int(v: v1) && isl_val_is_int(v: v2)) |
1358 | return isl_bool_ok(isl_int_le(v1->n, v2->n)); |
1359 | if (isl_val_is_nan(v: v1) || isl_val_is_nan(v: v2)) |
1360 | return isl_bool_false; |
1361 | if (isl_val_eq(v1, v2)) |
1362 | return isl_bool_true; |
1363 | if (isl_val_is_infty(v: v2)) |
1364 | return isl_bool_true; |
1365 | if (isl_val_is_infty(v: v1)) |
1366 | return isl_bool_false; |
1367 | if (isl_val_is_neginfty(v: v1)) |
1368 | return isl_bool_true; |
1369 | if (isl_val_is_neginfty(v: v2)) |
1370 | return isl_bool_false; |
1371 | |
1372 | isl_int_init(t); |
1373 | isl_int_mul(t, v1->n, v2->d); |
1374 | isl_int_submul(t, v2->n, v1->d); |
1375 | le = isl_bool_ok(isl_int_is_nonpos(t)); |
1376 | isl_int_clear(t); |
1377 | |
1378 | return le; |
1379 | } |
1380 | |
1381 | /* Is "v1" greater than or equal to "v2"? |
1382 | */ |
1383 | isl_bool isl_val_ge(__isl_keep isl_val *v1, __isl_keep isl_val *v2) |
1384 | { |
1385 | return isl_val_le(v1: v2, v2: v1); |
1386 | } |
1387 | |
1388 | /* How does "v" compare to "i"? |
1389 | * |
1390 | * Return 1 if v is greater, -1 if v is smaller and 0 if v is equal to i. |
1391 | * |
1392 | * If v is NaN (or NULL), then the result is undefined. |
1393 | */ |
1394 | int isl_val_cmp_si(__isl_keep isl_val *v, long i) |
1395 | { |
1396 | isl_int t; |
1397 | int cmp; |
1398 | |
1399 | if (!v) |
1400 | return 0; |
1401 | if (isl_val_is_int(v)) |
1402 | return isl_int_cmp_si(v->n, i); |
1403 | if (isl_val_is_nan(v)) |
1404 | return 0; |
1405 | if (isl_val_is_infty(v)) |
1406 | return 1; |
1407 | if (isl_val_is_neginfty(v)) |
1408 | return -1; |
1409 | |
1410 | isl_int_init(t); |
1411 | isl_int_mul_si(t, v->d, i); |
1412 | isl_int_sub(t, v->n, t); |
1413 | cmp = isl_int_sgn(t); |
1414 | isl_int_clear(t); |
1415 | |
1416 | return cmp; |
1417 | } |
1418 | |
1419 | /* Is "v1" equal to "v2"? |
1420 | */ |
1421 | isl_bool isl_val_eq(__isl_keep isl_val *v1, __isl_keep isl_val *v2) |
1422 | { |
1423 | if (!v1 || !v2) |
1424 | return isl_bool_error; |
1425 | if (isl_val_is_nan(v: v1) || isl_val_is_nan(v: v2)) |
1426 | return isl_bool_false; |
1427 | |
1428 | return isl_bool_ok(isl_int_eq(v1->n, v2->n) && |
1429 | isl_int_eq(v1->d, v2->d)); |
1430 | } |
1431 | |
1432 | /* Is "v" equal to "i"? |
1433 | */ |
1434 | isl_bool isl_val_eq_si(__isl_keep isl_val *v, long i) |
1435 | { |
1436 | if (!v) |
1437 | return isl_bool_error; |
1438 | if (!isl_val_is_int(v)) |
1439 | return isl_bool_false; |
1440 | return isl_bool_ok(isl_int_cmp_si(v->n, i) == 0); |
1441 | } |
1442 | |
1443 | /* Is "v1" equal to "v2" in absolute value? |
1444 | */ |
1445 | isl_bool isl_val_abs_eq(__isl_keep isl_val *v1, __isl_keep isl_val *v2) |
1446 | { |
1447 | if (!v1 || !v2) |
1448 | return isl_bool_error; |
1449 | if (isl_val_is_nan(v: v1) || isl_val_is_nan(v: v2)) |
1450 | return isl_bool_false; |
1451 | |
1452 | return isl_bool_ok(isl_int_abs_eq(v1->n, v2->n) && |
1453 | isl_int_eq(v1->d, v2->d)); |
1454 | } |
1455 | |
1456 | /* Is "v1" different from "v2"? |
1457 | */ |
1458 | isl_bool isl_val_ne(__isl_keep isl_val *v1, __isl_keep isl_val *v2) |
1459 | { |
1460 | if (!v1 || !v2) |
1461 | return isl_bool_error; |
1462 | if (isl_val_is_nan(v: v1) || isl_val_is_nan(v: v2)) |
1463 | return isl_bool_false; |
1464 | |
1465 | return isl_bool_ok(isl_int_ne(v1->n, v2->n) || |
1466 | isl_int_ne(v1->d, v2->d)); |
1467 | } |
1468 | |
1469 | /* Print a textual representation of "v" onto "p". |
1470 | */ |
1471 | __isl_give isl_printer *isl_printer_print_val(__isl_take isl_printer *p, |
1472 | __isl_keep isl_val *v) |
1473 | { |
1474 | int neg; |
1475 | |
1476 | if (!p || !v) |
1477 | return isl_printer_free(printer: p); |
1478 | |
1479 | neg = isl_int_is_neg(v->n); |
1480 | if (neg) { |
1481 | p = isl_printer_print_str(p, s: "-" ); |
1482 | isl_int_neg(v->n, v->n); |
1483 | } |
1484 | if (isl_int_is_zero(v->d)) { |
1485 | int sgn = isl_int_sgn(v->n); |
1486 | p = isl_printer_print_str(p, s: sgn < 0 ? "-infty" : |
1487 | sgn == 0 ? "NaN" : "infty" ); |
1488 | } else |
1489 | p = isl_printer_print_isl_int(p, i: v->n); |
1490 | if (neg) |
1491 | isl_int_neg(v->n, v->n); |
1492 | if (!isl_int_is_zero(v->d) && !isl_int_is_one(v->d)) { |
1493 | p = isl_printer_print_str(p, s: "/" ); |
1494 | p = isl_printer_print_isl_int(p, i: v->d); |
1495 | } |
1496 | |
1497 | return p; |
1498 | } |
1499 | |
1500 | /* Is "val1" (obviously) equal to "val2"? |
1501 | * |
1502 | * This is a private copy of isl_val_eq for use in the generic |
1503 | * isl_multi_*_plain_is_equal instantiated for isl_val. |
1504 | */ |
1505 | isl_bool isl_val_plain_is_equal(__isl_keep isl_val *val1, |
1506 | __isl_keep isl_val *val2) |
1507 | { |
1508 | return isl_val_eq(v1: val1, v2: val2); |
1509 | } |
1510 | |
1511 | /* Does "v" have any non-zero coefficients |
1512 | * for any dimension in the given range? |
1513 | * |
1514 | * This function is only meant to be used in the generic isl_multi_* |
1515 | * functions which have to deal with base objects that have an associated |
1516 | * space. Since an isl_val does not have any coefficients, this function |
1517 | * always returns isl_bool_false. |
1518 | */ |
1519 | isl_bool isl_val_involves_dims(__isl_keep isl_val *v, enum isl_dim_type type, |
1520 | unsigned first, unsigned n) |
1521 | { |
1522 | if (!v) |
1523 | return isl_bool_error; |
1524 | |
1525 | return isl_bool_false; |
1526 | } |
1527 | |
1528 | /* Insert "n" dimensions of type "type" at position "first". |
1529 | * |
1530 | * This function is only meant to be used in the generic isl_multi_* |
1531 | * functions which have to deal with base objects that have an associated |
1532 | * space. Since an isl_val does not have an associated space, this function |
1533 | * does not do anything. |
1534 | */ |
1535 | __isl_give isl_val *isl_val_insert_dims(__isl_take isl_val *v, |
1536 | enum isl_dim_type type, unsigned first, unsigned n) |
1537 | { |
1538 | return v; |
1539 | } |
1540 | |
1541 | /* Change the name of the dimension of type "type" at position "pos" to "s". |
1542 | * |
1543 | * This function is only meant to be used in the generic isl_multi_* |
1544 | * functions which have to deal with base objects that have an associated |
1545 | * space. Since an isl_val does not have an associated space, this function |
1546 | * does not do anything. |
1547 | */ |
1548 | __isl_give isl_val *isl_val_set_dim_name(__isl_take isl_val *v, |
1549 | enum isl_dim_type type, unsigned pos, const char *s) |
1550 | { |
1551 | return v; |
1552 | } |
1553 | |
1554 | /* Return an isl_val that is zero on "ls". |
1555 | * |
1556 | * This function is only meant to be used in the generic isl_multi_* |
1557 | * functions which have to deal with base objects that have an associated |
1558 | * space. Since an isl_val does not have an associated space, this function |
1559 | * simply returns a zero isl_val in the same context as "ls". |
1560 | */ |
1561 | __isl_give isl_val *isl_val_zero_on_domain(__isl_take isl_local_space *ls) |
1562 | { |
1563 | isl_ctx *ctx; |
1564 | |
1565 | if (!ls) |
1566 | return NULL; |
1567 | ctx = isl_local_space_get_ctx(ls); |
1568 | isl_local_space_free(ls); |
1569 | return isl_val_zero(ctx); |
1570 | } |
1571 | |
1572 | #define isl_val_involves_nan isl_val_is_nan |
1573 | |
1574 | #undef BASE |
1575 | #define BASE val |
1576 | |
1577 | #include <isl_multi_no_domain_templ.c> |
1578 | #include <isl_multi_no_explicit_domain.c> |
1579 | #include <isl_multi_templ.c> |
1580 | #include <isl_multi_un_op_templ.c> |
1581 | #include <isl_multi_bin_val_templ.c> |
1582 | #include <isl_multi_arith_templ.c> |
1583 | #include <isl_multi_dim_id_templ.c> |
1584 | #include <isl_multi_dims.c> |
1585 | #include <isl_multi_min_max_templ.c> |
1586 | #include <isl_multi_nan_templ.c> |
1587 | #include <isl_multi_product_templ.c> |
1588 | #include <isl_multi_splice_templ.c> |
1589 | #include <isl_multi_tuple_id_templ.c> |
1590 | #include <isl_multi_zero_templ.c> |
1591 | |
1592 | /* Does "mv" consist of only zeros? |
1593 | */ |
1594 | isl_bool isl_multi_val_is_zero(__isl_keep isl_multi_val *mv) |
1595 | { |
1596 | return isl_multi_val_every(multi: mv, test: &isl_val_is_zero); |
1597 | } |
1598 | |
1599 | /* Add "v" to each of the elements of "mv". |
1600 | */ |
1601 | __isl_give isl_multi_val *isl_multi_val_add_val(__isl_take isl_multi_val *mv, |
1602 | __isl_take isl_val *v) |
1603 | { |
1604 | if (!v) |
1605 | return isl_multi_val_free(multi: mv); |
1606 | if (isl_val_is_zero(v)) { |
1607 | isl_val_free(v); |
1608 | return mv; |
1609 | } |
1610 | return isl_multi_val_fn_val(multi: mv, fn: &isl_val_add, v); |
1611 | } |
1612 | |
1613 | /* Reduce the elements of "mv" modulo "v". |
1614 | */ |
1615 | __isl_give isl_multi_val *isl_multi_val_mod_val(__isl_take isl_multi_val *mv, |
1616 | __isl_take isl_val *v) |
1617 | { |
1618 | return isl_multi_val_fn_val(multi: mv, fn: &isl_val_mod, v); |
1619 | } |
1620 | |